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