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