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 
phFriNfc_LlcpTransport_GetFreeSap(phFriNfc_LlcpTransport_t * psTransport,phNfc_sData_t * psServiceName,uint8_t * pnSap)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 
phFriNfc_LlcpTransport_EncodeSdreqTlv(phNfc_sData_t * psTlvData,uint32_t * pOffset,uint8_t nTid,phNfc_sData_t * psServiceName)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 
phFriNfc_LlcpTransport_EncodeSdresTlv(phNfc_sData_t * psTlvData,uint32_t * pOffset,uint8_t nTid,uint8_t nSap)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 
phFriNfc_LlcpTransport_ServiceNameLoockup(phFriNfc_LlcpTransport_t * psTransport,phNfc_sData_t * pServiceName)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 
phFriNfc_LlcpTransport_DiscoveryAnswer(phFriNfc_LlcpTransport_t * psTransport)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 
Handle_Discovery_IncomingFrame(phFriNfc_LlcpTransport_t * psTransport,phNfc_sData_t * psData)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 */
phFriNfc_LlcpTransport__Recv_CB(void * pContext,phNfc_sData_t * psData,NFCSTATUS status)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 
testAndSetSendPending(phFriNfc_LlcpTransport_t * transport)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 
clearSendPending(phFriNfc_LlcpTransport_t * transport)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 */
phFriNfc_LlcpTransport_Send_CB(void * pContext,NFCSTATUS status)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 */
phFriNfc_LlcpTransport_Reset(phFriNfc_LlcpTransport_t * pLlcpTransport,phFriNfc_Llcp_t * pLlcp)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 */
phFriNfc_LlcpTransport_CloseAll(phFriNfc_LlcpTransport_t * pLlcpTransport)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 */
phFriNfc_LlcpTransport_LinkSend(phFriNfc_LlcpTransport_t * LlcpTransport,phFriNfc_Llcp_sPacketHeader_t * psHeader,phFriNfc_Llcp_sPacketSequence_t * psSequence,phNfc_sData_t * psInfo,phFriNfc_Llcp_LinkSend_CB_t pfSend_CB,uint8_t socketIndex,void * pContext)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 */
phFriNfc_LlcpTransport_SendFrameReject(phFriNfc_LlcpTransport_t * psTransport,uint8_t dsap,uint8_t rejectedPTYPE,uint8_t ssap,phFriNfc_Llcp_sPacketSequence_t * sLlcpSequence,uint8_t WFlag,uint8_t IFlag,uint8_t RFlag,uint8_t SFlag,uint8_t vs,uint8_t vsa,uint8_t vr,uint8_t vra)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  */
phFriNfc_LlcpTransport_SendDisconnectMode(phFriNfc_LlcpTransport_t * psTransport,uint8_t dsap,uint8_t ssap,uint8_t dmOpCode)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 */
phFriNfc_LlcpTransport_SocketGetLocalOptions(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phLibNfc_Llcp_sSocketOptions_t * psLocalOptions)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 */
phFriNfc_LlcpTransport_SocketGetRemoteOptions(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phLibNfc_Llcp_sSocketOptions_t * psRemoteOptions)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 
phFriNfc_LlcpTransport_DiscoverServicesEx(phFriNfc_LlcpTransport_t * psTransport)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  */
phFriNfc_LlcpTransport_DiscoverServices(phFriNfc_LlcpTransport_t * pLlcpTransport,phNfc_sData_t * psServiceNameList,uint8_t * pnSapList,uint8_t nListSize,pphFriNfc_Cr_t pDiscover_Cb,void * pContext)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 * */
phFriNfc_LlcpTransport_Socket(phFriNfc_LlcpTransport_t * pLlcpTransport,phFriNfc_LlcpTransport_eSocketType_t eType,phFriNfc_LlcpTransport_sSocketOptions_t * psOptions,phNfc_sData_t * psWorkingBuffer,phFriNfc_LlcpTransport_Socket_t ** pLlcpSocket,pphFriNfc_LlcpTransportSocketErrCb_t pErr_Cb,void * pContext)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 */
phFriNfc_LlcpTransport_Close(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket)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 
phFriNfc_LlcpTransport_Bind(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,uint8_t nSap,phNfc_sData_t * psServiceName)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 */
phFriNfc_LlcpTransport_Listen(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,pphFriNfc_LlcpTransportSocketListenCb_t pListen_Cb,void * pContext)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 */
phFriNfc_LlcpTransport_RegisterName(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,uint8_t nSap,phNfc_sData_t * psServiceName)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 */
phFriNfc_LlcpTransport_Accept(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phFriNfc_LlcpTransport_sSocketOptions_t * psOptions,phNfc_sData_t * psWorkingBuffer,pphFriNfc_LlcpTransportSocketErrCb_t pErr_Cb,pphFriNfc_LlcpTransportSocketAcceptCb_t pAccept_RspCb,void * pContext)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 */
phFriNfc_LlcpTransport_Reject(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,pphFriNfc_LlcpTransportSocketRejectCb_t pReject_RspCb,void * pContext)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 */
phFriNfc_LlcpTransport_Connect(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,uint8_t nSap,pphFriNfc_LlcpTransportSocketConnectCb_t pConnect_RspCb,void * pContext)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 */
phFriNfc_LlcpTransport_ConnectByUri(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phNfc_sData_t * psUri,pphFriNfc_LlcpTransportSocketConnectCb_t pConnect_RspCb,void * pContext)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 */
phFriNfc_LlcpTransport_Disconnect(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,pphLibNfc_LlcpSocketDisconnectCb_t pDisconnect_RspCb,void * pContext)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 */
phFriNfc_LlcpTransport_Send(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phNfc_sData_t * psBuffer,pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb,void * pContext)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 */
phFriNfc_LlcpTransport_Recv(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phNfc_sData_t * psBuffer,pphFriNfc_LlcpTransportSocketRecvCb_t pRecv_RspCb,void * pContext)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 */
phFriNfc_LlcpTransport_SendTo(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,uint8_t nSap,phNfc_sData_t * psBuffer,pphFriNfc_LlcpTransportSocketSendCb_t pSend_RspCb,void * pContext)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 */
phFriNfc_LlcpTransport_RecvFrom(phFriNfc_LlcpTransport_Socket_t * pLlcpSocket,phNfc_sData_t * psBuffer,pphFriNfc_LlcpTransportSocketRecvFromCb_t pRecv_Cb,void * pContext)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