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