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 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 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 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 * */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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