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_Llcp.c 19 * \brief NFC LLCP core 20 * 21 * Project: NFC-FRI 22 * 23 */ 24 25 /*include files*/ 26 #include <phNfcLlcpTypes.h> 27 #include <phOsalNfc_Timer.h> 28 29 #include <phFriNfc_Llcp.h> 30 #include <phFriNfc_LlcpUtils.h> 31 32 /** 33 * \internal 34 * \name States of the LLC state machine. 35 * 36 */ 37 /*@{*/ 38 #define PHFRINFC_LLCP_STATE_RESET_INIT 0 /**< \internal Initial state.*/ 39 #define PHFRINFC_LLCP_STATE_CHECKED 1 /**< \internal The tag has been checked for LLCP compliance.*/ 40 #define PHFRINFC_LLCP_STATE_ACTIVATION 2 /**< \internal The deactivation phase.*/ 41 #define PHFRINFC_LLCP_STATE_PAX 3 /**< \internal Parameter exchange phase.*/ 42 #define PHFRINFC_LLCP_STATE_OPERATION_RECV 4 /**< \internal Normal operation phase (ready to receive).*/ 43 #define PHFRINFC_LLCP_STATE_OPERATION_SEND 5 /**< \internal Normal operation phase (ready to send).*/ 44 #define PHFRINFC_LLCP_STATE_DEACTIVATION 6 /**< \internal The deactivation phase.*/ 45 /*@}*/ 46 47 /** 48 * \internal 49 * \name Masks used for VERSION parsing. 50 * 51 */ 52 /*@{*/ 53 #define PHFRINFC_LLCP_VERSION_MAJOR_MASK 0xF0 /**< \internal Mask to apply to get major version number.*/ 54 #define PHFRINFC_LLCP_VERSION_MINOR_MASK 0x0F /**< \internal Mask to apply to get major version number.*/ 55 /*@}*/ 56 57 /** 58 * \internal 59 * \name Invalid values for parameters. 60 * 61 */ 62 /*@{*/ 63 #define PHFRINFC_LLCP_INVALID_VERSION 0x00 /**< \internal Invalid VERSION value.*/ 64 /*@}*/ 65 66 /** 67 * \internal 68 * \name Internal constants. 69 * 70 */ 71 /*@{*/ 72 #define PHFRINFC_LLCP_MAX_PARAM_TLV_LENGTH \ 73 (( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_VERSION ) + \ 74 ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_MIUX ) + \ 75 ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_WKS ) + \ 76 ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_LTO ) + \ 77 ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_OPT )) /**< \internal Maximum size of link params TLV.*/ 78 /*@}*/ 79 80 81 82 /* --------------------------- Internal functions ------------------------------ */ 83 84 static void phFriNfc_Llcp_Receive_CB( void *pContext, 85 NFCSTATUS status, 86 phNfc_sData_t *psData); 87 static NFCSTATUS phFriNfc_Llcp_HandleIncomingPacket( phFriNfc_Llcp_t *Llcp, 88 phNfc_sData_t *psPacket ); 89 static void phFriNfc_Llcp_ResetLTO( phFriNfc_Llcp_t *Llcp ); 90 static NFCSTATUS phFriNfc_Llcp_InternalSend( phFriNfc_Llcp_t *Llcp, 91 phFriNfc_Llcp_sPacketHeader_t *psHeader, 92 phFriNfc_Llcp_sPacketSequence_t *psSequence, 93 phNfc_sData_t *psInfo ); 94 static bool_t phFriNfc_Llcp_HandlePendingSend ( phFriNfc_Llcp_t *Llcp ); 95 96 static phNfc_sData_t * phFriNfc_Llcp_AllocateAndCopy(phNfc_sData_t * pOrig) 97 { 98 phNfc_sData_t * pDest = NULL; 99 100 if (pOrig == NULL) 101 { 102 return NULL; 103 } 104 105 pDest = phOsalNfc_GetMemory(sizeof(phNfc_sData_t)); 106 if (pDest == NULL) 107 { 108 goto error; 109 } 110 111 pDest->buffer = phOsalNfc_GetMemory(pOrig->length); 112 if (pDest->buffer == NULL) 113 { 114 goto error; 115 } 116 117 memcpy(pDest->buffer, pOrig->buffer, pOrig->length); 118 pDest->length = pOrig->length; 119 120 return pDest; 121 122 error: 123 if (pDest != NULL) 124 { 125 if (pDest->buffer != NULL) 126 { 127 phOsalNfc_FreeMemory(pDest->buffer); 128 } 129 phOsalNfc_FreeMemory(pDest); 130 } 131 return NULL; 132 } 133 134 static void phFriNfc_Llcp_Deallocate(phNfc_sData_t * pData) 135 { 136 if (pData != NULL) 137 { 138 if (pData->buffer != NULL) 139 { 140 phOsalNfc_FreeMemory(pData->buffer); 141 } 142 else 143 { 144 LLCP_PRINT("Warning, deallocating empty buffer"); 145 } 146 phOsalNfc_FreeMemory(pData); 147 } 148 } 149 150 static NFCSTATUS phFriNfc_Llcp_InternalDeactivate( phFriNfc_Llcp_t *Llcp ) 151 { 152 phFriNfc_Llcp_Send_CB_t pfSendCB; 153 void * pSendContext; 154 if ((Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) || 155 (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND) || 156 (Llcp->state == PHFRINFC_LLCP_STATE_PAX) || 157 (Llcp->state == PHFRINFC_LLCP_STATE_ACTIVATION)) 158 { 159 /* Update state */ 160 Llcp->state = PHFRINFC_LLCP_STATE_DEACTIVATION; 161 162 /* Stop timer */ 163 phOsalNfc_Timer_Stop(Llcp->hSymmTimer); 164 165 /* Return delayed send operation in error, in any */ 166 if (Llcp->psSendInfo != NULL) 167 { 168 phFriNfc_Llcp_Deallocate(Llcp->psSendInfo); 169 Llcp->psSendInfo = NULL; 170 Llcp->psSendHeader = NULL; 171 Llcp->psSendSequence = NULL; 172 } 173 if (Llcp->pfSendCB != NULL) 174 { 175 /* Get Callback params */ 176 pfSendCB = Llcp->pfSendCB; 177 pSendContext = Llcp->pSendContext; 178 /* Reset callback params */ 179 Llcp->pfSendCB = NULL; 180 Llcp->pSendContext = NULL; 181 /* Call the callback */ 182 (pfSendCB)(pSendContext, NFCSTATUS_FAILED); 183 } 184 185 /* Notify service layer */ 186 Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkDeactivated); 187 188 /* Forward check request to MAC layer */ 189 return phFriNfc_LlcpMac_Deactivate(&Llcp->MAC); 190 } 191 192 return NFCSTATUS_SUCCESS; 193 } 194 195 196 static NFCSTATUS phFriNfc_Llcp_SendSymm( phFriNfc_Llcp_t *Llcp ) 197 { 198 phFriNfc_Llcp_sPacketHeader_t sHeader; 199 bool_t bPendingFlag; 200 201 /* Check for pending messages to send */ 202 bPendingFlag = phFriNfc_Llcp_HandlePendingSend(Llcp); 203 204 if (bPendingFlag == FALSE) 205 { 206 /* No send pending, send a SYMM instead */ 207 sHeader.dsap = PHFRINFC_LLCP_SAP_LINK; 208 sHeader.ssap = PHFRINFC_LLCP_SAP_LINK; 209 sHeader.ptype = PHFRINFC_LLCP_PTYPE_SYMM; 210 return phFriNfc_Llcp_InternalSend(Llcp, &sHeader, NULL, NULL); 211 } 212 else 213 { 214 /* A pending send has been sent, there is no need to send SYMM */ 215 return NFCSTATUS_SUCCESS; 216 } 217 } 218 219 220 static NFCSTATUS phFriNfc_Llcp_SendPax( phFriNfc_Llcp_t *Llcp, phFriNfc_Llcp_sLinkParameters_t *psLinkParams) 221 { 222 uint8_t pTLVBuffer[PHFRINFC_LLCP_MAX_PARAM_TLV_LENGTH]; 223 phNfc_sData_t sParamsTLV; 224 phFriNfc_Llcp_sPacketHeader_t sHeader; 225 NFCSTATUS result; 226 227 /* Prepare link parameters TLV */ 228 sParamsTLV.buffer = pTLVBuffer; 229 sParamsTLV.length = PHFRINFC_LLCP_MAX_PARAM_TLV_LENGTH; 230 result = phFriNfc_Llcp_EncodeLinkParams(&sParamsTLV, psLinkParams, PHFRINFC_LLCP_VERSION); 231 if (result != NFCSTATUS_SUCCESS) 232 { 233 /* Error while encoding */ 234 return NFCSTATUS_FAILED; 235 } 236 237 /* Check if ready to send */ 238 if (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND) 239 { 240 /* No send pending, send the PAX packet */ 241 sHeader.dsap = PHFRINFC_LLCP_SAP_LINK; 242 sHeader.ssap = PHFRINFC_LLCP_SAP_LINK; 243 sHeader.ptype = PHFRINFC_LLCP_PTYPE_PAX; 244 return phFriNfc_Llcp_InternalSend(Llcp, &sHeader, NULL, &sParamsTLV); 245 } 246 else 247 { 248 /* Error: A send is already pending, cannot send PAX */ 249 /* NOTE: this should not happen since PAX are sent before any other packet ! */ 250 return NFCSTATUS_FAILED; 251 } 252 } 253 254 255 static NFCSTATUS phFriNfc_Llcp_SendDisconnect( phFriNfc_Llcp_t *Llcp ) 256 { 257 phFriNfc_Llcp_sPacketHeader_t sHeader; 258 259 /* Check if ready to send */ 260 if (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND) 261 { 262 /* No send pending, send the DISC packet */ 263 sHeader.dsap = PHFRINFC_LLCP_SAP_LINK; 264 sHeader.ssap = PHFRINFC_LLCP_SAP_LINK; 265 sHeader.ptype = PHFRINFC_LLCP_PTYPE_DISC; 266 return phFriNfc_Llcp_InternalSend(Llcp, &sHeader, NULL, NULL); 267 } 268 else 269 { 270 /* A send is already pending, raise a flag to send DISC as soon as possible */ 271 Llcp->bDiscPendingFlag = TRUE; 272 return NFCSTATUS_PENDING; 273 } 274 } 275 276 277 static void phFriNfc_Llcp_Timer_CB(uint32_t TimerId, void *pContext) 278 { 279 phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; 280 281 PHNFC_UNUSED_VARIABLE(TimerId); 282 283 /* Check current state */ 284 if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) 285 { 286 /* No data is coming before LTO, disconnecting */ 287 phFriNfc_Llcp_InternalDeactivate(Llcp); 288 } 289 else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND) 290 { 291 /* Send SYMM */ 292 phFriNfc_Llcp_SendSymm(Llcp); 293 } 294 else 295 { 296 /* Nothing to do if not in Normal Operation state */ 297 } 298 } 299 300 301 static NFCSTATUS phFriNfc_Llcp_HandleAggregatedPacket( phFriNfc_Llcp_t *Llcp, 302 phNfc_sData_t *psRawPacket ) 303 { 304 phNfc_sData_t sInfo; 305 phNfc_sData_t sCurrentInfo; 306 uint16_t length; 307 NFCSTATUS status; 308 309 /* Get info field */ 310 sInfo.buffer = psRawPacket->buffer + PHFRINFC_LLCP_PACKET_HEADER_SIZE; 311 sInfo.length = psRawPacket->length - PHFRINFC_LLCP_PACKET_HEADER_SIZE; 312 313 /* Check for empty info field */ 314 if (sInfo.length == 0) 315 { 316 return NFCSTATUS_FAILED; 317 } 318 319 /* Check consistency */ 320 while (sInfo.length != 0) 321 { 322 /* Check if enough room to read length */ 323 if (sInfo.length < sizeof(sInfo.length)) 324 { 325 return NFCSTATUS_FAILED; 326 } 327 /* Read length */ 328 length = (sInfo.buffer[0] << 8) | sInfo.buffer[1]; 329 /* Update info buffer */ 330 sInfo.buffer += 2; /*Size of length field is 2*/ 331 sInfo.length -= 2; /*Size of length field is 2*/ 332 /* Check if declared length fits in remaining space */ 333 if (length > sInfo.length) 334 { 335 return NFCSTATUS_FAILED; 336 } 337 /* Update info buffer */ 338 sInfo.buffer += length; 339 sInfo.length -= length; 340 } 341 342 /* Get info field */ 343 sInfo.buffer = psRawPacket->buffer + PHFRINFC_LLCP_PACKET_HEADER_SIZE; 344 sInfo.length = psRawPacket->length - PHFRINFC_LLCP_PACKET_HEADER_SIZE; 345 346 /* Handle aggregated packets */ 347 while (sInfo.length != 0) 348 { 349 /* Read length */ 350 length = (sInfo.buffer[0] << 8) | sInfo.buffer[1]; 351 /* Update info buffer */ 352 sInfo.buffer += 2; /* Size of length field is 2 */ 353 sInfo.length -= 2; /*Size of length field is 2*/ 354 /* Handle aggregated packet */ 355 sCurrentInfo.buffer=sInfo.buffer; 356 sCurrentInfo.length=length; 357 status = phFriNfc_Llcp_HandleIncomingPacket(Llcp, &sCurrentInfo); 358 if ( (status != NFCSTATUS_SUCCESS) && 359 (status != NFCSTATUS_PENDING) ) 360 { 361 /* TODO: Error: invalid frame */ 362 } 363 /* Update info buffer */ 364 sInfo.buffer += length; 365 sInfo.length -= length; 366 } 367 return NFCSTATUS_SUCCESS; 368 } 369 370 371 static NFCSTATUS phFriNfc_Llcp_ParseLinkParams( phNfc_sData_t *psParamsTLV, 372 phFriNfc_Llcp_sLinkParameters_t *psParsedParams, 373 uint8_t *pnParsedVersion ) 374 { 375 NFCSTATUS status; 376 uint8_t type; 377 phFriNfc_Llcp_sLinkParameters_t sParams; 378 phNfc_sData_t sValueBuffer; 379 uint32_t offset = 0; 380 uint8_t version = PHFRINFC_LLCP_INVALID_VERSION; 381 382 /* Check for NULL pointers */ 383 if ((psParamsTLV == NULL) || (psParsedParams == NULL) || (pnParsedVersion == NULL)) 384 { 385 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 386 } 387 388 /* Prepare default param structure */ 389 sParams.miu = PHFRINFC_LLCP_MIU_DEFAULT; 390 sParams.wks = PHFRINFC_LLCP_WKS_DEFAULT; 391 sParams.lto = PHFRINFC_LLCP_LTO_DEFAULT; 392 sParams.option = PHFRINFC_LLCP_OPTION_DEFAULT; 393 394 /* Decode TLV */ 395 while (offset < psParamsTLV->length) 396 { 397 status = phFriNfc_Llcp_DecodeTLV(psParamsTLV, &offset, &type, &sValueBuffer); 398 if (status != NFCSTATUS_SUCCESS) 399 { 400 /* Error: Ill-formed TLV */ 401 return status; 402 } 403 switch(type) 404 { 405 case PHFRINFC_LLCP_TLV_TYPE_VERSION: 406 { 407 /* Check length */ 408 if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_VERSION) 409 { 410 /* Error : Ill-formed VERSION parameter TLV */ 411 break; 412 } 413 /* Get VERSION */ 414 version = sValueBuffer.buffer[0]; 415 break; 416 } 417 case PHFRINFC_LLCP_TLV_TYPE_MIUX: 418 { 419 /* Check length */ 420 if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_MIUX) 421 { 422 /* Error : Ill-formed MIUX parameter TLV */ 423 break; 424 } 425 /* Get MIU */ 426 sParams.miu = PHFRINFC_LLCP_MIU_DEFAULT + ((sValueBuffer.buffer[0] << 8) | sValueBuffer.buffer[1]) & PHFRINFC_LLCP_TLV_MIUX_MASK; 427 break; 428 } 429 case PHFRINFC_LLCP_TLV_TYPE_WKS: 430 { 431 /* Check length */ 432 if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_WKS) 433 { 434 /* Error : Ill-formed MIUX parameter TLV */ 435 break; 436 } 437 /* Get WKS */ 438 sParams.wks = (sValueBuffer.buffer[0] << 8) | sValueBuffer.buffer[1]; 439 /* Ignored bits must always be set */ 440 sParams.wks |= PHFRINFC_LLCP_TLV_WKS_MASK; 441 break; 442 } 443 case PHFRINFC_LLCP_TLV_TYPE_LTO: 444 { 445 /* Check length */ 446 if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_LTO) 447 { 448 /* Error : Ill-formed LTO parameter TLV */ 449 break; 450 } 451 /* Get LTO */ 452 sParams.lto = sValueBuffer.buffer[0]; 453 break; 454 } 455 case PHFRINFC_LLCP_TLV_TYPE_OPT: 456 { 457 /* Check length */ 458 if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_OPT) 459 { 460 /* Error : Ill-formed OPT parameter TLV */ 461 break;; 462 } 463 /* Get OPT */ 464 sParams.option = sValueBuffer.buffer[0] & PHFRINFC_LLCP_TLV_OPT_MASK; 465 break; 466 } 467 default: 468 { 469 /* Error : Unknown Type */ 470 break; 471 } 472 } 473 } 474 475 /* Check if a VERSION parameter has been provided */ 476 if (version == PHFRINFC_LLCP_INVALID_VERSION) 477 { 478 /* Error : Mandatory VERSION parameter not provided */ 479 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 480 } 481 482 /* Save response */ 483 *pnParsedVersion = version; 484 memcpy(psParsedParams, &sParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); 485 486 return NFCSTATUS_SUCCESS; 487 } 488 489 490 static NFCSTATUS phFriNfc_Llcp_VersionAgreement( uint8_t localVersion, 491 uint8_t remoteVersion, 492 uint8_t *pNegociatedVersion ) 493 { 494 uint8_t localMajor = localVersion & PHFRINFC_LLCP_VERSION_MAJOR_MASK; 495 uint8_t localMinor = localVersion & PHFRINFC_LLCP_VERSION_MINOR_MASK; 496 uint8_t remoteMajor = remoteVersion & PHFRINFC_LLCP_VERSION_MAJOR_MASK; 497 uint8_t remoteMinor = remoteVersion & PHFRINFC_LLCP_VERSION_MINOR_MASK; 498 uint8_t negociatedVersion; 499 500 /* Check for NULL pointers */ 501 if (pNegociatedVersion == NULL) 502 { 503 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 504 } 505 506 /* Compare Major numbers */ 507 if (localMajor == remoteMajor) 508 { 509 /* Version agreement succeed : use lowest version */ 510 negociatedVersion = localMajor | ((remoteMinor<localMinor)?remoteMinor:localMinor); 511 } 512 else if (localMajor > remoteMajor) 513 { 514 /* Decide if versions are compatible */ 515 /* Currently, there is no backward compatibility to handle */ 516 return NFCSTATUS_FAILED; 517 } 518 else /* if (localMajor < remoteMajor) */ 519 { 520 /* It is up to the remote host to decide if versions are compatible */ 521 /* Set negociated version to our local version, the remote will 522 deacivate the link if its own version agreement fails */ 523 negociatedVersion = localVersion; 524 } 525 526 /* Save response */ 527 *pNegociatedVersion = negociatedVersion; 528 529 return NFCSTATUS_SUCCESS; 530 } 531 532 533 static NFCSTATUS phFriNfc_Llcp_InternalActivate( phFriNfc_Llcp_t *Llcp, 534 phNfc_sData_t *psParamsTLV) 535 { 536 NFCSTATUS status; 537 phFriNfc_Llcp_sLinkParameters_t sRemoteParams; 538 uint8_t remoteVersion; 539 uint8_t negociatedVersion; 540 const uint16_t nMaxHeaderSize = PHFRINFC_LLCP_PACKET_HEADER_SIZE + 541 PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE; 542 543 /* Parse parameters */ 544 status = phFriNfc_Llcp_ParseLinkParams(psParamsTLV, &sRemoteParams, &remoteVersion); 545 if (status != NFCSTATUS_SUCCESS) 546 { 547 /* Error: invalid parameters TLV */ 548 status = NFCSTATUS_FAILED; 549 } 550 else 551 { 552 /* Version agreement procedure */ 553 status = phFriNfc_Llcp_VersionAgreement(PHFRINFC_LLCP_VERSION , remoteVersion, &negociatedVersion); 554 if (status != NFCSTATUS_SUCCESS) 555 { 556 /* Error: version agreement failed */ 557 status = NFCSTATUS_FAILED; 558 } 559 else 560 { 561 /* Save parameters */ 562 Llcp->version = negociatedVersion; 563 memcpy(&Llcp->sRemoteParams, &sRemoteParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); 564 565 /* Update remote MIU to match local Tx buffer size */ 566 if (Llcp->nTxBufferLength < (Llcp->sRemoteParams.miu + nMaxHeaderSize)) 567 { 568 Llcp->sRemoteParams.miu = Llcp->nTxBufferLength - nMaxHeaderSize; 569 } 570 571 /* Initiate Symmetry procedure by resetting LTO timer */ 572 /* NOTE: this also updates current state */ 573 phFriNfc_Llcp_ResetLTO(Llcp); 574 } 575 } 576 577 /* Notify upper layer, if Activation failed CB called by Deactivate */ 578 if (status == NFCSTATUS_SUCCESS) 579 { 580 /* Link activated ! */ 581 Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkActivated); 582 } 583 584 return status; 585 } 586 587 588 static NFCSTATUS phFriNfc_Llcp_HandleMACLinkActivated( phFriNfc_Llcp_t *Llcp, 589 phNfc_sData_t *psParamsTLV) 590 { 591 NFCSTATUS status = NFCSTATUS_SUCCESS; 592 593 /* Create the timer */ 594 Llcp->hSymmTimer = phOsalNfc_Timer_Create(); 595 if (Llcp->hSymmTimer == PH_OSALNFC_INVALID_TIMER_ID) 596 { 597 /* Error: unable to create timer */ 598 return NFCSTATUS_INSUFFICIENT_RESOURCES; 599 } 600 601 /* Check if params received from MAC activation procedure */ 602 if (psParamsTLV == NULL) 603 { 604 /* No params with selected MAC mapping, enter PAX mode for parameter exchange */ 605 Llcp->state = PHFRINFC_LLCP_STATE_PAX; 606 /* Set default MIU for PAX exchange */ 607 Llcp->sRemoteParams.miu = PHFRINFC_LLCP_MIU_DEFAULT; 608 /* If the local device is the initiator, it must initiate PAX exchange */ 609 if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeInitiator) 610 { 611 /* Send PAX */ 612 status = phFriNfc_Llcp_SendPax(Llcp, &Llcp->sLocalParams); 613 } 614 } 615 else 616 { 617 /* Params exchanged during MAX activation, try LLC activation */ 618 status = phFriNfc_Llcp_InternalActivate(Llcp, psParamsTLV); 619 } 620 621 if (status == NFCSTATUS_SUCCESS) 622 { 623 /* Start listening for incoming packets */ 624 Llcp->sRxBuffer.length = Llcp->nRxBufferLength; 625 phFriNfc_LlcpMac_Receive(&Llcp->MAC, &Llcp->sRxBuffer, phFriNfc_Llcp_Receive_CB, Llcp); 626 } 627 628 return status; 629 } 630 631 632 static void phFriNfc_Llcp_HandleMACLinkDeactivated( phFriNfc_Llcp_t *Llcp ) 633 { 634 uint8_t state = Llcp->state; 635 636 /* Delete the timer */ 637 if (Llcp->hSymmTimer != PH_OSALNFC_INVALID_TIMER_ID) 638 { 639 phOsalNfc_Timer_Delete(Llcp->hSymmTimer); 640 } 641 642 /* Reset state */ 643 Llcp->state = PHFRINFC_LLCP_STATE_CHECKED; 644 645 switch (state) 646 { 647 case PHFRINFC_LLCP_STATE_DEACTIVATION: 648 { 649 /* The service layer has already been notified, nothing more to do */ 650 break; 651 } 652 default: 653 { 654 /* Notify service layer of link failure */ 655 Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkDeactivated); 656 break; 657 } 658 } 659 } 660 661 662 static void phFriNfc_Llcp_ChkLlcp_CB( void *pContext, 663 NFCSTATUS status ) 664 { 665 /* Get monitor from context */ 666 phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; 667 668 /* Update state */ 669 Llcp->state = PHFRINFC_LLCP_STATE_CHECKED; 670 671 /* Invoke callback */ 672 Llcp->pfChk_CB(Llcp->pChkContext, status); 673 } 674 675 static void phFriNfc_Llcp_LinkStatus_CB( void *pContext, 676 phFriNfc_LlcpMac_eLinkStatus_t eLinkStatus, 677 phNfc_sData_t *psParamsTLV, 678 phFriNfc_LlcpMac_eType_t PeerRemoteDevType) 679 { 680 NFCSTATUS status; 681 682 /* Get monitor from context */ 683 phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; 684 685 /* Save the local peer role (initiator/target) */ 686 Llcp->eRole = PeerRemoteDevType; 687 688 /* Check new link status */ 689 switch(eLinkStatus) 690 { 691 case phFriNfc_LlcpMac_eLinkActivated: 692 { 693 /* Handle MAC link activation */ 694 status = phFriNfc_Llcp_HandleMACLinkActivated(Llcp, psParamsTLV); 695 if (status != NFCSTATUS_SUCCESS) 696 { 697 /* Error: LLC link activation procedure failed, deactivate MAC link */ 698 status = phFriNfc_Llcp_InternalDeactivate(Llcp); 699 } 700 break; 701 } 702 case phFriNfc_LlcpMac_eLinkDeactivated: 703 { 704 /* Handle MAC link deactivation (cannot fail) */ 705 phFriNfc_Llcp_HandleMACLinkDeactivated(Llcp); 706 break; 707 } 708 default: 709 { 710 /* Warning: Unknown link status, should not happen */ 711 } 712 } 713 } 714 715 716 static void phFriNfc_Llcp_ResetLTO( phFriNfc_Llcp_t *Llcp ) 717 { 718 uint32_t nDuration; 719 720 /* Stop timer */ 721 phOsalNfc_Timer_Stop(Llcp->hSymmTimer); 722 723 724 /* Update state */ 725 if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) 726 { 727 Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_SEND; 728 } 729 else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND) 730 { 731 Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_RECV; 732 } 733 else 734 { 735 /* Not yet in OPERATION state, perform first reset */ 736 if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeInitiator) 737 { 738 Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_SEND; 739 } 740 else 741 { 742 Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_RECV; 743 } 744 } 745 746 /* Calculate timer duration */ 747 /* NOTE: nDuration is in 1/100s, and timer system takes values in 1/1000s */ 748 if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) 749 { 750 /* Response must be received before LTO announced by remote peer */ 751 nDuration = Llcp->sRemoteParams.lto * 10; 752 } 753 else 754 { 755 /* Must answer before the local announced LTO */ 756 /* NOTE: to ensure the answer is completely sent before LTO, the 757 timer is triggered _before_ LTO expiration */ 758 /* TODO: make sure time scope is enough, and avoid use of magic number */ 759 nDuration = (Llcp->sLocalParams.lto * 10) / 2; 760 } 761 762 /* Restart timer */ 763 phOsalNfc_Timer_Start( 764 Llcp->hSymmTimer, 765 nDuration, 766 phFriNfc_Llcp_Timer_CB, 767 Llcp); 768 } 769 770 771 static NFCSTATUS phFriNfc_Llcp_HandleLinkPacket( phFriNfc_Llcp_t *Llcp, 772 phNfc_sData_t *psPacket ) 773 { 774 NFCSTATUS result; 775 phFriNfc_Llcp_sPacketHeader_t sHeader; 776 777 /* Parse header */ 778 phFriNfc_Llcp_Buffer2Header(psPacket->buffer, 0, &sHeader); 779 780 /* Check packet type */ 781 switch (sHeader.ptype) 782 { 783 case PHFRINFC_LLCP_PTYPE_SYMM: 784 { 785 /* Nothing to do, the LTO is handled upon all packet reception */ 786 result = NFCSTATUS_SUCCESS; 787 break; 788 } 789 790 case PHFRINFC_LLCP_PTYPE_AGF: 791 { 792 /* Handle the aggregated packet */ 793 result = phFriNfc_Llcp_HandleAggregatedPacket(Llcp, psPacket); 794 if (result != NFCSTATUS_SUCCESS) 795 { 796 /* Error: invalid info field, dropping frame */ 797 } 798 break; 799 } 800 801 case PHFRINFC_LLCP_PTYPE_DISC: 802 { 803 /* Handle link disconnection request */ 804 result = phFriNfc_Llcp_InternalDeactivate(Llcp); 805 break; 806 } 807 808 809 case PHFRINFC_LLCP_PTYPE_FRMR: 810 { 811 /* TODO: what to do upon reception of FRMR on Link SAP ? */ 812 result = NFCSTATUS_SUCCESS; 813 break; 814 } 815 816 case PHFRINFC_LLCP_PTYPE_PAX: 817 { 818 /* Ignore PAX when in Normal Operation */ 819 result = NFCSTATUS_SUCCESS; 820 break; 821 } 822 823 default: 824 { 825 /* Error: invalid ptype field, dropping packet */ 826 break; 827 } 828 } 829 830 return result; 831 } 832 833 834 static NFCSTATUS phFriNfc_Llcp_HandleTransportPacket( phFriNfc_Llcp_t *Llcp, 835 phNfc_sData_t *psPacket ) 836 { 837 phFriNfc_Llcp_Recv_CB_t pfRecvCB; 838 void *pContext; 839 NFCSTATUS result = NFCSTATUS_SUCCESS; 840 phFriNfc_Llcp_sPacketHeader_t sHeader; 841 842 /* Forward to upper layer */ 843 if (Llcp->pfRecvCB != NULL) 844 { 845 /* Get callback details */ 846 pfRecvCB = Llcp->pfRecvCB; 847 pContext = Llcp->pRecvContext; 848 /* Reset callback details */ 849 Llcp->pfRecvCB = NULL; 850 Llcp->pRecvContext = NULL; 851 /* Call the callback */ 852 (pfRecvCB)(pContext, psPacket, NFCSTATUS_SUCCESS); 853 } 854 855 return result; 856 } 857 858 859 static bool_t phFriNfc_Llcp_HandlePendingSend ( phFriNfc_Llcp_t *Llcp ) 860 { 861 phFriNfc_Llcp_sPacketHeader_t sHeader; 862 phNfc_sData_t sInfoBuffer; 863 phFriNfc_Llcp_sPacketHeader_t *psSendHeader = NULL; 864 phFriNfc_Llcp_sPacketSequence_t *psSendSequence = NULL; 865 phNfc_sData_t *psSendInfo = NULL; 866 NFCSTATUS result; 867 uint8_t bDeallocate = FALSE; 868 uint8_t return_value = FALSE; 869 870 /* Handle pending disconnection request */ 871 if (Llcp->bDiscPendingFlag == TRUE) 872 { 873 /* Last send si acheived, send the pending DISC packet */ 874 sHeader.dsap = PHFRINFC_LLCP_SAP_LINK; 875 sHeader.ssap = PHFRINFC_LLCP_SAP_LINK; 876 sHeader.ptype = PHFRINFC_LLCP_PTYPE_DISC; 877 /* Set send params */ 878 psSendHeader = &sHeader; 879 /* Reset flag */ 880 Llcp->bDiscPendingFlag = FALSE; 881 } 882 /* Handle pending frame reject request */ 883 else if (Llcp->bFrmrPendingFlag == TRUE) 884 { 885 /* Last send si acheived, send the pending FRMR packet */ 886 sInfoBuffer.buffer = Llcp->pFrmrInfo; 887 sInfoBuffer.length = sizeof(Llcp->pFrmrInfo); 888 /* Set send params */ 889 psSendHeader = &Llcp->sFrmrHeader; 890 psSendInfo = &sInfoBuffer; 891 /* Reset flag */ 892 Llcp->bFrmrPendingFlag = FALSE; 893 } 894 /* Handle pending service frame */ 895 else if (Llcp->pfSendCB != NULL) 896 { 897 /* Set send params */ 898 psSendHeader = Llcp->psSendHeader; 899 psSendSequence = Llcp->psSendSequence; 900 psSendInfo = Llcp->psSendInfo; 901 /* Reset pending send infos */ 902 Llcp->psSendHeader = NULL; 903 Llcp->psSendSequence = NULL; 904 Llcp->psSendInfo = NULL; 905 bDeallocate = TRUE; 906 } 907 908 /* Perform send, if needed */ 909 if (psSendHeader != NULL) 910 { 911 result = phFriNfc_Llcp_InternalSend(Llcp, psSendHeader, psSendSequence, psSendInfo); 912 if ((result != NFCSTATUS_SUCCESS) && (result != NFCSTATUS_PENDING)) 913 { 914 /* Error: send failed, impossible to recover */ 915 phFriNfc_Llcp_InternalDeactivate(Llcp); 916 } 917 return_value = TRUE; 918 } 919 920 clean_and_return: 921 if (bDeallocate) 922 { 923 phFriNfc_Llcp_Deallocate(psSendInfo); 924 } 925 926 return return_value; 927 } 928 929 static NFCSTATUS phFriNfc_Llcp_HandleIncomingPacket( phFriNfc_Llcp_t *Llcp, 930 phNfc_sData_t *psPacket ) 931 { 932 NFCSTATUS status = NFCSTATUS_SUCCESS; 933 phFriNfc_Llcp_sPacketHeader_t sHeader; 934 935 /* Parse header */ 936 phFriNfc_Llcp_Buffer2Header(psPacket->buffer, 0, &sHeader); 937 938 /* Check destination */ 939 if (sHeader.dsap == PHFRINFC_LLCP_SAP_LINK) 940 { 941 /* Handle packet as destinated to the Link SAP */ 942 status = phFriNfc_Llcp_HandleLinkPacket(Llcp, psPacket); 943 } 944 else if (sHeader.dsap >= PHFRINFC_LLCP_SAP_NUMBER) 945 { 946 /* NOTE: this cannot happen since "psHeader->dsap" is only 6-bit wide */ 947 status = NFCSTATUS_FAILED; 948 } 949 else 950 { 951 /* Handle packet as destinated to the SDP and transport SAPs */ 952 status = phFriNfc_Llcp_HandleTransportPacket(Llcp, psPacket); 953 } 954 return status; 955 } 956 957 958 static void phFriNfc_Llcp_Receive_CB( void *pContext, 959 NFCSTATUS status, 960 phNfc_sData_t *psData) 961 { 962 /* Get monitor from context */ 963 phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; 964 NFCSTATUS result = NFCSTATUS_SUCCESS; 965 phFriNfc_Llcp_sPacketHeader_t sPacketHeader; 966 967 /* Check reception status and for pending disconnection */ 968 if ((status != NFCSTATUS_SUCCESS) || (Llcp->bDiscPendingFlag == TRUE)) 969 { 970 LLCP_DEBUG("\nReceived LLCP packet error - status = 0x%04x", status); 971 /* Reset disconnection operation */ 972 Llcp->bDiscPendingFlag = FALSE; 973 /* Deactivate the link */ 974 phFriNfc_Llcp_InternalDeactivate(Llcp); 975 return; 976 } 977 978 /* Parse header */ 979 phFriNfc_Llcp_Buffer2Header(psData->buffer, 0, &sPacketHeader); 980 981 if (sPacketHeader.ptype != PHFRINFC_LLCP_PTYPE_SYMM) 982 { 983 LLCP_PRINT_BUFFER("\nReceived LLCP packet :", psData->buffer, psData->length); 984 } 985 else 986 { 987 LLCP_PRINT("?"); 988 } 989 990 991 /* Check new link status */ 992 switch(Llcp->state) 993 { 994 /* Handle packets in PAX-waiting state */ 995 case PHFRINFC_LLCP_STATE_PAX: 996 { 997 /* Check packet type */ 998 if (sPacketHeader.ptype == PHFRINFC_LLCP_PTYPE_PAX) 999 { 1000 /* Params exchanged during MAC activation, try LLC activation */ 1001 result = phFriNfc_Llcp_InternalActivate(Llcp, psData+PHFRINFC_LLCP_PACKET_HEADER_SIZE); 1002 /* If the local LLC is the target, it must answer the PAX */ 1003 if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeTarget) 1004 { 1005 /* Send PAX */ 1006 result = phFriNfc_Llcp_SendPax(Llcp, &Llcp->sLocalParams); 1007 } 1008 } 1009 else 1010 { 1011 /* Warning: Received packet with unhandled type in PAX-waiting state, drop it */ 1012 } 1013 break; 1014 } 1015 1016 /* Handle normal operation packets */ 1017 case PHFRINFC_LLCP_STATE_OPERATION_RECV: 1018 case PHFRINFC_LLCP_STATE_OPERATION_SEND: 1019 { 1020 /* Handle Symmetry procedure by resetting LTO timer */ 1021 phFriNfc_Llcp_ResetLTO(Llcp); 1022 /* Handle packet */ 1023 result = phFriNfc_Llcp_HandleIncomingPacket(Llcp, psData); 1024 if ( (result != NFCSTATUS_SUCCESS) && 1025 (result != NFCSTATUS_PENDING) ) 1026 { 1027 /* TODO: Error: invalid frame */ 1028 } 1029 /* Perform pending send request, if any */ 1030 phFriNfc_Llcp_HandlePendingSend(Llcp); 1031 break; 1032 } 1033 1034 default: 1035 { 1036 /* Warning: Should not receive packets in other states, drop them */ 1037 } 1038 } 1039 1040 /* Restart reception */ 1041 Llcp->sRxBuffer.length = Llcp->nRxBufferLength; 1042 phFriNfc_LlcpMac_Receive(&Llcp->MAC, &Llcp->sRxBuffer, phFriNfc_Llcp_Receive_CB, Llcp); 1043 } 1044 1045 1046 static void phFriNfc_Llcp_Send_CB( void *pContext, 1047 NFCSTATUS status ) 1048 { 1049 /* Get monitor from context */ 1050 phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; 1051 phFriNfc_Llcp_Send_CB_t pfSendCB; 1052 void *pSendContext; 1053 1054 /* Call the upper layer callback if last packet sent was */ 1055 /* NOTE: if Llcp->psSendHeader is not NULL, this means that the send operation is still not initiated */ 1056 if (Llcp->psSendHeader == NULL) 1057 { 1058 if (Llcp->pfSendCB != NULL) 1059 { 1060 /* Get Callback params */ 1061 pfSendCB = Llcp->pfSendCB; 1062 pSendContext = Llcp->pSendContext; 1063 /* Reset callback params */ 1064 Llcp->pfSendCB = NULL; 1065 Llcp->pSendContext = NULL; 1066 /* Call the callback */ 1067 (pfSendCB)(pSendContext, status); 1068 } 1069 } 1070 1071 /* Check reception status */ 1072 if (status != NFCSTATUS_SUCCESS) 1073 { 1074 /* Error: Reception failed, link must be down */ 1075 phFriNfc_Llcp_InternalDeactivate(Llcp); 1076 } 1077 } 1078 1079 1080 static NFCSTATUS phFriNfc_Llcp_InternalSend( phFriNfc_Llcp_t *Llcp, 1081 phFriNfc_Llcp_sPacketHeader_t *psHeader, 1082 phFriNfc_Llcp_sPacketSequence_t *psSequence, 1083 phNfc_sData_t *psInfo ) 1084 { 1085 NFCSTATUS status; 1086 phNfc_sData_t *psRawPacket = &Llcp->sTxBuffer; /* Use internal Tx buffer */ 1087 1088 /* Handle Symmetry procedure */ 1089 phFriNfc_Llcp_ResetLTO(Llcp); 1090 1091 /* Generate raw packet to send (aggregate header + sequence + info fields) */ 1092 psRawPacket->length = 0; 1093 psRawPacket->length += phFriNfc_Llcp_Header2Buffer(psHeader, psRawPacket->buffer, psRawPacket->length); 1094 if (psSequence != NULL) 1095 { 1096 psRawPacket->length += phFriNfc_Llcp_Sequence2Buffer(psSequence, psRawPacket->buffer, psRawPacket->length); 1097 } 1098 if (psInfo != NULL) 1099 { 1100 memcpy(psRawPacket->buffer + psRawPacket->length, psInfo->buffer, psInfo->length); 1101 psRawPacket->length += psInfo->length; 1102 } 1103 1104 if (psHeader->ptype != PHFRINFC_LLCP_PTYPE_SYMM) 1105 { 1106 LLCP_PRINT_BUFFER("\nSending LLCP packet :", psRawPacket->buffer, psRawPacket->length); 1107 } 1108 else 1109 { 1110 LLCP_PRINT("!"); 1111 } 1112 1113 /* Send raw packet */ 1114 status = phFriNfc_LlcpMac_Send ( 1115 &Llcp->MAC, 1116 psRawPacket, 1117 phFriNfc_Llcp_Send_CB, 1118 Llcp ); 1119 1120 return status; 1121 } 1122 1123 /* ---------------------------- Public functions ------------------------------- */ 1124 1125 NFCSTATUS phFriNfc_Llcp_EncodeLinkParams( phNfc_sData_t *psRawBuffer, 1126 phFriNfc_Llcp_sLinkParameters_t *psLinkParams, 1127 uint8_t nVersion ) 1128 { 1129 uint32_t nOffset = 0; 1130 uint16_t miux; 1131 uint16_t wks; 1132 uint8_t pValue[2]; 1133 NFCSTATUS result = NFCSTATUS_SUCCESS; 1134 1135 /* Check parameters */ 1136 if ((psRawBuffer == NULL) || (psLinkParams == NULL)) 1137 { 1138 return NFCSTATUS_INVALID_PARAMETER; 1139 } 1140 1141 /* Encode mandatory VERSION field */ 1142 if (result == NFCSTATUS_SUCCESS) 1143 { 1144 result = phFriNfc_Llcp_EncodeTLV( 1145 psRawBuffer, 1146 &nOffset, 1147 PHFRINFC_LLCP_TLV_TYPE_VERSION, 1148 PHFRINFC_LLCP_TLV_LENGTH_VERSION, 1149 &nVersion); 1150 } 1151 1152 /* Encode mandatory VERSION field */ 1153 if (result == NFCSTATUS_SUCCESS) 1154 { 1155 /* Encode MIUX field, if needed */ 1156 if (psLinkParams->miu != PHFRINFC_LLCP_MIU_DEFAULT) 1157 { 1158 miux = (psLinkParams->miu - PHFRINFC_LLCP_MIU_DEFAULT) & PHFRINFC_LLCP_TLV_MIUX_MASK; 1159 pValue[0] = (miux >> 8) & 0xFF; 1160 pValue[1] = miux & 0xFF; 1161 result = phFriNfc_Llcp_EncodeTLV( 1162 psRawBuffer, 1163 &nOffset, 1164 PHFRINFC_LLCP_TLV_TYPE_MIUX, 1165 PHFRINFC_LLCP_TLV_LENGTH_MIUX, 1166 pValue); 1167 } 1168 } 1169 1170 /* Encode WKS field */ 1171 if (result == NFCSTATUS_SUCCESS) 1172 { 1173 wks = psLinkParams->wks | PHFRINFC_LLCP_TLV_WKS_MASK; 1174 pValue[0] = (wks >> 8) & 0xFF; 1175 pValue[1] = wks & 0xFF; 1176 result = phFriNfc_Llcp_EncodeTLV( 1177 psRawBuffer, 1178 &nOffset, 1179 PHFRINFC_LLCP_TLV_TYPE_WKS, 1180 PHFRINFC_LLCP_TLV_LENGTH_WKS, 1181 pValue); 1182 } 1183 1184 /* Encode LTO field, if needed */ 1185 if (result == NFCSTATUS_SUCCESS) 1186 { 1187 if (psLinkParams->lto != PHFRINFC_LLCP_LTO_DEFAULT) 1188 { 1189 result = phFriNfc_Llcp_EncodeTLV( 1190 psRawBuffer, 1191 &nOffset, 1192 PHFRINFC_LLCP_TLV_TYPE_LTO, 1193 PHFRINFC_LLCP_TLV_LENGTH_LTO, 1194 &psLinkParams->lto); 1195 } 1196 } 1197 1198 /* Encode OPT field, if needed */ 1199 if (result == NFCSTATUS_SUCCESS) 1200 { 1201 if (psLinkParams->option != PHFRINFC_LLCP_OPTION_DEFAULT) 1202 { 1203 result = phFriNfc_Llcp_EncodeTLV( 1204 psRawBuffer, 1205 &nOffset, 1206 PHFRINFC_LLCP_TLV_TYPE_OPT, 1207 PHFRINFC_LLCP_TLV_LENGTH_OPT, 1208 &psLinkParams->option); 1209 } 1210 } 1211 1212 if (result != NFCSTATUS_SUCCESS) 1213 { 1214 /* Error: failed to encode TLV */ 1215 return NFCSTATUS_FAILED; 1216 } 1217 1218 /* Save new buffer size */ 1219 psRawBuffer->length = nOffset; 1220 1221 return result; 1222 } 1223 1224 1225 NFCSTATUS phFriNfc_Llcp_Reset( phFriNfc_Llcp_t *Llcp, 1226 void *LowerDevice, 1227 phFriNfc_Llcp_sLinkParameters_t *psLinkParams, 1228 void *pRxBuffer, 1229 uint16_t nRxBufferLength, 1230 void *pTxBuffer, 1231 uint16_t nTxBufferLength, 1232 phFriNfc_Llcp_LinkStatus_CB_t pfLink_CB, 1233 void *pContext ) 1234 { 1235 const uint16_t nMaxHeaderSize = PHFRINFC_LLCP_PACKET_HEADER_SIZE + 1236 PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE; 1237 NFCSTATUS result; 1238 1239 /* Check parameters presence */ 1240 if ((Llcp == NULL) || (LowerDevice == NULL) || (pfLink_CB == NULL) || 1241 (pRxBuffer == NULL) || (pTxBuffer == NULL) ) 1242 { 1243 return NFCSTATUS_INVALID_PARAMETER; 1244 } 1245 1246 /* Check parameters value */ 1247 if (psLinkParams->miu < PHFRINFC_LLCP_MIU_DEFAULT) 1248 { 1249 return NFCSTATUS_INVALID_PARAMETER; 1250 } 1251 1252 /* Check if buffers are large enough to support minimal MIU */ 1253 if ((nRxBufferLength < (nMaxHeaderSize + PHFRINFC_LLCP_MIU_DEFAULT)) || 1254 (nTxBufferLength < (nMaxHeaderSize + PHFRINFC_LLCP_MIU_DEFAULT)) ) 1255 { 1256 return NFCSTATUS_BUFFER_TOO_SMALL; 1257 } 1258 1259 /* Check compatibility between reception buffer size and announced MIU */ 1260 if (nRxBufferLength < (nMaxHeaderSize + psLinkParams->miu)) 1261 { 1262 return NFCSTATUS_BUFFER_TOO_SMALL; 1263 } 1264 1265 /* Start with a zero-filled monitor */ 1266 memset(Llcp, 0x00, sizeof(phFriNfc_Llcp_t)); 1267 1268 /* Reset the MAC Mapping layer */ 1269 result = phFriNfc_LlcpMac_Reset(&Llcp->MAC, LowerDevice, phFriNfc_Llcp_LinkStatus_CB, Llcp); 1270 if (result != NFCSTATUS_SUCCESS) { 1271 return result; 1272 } 1273 1274 /* Save the working buffers */ 1275 Llcp->sRxBuffer.buffer = pRxBuffer; 1276 Llcp->sRxBuffer.length = nRxBufferLength; 1277 Llcp->nRxBufferLength = nRxBufferLength; 1278 Llcp->sTxBuffer.buffer = pTxBuffer; 1279 Llcp->sTxBuffer.length = nTxBufferLength; 1280 Llcp->nTxBufferLength = nTxBufferLength; 1281 1282 /* Save the link status callback references */ 1283 Llcp->pfLink_CB = pfLink_CB; 1284 Llcp->pLinkContext = pContext; 1285 1286 /* Save the local link parameters */ 1287 memcpy(&Llcp->sLocalParams, psLinkParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); 1288 1289 return NFCSTATUS_SUCCESS; 1290 } 1291 1292 1293 NFCSTATUS phFriNfc_Llcp_ChkLlcp( phFriNfc_Llcp_t *Llcp, 1294 phHal_sRemoteDevInformation_t *psRemoteDevInfo, 1295 phFriNfc_Llcp_Check_CB_t pfCheck_CB, 1296 void *pContext ) 1297 { 1298 /* Check parameters */ 1299 if ( (Llcp == NULL) || (psRemoteDevInfo == NULL) || (pfCheck_CB == NULL) ) 1300 { 1301 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 1302 } 1303 1304 /* Check current state */ 1305 if( Llcp->state != PHFRINFC_LLCP_STATE_RESET_INIT ) { 1306 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE); 1307 } 1308 1309 /* Save the compliance check callback */ 1310 Llcp->pfChk_CB = pfCheck_CB; 1311 Llcp->pChkContext = pContext; 1312 1313 /* Forward check request to MAC layer */ 1314 return phFriNfc_LlcpMac_ChkLlcp(&Llcp->MAC, psRemoteDevInfo, phFriNfc_Llcp_ChkLlcp_CB, (void*)Llcp); 1315 } 1316 1317 1318 NFCSTATUS phFriNfc_Llcp_Activate( phFriNfc_Llcp_t *Llcp ) 1319 { 1320 /* Check parameters */ 1321 if (Llcp == NULL) 1322 { 1323 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 1324 } 1325 1326 /* Check current state */ 1327 if( Llcp->state != PHFRINFC_LLCP_STATE_CHECKED ) { 1328 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE); 1329 } 1330 1331 /* Update state */ 1332 Llcp->state = PHFRINFC_LLCP_STATE_ACTIVATION; 1333 1334 /* Forward check request to MAC layer */ 1335 return phFriNfc_LlcpMac_Activate(&Llcp->MAC); 1336 } 1337 1338 1339 NFCSTATUS phFriNfc_Llcp_Deactivate( phFriNfc_Llcp_t *Llcp ) 1340 { 1341 NFCSTATUS status; 1342 1343 /* Check parameters */ 1344 if (Llcp == NULL) 1345 { 1346 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 1347 } 1348 1349 /* Check current state */ 1350 if( (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_RECV) && 1351 (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND) ) { 1352 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE); 1353 } 1354 1355 /* Send DISC packet */ 1356 status = phFriNfc_Llcp_SendDisconnect(Llcp); 1357 if (status == NFCSTATUS_PENDING) 1358 { 1359 /* Wait for packet to be sent before deactivate link */ 1360 return status; 1361 } 1362 1363 /* Perform actual deactivation */ 1364 return phFriNfc_Llcp_InternalDeactivate(Llcp); 1365 } 1366 1367 1368 NFCSTATUS phFriNfc_Llcp_GetLocalInfo( phFriNfc_Llcp_t *Llcp, 1369 phFriNfc_Llcp_sLinkParameters_t *pParams ) 1370 { 1371 /* Check parameters */ 1372 if ((Llcp == NULL) || (pParams == NULL)) 1373 { 1374 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 1375 } 1376 1377 /* Copy response */ 1378 memcpy(pParams, &Llcp->sLocalParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); 1379 1380 return NFCSTATUS_SUCCESS; 1381 } 1382 1383 1384 NFCSTATUS phFriNfc_Llcp_GetRemoteInfo( phFriNfc_Llcp_t *Llcp, 1385 phFriNfc_Llcp_sLinkParameters_t *pParams ) 1386 { 1387 /* Check parameters */ 1388 if ((Llcp == NULL) || (pParams == NULL)) 1389 { 1390 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 1391 } 1392 1393 /* Copy response */ 1394 memcpy(pParams, &Llcp->sRemoteParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); 1395 1396 return NFCSTATUS_SUCCESS; 1397 } 1398 1399 1400 NFCSTATUS phFriNfc_Llcp_Send( phFriNfc_Llcp_t *Llcp, 1401 phFriNfc_Llcp_sPacketHeader_t *psHeader, 1402 phFriNfc_Llcp_sPacketSequence_t *psSequence, 1403 phNfc_sData_t *psInfo, 1404 phFriNfc_Llcp_Send_CB_t pfSend_CB, 1405 void *pContext ) 1406 { 1407 NFCSTATUS result; 1408 1409 /* Check parameters */ 1410 if ((Llcp == NULL) || (psHeader == NULL) || (pfSend_CB == NULL)) 1411 { 1412 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 1413 } 1414 1415 /* Check if previous phFriNfc_Llcp_Send() has finished */ 1416 if (Llcp->pfSendCB != NULL) 1417 { 1418 /* Error: a send operation is already running */ 1419 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_REJECTED); 1420 } 1421 1422 /* Save the callback parameters */ 1423 Llcp->pfSendCB = pfSend_CB; 1424 Llcp->pSendContext = pContext; 1425 1426 if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND) 1427 { 1428 /* Ready to send */ 1429 result = phFriNfc_Llcp_InternalSend(Llcp, psHeader, psSequence, psInfo); 1430 } 1431 else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) 1432 { 1433 /* Not ready to send, save send params for later use */ 1434 Llcp->psSendHeader = psHeader; 1435 Llcp->psSendSequence = psSequence; 1436 Llcp->psSendInfo = phFriNfc_Llcp_AllocateAndCopy(psInfo); 1437 result = NFCSTATUS_PENDING; 1438 } 1439 else 1440 { 1441 /* Incorrect state for sending ! */ 1442 result = PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);; 1443 } 1444 return result; 1445 } 1446 1447 1448 NFCSTATUS phFriNfc_Llcp_Recv( phFriNfc_Llcp_t *Llcp, 1449 phFriNfc_Llcp_Recv_CB_t pfRecv_CB, 1450 void *pContext ) 1451 { 1452 NFCSTATUS result = NFCSTATUS_SUCCESS; 1453 1454 /* Check parameters */ 1455 if ((Llcp == NULL) || (pfRecv_CB == NULL)) 1456 { 1457 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 1458 } 1459 1460 /* Check if previous phFriNfc_Llcp_Recv() has finished */ 1461 if (Llcp->pfRecvCB != NULL) 1462 { 1463 /* Error: a send operation is already running */ 1464 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_REJECTED); 1465 } 1466 1467 /* Save the callback parameters */ 1468 Llcp->pfRecvCB = pfRecv_CB; 1469 Llcp->pRecvContext = pContext; 1470 1471 /* NOTE: nothing more to do, the receive function is called in background */ 1472 1473 return result; 1474 } 1475