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