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