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_LlcpTransport.c
     19  * \brief
     20  *
     21  * Project: NFC-FRI
     22  *
     23  */
     24 
     25 /*include files*/
     26 #include <phOsalNfc.h>
     27 #include <phLibNfcStatus.h>
     28 #include <phLibNfc.h>
     29 #include <phNfcLlcpTypes.h>
     30 #include <phFriNfc_Llcp.h>
     31 #include <phFriNfc_LlcpTransport.h>
     32 #include <phFriNfc_LlcpTransport_Connectionless.h>
     33 #include <phFriNfc_LlcpTransport_Connection.h>
     34 
     35 /* local macros */
     36 
     37 /* Check if (a <= x < b) */
     38 #define IS_BETWEEN(x, a, b) (((x)>=(a)) && ((x)<(b)))
     39 
     40 static NFCSTATUS phFriNfc_LlcpTransport_RegisterName(phFriNfc_LlcpTransport_Socket_t*   pLlcpSocket,
     41                                                      uint8_t                            nSap,
     42                                                      phNfc_sData_t                      *psServiceName);
     43 
     44 static NFCSTATUS phFriNfc_LlcpTransport_DiscoverServicesEx(phFriNfc_LlcpTransport_t *psTransport);
     45 
     46 static void phFriNfc_LlcpTransport_Send_CB(void            *pContext,
     47                                            NFCSTATUS        status);
     48 
     49 static NFCSTATUS phFriNfc_LlcpTransport_GetFreeSap(phFriNfc_LlcpTransport_t * psTransport, phNfc_sData_t *psServiceName, uint8_t * pnSap)
     50 {
     51    uint8_t i;
     52    uint8_t sap;
     53    uint8_t min_sap_range, max_sap_range;
     54    phFriNfc_LlcpTransport_Socket_t* pSocketTable = psTransport->pSocketTable;
     55 
     56    /* Calculate authorized SAP range */
     57    if ((psServiceName != NULL) && (psServiceName->length > 0))
     58    {
     59       /* Make sure that we will return the same SAP if service name was already used in the past */
     60       for(i=0 ; i<PHFRINFC_LLCP_SDP_ADVERTISED_NB ; i++)
     61       {
     62          if((psTransport->pCachedServiceNames[i].sServiceName.length > 0) &&
     63             (memcmp(psTransport->pCachedServiceNames[i].sServiceName.buffer, psServiceName->buffer, psServiceName->length) == 0))
     64          {
     65             /* Service name matched in cached service names list */
     66             *pnSap = psTransport->pCachedServiceNames[i].nSap;
     67             return NFCSTATUS_SUCCESS;
     68          }
     69       }
     70 
     71       /* SDP advertised service */
     72       min_sap_range = PHFRINFC_LLCP_SAP_SDP_ADVERTISED_FIRST;
     73       max_sap_range = PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST;
     74    }
     75    else
     76    {
     77       /* Non-SDP advertised service */
     78       min_sap_range = PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST;
     79       max_sap_range = PHFRINFC_LLCP_SAP_NUMBER;
     80    }
     81 
     82    /* Try all possible SAPs */
     83    for(sap=min_sap_range ; sap<max_sap_range ; sap++)
     84    {
     85       /* Go through socket list to check if current SAP is in use */
     86       for(i=0 ; i<PHFRINFC_LLCP_NB_SOCKET_MAX ; i++)
     87       {
     88          if((pSocketTable[i].eSocket_State >= phFriNfc_LlcpTransportSocket_eSocketBound) &&
     89             (pSocketTable[i].socket_sSap == sap))
     90          {
     91             /* SAP is already in use */
     92             break;
     93          }
     94       }
     95 
     96       if (i >= PHFRINFC_LLCP_NB_SOCKET_MAX)
     97       {
     98          /* No socket is using current SAP, proceed with binding */
     99          *pnSap = sap;
    100          return NFCSTATUS_SUCCESS;
    101       }
    102    }
    103 
    104    /* If we reach this point, it means that no SAP is free */
    105    return NFCSTATUS_INSUFFICIENT_RESOURCES;
    106 }
    107 
    108 static NFCSTATUS phFriNfc_LlcpTransport_EncodeSdreqTlv(phNfc_sData_t  *psTlvData,
    109                                                        uint32_t       *pOffset,
    110                                                        uint8_t        nTid,
    111                                                        phNfc_sData_t  *psServiceName)
    112 {
    113    NFCSTATUS result;
    114    uint32_t nTlvOffset = *pOffset;
    115    uint32_t nTlvStartOffset = nTlvOffset;
    116 
    117    /* Encode the TID */
    118    result = phFriNfc_Llcp_EncodeTLV(psTlvData,
    119                                     &nTlvOffset,
    120                                     PHFRINFC_LLCP_TLV_TYPE_SDREQ,
    121                                     1,
    122                                     &nTid);
    123    if (result != NFCSTATUS_SUCCESS)
    124    {
    125       goto clean_and_return;
    126    }
    127 
    128    /* Encode the service name itself */
    129    result = phFriNfc_Llcp_AppendTLV(psTlvData,
    130                                     nTlvStartOffset,
    131                                     &nTlvOffset,
    132                                     psServiceName->length,
    133                                     psServiceName->buffer);
    134    if (result != NFCSTATUS_SUCCESS)
    135    {
    136       goto clean_and_return;
    137    }
    138 
    139 clean_and_return:
    140    /* Save offset if no error occured */
    141    if (result == NFCSTATUS_SUCCESS)
    142    {
    143       *pOffset = nTlvOffset;
    144    }
    145 
    146    return result;
    147 }
    148 
    149 static NFCSTATUS phFriNfc_LlcpTransport_EncodeSdresTlv(phNfc_sData_t  *psTlvData,
    150                                                        uint32_t       *pOffset,
    151                                                        uint8_t        nTid,
    152                                                        uint8_t        nSap)
    153 {
    154    NFCSTATUS result;
    155    uint32_t nTlvStartOffset = *pOffset;
    156 
    157    /* Encode the TID */
    158    result = phFriNfc_Llcp_EncodeTLV(psTlvData,
    159                                     pOffset,
    160                                     PHFRINFC_LLCP_TLV_TYPE_SDRES,
    161                                     1,
    162                                     &nTid);
    163    if (result != NFCSTATUS_SUCCESS)
    164    {
    165       goto clean_and_return;
    166    }
    167 
    168    /* Encode the service name itself */
    169    result = phFriNfc_Llcp_AppendTLV(psTlvData,
    170                                     nTlvStartOffset,
    171                                     pOffset,
    172                                     1,
    173                                     &nSap);
    174    if (result != NFCSTATUS_SUCCESS)
    175    {
    176       goto clean_and_return;
    177    }
    178 
    179 clean_and_return:
    180    /* Restore previous offset if an error occured */
    181    if (result != NFCSTATUS_SUCCESS)
    182    {
    183       *pOffset = nTlvStartOffset;
    184    }
    185 
    186    return result;
    187 }
    188 
    189 static phFriNfc_LlcpTransport_Socket_t* phFriNfc_LlcpTransport_ServiceNameLoockup(phFriNfc_LlcpTransport_t *psTransport,
    190                                                                                   phNfc_sData_t            *pServiceName)
    191 {
    192    uint32_t                            index;
    193    uint8_t                             cacheIndex;
    194    phFriNfc_Llcp_CachedServiceName_t * pCachedServiceName;
    195    phFriNfc_LlcpTransport_Socket_t *   pSocket;
    196 
    197    /* Search a socket with the SN */
    198    for(index=0;index<PHFRINFC_LLCP_NB_SOCKET_MAX;index++)
    199    {
    200       pSocket = &psTransport->pSocketTable[index];
    201       /* Test if the CO socket is in Listen state or the CL socket is bound
    202          and if its SN is the good one */
    203       if((((pSocket->eSocket_Type == phFriNfc_LlcpTransport_eConnectionOriented)
    204          && (pSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketRegistered))
    205          || ((pSocket->eSocket_Type == phFriNfc_LlcpTransport_eConnectionLess)
    206          && (pSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketBound)))
    207          &&
    208          (pServiceName->length == pSocket->sServiceName.length)
    209          && !memcmp(pServiceName->buffer, pSocket->sServiceName.buffer, pServiceName->length))
    210       {
    211          /* Add new entry to cached service name/sap if not already in table */
    212          for(cacheIndex=0;cacheIndex<PHFRINFC_LLCP_SDP_ADVERTISED_NB;cacheIndex++)
    213          {
    214             pCachedServiceName = &psTransport->pCachedServiceNames[cacheIndex];
    215             if (pCachedServiceName->sServiceName.buffer != NULL)
    216             {
    217                if ((pCachedServiceName->sServiceName.length == pServiceName->length) &&
    218                    (memcmp(pCachedServiceName->sServiceName.buffer, pServiceName->buffer, pServiceName->length) == 0))
    219                {
    220                   /* Already registered */
    221                   break;
    222                }
    223             }
    224             else
    225             {
    226                /* Reached end of existing entries and not found the service name,
    227                 * => Add the new entry
    228                 */
    229                pCachedServiceName->nSap = pSocket->socket_sSap;
    230                pCachedServiceName->sServiceName.buffer = phOsalNfc_GetMemory(pServiceName->length);
    231                if (pCachedServiceName->sServiceName.buffer == NULL)
    232                {
    233                   /* Unable to cache this entry, so report this service as not found */
    234                   return NULL;
    235                }
    236                memcpy(pCachedServiceName->sServiceName.buffer, pServiceName->buffer, pServiceName->length);
    237                pCachedServiceName->sServiceName.length = pServiceName->length;
    238                break;
    239             }
    240          }
    241 
    242          return pSocket;
    243       }
    244    }
    245 
    246    return NULL;
    247 }
    248 
    249 
    250 static NFCSTATUS phFriNfc_LlcpTransport_DiscoveryAnswer(phFriNfc_LlcpTransport_t *psTransport)
    251 {
    252    NFCSTATUS         result = NFCSTATUS_PENDING;
    253    phNfc_sData_t     sInfoBuffer;
    254    uint32_t          nTlvOffset;
    255    uint8_t           index;
    256    uint8_t           nTid, nSap;
    257 
    258    /* Test if a send is pending */
    259    if(!psTransport->bSendPending)
    260    {
    261       /* Set the header */
    262       psTransport->sLlcpHeader.dsap  = PHFRINFC_LLCP_SAP_SDP;
    263       psTransport->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_SNL;
    264       psTransport->sLlcpHeader.ssap  = PHFRINFC_LLCP_SAP_SDP;
    265 
    266       /* Prepare the info buffer */
    267       sInfoBuffer.buffer = psTransport->pDiscoveryBuffer;
    268       sInfoBuffer.length = sizeof(psTransport->pDiscoveryBuffer);
    269 
    270       /* Encode as many requests as possible */
    271       nTlvOffset = 0;
    272       for(index=0 ; index<psTransport->nDiscoveryResListSize ; index++)
    273       {
    274          /* Get current TID/SAP and try to encode them in SNL frame */
    275          nTid = psTransport->nDiscoveryResTidList[index];
    276          nSap = psTransport->nDiscoveryResSapList[index];
    277          /* Encode response */
    278          result = phFriNfc_LlcpTransport_EncodeSdresTlv(&sInfoBuffer,
    279                                                         &nTlvOffset,
    280                                                         nTid,
    281                                                         nSap);
    282          if (result != NFCSTATUS_SUCCESS)
    283          {
    284             /* Impossible to fit the entire response */
    285             /* TODO: support reponse framgentation */
    286             break;
    287          }
    288       }
    289 
    290       /* Reset list size to be able to handle a new request */
    291       psTransport->nDiscoveryResListSize = 0;
    292 
    293       /* Update buffer length to match real TLV size */
    294       sInfoBuffer.length = nTlvOffset;
    295 
    296       /* Send Pending */
    297       psTransport->bSendPending = TRUE;
    298 
    299       /* Send SNL frame */
    300       result =  phFriNfc_Llcp_Send(psTransport->pLlcp,
    301                                    &psTransport->sLlcpHeader,
    302                                    NULL,
    303                                    &sInfoBuffer,
    304                                    phFriNfc_LlcpTransport_Send_CB,
    305                                    psTransport);
    306    }
    307    else
    308    {
    309       /* Impossible to send now, this function will be called again on next opportunity */
    310    }
    311 
    312    return result;
    313 }
    314 
    315 
    316 static void Handle_Discovery_IncomingFrame(phFriNfc_LlcpTransport_t           *psTransport,
    317                                            phNfc_sData_t                      *psData)
    318 {
    319    NFCSTATUS                        result;
    320    phNfc_sData_t                    sValue;
    321    phNfc_sData_t                    sResponseData;
    322    phNfc_sData_t                    sServiceName;
    323    uint32_t                         nInTlvOffset;
    324    uint8_t                          nType;
    325    uint8_t                          nTid;
    326    uint8_t                          nSap;
    327    pphFriNfc_Cr_t                   pfSavedCb;
    328    void                             *pfSavedContext;
    329    phFriNfc_LlcpTransport_Socket_t  *pSocket;
    330 
    331 
    332    /* Prepare buffer */
    333    sResponseData.buffer = psTransport->pDiscoveryBuffer;
    334    sResponseData.length = sizeof(psTransport->pDiscoveryBuffer);
    335 
    336    /* Parse all TLVs in frame */
    337    nInTlvOffset = 0;
    338    while(nInTlvOffset < psData->length)
    339    {
    340       result = phFriNfc_Llcp_DecodeTLV(psData,
    341                                        &nInTlvOffset,
    342                                        &nType,
    343                                        &sValue );
    344       switch(nType)
    345       {
    346          case PHFRINFC_LLCP_TLV_TYPE_SDREQ:
    347             if (sValue.length < 2)
    348             {
    349                /* Erroneous request, ignore */
    350                break;
    351             }
    352             /* Decode TID */
    353             nTid = sValue.buffer[0];
    354             /* Decode service name */
    355             sServiceName.buffer = sValue.buffer + 1;
    356             sServiceName.length = sValue.length - 1;
    357 
    358             /* Handle SDP service name */
    359             if((sServiceName.length == sizeof(PHFRINFC_LLCP_SERVICENAME_SDP)-1)
    360                && !memcmp(sServiceName.buffer, PHFRINFC_LLCP_SERVICENAME_SDP, sServiceName.length))
    361             {
    362                nSap = PHFRINFC_LLCP_SAP_SDP;
    363             }
    364             else
    365             {
    366                /* Match service name in socket list */
    367                pSocket = phFriNfc_LlcpTransport_ServiceNameLoockup(psTransport, &sServiceName);
    368                if (pSocket != NULL)
    369                {
    370                   nSap = pSocket->socket_sSap;
    371                }
    372                else
    373                {
    374                   nSap = 0;
    375                }
    376             }
    377 
    378             /* Encode response */
    379             if (psTransport->nDiscoveryResListSize < PHFRINFC_LLCP_SNL_RESPONSE_MAX)
    380             {
    381                psTransport->nDiscoveryResSapList[psTransport->nDiscoveryResListSize] = nSap;
    382                psTransport->nDiscoveryResTidList[psTransport->nDiscoveryResListSize] = nTid;
    383                psTransport->nDiscoveryResListSize++;
    384             }
    385             else
    386             {
    387                /* Remote peer is sending more than max. allowed requests (max. 256
    388                   different TID values), drop invalid requests to avoid buffer overflow
    389                */
    390             }
    391             break;
    392 
    393          case PHFRINFC_LLCP_TLV_TYPE_SDRES:
    394             if (psTransport->pfDiscover_Cb == NULL)
    395             {
    396                /* Ignore response when no requests are pending */
    397                break;
    398             }
    399             if (sValue.length != 2)
    400             {
    401                /* Erroneous response, ignore it */
    402                break;
    403             }
    404             /* Decode TID and SAP */
    405             nTid = sValue.buffer[0];
    406             if (nTid >= psTransport->nDiscoveryListSize)
    407             {
    408                /* Unkown TID, ignore it */
    409                break;
    410             }
    411             nSap = sValue.buffer[1];
    412             /* Save response */
    413             psTransport->pnDiscoverySapList[nTid] = nSap;
    414             /* Update response counter */
    415             psTransport->nDiscoveryResOffset++;
    416             break;
    417 
    418          default:
    419             /* Ignored */
    420             break;
    421       }
    422    }
    423 
    424    /* If discovery requests have been received, send response */
    425    if (psTransport->nDiscoveryResListSize > 0)
    426    {
    427       phFriNfc_LlcpTransport_DiscoveryAnswer(psTransport);
    428    }
    429 
    430    /* If all discovery responses have been received, trigger callback (if any) */
    431    if ((psTransport->pfDiscover_Cb != NULL) &&
    432        (psTransport->nDiscoveryResOffset >= psTransport->nDiscoveryListSize))
    433    {
    434       pfSavedCb = psTransport->pfDiscover_Cb;
    435       pfSavedContext = psTransport->pDiscoverContext;
    436 
    437       psTransport->pfDiscover_Cb = NULL;
    438       psTransport->pDiscoverContext = NULL;
    439 
    440       pfSavedCb(pfSavedContext, NFCSTATUS_SUCCESS);
    441    }
    442 }
    443 
    444 
    445 /* TODO: comment function Transport recv CB */
    446 static void phFriNfc_LlcpTransport__Recv_CB(void            *pContext,
    447                                             phNfc_sData_t   *psData,
    448                                             NFCSTATUS        status)
    449 {
    450    phFriNfc_Llcp_sPacketHeader_t   sLlcpLocalHeader;
    451    uint8_t   dsap;
    452    uint8_t   ptype;
    453    uint8_t   ssap;
    454 
    455    phFriNfc_LlcpTransport_t* pLlcpTransport = (phFriNfc_LlcpTransport_t*)pContext;
    456 
    457    if(status != NFCSTATUS_SUCCESS)
    458    {
    459       pLlcpTransport->LinkStatusError = TRUE;
    460    }
    461    else
    462    {
    463       phFriNfc_Llcp_Buffer2Header( psData->buffer,0x00, &sLlcpLocalHeader);
    464 
    465       dsap  = (uint8_t)sLlcpLocalHeader.dsap;
    466       ptype = (uint8_t)sLlcpLocalHeader.ptype;
    467       ssap  = (uint8_t)sLlcpLocalHeader.ssap;
    468 
    469       /* Update the length value (without the header length) */
    470       psData->length = psData->length - PHFRINFC_LLCP_PACKET_HEADER_SIZE;
    471 
    472       /* Update the buffer pointer */
    473       psData->buffer = psData->buffer + PHFRINFC_LLCP_PACKET_HEADER_SIZE;
    474 
    475       switch(ptype)
    476       {
    477       /* Connectionless */
    478       case PHFRINFC_LLCP_PTYPE_UI:
    479          {
    480             Handle_Connectionless_IncommingFrame(pLlcpTransport,
    481                                                  psData,
    482                                                  dsap,
    483                                                  ssap);
    484          }break;
    485 
    486       /* Service Discovery Protocol */
    487       case PHFRINFC_LLCP_PTYPE_SNL:
    488          {
    489             if ((ssap == PHFRINFC_LLCP_SAP_SDP) && (dsap == PHFRINFC_LLCP_SAP_SDP))
    490             {
    491                Handle_Discovery_IncomingFrame(pLlcpTransport,
    492                                               psData);
    493             }
    494             else
    495             {
    496                /* Ignore frame if source and destination are not the SDP service */
    497             }
    498          }break;
    499 
    500       /* Connection oriented */
    501       /* NOTE: forward reserved PTYPE to enable FRMR sending */
    502       case PHFRINFC_LLCP_PTYPE_CONNECT:
    503       case PHFRINFC_LLCP_PTYPE_CC:
    504       case PHFRINFC_LLCP_PTYPE_DISC:
    505       case PHFRINFC_LLCP_PTYPE_DM:
    506       case PHFRINFC_LLCP_PTYPE_I:
    507       case PHFRINFC_LLCP_PTYPE_RR:
    508       case PHFRINFC_LLCP_PTYPE_RNR:
    509       case PHFRINFC_LLCP_PTYPE_FRMR:
    510       case PHFRINFC_LLCP_PTYPE_RESERVED1:
    511       case PHFRINFC_LLCP_PTYPE_RESERVED2:
    512       case PHFRINFC_LLCP_PTYPE_RESERVED3:
    513          {
    514             Handle_ConnectionOriented_IncommingFrame(pLlcpTransport,
    515                                                      psData,
    516                                                      dsap,
    517                                                      ptype,
    518                                                      ssap);
    519          }break;
    520       default:
    521          {
    522 
    523          }break;
    524       }
    525 
    526       /*Restart the Receive Loop */
    527       status  = phFriNfc_Llcp_Recv(pLlcpTransport->pLlcp,
    528                                    phFriNfc_LlcpTransport__Recv_CB,
    529                                    pLlcpTransport);
    530    }
    531 }
    532 
    533 
    534 /* TODO: comment function Transport recv CB */
    535 static void phFriNfc_LlcpTransport_Send_CB(void            *pContext,
    536                                            NFCSTATUS        status)
    537 {
    538    phFriNfc_LlcpTransport_t         *psTransport = (phFriNfc_LlcpTransport_t*)pContext;
    539    NFCSTATUS                        result = NFCSTATUS_FAILED;
    540    phNfc_sData_t                    sFrmrBuffer;
    541    phFriNfc_Llcp_Send_CB_t          pfSavedCb;
    542    void                             *pSavedContext;
    543    phFriNfc_LlcpTransport_Socket_t  *pCurrentSocket = NULL;
    544    uint8_t                          index;
    545 
    546    /* 1 - Reset the FLAG send pending*/
    547    psTransport->bSendPending = FALSE;
    548 
    549    /* 2 - Handle pending error responses */
    550 
    551    if(psTransport->bFrmrPending)
    552    {
    553       /* Reset FRMR pending */
    554       psTransport->bFrmrPending = FALSE;
    555 
    556       /* Send Frmr */
    557       sFrmrBuffer.buffer = psTransport->FrmrInfoBuffer;
    558       sFrmrBuffer.length = 0x04; /* Size of FRMR Information field */
    559 
    560       /* Send Pending */
    561       psTransport->bSendPending = TRUE;
    562 
    563       result =  phFriNfc_Llcp_Send(psTransport->pLlcp,
    564                                    &psTransport->sLlcpHeader,
    565                                    NULL,
    566                                    &sFrmrBuffer,
    567                                    phFriNfc_LlcpTransport_Send_CB,
    568                                    psTransport);
    569 
    570    }
    571    else if(psTransport->bDmPending)
    572    {
    573       /* Reset DM pending */
    574       psTransport->bDmPending = FALSE;
    575 
    576       /* Send DM pending */
    577       result = phFriNfc_LlcpTransport_SendDisconnectMode(psTransport,
    578                                                          psTransport->DmInfoBuffer[0],
    579                                                          psTransport->DmInfoBuffer[1],
    580                                                          psTransport->DmInfoBuffer[2]);
    581    }
    582 
    583    /* 3 - Call the original callback */
    584 
    585    if (psTransport->pfLinkSendCb != NULL)
    586    {
    587       pfSavedCb = psTransport->pfLinkSendCb;
    588       pSavedContext = psTransport->pLinkSendContext;
    589 
    590       psTransport->pfLinkSendCb = NULL;
    591       psTransport->pLinkSendContext = NULL;
    592 
    593       (*pfSavedCb)(pSavedContext, status);
    594    }
    595 
    596    /* 4 - Handle pending send operations */
    597 
    598    /* Check for pending discovery requests/responses */
    599    if (psTransport->nDiscoveryResListSize > 0)
    600    {
    601       phFriNfc_LlcpTransport_DiscoveryAnswer(psTransport);
    602    }
    603    if ( (psTransport->pfDiscover_Cb != NULL) &&
    604         (psTransport->nDiscoveryReqOffset < psTransport->nDiscoveryListSize) )
    605    {
    606       result = phFriNfc_LlcpTransport_DiscoverServicesEx(psTransport);
    607    }
    608 
    609    /* Init index */
    610    index = psTransport->socketIndex;
    611 
    612    /* Check all sockets for pending operation */
    613    do
    614    {
    615       /* Modulo-increment index */
    616       index = (index + 1) % PHFRINFC_LLCP_NB_SOCKET_MAX;
    617 
    618       pCurrentSocket = &psTransport->pSocketTable[index];
    619 
    620       /* Dispatch to the corresponding transport layer */
    621       if (pCurrentSocket->eSocket_Type == phFriNfc_LlcpTransport_eConnectionOriented)
    622       {
    623          result = phFriNfc_LlcpTransport_ConnectionOriented_HandlePendingOperations(pCurrentSocket);
    624       }
    625       else if (pCurrentSocket->eSocket_Type == phFriNfc_LlcpTransport_eConnectionLess)
    626       {
    627          result = phFriNfc_LlcpTransport_Connectionless_HandlePendingOperations(pCurrentSocket);
    628       }
    629 
    630       if (result != NFCSTATUS_FAILED)
    631       {
    632          /* Stop looping if pending operation has been found */
    633          break;
    634       }
    635 
    636    } while(index != psTransport->socketIndex);
    637 
    638    /* Save the new index */
    639    psTransport->socketIndex = index;
    640 }
    641 
    642 
    643 /* TODO: comment function Transport reset */
    644 NFCSTATUS phFriNfc_LlcpTransport_Reset (phFriNfc_LlcpTransport_t      *pLlcpTransport,
    645                                         phFriNfc_Llcp_t               *pLlcp)
    646 {
    647    NFCSTATUS status = NFCSTATUS_SUCCESS;
    648    uint8_t i;
    649 
    650    /* Check for NULL pointers */
    651    if(pLlcpTransport == NULL || pLlcp == NULL)
    652    {
    653       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
    654    }
    655    else
    656    {
    657       /* Reset Transport structure */
    658       pLlcpTransport->pLlcp            = pLlcp;
    659       pLlcpTransport->LinkStatusError  = FALSE;
    660       pLlcpTransport->bSendPending     = FALSE;
    661       pLlcpTransport->bRecvPending     = FALSE;
    662       pLlcpTransport->bDmPending       = FALSE;
    663       pLlcpTransport->bFrmrPending     = FALSE;
    664       pLlcpTransport->socketIndex      = FALSE;
    665       pLlcpTransport->LinkStatusError  = 0;
    666       pLlcpTransport->pfDiscover_Cb    = NULL;
    667 
    668       /* Initialize cached service name/sap table */
    669       memset(pLlcpTransport->pCachedServiceNames, 0x00, sizeof(phFriNfc_Llcp_CachedServiceName_t)*PHFRINFC_LLCP_SDP_ADVERTISED_NB);
    670 
    671       /* Reset all the socket info in the table */
    672       for(i=0;i<PHFRINFC_LLCP_NB_SOCKET_MAX;i++)
    673       {
    674          pLlcpTransport->pSocketTable[i].eSocket_State                  = phFriNfc_LlcpTransportSocket_eSocketDefault;
    675          pLlcpTransport->pSocketTable[i].eSocket_Type                   = phFriNfc_LlcpTransport_eDefaultType;
    676          pLlcpTransport->pSocketTable[i].index                          = i;
    677          pLlcpTransport->pSocketTable[i].pContext                       = NULL;
    678          pLlcpTransport->pSocketTable[i].pListenContext                 = NULL;
    679          pLlcpTransport->pSocketTable[i].pAcceptContext                 = NULL;
    680          pLlcpTransport->pSocketTable[i].pRejectContext                 = NULL;
    681          pLlcpTransport->pSocketTable[i].pConnectContext                = NULL;
    682          pLlcpTransport->pSocketTable[i].pDisonnectContext              = NULL;
    683          pLlcpTransport->pSocketTable[i].pSendContext                   = NULL;
    684          pLlcpTransport->pSocketTable[i].pRecvContext                   = NULL;
    685          pLlcpTransport->pSocketTable[i].pSocketErrCb                   = NULL;
    686          pLlcpTransport->pSocketTable[i].bufferLinearLength             = 0;
    687          pLlcpTransport->pSocketTable[i].bufferSendMaxLength            = 0;
    688          pLlcpTransport->pSocketTable[i].bufferRwMaxLength              = 0;
    689          pLlcpTransport->pSocketTable[i].ReceiverBusyCondition          = FALSE;
    690          pLlcpTransport->pSocketTable[i].RemoteBusyConditionInfo        = FALSE;
    691          pLlcpTransport->pSocketTable[i].socket_sSap                    = PHFRINFC_LLCP_SAP_DEFAULT;
    692          pLlcpTransport->pSocketTable[i].socket_dSap                    = PHFRINFC_LLCP_SAP_DEFAULT;
    693          pLlcpTransport->pSocketTable[i].bSocketRecvPending             = FALSE;
    694          pLlcpTransport->pSocketTable[i].bSocketSendPending             = FALSE;
    695          pLlcpTransport->pSocketTable[i].bSocketListenPending           = FALSE;
    696          pLlcpTransport->pSocketTable[i].bSocketDiscPending             = FALSE;
    697          pLlcpTransport->pSocketTable[i].bSocketConnectPending          = FALSE;
    698          pLlcpTransport->pSocketTable[i].bSocketAcceptPending           = FALSE;
    699          pLlcpTransport->pSocketTable[i].bSocketRRPending               = FALSE;
    700          pLlcpTransport->pSocketTable[i].bSocketRNRPending              = FALSE;
    701          pLlcpTransport->pSocketTable[i].psTransport                    = pLlcpTransport;
    702          pLlcpTransport->pSocketTable[i].pfSocketSend_Cb                = NULL;
    703          pLlcpTransport->pSocketTable[i].pfSocketRecv_Cb                = NULL;
    704          pLlcpTransport->pSocketTable[i].pfSocketRecvFrom_Cb            = NULL;
    705          pLlcpTransport->pSocketTable[i].pfSocketListen_Cb              = NULL;
    706          pLlcpTransport->pSocketTable[i].pfSocketConnect_Cb             = NULL;
    707          pLlcpTransport->pSocketTable[i].pfSocketDisconnect_Cb          = NULL;
    708          pLlcpTransport->pSocketTable[i].socket_VS                      = 0;
    709          pLlcpTransport->pSocketTable[i].socket_VSA                     = 0;
    710          pLlcpTransport->pSocketTable[i].socket_VR                      = 0;
    711          pLlcpTransport->pSocketTable[i].socket_VRA                     = 0;
    712          pLlcpTransport->pSocketTable[i].remoteRW                       = 0;
    713          pLlcpTransport->pSocketTable[i].localRW                        = 0;
    714          pLlcpTransport->pSocketTable[i].remoteMIU                      = 0;
    715          pLlcpTransport->pSocketTable[i].localMIUX                      = 0;
    716          pLlcpTransport->pSocketTable[i].index                          = 0;
    717          pLlcpTransport->pSocketTable[i].indexRwRead                    = 0;
    718          pLlcpTransport->pSocketTable[i].indexRwWrite                   = 0;
    719 
    720          memset(&pLlcpTransport->pSocketTable[i].sSocketOption, 0x00, sizeof(phFriNfc_LlcpTransport_sSocketOptions_t));
    721 
    722          if (pLlcpTransport->pSocketTable[i].sServiceName.buffer != NULL) {
    723             phOsalNfc_FreeMemory(pLlcpTransport->pSocketTable[i].sServiceName.buffer);
    724          }
    725          pLlcpTransport->pSocketTable[i].sServiceName.buffer = NULL;
    726          pLlcpTransport->pSocketTable[i].sServiceName.length = 0;
    727       }
    728 
    729       /* Start The Receive Loop */
    730       status  = phFriNfc_Llcp_Recv(pLlcpTransport->pLlcp,
    731                                    phFriNfc_LlcpTransport__Recv_CB,
    732                                    pLlcpTransport);
    733    }
    734    return status;
    735 }
    736 
    737 /* TODO: comment function Transport CloseAll */
    738 NFCSTATUS phFriNfc_LlcpTransport_CloseAll (phFriNfc_LlcpTransport_t *pLlcpTransport)
    739 {
    740    NFCSTATUS                           status = NFCSTATUS_SUCCESS;
    741    phFriNfc_Llcp_CachedServiceName_t * pCachedServiceName;
    742    uint8_t                             i;
    743 
    744    /* Check for NULL pointers */
    745    if(pLlcpTransport == NULL)
    746    {
    747       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
    748    }
    749 
    750    /* Close all sockets */
    751    for(i=0;i<PHFRINFC_LLCP_NB_SOCKET_MAX;i++)
    752    {
    753       if(pLlcpTransport->pSocketTable[i].eSocket_Type == phFriNfc_LlcpTransport_eConnectionOriented)
    754       {
    755          switch(pLlcpTransport->pSocketTable[i].eSocket_State)
    756          {
    757          case phFriNfc_LlcpTransportSocket_eSocketConnected:
    758          case phFriNfc_LlcpTransportSocket_eSocketConnecting:
    759          case phFriNfc_LlcpTransportSocket_eSocketAccepted:
    760          case phFriNfc_LlcpTransportSocket_eSocketDisconnected:
    761          case phFriNfc_LlcpTransportSocket_eSocketDisconnecting:
    762          case phFriNfc_LlcpTransportSocket_eSocketRejected:
    763             phFriNfc_LlcpTransport_Close(&pLlcpTransport->pSocketTable[i]);
    764             break;
    765          default:
    766             /* Do nothing */
    767             break;
    768          }
    769       }
    770       else
    771       {
    772          phFriNfc_LlcpTransport_Close(&pLlcpTransport->pSocketTable[i]);
    773       }
    774    }
    775 
    776    /* Reset cached service name/sap table */
    777    for(i=0;i<PHFRINFC_LLCP_SDP_ADVERTISED_NB;i++)
    778    {
    779       pCachedServiceName = &pLlcpTransport->pCachedServiceNames[i];
    780 
    781       pCachedServiceName->nSap = 0;
    782       if (pCachedServiceName->sServiceName.buffer != NULL)
    783       {
    784          phOsalNfc_FreeMemory(pCachedServiceName->sServiceName.buffer);
    785          pCachedServiceName->sServiceName.buffer = NULL;
    786       }
    787       pCachedServiceName->sServiceName.length = 0;
    788    }
    789 
    790    return status;
    791 }
    792 
    793 
    794 /* TODO: comment function Transport LinkSend */
    795 NFCSTATUS phFriNfc_LlcpTransport_LinkSend( phFriNfc_LlcpTransport_t         *LlcpTransport,
    796                                            phFriNfc_Llcp_sPacketHeader_t    *psHeader,
    797                                            phFriNfc_Llcp_sPacketSequence_t  *psSequence,
    798                                            phNfc_sData_t                    *psInfo,
    799                                            phFriNfc_Llcp_Send_CB_t          pfSend_CB,
    800                                            void                             *pContext )
    801 {
    802    NFCSTATUS status;
    803    /* Check if a send is already ongoing */
    804    if (LlcpTransport->pfLinkSendCb != NULL)
    805    {
    806       return NFCSTATUS_BUSY;
    807    }
    808    /* Save callback details */
    809    LlcpTransport->pfLinkSendCb = pfSend_CB;
    810    LlcpTransport->pLinkSendContext = pContext;
    811 
    812    /* Call the link-level send function */
    813    status = phFriNfc_Llcp_Send(LlcpTransport->pLlcp, psHeader, psSequence, psInfo, phFriNfc_LlcpTransport_Send_CB, (void*)LlcpTransport);
    814    if (status != NFCSTATUS_PENDING && status != NFCSTATUS_SUCCESS) {
    815        // Clear out callbacks
    816        LlcpTransport->pfLinkSendCb = NULL;
    817        LlcpTransport->pLinkSendContext = NULL;
    818    }
    819    return status;
    820 }
    821 
    822 
    823 /* TODO: comment function Transport SendFrameReject */
    824 NFCSTATUS phFriNfc_LlcpTransport_SendFrameReject(phFriNfc_LlcpTransport_t           *psTransport,
    825                                                  uint8_t                            dsap,
    826                                                  uint8_t                            rejectedPTYPE,
    827                                                  uint8_t                            ssap,
    828                                                  phFriNfc_Llcp_sPacketSequence_t*   sLlcpSequence,
    829                                                  uint8_t                            WFlag,
    830                                                  uint8_t                            IFlag,
    831                                                  uint8_t                            RFlag,
    832                                                  uint8_t                            SFlag,
    833                                                  uint8_t                            vs,
    834                                                  uint8_t                            vsa,
    835                                                  uint8_t                            vr,
    836                                                  uint8_t                            vra)
    837 {
    838    NFCSTATUS                       status = NFCSTATUS_SUCCESS;
    839    phNfc_sData_t                   sFrmrBuffer;
    840    uint8_t                         flagValue;
    841    uint8_t                         sequence = 0;
    842    uint8_t     index;
    843    uint8_t     socketFound = FALSE;
    844 
    845    /* Search a socket waiting for a FRAME */
    846    for(index=0;index<PHFRINFC_LLCP_NB_SOCKET_MAX;index++)
    847    {
    848       /* Test if the socket is in connected state and if its SSAP and DSAP are valid */
    849       if(psTransport->pSocketTable[index].socket_sSap == dsap
    850          && psTransport->pSocketTable[index].socket_dSap == ssap)
    851       {
    852          /* socket found */
    853          socketFound = TRUE;
    854          break;
    855       }
    856    }
    857 
    858    /* Test if a socket has been found */
    859    if(socketFound)
    860    {
    861       /* Set socket state to disconnected */
    862       psTransport->pSocketTable[index].eSocket_State =  phFriNfc_LlcpTransportSocket_eSocketDefault;
    863 
    864       /* Call ErrCB due to a FRMR*/
    865       psTransport->pSocketTable[index].pSocketErrCb( psTransport->pSocketTable[index].pContext,PHFRINFC_LLCP_ERR_FRAME_REJECTED);
    866 
    867       /* Close the socket */
    868       status = phFriNfc_LlcpTransport_ConnectionOriented_Close(&psTransport->pSocketTable[index]);
    869 
    870       /* Set FRMR Header */
    871       psTransport->sLlcpHeader.dsap   = ssap;
    872       psTransport->sLlcpHeader.ptype  = PHFRINFC_LLCP_PTYPE_FRMR;
    873       psTransport->sLlcpHeader.ssap   = dsap;
    874 
    875       /* Set FRMR Information Field */
    876       flagValue = (WFlag<<7) | (IFlag<<6) | (RFlag<<5) | (SFlag<<4) | rejectedPTYPE;
    877       if (sLlcpSequence != NULL)
    878       {
    879          sequence = (uint8_t)((sLlcpSequence->ns<<4)|(sLlcpSequence->nr));
    880       }
    881 
    882       psTransport->FrmrInfoBuffer[0] = flagValue;
    883       psTransport->FrmrInfoBuffer[1] = sequence;
    884       psTransport->FrmrInfoBuffer[2] = (vs<<4)|vr ;
    885       psTransport->FrmrInfoBuffer[3] = (vsa<<4)|vra ;
    886 
    887       /* Test if a send is pending */
    888       if(psTransport->bSendPending)
    889       {
    890          psTransport->bFrmrPending = TRUE;
    891          status = NFCSTATUS_PENDING;
    892       }
    893       else
    894       {
    895          sFrmrBuffer.buffer =  psTransport->FrmrInfoBuffer;
    896          sFrmrBuffer.length =  0x04; /* Size of FRMR Information field */
    897 
    898          /* Send Pending */
    899          psTransport->bSendPending = TRUE;
    900 
    901          /* Send FRMR frame */
    902          status =  phFriNfc_Llcp_Send(psTransport->pLlcp,
    903                                       &psTransport->sLlcpHeader,
    904                                       NULL,
    905                                       &sFrmrBuffer,
    906                                       phFriNfc_LlcpTransport_Send_CB,
    907                                       psTransport);
    908       }
    909    }
    910    else
    911    {
    912       /* No active  socket*/
    913       /* FRMR Frame not handled*/
    914    }
    915    return status;
    916 }
    917 
    918 
    919 /* TODO: comment function Transport SendDisconnectMode (NOTE: used only
    920  * for requests not bound to a socket, like "service not found")
    921  */
    922 NFCSTATUS phFriNfc_LlcpTransport_SendDisconnectMode(phFriNfc_LlcpTransport_t* psTransport,
    923                                                     uint8_t                   dsap,
    924                                                     uint8_t                   ssap,
    925                                                     uint8_t                   dmOpCode)
    926 {
    927    NFCSTATUS                       status = NFCSTATUS_SUCCESS;
    928 
    929    /* Test if a send is pending */
    930    if(psTransport->bSendPending)
    931    {
    932       /* DM pending */
    933       psTransport->bDmPending        = TRUE;
    934 
    935       /* Store DM Info */
    936       psTransport->DmInfoBuffer[0] = dsap;
    937       psTransport->DmInfoBuffer[1] = ssap;
    938       psTransport->DmInfoBuffer[2] = dmOpCode;
    939 
    940      status = NFCSTATUS_PENDING;
    941    }
    942    else
    943    {
    944       /* Set the header */
    945       psTransport->sDmHeader.dsap  = dsap;
    946       psTransport->sDmHeader.ptype = PHFRINFC_LLCP_PTYPE_DM;
    947       psTransport->sDmHeader.ssap  = ssap;
    948 
    949       /* Save Operation Code to be provided in DM frame payload */
    950       psTransport->DmInfoBuffer[2] = dmOpCode;
    951       psTransport->sDmPayload.buffer    = &psTransport->DmInfoBuffer[2];
    952       psTransport->sDmPayload.length    = PHFRINFC_LLCP_DM_LENGTH;
    953 
    954       /* Send Pending */
    955       psTransport->bSendPending = TRUE;
    956 
    957       /* Send DM frame */
    958       status =  phFriNfc_Llcp_Send(psTransport->pLlcp,
    959                                    &psTransport->sDmHeader,
    960                                    NULL,
    961                                    &psTransport->sDmPayload,
    962                                    phFriNfc_LlcpTransport_Send_CB,
    963                                    psTransport);
    964    }
    965 
    966    return status;
    967 }
    968 
    969 
    970 /**
    971 * \ingroup grp_lib_nfc
    972 * \brief <b>Get the local options of a socket</b>.
    973 *
    974 * This function returns the local options (maximum packet size and receive window size) used
    975 * for a given connection-oriented socket. This function shall not be used with connectionless
    976 * sockets.
    977 *
    978 * \param[out] pLlcpSocket           A pointer to a phFriNfc_LlcpTransport_Socket_t.
    979 * \param[in]  psLocalOptions        A pointer to be filled with the local options of the socket.
    980 *
    981 * \retval NFCSTATUS_SUCCESS                  Operation successful.
    982 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
    983 *                                            could not be properly interpreted.
    984 * \retval NFCSTATUS_INVALID_STATE            The socket is not in a valid state, or not of
    985 *                                            a valid type to perform the requsted operation.
    986 * \retval NFCSTATUS_NOT_INITIALISED          Indicates stack is not yet initialized.
    987 * \retval NFCSTATUS_SHUTDOWN                 Shutdown in progress.
    988 * \retval NFCSTATUS_FAILED                   Operation failed.
    989 */
    990 NFCSTATUS phFriNfc_LlcpTransport_SocketGetLocalOptions(phFriNfc_LlcpTransport_Socket_t  *pLlcpSocket,
    991                                                        phLibNfc_Llcp_sSocketOptions_t   *psLocalOptions)
    992 {
    993    NFCSTATUS status = NFCSTATUS_SUCCESS;
    994 
    995    /* Check for NULL pointers */
    996    if (pLlcpSocket == NULL || psLocalOptions == NULL)
    997    {
    998       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
    999    }
   1000    /*  Test the socket type */
   1001    else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
   1002    {
   1003       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1004    }
   1005    /*  Test the socket state */
   1006    else if(pLlcpSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketDefault)
   1007    {
   1008       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
   1009    }
   1010    else
   1011    {
   1012      status = phFriNfc_LlcpTransport_ConnectionOriented_SocketGetLocalOptions(pLlcpSocket,
   1013                                                                               psLocalOptions);
   1014    }
   1015 
   1016    return status;
   1017 }
   1018 
   1019 
   1020 /**
   1021 * \ingroup grp_lib_nfc
   1022 * \brief <b>Get the local options of a socket</b>.
   1023 *
   1024 * This function returns the remote options (maximum packet size and receive window size) used
   1025 * for a given connection-oriented socket. This function shall not be used with connectionless
   1026 * sockets.
   1027 *
   1028 * \param[out] pLlcpSocket           A pointer to a phFriNfc_LlcpTransport_Socket_t.
   1029 * \param[in]  psRemoteOptions       A pointer to be filled with the remote options of the socket.
   1030 *
   1031 * \retval NFCSTATUS_SUCCESS                  Operation successful.
   1032 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
   1033 *                                            could not be properly interpreted.
   1034 * \retval NFCSTATUS_INVALID_STATE            The socket is not in a valid state, or not of
   1035 *                                            a valid type to perform the requsted operation.
   1036 * \retval NFCSTATUS_NOT_INITIALISED          Indicates stack is not yet initialized.
   1037 * \retval NFCSTATUS_SHUTDOWN                 Shutdown in progress.
   1038 * \retval NFCSTATUS_FAILED                   Operation failed.
   1039 */
   1040 NFCSTATUS phFriNfc_LlcpTransport_SocketGetRemoteOptions(phFriNfc_LlcpTransport_Socket_t*   pLlcpSocket,
   1041                                                         phLibNfc_Llcp_sSocketOptions_t*    psRemoteOptions)
   1042 {
   1043    NFCSTATUS status = NFCSTATUS_SUCCESS;
   1044 
   1045    /* Check for NULL pointers */
   1046    if (pLlcpSocket == NULL || psRemoteOptions == NULL)
   1047    {
   1048       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1049    }
   1050    /*  Test the socket type */
   1051    else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
   1052    {
   1053       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1054    }
   1055    /*  Test the socket state */
   1056    else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketConnected)
   1057    {
   1058       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
   1059    }
   1060    else
   1061    {
   1062       status = phFriNfc_LlcpTransport_ConnectionOriented_SocketGetRemoteOptions(pLlcpSocket,
   1063                                                                                 psRemoteOptions);
   1064    }
   1065 
   1066    return status;
   1067 }
   1068 
   1069 
   1070 static NFCSTATUS phFriNfc_LlcpTransport_DiscoverServicesEx(phFriNfc_LlcpTransport_t *psTransport)
   1071 {
   1072    NFCSTATUS         result = NFCSTATUS_PENDING;
   1073    phNfc_sData_t     sInfoBuffer;
   1074    phNfc_sData_t     *psServiceName;
   1075    uint32_t          nTlvOffset;
   1076 
   1077    /* Test if a send is pending */
   1078    if(!psTransport->bSendPending)
   1079    {
   1080       /* Set the header */
   1081       psTransport->sLlcpHeader.dsap  = PHFRINFC_LLCP_SAP_SDP;
   1082       psTransport->sLlcpHeader.ptype = PHFRINFC_LLCP_PTYPE_SNL;
   1083       psTransport->sLlcpHeader.ssap  = PHFRINFC_LLCP_SAP_SDP;
   1084 
   1085       /* Prepare the info buffer */
   1086       sInfoBuffer.buffer = psTransport->pDiscoveryBuffer;
   1087       sInfoBuffer.length = sizeof(psTransport->pDiscoveryBuffer);
   1088 
   1089       /* Encode as many requests as possible */
   1090       nTlvOffset = 0;
   1091       while(psTransport->nDiscoveryReqOffset < psTransport->nDiscoveryListSize)
   1092       {
   1093          /* Get current service name and try to encode it in SNL frame */
   1094          psServiceName = &psTransport->psDiscoveryServiceNameList[psTransport->nDiscoveryReqOffset];
   1095          result = phFriNfc_LlcpTransport_EncodeSdreqTlv(&sInfoBuffer,
   1096                                                         &nTlvOffset,
   1097                                                         psTransport->nDiscoveryReqOffset,
   1098                                                         psServiceName);
   1099          if (result != NFCSTATUS_SUCCESS)
   1100          {
   1101             /* Impossible to fit more requests in a single frame,
   1102              * will be continued on next opportunity
   1103              */
   1104             break;
   1105          }
   1106 
   1107          /* Update request counter */
   1108          psTransport->nDiscoveryReqOffset++;
   1109       }
   1110 
   1111       /* Update buffer length to match real TLV size */
   1112       sInfoBuffer.length = nTlvOffset;
   1113 
   1114       /* Send Pending */
   1115       psTransport->bSendPending = TRUE;
   1116 
   1117       /* Send SNL frame */
   1118       result =  phFriNfc_Llcp_Send(psTransport->pLlcp,
   1119                                    &psTransport->sLlcpHeader,
   1120                                    NULL,
   1121                                    &sInfoBuffer,
   1122                                    phFriNfc_LlcpTransport_Send_CB,
   1123                                    psTransport);
   1124    }
   1125    else
   1126    {
   1127       /* Impossible to send now, this function will be called again on next opportunity */
   1128    }
   1129 
   1130    return result;
   1131 }
   1132 
   1133 /*!
   1134 * \ingroup grp_fri_nfc
   1135 * \brief <b>Discover remote services SAP using SDP protocol</b>.
   1136  */
   1137 NFCSTATUS phFriNfc_LlcpTransport_DiscoverServices( phFriNfc_LlcpTransport_t  *pLlcpTransport,
   1138                                                    phNfc_sData_t             *psServiceNameList,
   1139                                                    uint8_t                   *pnSapList,
   1140                                                    uint8_t                   nListSize,
   1141                                                    pphFriNfc_Cr_t            pDiscover_Cb,
   1142                                                    void                      *pContext )
   1143 {
   1144    NFCSTATUS         result = NFCSTATUS_FAILED;
   1145 
   1146    /* Save request details */
   1147    pLlcpTransport->psDiscoveryServiceNameList = psServiceNameList;
   1148    pLlcpTransport->pnDiscoverySapList = pnSapList;
   1149    pLlcpTransport->nDiscoveryListSize = nListSize;
   1150    pLlcpTransport->pfDiscover_Cb = pDiscover_Cb;
   1151    pLlcpTransport->pDiscoverContext = pContext;
   1152 
   1153    /* Reset internal counters */
   1154    pLlcpTransport->nDiscoveryReqOffset = 0;
   1155    pLlcpTransport->nDiscoveryResOffset = 0;
   1156 
   1157    /* Perform request */
   1158    result = phFriNfc_LlcpTransport_DiscoverServicesEx(pLlcpTransport);
   1159 
   1160    return result;
   1161 }
   1162 
   1163 
   1164  /**
   1165 * \ingroup grp_fri_nfc
   1166 * \brief <b>Create a socket on a LLCP-connected device</b>.
   1167 *
   1168 * This function creates a socket for a given LLCP link. Sockets can be of two types :
   1169 * connection-oriented and connectionless. If the socket is connection-oriented, the caller
   1170 * must provide a working buffer to the socket in order to handle incoming data. This buffer
   1171 * must be large enough to fit the receive window (RW * MIU), the remaining space being
   1172 * used as a linear buffer to store incoming data as a stream. Data will be readable later
   1173 * using the phLibNfc_LlcpTransport_Recv function.
   1174 * The options and working buffer are not required if the socket is used as a listening socket,
   1175 * since it cannot be directly used for communication.
   1176 *
   1177 * \param[in]  pLlcpSocketTable      A pointer to a table of PHFRINFC_LLCP_NB_SOCKET_DEFAULT sockets.
   1178 * \param[in]  eType                 The socket type.
   1179 * \param[in]  psOptions             The options to be used with the socket.
   1180 * \param[in]  psWorkingBuffer       A working buffer to be used by the library.
   1181 * \param[out] pLlcpSocket           A pointer on the socket to be filled with a
   1182                                     socket found on the socket table.
   1183 * \param[in]  pErr_Cb               The callback to be called each time the socket
   1184 *                                   is in error.
   1185 * \param[in]  pContext              Upper layer context to be returned in the callback.
   1186 *
   1187 * \retval NFCSTATUS_SUCCESS                  Operation successful.
   1188 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
   1189 *                                            could not be properly interpreted.
   1190 * \retval NFCSTATUS_BUFFER_TOO_SMALL         The working buffer is too small for the MIU and RW
   1191 *                                            declared in the options.
   1192 * \retval NFCSTATUS_INSUFFICIENT_RESOURCES   No more socket handle available.
   1193 * \retval NFCSTATUS_FAILED                   Operation failed.
   1194 * */
   1195 NFCSTATUS phFriNfc_LlcpTransport_Socket(phFriNfc_LlcpTransport_t                  *pLlcpTransport,
   1196                                         phFriNfc_LlcpTransport_eSocketType_t      eType,
   1197                                         phFriNfc_LlcpTransport_sSocketOptions_t   *psOptions,
   1198                                         phNfc_sData_t                             *psWorkingBuffer,
   1199                                         phFriNfc_LlcpTransport_Socket_t           **pLlcpSocket,
   1200                                         pphFriNfc_LlcpTransportSocketErrCb_t      pErr_Cb,
   1201                                         void                                      *pContext)
   1202 {
   1203    NFCSTATUS status = NFCSTATUS_SUCCESS;
   1204    phFriNfc_Llcp_sLinkParameters_t  LlcpLinkParamInfo;
   1205    uint8_t index=0;
   1206    uint8_t cpt;
   1207 
   1208    /* Check for NULL pointers */
   1209    if (   ((psOptions == NULL) && (eType == phFriNfc_LlcpTransport_eConnectionOriented))
   1210        || ((psWorkingBuffer == NULL) && (eType == phFriNfc_LlcpTransport_eConnectionOriented))
   1211        || (pLlcpSocket == NULL)
   1212        || (pErr_Cb == NULL)
   1213        || (pContext == NULL)
   1214        || (pLlcpTransport == NULL))
   1215    {
   1216       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1217       return status;
   1218    }
   1219    /*  Test the socket type*/
   1220    else if(eType != phFriNfc_LlcpTransport_eConnectionOriented && eType != phFriNfc_LlcpTransport_eConnectionLess)
   1221    {
   1222       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1223       return status;
   1224    }
   1225    /* Connectionless sockets don't support options */
   1226    else if ((psOptions != NULL) && (eType == phFriNfc_LlcpTransport_eConnectionLess))
   1227    {
   1228       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1229       return status;
   1230    }
   1231 
   1232    /* Get the local parameters of the LLCP Link */
   1233    status = phFriNfc_Llcp_GetLocalInfo(pLlcpTransport->pLlcp,&LlcpLinkParamInfo);
   1234    if(status != NFCSTATUS_SUCCESS)
   1235    {
   1236       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_FAILED);
   1237       return status;
   1238    }
   1239    else
   1240    {
   1241       /* Search a socket free in the Socket Table*/
   1242       do
   1243       {
   1244          if(pLlcpTransport->pSocketTable[index].eSocket_State == phFriNfc_LlcpTransportSocket_eSocketDefault)
   1245          {
   1246             /* Set the socket pointer to socket of the table */
   1247             *pLlcpSocket = &pLlcpTransport->pSocketTable[index];
   1248 
   1249             /* Store the socket info in the socket pointer */
   1250             pLlcpTransport->pSocketTable[index].eSocket_Type     = eType;
   1251             pLlcpTransport->pSocketTable[index].pSocketErrCb     = pErr_Cb;
   1252 
   1253             /* Store the context of the upper layer */
   1254             pLlcpTransport->pSocketTable[index].pContext   = pContext;
   1255 
   1256             /* Set the pointers to the different working buffers */
   1257             if (eType == phFriNfc_LlcpTransport_eConnectionOriented)
   1258             {
   1259                 /* Test the socket options */
   1260                 if (psOptions->rw > PHFRINFC_LLCP_RW_MAX)
   1261                 {
   1262                     status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1263                     return status;
   1264                 }
   1265 
   1266                 /* Set socket options */
   1267                 memcpy(&pLlcpTransport->pSocketTable[index].sSocketOption, psOptions, sizeof(phFriNfc_LlcpTransport_sSocketOptions_t));
   1268 
   1269                 /* Set socket local params (MIUX & RW) */
   1270                 pLlcpTransport->pSocketTable[index].localMIUX = (pLlcpTransport->pSocketTable[index].sSocketOption.miu - PHFRINFC_LLCP_MIU_DEFAULT) & PHFRINFC_LLCP_TLV_MIUX_MASK;
   1271                 pLlcpTransport->pSocketTable[index].localRW   = pLlcpTransport->pSocketTable[index].sSocketOption.rw & PHFRINFC_LLCP_TLV_RW_MASK;
   1272 
   1273                 /* Set the Max length for the Send and Receive Window Buffer */
   1274                 pLlcpTransport->pSocketTable[index].bufferSendMaxLength   = pLlcpTransport->pSocketTable[index].sSocketOption.miu;
   1275                 pLlcpTransport->pSocketTable[index].bufferRwMaxLength     = pLlcpTransport->pSocketTable[index].sSocketOption.miu * ((pLlcpTransport->pSocketTable[index].sSocketOption.rw & PHFRINFC_LLCP_TLV_RW_MASK));
   1276                 pLlcpTransport->pSocketTable[index].bufferLinearLength    = psWorkingBuffer->length - pLlcpTransport->pSocketTable[index].bufferSendMaxLength - pLlcpTransport->pSocketTable[index].bufferRwMaxLength;
   1277 
   1278                 /* Test the connection oriented buffers length */
   1279                 if((pLlcpTransport->pSocketTable[index].bufferSendMaxLength + pLlcpTransport->pSocketTable[index].bufferRwMaxLength) > psWorkingBuffer->length
   1280                     || ((pLlcpTransport->pSocketTable[index].bufferLinearLength < PHFRINFC_LLCP_MIU_DEFAULT) && (pLlcpTransport->pSocketTable[index].bufferLinearLength != 0)))
   1281                 {
   1282                     status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_BUFFER_TOO_SMALL);
   1283                     return status;
   1284                 }
   1285 
   1286                 /* Set the pointer and the length for the Receive Window Buffer */
   1287                 for(cpt=0;cpt<pLlcpTransport->pSocketTable[index].localRW;cpt++)
   1288                 {
   1289                     pLlcpTransport->pSocketTable[index].sSocketRwBufferTable[cpt].buffer = psWorkingBuffer->buffer + (cpt*pLlcpTransport->pSocketTable[index].sSocketOption.miu);
   1290                     pLlcpTransport->pSocketTable[index].sSocketRwBufferTable[cpt].length = 0;
   1291                 }
   1292 
   1293                 /* Set the pointer and the length for the Send Buffer */
   1294                 pLlcpTransport->pSocketTable[index].sSocketSendBuffer.buffer     = psWorkingBuffer->buffer + pLlcpTransport->pSocketTable[index].bufferRwMaxLength;
   1295                 pLlcpTransport->pSocketTable[index].sSocketSendBuffer.length     = pLlcpTransport->pSocketTable[index].bufferSendMaxLength;
   1296 
   1297                 /** Set the pointer and the length for the Linear Buffer */
   1298                 pLlcpTransport->pSocketTable[index].sSocketLinearBuffer.buffer   = psWorkingBuffer->buffer + pLlcpTransport->pSocketTable[index].bufferRwMaxLength + pLlcpTransport->pSocketTable[index].bufferSendMaxLength;
   1299                 pLlcpTransport->pSocketTable[index].sSocketLinearBuffer.length   = pLlcpTransport->pSocketTable[index].bufferLinearLength;
   1300 
   1301                 if(pLlcpTransport->pSocketTable[index].sSocketLinearBuffer.length != 0)
   1302                 {
   1303                     /* Init Cyclic Fifo */
   1304                     phFriNfc_Llcp_CyclicFifoInit(&pLlcpTransport->pSocketTable[index].sCyclicFifoBuffer,
   1305                                                 pLlcpTransport->pSocketTable[index].sSocketLinearBuffer.buffer,
   1306                                                 pLlcpTransport->pSocketTable[index].sSocketLinearBuffer.length);
   1307                 }
   1308             }
   1309             /* Handle connectionless socket with buffering option */
   1310             else if (eType == phFriNfc_LlcpTransport_eConnectionLess)
   1311             {
   1312                /* Determine how many packets can be bufferized in working buffer */
   1313                if (psWorkingBuffer != NULL)
   1314                {
   1315                   /* NOTE: the extra byte is used to store SSAP */
   1316                   pLlcpTransport->pSocketTable[index].localRW = psWorkingBuffer->length / (pLlcpTransport->pLlcp->sLocalParams.miu + 1);
   1317                }
   1318                else
   1319                {
   1320                   pLlcpTransport->pSocketTable[index].localRW = 0;
   1321                }
   1322 
   1323                if (pLlcpTransport->pSocketTable[index].localRW > PHFRINFC_LLCP_RW_MAX)
   1324                {
   1325                   pLlcpTransport->pSocketTable[index].localRW = PHFRINFC_LLCP_RW_MAX;
   1326                }
   1327 
   1328                /* Set the pointers and the lengths for buffering */
   1329                for(cpt=0 ; cpt<pLlcpTransport->pSocketTable[index].localRW ; cpt++)
   1330                {
   1331                   pLlcpTransport->pSocketTable[index].sSocketRwBufferTable[cpt].buffer = psWorkingBuffer->buffer + (cpt*(pLlcpTransport->pLlcp->sLocalParams.miu + 1));
   1332                   pLlcpTransport->pSocketTable[index].sSocketRwBufferTable[cpt].length = 0;
   1333                }
   1334 
   1335                /* Set other socket internals */
   1336                pLlcpTransport->pSocketTable[index].indexRwRead      = 0;
   1337                pLlcpTransport->pSocketTable[index].indexRwWrite     = 0;
   1338             }
   1339 
   1340             /* Store index of the socket */
   1341             pLlcpTransport->pSocketTable[index].index = index;
   1342 
   1343             /* Set the socket into created state */
   1344             pLlcpTransport->pSocketTable[index].eSocket_State = phFriNfc_LlcpTransportSocket_eSocketCreated;
   1345             return status;
   1346          }
   1347          else
   1348          {
   1349             index++;
   1350          }
   1351       }while(index<PHFRINFC_LLCP_NB_SOCKET_MAX);
   1352 
   1353       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INSUFFICIENT_RESOURCES);
   1354    }
   1355    return status;
   1356 }
   1357 
   1358 /**
   1359 * \ingroup grp_fri_nfc
   1360 * \brief <b>Close a socket on a LLCP-connected device</b>.
   1361 *
   1362 * This function closes a LLCP socket previously created using phFriNfc_LlcpTransport_Socket.
   1363 * If the socket was connected, it is first disconnected, and then closed.
   1364 *
   1365 * \param[in]  pLlcpSocket                    A pointer to a phFriNfc_LlcpTransport_Socket_t.
   1366 
   1367 * \retval NFCSTATUS_SUCCESS                  Operation successful.
   1368 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
   1369 *                                            could not be properly interpreted.
   1370 * \retval NFCSTATUS_FAILED                   Operation failed.
   1371 */
   1372 NFCSTATUS phFriNfc_LlcpTransport_Close(phFriNfc_LlcpTransport_Socket_t*   pLlcpSocket)
   1373 {
   1374    NFCSTATUS status = NFCSTATUS_SUCCESS;
   1375 
   1376    /* Check for NULL pointers */
   1377    if( pLlcpSocket == NULL)
   1378    {
   1379       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1380    }
   1381    else if(pLlcpSocket->eSocket_Type == phFriNfc_LlcpTransport_eConnectionOriented)
   1382    {
   1383       status = phFriNfc_LlcpTransport_ConnectionOriented_Close(pLlcpSocket);
   1384    }
   1385    else if(pLlcpSocket->eSocket_Type ==  phFriNfc_LlcpTransport_eConnectionLess)
   1386    {
   1387       status = phFriNfc_LlcpTransport_Connectionless_Close(pLlcpSocket);
   1388    }
   1389    else
   1390    {
   1391       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1392    }
   1393 
   1394    return status;
   1395 }
   1396 
   1397 /**
   1398 * \ingroup grp_fri_nfc
   1399 * \brief <b>Bind a socket to a local SAP</b>.
   1400 *
   1401 * This function binds the socket to a local Service Access Point.
   1402 *
   1403 * \param[in]  pLlcpSocket           A pointer to a phFriNfc_LlcpTransport_Socket_t.
   1404 * \param[in]  nSap                  The SAP number to bind with, or 0 for auto-bind to a free SAP.
   1405 * \param[in]  psServiceName         A pointer to Service Name, or NULL if no service name.
   1406 *
   1407 * \retval NFCSTATUS_SUCCESS                  Operation successful.
   1408 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
   1409 *                                            could not be properly interpreted.
   1410 * \retval NFCSTATUS_INVALID_STATE            The socket is not in a valid state, or not of
   1411 *                                            a valid type to perform the requsted operation.
   1412 * \retval NFCSTATUS_ALREADY_REGISTERED       The selected SAP is already bound to another
   1413                                              socket.
   1414 * \retval NFCSTATUS_FAILED                   Operation failed.
   1415 */
   1416 
   1417 NFCSTATUS phFriNfc_LlcpTransport_Bind(phFriNfc_LlcpTransport_Socket_t    *pLlcpSocket,
   1418                                       uint8_t                            nSap,
   1419                                       phNfc_sData_t                      *psServiceName)
   1420 {
   1421    NFCSTATUS status = NFCSTATUS_SUCCESS;
   1422    uint8_t i;
   1423    uint8_t min_sap_range;
   1424    uint8_t max_sap_range;
   1425 
   1426    /* Check for NULL pointers */
   1427    if(pLlcpSocket == NULL)
   1428    {
   1429       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1430    }
   1431    else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketCreated)
   1432    {
   1433       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
   1434    }
   1435    else
   1436    {
   1437       /* Calculate authorized SAP range */
   1438       if ((psServiceName != NULL) && (psServiceName->length > 0))
   1439       {
   1440          /* SDP advertised service */
   1441          min_sap_range = PHFRINFC_LLCP_SAP_SDP_ADVERTISED_FIRST;
   1442          max_sap_range = PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST;
   1443       }
   1444       else
   1445       {
   1446          /* Non-SDP advertised service */
   1447          min_sap_range = PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST;
   1448          max_sap_range = PHFRINFC_LLCP_SAP_NUMBER;
   1449       }
   1450 
   1451       /* Handle dynamic SAP allocation */
   1452       if (nSap == 0)
   1453       {
   1454          status = phFriNfc_LlcpTransport_GetFreeSap(pLlcpSocket->psTransport, psServiceName, &nSap);
   1455          if (status != NFCSTATUS_SUCCESS)
   1456          {
   1457             return status;
   1458          }
   1459       }
   1460 
   1461       /* Test the SAP range */
   1462       if(!IS_BETWEEN(nSap, min_sap_range, max_sap_range) &&
   1463          !IS_BETWEEN(nSap, PHFRINFC_LLCP_SAP_WKS_FIRST, PHFRINFC_LLCP_SAP_SDP_ADVERTISED_FIRST))
   1464       {
   1465          status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1466       }
   1467       else
   1468       {
   1469          /* Test if the nSap it is used by another socket */
   1470          for(i=0;i<PHFRINFC_LLCP_NB_SOCKET_MAX;i++)
   1471          {
   1472             if(pLlcpSocket->psTransport->pSocketTable[i].socket_sSap == nSap)
   1473             {
   1474                return status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_ALREADY_REGISTERED);
   1475             }
   1476          }
   1477          /* Set service name */
   1478          status = phFriNfc_LlcpTransport_RegisterName(pLlcpSocket, nSap, psServiceName);
   1479          if (status != NFCSTATUS_SUCCESS)
   1480          {
   1481             return status;
   1482          }
   1483          /* Set the nSap value of the socket */
   1484          pLlcpSocket->socket_sSap = nSap;
   1485          /* Set the socket state */
   1486          pLlcpSocket->eSocket_State = phFriNfc_LlcpTransportSocket_eSocketBound;
   1487       }
   1488    }
   1489    return status;
   1490 }
   1491 
   1492 /*********************************************/
   1493 /*           ConnectionOriented              */
   1494 /*********************************************/
   1495 
   1496 /**
   1497 * \ingroup grp_fri_nfc
   1498 * \brief <b>Listen for incoming connection requests on a socket</b>.
   1499 *
   1500 * This function switches a socket into a listening state and registers a callback on
   1501 * incoming connection requests. In this state, the socket is not able to communicate
   1502 * directly. The listening state is only available for connection-oriented sockets
   1503 * which are still not connected. The socket keeps listening until it is closed, and
   1504 * thus can trigger several times the pListen_Cb callback.
   1505 *
   1506 *
   1507 * \param[in]  pLlcpSocket        A pointer to a phFriNfc_LlcpTransport_Socket_t.
   1508 * \param[in]  pListen_Cb         The callback to be called each time the
   1509 *                                socket receive a connection request.
   1510 * \param[in]  pContext           Upper layer context to be returned in
   1511 *                                the callback.
   1512 *
   1513 * \retval NFCSTATUS_SUCCESS                  Operation successful.
   1514 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
   1515 *                                            could not be properly interpreted.
   1516 * \retval NFCSTATUS_INVALID_STATE            The socket is not in a valid state to switch
   1517 *                                            to listening state.
   1518 * \retval NFCSTATUS_FAILED                   Operation failed.
   1519 */
   1520 NFCSTATUS phFriNfc_LlcpTransport_Listen(phFriNfc_LlcpTransport_Socket_t*          pLlcpSocket,
   1521                                         pphFriNfc_LlcpTransportSocketListenCb_t   pListen_Cb,
   1522                                         void*                                     pContext)
   1523 {
   1524    NFCSTATUS status = NFCSTATUS_SUCCESS;
   1525 
   1526    /* Check for NULL pointers */
   1527    if(pLlcpSocket == NULL || pListen_Cb == NULL|| pContext == NULL )
   1528    {
   1529       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1530    }
   1531    /* Check for socket state */
   1532    else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
   1533    {
   1534       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
   1535    }
   1536    /* Check for socket type */
   1537    else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
   1538    {
   1539       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1540    }
   1541    /* Test if a listen is not pending with this socket */
   1542    else if(pLlcpSocket->bSocketListenPending)
   1543    {
   1544       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1545    }
   1546    else
   1547    {
   1548       status = phFriNfc_LlcpTransport_ConnectionOriented_Listen(pLlcpSocket,
   1549                                                                 pListen_Cb,
   1550                                                                 pContext);
   1551    }
   1552    return status;
   1553 }
   1554 
   1555 
   1556 /**
   1557 * \ingroup grp_fri_nfc
   1558 * \brief <b>Register the socket service name</b>.
   1559 *
   1560 * This function changes the service name of the corresponding socket.
   1561 *
   1562 * \param[in]  pLlcpSocket        A pointer to a phFriNfc_LlcpTransport_Socket_t.
   1563 * \param[in]  nSap               SAP number associated to the service name.
   1564 * \param[in]  psServiceName      A pointer to a Service Name.
   1565 *
   1566 * \retval NFCSTATUS_SUCCESS                  Operation successful.
   1567 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
   1568 *                                            could not be properly interpreted.
   1569 * \retval NFCSTATUS_FAILED                   Operation failed.
   1570 */
   1571 static NFCSTATUS phFriNfc_LlcpTransport_RegisterName(phFriNfc_LlcpTransport_Socket_t*   pLlcpSocket,
   1572                                                      uint8_t                            nSap,
   1573                                                      phNfc_sData_t                      *psServiceName)
   1574 {
   1575    phFriNfc_LlcpTransport_t *       psTransport = pLlcpSocket->psTransport;
   1576    uint8_t                          index;
   1577    uint8_t                          bSnMatch, bSapMatch;
   1578 
   1579    /* Check in cache if sap has been used for different service name */
   1580    for(index=0 ; index<PHFRINFC_LLCP_SDP_ADVERTISED_NB ; index++)
   1581    {
   1582       if(psTransport->pCachedServiceNames[index].sServiceName.length == 0)
   1583       {
   1584          /* Reached end of table */
   1585          break;
   1586       }
   1587 
   1588       bSnMatch = (memcmp(psTransport->pCachedServiceNames[index].sServiceName.buffer, psServiceName->buffer, psServiceName->length) == 0);
   1589       bSapMatch = psTransport->pCachedServiceNames[index].nSap == nSap;
   1590       if(bSnMatch && bSapMatch)
   1591       {
   1592          /* Request match cache */
   1593          break;
   1594       }
   1595       else if((bSnMatch && !bSapMatch) || (!bSnMatch && bSapMatch))
   1596       {
   1597          /* Request mismatch with cache */
   1598          return NFCSTATUS_INVALID_PARAMETER;
   1599       }
   1600    }
   1601 
   1602    /* Handle service with no name */
   1603    if (psServiceName == NULL)
   1604    {
   1605       if (pLlcpSocket->sServiceName.buffer != NULL)
   1606       {
   1607          phOsalNfc_FreeMemory(pLlcpSocket->sServiceName.buffer);
   1608       }
   1609       pLlcpSocket->sServiceName.buffer = NULL;
   1610       pLlcpSocket->sServiceName.length = 0;
   1611    }
   1612    else
   1613    {
   1614       /* Check if name already in use */
   1615       for(index=0;index<PHFRINFC_LLCP_NB_SOCKET_MAX;index++)
   1616       {
   1617          phFriNfc_LlcpTransport_Socket_t* pCurrentSocket = &pLlcpSocket->psTransport->pSocketTable[index];
   1618 
   1619          if(   (pCurrentSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
   1620             && (pCurrentSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketRegistered))
   1621          {
   1622             /* Only bound or listening sockets may have a service name */
   1623             continue;
   1624          }
   1625          if(pCurrentSocket->sServiceName.length != psServiceName->length) {
   1626             /* Service name do not match, check next */
   1627             continue;
   1628          }
   1629          if(memcmp(pCurrentSocket->sServiceName.buffer, psServiceName->buffer, psServiceName->length) == 0)
   1630          {
   1631             /* Service name already in use */
   1632             return NFCSTATUS_INVALID_PARAMETER;
   1633          }
   1634       }
   1635 
   1636       /* Store the listen socket SN */
   1637       pLlcpSocket->sServiceName.length = psServiceName->length;
   1638       pLlcpSocket->sServiceName.buffer = phOsalNfc_GetMemory(psServiceName->length);
   1639       if (pLlcpSocket->sServiceName.buffer == NULL)
   1640       {
   1641           return NFCSTATUS_NOT_ENOUGH_MEMORY;
   1642       }
   1643       memcpy(pLlcpSocket->sServiceName.buffer, psServiceName->buffer, psServiceName->length);
   1644    }
   1645 
   1646    return NFCSTATUS_SUCCESS;
   1647 }
   1648 
   1649 /**
   1650 * \ingroup grp_fri_nfc
   1651 * \brief <b>Accept an incoming connection request for a socket</b>.
   1652 *
   1653 * This functions allows the client to accept an incoming connection request.
   1654 * It must be used with the socket provided within the listen callback. The socket
   1655 * is implicitly switched to the connected state when the function is called.
   1656 *
   1657 * \param[in]  pLlcpSocket           A pointer to a phFriNfc_LlcpTransport_Socket_t.
   1658 * \param[in]  psOptions             The options to be used with the socket.
   1659 * \param[in]  psWorkingBuffer       A working buffer to be used by the library.
   1660 * \param[in]  pErr_Cb               The callback to be called each time the accepted socket
   1661 *                                   is in error.
   1662 * \param[in]  pContext              Upper layer context to be returned in the callback.
   1663 *
   1664 * \retval NFCSTATUS_SUCCESS                  Operation successful.
   1665 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
   1666 *                                            could not be properly interpreted.
   1667 * \retval NFCSTATUS_BUFFER_TOO_SMALL         The working buffer is too small for the MIU and RW
   1668 *                                            declared in the options.
   1669 * \retval NFCSTATUS_FAILED                   Operation failed.
   1670 */
   1671 NFCSTATUS phFriNfc_LlcpTransport_Accept(phFriNfc_LlcpTransport_Socket_t*             pLlcpSocket,
   1672                                         phFriNfc_LlcpTransport_sSocketOptions_t*     psOptions,
   1673                                         phNfc_sData_t*                               psWorkingBuffer,
   1674                                         pphFriNfc_LlcpTransportSocketErrCb_t         pErr_Cb,
   1675                                         pphFriNfc_LlcpTransportSocketAcceptCb_t      pAccept_RspCb,
   1676                                         void*                                        pContext)
   1677 {
   1678    NFCSTATUS status = NFCSTATUS_SUCCESS;
   1679 
   1680    /* Check for NULL pointers */
   1681    if(pLlcpSocket == NULL || psOptions == NULL || psWorkingBuffer == NULL || pErr_Cb == NULL || pContext == NULL)
   1682    {
   1683       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1684    }
   1685    /* Check for socket state */
   1686    else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
   1687    {
   1688       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
   1689    }
   1690    /* Check for socket type */
   1691    else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
   1692    {
   1693       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1694    }
   1695    /* Test the socket options */
   1696    else if(psOptions->rw > PHFRINFC_LLCP_RW_MAX)
   1697    {
   1698       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1699    }
   1700    else
   1701    {
   1702       /* Set the Max length for the Send and Receive Window Buffer */
   1703       pLlcpSocket->bufferSendMaxLength   = psOptions->miu;
   1704       pLlcpSocket->bufferRwMaxLength     = psOptions->miu * ((psOptions->rw & PHFRINFC_LLCP_TLV_RW_MASK));
   1705       pLlcpSocket->bufferLinearLength    = psWorkingBuffer->length - pLlcpSocket->bufferSendMaxLength - pLlcpSocket->bufferRwMaxLength;
   1706 
   1707       /* Test the buffers length */
   1708       if((pLlcpSocket->bufferSendMaxLength + pLlcpSocket->bufferRwMaxLength) > psWorkingBuffer->length
   1709           || ((pLlcpSocket->bufferLinearLength < PHFRINFC_LLCP_MIU_DEFAULT)  && (pLlcpSocket->bufferLinearLength != 0)))
   1710       {
   1711          status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_BUFFER_TOO_SMALL);
   1712       }
   1713       else
   1714       {
   1715          pLlcpSocket->psTransport->socketIndex = pLlcpSocket->index;
   1716 
   1717          status  = phFriNfc_LlcpTransport_ConnectionOriented_Accept(pLlcpSocket,
   1718                                                                     psOptions,
   1719                                                                     psWorkingBuffer,
   1720                                                                     pErr_Cb,
   1721                                                                     pAccept_RspCb,
   1722                                                                     pContext);
   1723       }
   1724    }
   1725    return status;
   1726 }
   1727 
   1728  /**
   1729 * \ingroup grp_fri_nfc
   1730 * \brief <b>Reject an incoming connection request for a socket</b>.
   1731 *
   1732 * This functions allows the client to reject an incoming connection request.
   1733 * It must be used with the socket provided within the listen callback. The socket
   1734 * is implicitly closed when the function is called.
   1735 *
   1736 * \param[in]  pLlcpSocket           A pointer to a phFriNfc_LlcpTransport_Socket_t.
   1737 * \param[in]  pReject_RspCb         The callback to be call when the Reject operation is completed
   1738 * \param[in]  pContext              Upper layer context to be returned in the callback.
   1739 *
   1740 * \retval NFCSTATUS_SUCCESS                  Operation successful.
   1741 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
   1742 *                                            could not be properly interpreted.
   1743 * \retval NFCSTATUS_FAILED                   Operation failed.
   1744 */
   1745 NFCSTATUS phFriNfc_LlcpTransport_Reject( phFriNfc_LlcpTransport_Socket_t*           pLlcpSocket,
   1746                                           pphFriNfc_LlcpTransportSocketRejectCb_t   pReject_RspCb,
   1747                                           void                                      *pContext)
   1748 {
   1749    NFCSTATUS status = NFCSTATUS_SUCCESS;
   1750 
   1751    /* Check for NULL pointers */
   1752    if(pLlcpSocket == NULL)
   1753    {
   1754       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1755    }
   1756    /* Check for socket state */
   1757    else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
   1758    {
   1759       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
   1760    }
   1761    /* Check for socket type */
   1762    else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
   1763    {
   1764       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1765    }
   1766    else
   1767    {
   1768       status = phLibNfc_LlcpTransport_ConnectionOriented_Reject(pLlcpSocket,
   1769                                                                 pReject_RspCb,
   1770                                                                 pContext);
   1771    }
   1772 
   1773    return status;
   1774 }
   1775 
   1776 /**
   1777 * \ingroup grp_fri_nfc
   1778 * \brief <b>Try to establish connection with a socket on a remote SAP</b>.
   1779 *
   1780 * This function tries to connect to a given SAP on the remote peer. If the
   1781 * socket is not bound to a local SAP, it is implicitly bound to a free SAP.
   1782 *
   1783 * \param[in]  pLlcpSocket        A pointer to a phFriNfc_LlcpTransport_Socket_t.
   1784 * \param[in]  nSap               The destination SAP to connect to.
   1785 * \param[in]  pConnect_RspCb     The callback to be called when the connection
   1786 *                                operation is completed.
   1787 * \param[in]  pContext           Upper layer context to be returned in
   1788 *                                the callback.
   1789 *
   1790 * \retval NFCSTATUS_SUCCESS                  Operation successful.
   1791 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
   1792 *                                            could not be properly interpreted.
   1793 * \retval NFCSTATUS_PENDING                  Connection operation is in progress,
   1794 *                                            pConnect_RspCb will be called upon completion.
   1795 * \retval NFCSTATUS_INVALID_STATE            The socket is not in a valid state, or not of
   1796 *                                            a valid type to perform the requsted operation.
   1797 * \retval NFCSTATUS_FAILED                   Operation failed.
   1798 */
   1799 NFCSTATUS phFriNfc_LlcpTransport_Connect( phFriNfc_LlcpTransport_Socket_t*           pLlcpSocket,
   1800                                           uint8_t                                    nSap,
   1801                                           pphFriNfc_LlcpTransportSocketConnectCb_t   pConnect_RspCb,
   1802                                           void*                                      pContext)
   1803 {
   1804    NFCSTATUS status = NFCSTATUS_SUCCESS;
   1805    uint8_t nLocalSap;
   1806    uint8_t i;
   1807 
   1808    /* Check for NULL pointers */
   1809    if(pLlcpSocket == NULL || pConnect_RspCb == NULL || pContext == NULL)
   1810    {
   1811       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1812    }
   1813    /* Test the port number value */
   1814    else if(nSap<02 || nSap>63)
   1815    {
   1816       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1817    }
   1818    /* Test if the socket is a connectionOriented socket */
   1819    else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
   1820    {
   1821       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1822    }
   1823    /* Test if the socket has a service name */
   1824    else if(pLlcpSocket->sServiceName.length != 0)
   1825    {
   1826       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
   1827    }
   1828    /* Test if the socket is not in connecting or connected state*/
   1829    else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketCreated && pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
   1830    {
   1831       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
   1832    }
   1833    else
   1834    {
   1835       /* Implicit bind if socket is not already bound */
   1836       if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
   1837       {
   1838          /* Bind to a free sap */
   1839          status = phFriNfc_LlcpTransport_GetFreeSap(pLlcpSocket->psTransport, NULL, &nLocalSap);
   1840          if (status != NFCSTATUS_SUCCESS)
   1841          {
   1842             return status;
   1843          }
   1844          pLlcpSocket->socket_sSap = nLocalSap;
   1845       }
   1846 
   1847       /* Test the SAP range for non SDP-advertised services */
   1848       if(!IS_BETWEEN(pLlcpSocket->socket_sSap, PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST, PHFRINFC_LLCP_SAP_NUMBER))
   1849       {
   1850          status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1851       }
   1852       else
   1853       {
   1854          status = phFriNfc_LlcpTransport_ConnectionOriented_Connect(pLlcpSocket,
   1855                                                                     nSap,
   1856                                                                     NULL,
   1857                                                                     pConnect_RspCb,
   1858                                                                     pContext);
   1859       }
   1860    }
   1861 
   1862    return status;
   1863 }
   1864 
   1865 /**
   1866 * \ingroup grp_fri_nfc
   1867 * \brief <b>Try to establish connection with a socket on a remote service, given its URI</b>.
   1868 *
   1869 * This function tries to connect to a SAP designated by an URI. If the
   1870 * socket is not bound to a local SAP, it is implicitly bound to a free SAP.
   1871 *
   1872 * \param[in]  pLlcpSocket           A pointer to a phFriNfc_LlcpTransport_Socket_t.
   1873 * \param[in]  psUri              The URI corresponding to the destination SAP to connect to.
   1874 * \param[in]  pConnect_RspCb     The callback to be called when the connection
   1875 *                                operation is completed.
   1876 * \param[in]  pContext           Upper layer context to be returned in
   1877 *                                the callback.
   1878 *
   1879 * \retval NFCSTATUS_SUCCESS                  Operation successful.
   1880 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
   1881 *                                            could not be properly interpreted.
   1882 * \retval NFCSTATUS_PENDING                  Connection operation is in progress,
   1883 *                                            pConnect_RspCb will be called upon completion.
   1884 * \retval NFCSTATUS_INVALID_STATE            The socket is not in a valid state, or not of
   1885 *                                            a valid type to perform the requsted operation.
   1886 * \retval NFCSTATUS_NOT_INITIALISED          Indicates stack is not yet initialized.
   1887 * \retval NFCSTATUS_SHUTDOWN                 Shutdown in progress.
   1888 * \retval NFCSTATUS_FAILED                   Operation failed.
   1889 */
   1890 NFCSTATUS phFriNfc_LlcpTransport_ConnectByUri(phFriNfc_LlcpTransport_Socket_t*           pLlcpSocket,
   1891                                               phNfc_sData_t*                             psUri,
   1892                                               pphFriNfc_LlcpTransportSocketConnectCb_t   pConnect_RspCb,
   1893                                               void*                                      pContext)
   1894 {
   1895    NFCSTATUS status = NFCSTATUS_SUCCESS;
   1896    uint8_t i;
   1897    uint8_t nLocalSap;
   1898 
   1899    /* Check for NULL pointers */
   1900    if(pLlcpSocket == NULL || pConnect_RspCb == NULL || pContext == NULL)
   1901    {
   1902       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1903    }
   1904    /* Test if the socket is a connectionOriented socket */
   1905    else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
   1906    {
   1907       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1908    }
   1909    /* Test if the socket is not in connect pending or connected state*/
   1910    else if(pLlcpSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketConnecting || pLlcpSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketConnected)
   1911    {
   1912       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1913    }
   1914    /* Test the length of the SN */
   1915    else if(psUri->length > PHFRINFC_LLCP_SN_MAX_LENGTH)
   1916    {
   1917       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1918    }
   1919    else
   1920    {
   1921       /* Implicit bind if socket is not already bound */
   1922       if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
   1923       {
   1924          /* Bind to a free sap */
   1925          status = phFriNfc_LlcpTransport_GetFreeSap(pLlcpSocket->psTransport, NULL, &nLocalSap);
   1926          if (status != NFCSTATUS_SUCCESS)
   1927          {
   1928             return status;
   1929          }
   1930          pLlcpSocket->socket_sSap = nLocalSap;
   1931       }
   1932 
   1933       /* Test the SAP range for non SDP-advertised services */
   1934       if(!IS_BETWEEN(pLlcpSocket->socket_sSap, PHFRINFC_LLCP_SAP_SDP_UNADVERTISED_FIRST, PHFRINFC_LLCP_SAP_NUMBER))
   1935       {
   1936          status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1937       }
   1938       else
   1939       {
   1940          status = phFriNfc_LlcpTransport_ConnectionOriented_Connect(pLlcpSocket,
   1941                                                                     PHFRINFC_LLCP_SAP_DEFAULT,
   1942                                                                     psUri,
   1943                                                                     pConnect_RspCb,
   1944                                                                     pContext);
   1945       }
   1946    }
   1947 
   1948    return status;
   1949 }
   1950 
   1951 /**
   1952 * \ingroup grp_lib_nfc
   1953 * \brief <b>Disconnect a currently connected socket</b>.
   1954 *
   1955 * This function initiates the disconnection of a previously connected socket.
   1956 *
   1957 * \param[in]  pLlcpSocket        A pointer to a phFriNfc_LlcpTransport_Socket_t.
   1958 * \param[in]  pDisconnect_RspCb  The callback to be called when the
   1959 *                                operation is completed.
   1960 * \param[in]  pContext           Upper layer context to be returned in
   1961 *                                the callback.
   1962 *
   1963 * \retval NFCSTATUS_SUCCESS                  Operation successful.
   1964 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
   1965 *                                            could not be properly interpreted.
   1966 * \retval NFCSTATUS_PENDING                  Disconnection operation is in progress,
   1967 *                                            pDisconnect_RspCb will be called upon completion.
   1968 * \retval NFCSTATUS_INVALID_STATE            The socket is not in a valid state, or not of
   1969 *                                            a valid type to perform the requsted operation.
   1970 * \retval NFCSTATUS_NOT_INITIALISED          Indicates stack is not yet initialized.
   1971 * \retval NFCSTATUS_SHUTDOWN                 Shutdown in progress.
   1972 * \retval NFCSTATUS_FAILED                   Operation failed.
   1973 */
   1974 NFCSTATUS phFriNfc_LlcpTransport_Disconnect(phFriNfc_LlcpTransport_Socket_t*           pLlcpSocket,
   1975                                             pphLibNfc_LlcpSocketDisconnectCb_t         pDisconnect_RspCb,
   1976                                             void*                                      pContext)
   1977 {
   1978    NFCSTATUS status = NFCSTATUS_SUCCESS;
   1979 
   1980    /* Check for NULL pointers */
   1981    if(pLlcpSocket == NULL || pDisconnect_RspCb == NULL || pContext == NULL)
   1982    {
   1983       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1984    }
   1985    /* Test if the socket is a connectionOriented socket */
   1986    else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
   1987    {
   1988       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1989    }
   1990    /* Test if the socket is connected  state*/
   1991    else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketConnected)
   1992    {
   1993        status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   1994    }
   1995    else
   1996    {
   1997       status = phLibNfc_LlcpTransport_ConnectionOriented_Disconnect(pLlcpSocket,
   1998                                                                     pDisconnect_RspCb,
   1999                                                                     pContext);
   2000    }
   2001 
   2002    return status;
   2003 }
   2004 
   2005 /**
   2006 * \ingroup grp_fri_nfc
   2007 * \brief <b>Send data on a socket</b>.
   2008 *
   2009 * This function is used to write data on a socket. This function
   2010 * can only be called on a connection-oriented socket which is already
   2011 * in a connected state.
   2012 *
   2013 *
   2014 * \param[in]  pLlcpSocket        A pointer to a phFriNfc_LlcpTransport_Socket_t.
   2015 * \param[in]  psBuffer           The buffer containing the data to send.
   2016 * \param[in]  pSend_RspCb        The callback to be called when the
   2017 *                                operation is completed.
   2018 * \param[in]  pContext           Upper layer context to be returned in
   2019 *                                the callback.
   2020 *
   2021 * \retval NFCSTATUS_SUCCESS                  Operation successful.
   2022 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
   2023 *                                            could not be properly interpreted.
   2024 * \retval NFCSTATUS_PENDING                  Reception operation is in progress,
   2025 *                                            pSend_RspCb will be called upon completion.
   2026 * \retval NFCSTATUS_INVALID_STATE            The socket is not in a valid state, or not of
   2027 *                                            a valid type to perform the requsted operation.
   2028 * \retval NFCSTATUS_FAILED                   Operation failed.
   2029 */
   2030 NFCSTATUS phFriNfc_LlcpTransport_Send(phFriNfc_LlcpTransport_Socket_t*             pLlcpSocket,
   2031                                       phNfc_sData_t*                               psBuffer,
   2032                                       pphFriNfc_LlcpTransportSocketSendCb_t        pSend_RspCb,
   2033                                       void*                                        pContext)
   2034 {
   2035    NFCSTATUS status = NFCSTATUS_SUCCESS;
   2036 
   2037    /* Check for NULL pointers */
   2038    if(pLlcpSocket == NULL || psBuffer == NULL || pSend_RspCb == NULL || pContext == NULL)
   2039    {
   2040       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   2041    }
   2042    /* Test if the socket is a connectionOriented socket */
   2043    else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
   2044    {
   2045       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   2046    }
   2047    /* Test if the socket is in connected state */
   2048    else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketConnected)
   2049    {
   2050       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
   2051    }
   2052    /* Test the length of the buffer */
   2053    else if(psBuffer->length > pLlcpSocket->remoteMIU )
   2054    {
   2055       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   2056    }
   2057    /* Test if a send is pending */
   2058    else if(pLlcpSocket->pfSocketSend_Cb != NULL)
   2059    {
   2060       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED);
   2061    }
   2062    else
   2063    {
   2064       status = phFriNfc_LlcpTransport_ConnectionOriented_Send(pLlcpSocket,
   2065                                                               psBuffer,
   2066                                                               pSend_RspCb,
   2067                                                               pContext);
   2068    }
   2069 
   2070    return status;
   2071 }
   2072 
   2073  /**
   2074 * \ingroup grp_fri_nfc
   2075 * \brief <b>Read data on a socket</b>.
   2076 *
   2077 * This function is used to read data from a socket. It reads at most the
   2078 * size of the reception buffer, but can also return less bytes if less bytes
   2079 * are available. If no data is available, the function will be pending until
   2080 * more data comes, and the response will be sent by the callback. This function
   2081 * can only be called on a connection-oriented socket.
   2082 *
   2083 *
   2084 * \param[in]  pLlcpSocket        A pointer to a phFriNfc_LlcpTransport_Socket_t.
   2085 * \param[in]  psBuffer           The buffer receiving the data.
   2086 * \param[in]  pRecv_RspCb        The callback to be called when the
   2087 *                                operation is completed.
   2088 * \param[in]  pContext           Upper layer context to be returned in
   2089 *                                the callback.
   2090 *
   2091 * \retval NFCSTATUS_SUCCESS                  Operation successful.
   2092 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
   2093 *                                            could not be properly interpreted.
   2094 * \retval NFCSTATUS_PENDING                  Reception operation is in progress,
   2095 *                                            pRecv_RspCb will be called upon completion.
   2096 * \retval NFCSTATUS_INVALID_STATE            The socket is not in a valid state, or not of
   2097 *                                            a valid type to perform the requsted operation.
   2098 * \retval NFCSTATUS_FAILED                   Operation failed.
   2099 */
   2100 NFCSTATUS phFriNfc_LlcpTransport_Recv( phFriNfc_LlcpTransport_Socket_t*             pLlcpSocket,
   2101                                        phNfc_sData_t*                               psBuffer,
   2102                                        pphFriNfc_LlcpTransportSocketRecvCb_t        pRecv_RspCb,
   2103                                        void*                                        pContext)
   2104 {
   2105    NFCSTATUS status = NFCSTATUS_SUCCESS;
   2106 
   2107    /* Check for NULL pointers */
   2108    if(pLlcpSocket == NULL || psBuffer == NULL || pRecv_RspCb == NULL || pContext == NULL)
   2109    {
   2110       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   2111    }
   2112    /* Test if the socket is a connectionOriented socket */
   2113    else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionOriented)
   2114    {
   2115       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   2116    }
   2117    /* Test if the socket is in connected state */
   2118    else if(pLlcpSocket->eSocket_State == phFriNfc_LlcpTransportSocket_eSocketDefault)
   2119    {
   2120       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   2121    }
   2122    /* Test if a receive is pending */
   2123    else if(pLlcpSocket->bSocketRecvPending == TRUE)
   2124    {
   2125       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED);
   2126    }
   2127    else
   2128    {
   2129       status = phFriNfc_LlcpTransport_ConnectionOriented_Recv(pLlcpSocket,
   2130                                                               psBuffer,
   2131                                                               pRecv_RspCb,
   2132                                                               pContext);
   2133    }
   2134 
   2135    return status;
   2136 }
   2137 
   2138 /*****************************************/
   2139 /*           ConnectionLess              */
   2140 /*****************************************/
   2141 
   2142 /**
   2143 * \ingroup grp_fri_nfc
   2144 * \brief <b>Send data on a socket to a given destination SAP</b>.
   2145 *
   2146 * This function is used to write data on a socket to a given destination SAP.
   2147 * This function can only be called on a connectionless socket.
   2148 *
   2149 *
   2150 * \param[in]  pLlcpSocket        A pointer to a LlcpSocket created.
   2151 * \param[in]  nSap               The destination SAP.
   2152 * \param[in]  psBuffer           The buffer containing the data to send.
   2153 * \param[in]  pSend_RspCb        The callback to be called when the
   2154 *                                operation is completed.
   2155 * \param[in]  pContext           Upper layer context to be returned in
   2156 *                                the callback.
   2157 *
   2158 * \retval NFCSTATUS_SUCCESS                  Operation successful.
   2159 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
   2160 *                                            could not be properly interpreted.
   2161 * \retval NFCSTATUS_PENDING                  Reception operation is in progress,
   2162 *                                            pSend_RspCb will be called upon completion.
   2163 * \retval NFCSTATUS_INVALID_STATE            The socket is not in a valid state, or not of
   2164 *                                            a valid type to perform the requsted operation.
   2165 * \retval NFCSTATUS_FAILED                   Operation failed.
   2166 */
   2167 NFCSTATUS phFriNfc_LlcpTransport_SendTo( phFriNfc_LlcpTransport_Socket_t             *pLlcpSocket,
   2168                                          uint8_t                                     nSap,
   2169                                          phNfc_sData_t                               *psBuffer,
   2170                                          pphFriNfc_LlcpTransportSocketSendCb_t       pSend_RspCb,
   2171                                          void*                                       pContext)
   2172 {
   2173    NFCSTATUS status = NFCSTATUS_SUCCESS;
   2174    phFriNfc_Llcp_sLinkParameters_t  LlcpRemoteLinkParamInfo;
   2175 
   2176    if(pLlcpSocket == NULL || psBuffer == NULL || pSend_RspCb == NULL || pContext == NULL)
   2177    {
   2178       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   2179    }
   2180    /* Test the port number value */
   2181    else if(nSap<2 || nSap>63)
   2182    {
   2183       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   2184    }
   2185    /* Test if the socket is a connectionless socket */
   2186    else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionLess)
   2187    {
   2188        status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   2189    }
   2190    /* Test if the socket is in an updated state */
   2191    else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
   2192    {
   2193       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
   2194    }
   2195    /* Test if a send is pending */
   2196    else if(pLlcpSocket->pfSocketSend_Cb != NULL)
   2197    {
   2198       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED);
   2199    }
   2200    else
   2201    {
   2202       /* Get the local parameters of the LLCP Link */
   2203       status = phFriNfc_Llcp_GetRemoteInfo(pLlcpSocket->psTransport->pLlcp,&LlcpRemoteLinkParamInfo);
   2204       if(status != NFCSTATUS_SUCCESS)
   2205       {
   2206          status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_FAILED);
   2207       }
   2208       /* Test the length of the socket buffer for ConnectionLess mode*/
   2209       else if(psBuffer->length > LlcpRemoteLinkParamInfo.miu)
   2210       {
   2211          status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   2212       }
   2213       /* Test if the link is in error state */
   2214       else if(pLlcpSocket->psTransport->LinkStatusError)
   2215       {
   2216          status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED);
   2217       }
   2218       else
   2219       {
   2220          status = phFriNfc_LlcpTransport_Connectionless_SendTo(pLlcpSocket,
   2221                                                                nSap,
   2222                                                                psBuffer,
   2223                                                                pSend_RspCb,
   2224                                                                pContext);
   2225       }
   2226    }
   2227 
   2228    return status;
   2229 }
   2230 
   2231 
   2232  /**
   2233 * \ingroup grp_lib_nfc
   2234 * \brief <b>Read data on a socket and get the source SAP</b>.
   2235 *
   2236 * This function is the same as phLibNfc_Llcp_Recv, except that the callback includes
   2237 * the source SAP. This functions can only be called on a connectionless socket.
   2238 *
   2239 *
   2240 * \param[in]  pLlcpSocket        A pointer to a LlcpSocket created.
   2241 * \param[in]  psBuffer           The buffer receiving the data.
   2242 * \param[in]  pRecv_RspCb        The callback to be called when the
   2243 *                                operation is completed.
   2244 * \param[in]  pContext           Upper layer context to be returned in
   2245 *                                the callback.
   2246 *
   2247 * \retval NFCSTATUS_SUCCESS                  Operation successful.
   2248 * \retval NFCSTATUS_INVALID_PARAMETER        One or more of the supplied parameters
   2249 *                                            could not be properly interpreted.
   2250 * \retval NFCSTATUS_PENDING                  Reception operation is in progress,
   2251 *                                            pRecv_RspCb will be called upon completion.
   2252 * \retval NFCSTATUS_INVALID_STATE            The socket is not in a valid state, or not of
   2253 *                                            a valid type to perform the requsted operation.
   2254 * \retval NFCSTATUS_NOT_INITIALISED          Indicates stack is not yet initialized.
   2255 * \retval NFCSTATUS_SHUTDOWN                 Shutdown in progress.
   2256 * \retval NFCSTATUS_FAILED                   Operation failed.
   2257 */
   2258 NFCSTATUS phFriNfc_LlcpTransport_RecvFrom( phFriNfc_LlcpTransport_Socket_t                   *pLlcpSocket,
   2259                                            phNfc_sData_t*                                    psBuffer,
   2260                                            pphFriNfc_LlcpTransportSocketRecvFromCb_t         pRecv_Cb,
   2261                                            void*                                             pContext)
   2262 {
   2263    NFCSTATUS status = NFCSTATUS_SUCCESS;
   2264    if(pLlcpSocket == NULL || psBuffer == NULL || pRecv_Cb == NULL || pContext == NULL)
   2265    {
   2266       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   2267    }
   2268    /* Test if the socket is a connectionless socket */
   2269    else if(pLlcpSocket->eSocket_Type != phFriNfc_LlcpTransport_eConnectionLess)
   2270    {
   2271       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_PARAMETER);
   2272    }
   2273    /* Test if the socket is in an updated state */
   2274    else if(pLlcpSocket->eSocket_State != phFriNfc_LlcpTransportSocket_eSocketBound)
   2275    {
   2276       status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_INVALID_STATE);
   2277    }
   2278    else
   2279    {
   2280       if(pLlcpSocket->bSocketRecvPending)
   2281       {
   2282          status = PHNFCSTVAL(CID_FRI_NFC_LLCP_TRANSPORT, NFCSTATUS_REJECTED);
   2283       }
   2284       else
   2285       {
   2286          status = phLibNfc_LlcpTransport_Connectionless_RecvFrom(pLlcpSocket,
   2287                                                                  psBuffer,
   2288                                                                  pRecv_Cb,
   2289                                                                  pContext);
   2290       }
   2291    }
   2292 
   2293    return status;
   2294 }
   2295