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