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