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_CHECKED; 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 721 { 722 /* Not yet in OPERATION state, perform first reset */ 723 if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeInitiator) 724 { 725 Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_SEND; 726 } 727 else 728 { 729 Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_RECV; 730 } 731 } 732 733 /* Calculate timer duration */ 734 /* NOTE: nDuration is in 1/100s, and timer system takes values in 1/1000s */ 735 if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) 736 { 737 /* Response must be received before LTO announced by remote peer */ 738 nDuration = Llcp->sRemoteParams.lto * 10; 739 } 740 else 741 { 742 /* Must answer before the local announced LTO */ 743 /* NOTE: to ensure the answer is completely sent before LTO, the 744 timer is triggered _before_ LTO expiration */ 745 /* TODO: make sure time scope is enough, and avoid use of magic number */ 746 nDuration = (Llcp->sLocalParams.lto * 10) / 2; 747 } 748 749 LLCP_DEBUG("Starting LLCP timer with duration %d", nDuration); 750 751 /* Restart timer */ 752 phOsalNfc_Timer_Start( 753 Llcp->hSymmTimer, 754 nDuration, 755 phFriNfc_Llcp_Timer_CB, 756 Llcp); 757 } 758 759 760 static NFCSTATUS phFriNfc_Llcp_HandleLinkPacket( phFriNfc_Llcp_t *Llcp, 761 phNfc_sData_t *psPacket ) 762 { 763 NFCSTATUS result; 764 phFriNfc_Llcp_sPacketHeader_t sHeader; 765 766 /* Parse header */ 767 phFriNfc_Llcp_Buffer2Header(psPacket->buffer, 0, &sHeader); 768 769 /* Check packet type */ 770 switch (sHeader.ptype) 771 { 772 case PHFRINFC_LLCP_PTYPE_SYMM: 773 { 774 /* Nothing to do, the LTO is handled upon all packet reception */ 775 result = NFCSTATUS_SUCCESS; 776 break; 777 } 778 779 case PHFRINFC_LLCP_PTYPE_AGF: 780 { 781 /* Handle the aggregated packet */ 782 result = phFriNfc_Llcp_HandleAggregatedPacket(Llcp, psPacket); 783 if (result != NFCSTATUS_SUCCESS) 784 { 785 /* Error: invalid info field, dropping frame */ 786 } 787 break; 788 } 789 790 case PHFRINFC_LLCP_PTYPE_DISC: 791 { 792 /* Handle link disconnection request */ 793 result = phFriNfc_Llcp_InternalDeactivate(Llcp); 794 break; 795 } 796 797 798 case PHFRINFC_LLCP_PTYPE_FRMR: 799 { 800 /* TODO: what to do upon reception of FRMR on Link SAP ? */ 801 result = NFCSTATUS_SUCCESS; 802 break; 803 } 804 805 case PHFRINFC_LLCP_PTYPE_PAX: 806 { 807 /* Ignore PAX when in Normal Operation */ 808 result = NFCSTATUS_SUCCESS; 809 break; 810 } 811 812 default: 813 { 814 /* Error: invalid ptype field, dropping packet */ 815 break; 816 } 817 } 818 819 return result; 820 } 821 822 823 static NFCSTATUS phFriNfc_Llcp_HandleTransportPacket( phFriNfc_Llcp_t *Llcp, 824 phNfc_sData_t *psPacket ) 825 { 826 phFriNfc_Llcp_Recv_CB_t pfRecvCB; 827 void *pContext; 828 NFCSTATUS result = NFCSTATUS_SUCCESS; 829 phFriNfc_Llcp_sPacketHeader_t sHeader; 830 831 /* Forward to upper layer */ 832 if (Llcp->pfRecvCB != NULL) 833 { 834 /* Get callback details */ 835 pfRecvCB = Llcp->pfRecvCB; 836 pContext = Llcp->pRecvContext; 837 /* Reset callback details */ 838 Llcp->pfRecvCB = NULL; 839 Llcp->pRecvContext = NULL; 840 /* Call the callback */ 841 (pfRecvCB)(pContext, psPacket, NFCSTATUS_SUCCESS); 842 } 843 844 return result; 845 } 846 847 848 static bool_t phFriNfc_Llcp_HandlePendingSend ( phFriNfc_Llcp_t *Llcp ) 849 { 850 phFriNfc_Llcp_sPacketHeader_t sHeader; 851 phNfc_sData_t sInfoBuffer; 852 phFriNfc_Llcp_sPacketHeader_t *psSendHeader = NULL; 853 phFriNfc_Llcp_sPacketSequence_t *psSendSequence = NULL; 854 phNfc_sData_t *psSendInfo = NULL; 855 NFCSTATUS result; 856 uint8_t bDeallocate = FALSE; 857 uint8_t return_value = FALSE; 858 859 /* Handle pending disconnection request */ 860 if (Llcp->bDiscPendingFlag == TRUE) 861 { 862 /* Last send si acheived, send the pending DISC packet */ 863 sHeader.dsap = PHFRINFC_LLCP_SAP_LINK; 864 sHeader.ssap = PHFRINFC_LLCP_SAP_LINK; 865 sHeader.ptype = PHFRINFC_LLCP_PTYPE_DISC; 866 /* Set send params */ 867 psSendHeader = &sHeader; 868 /* Reset flag */ 869 Llcp->bDiscPendingFlag = FALSE; 870 } 871 /* Handle pending frame reject request */ 872 else if (Llcp->bFrmrPendingFlag == TRUE) 873 { 874 /* Last send si acheived, send the pending FRMR packet */ 875 sInfoBuffer.buffer = Llcp->pFrmrInfo; 876 sInfoBuffer.length = sizeof(Llcp->pFrmrInfo); 877 /* Set send params */ 878 psSendHeader = &Llcp->sFrmrHeader; 879 psSendInfo = &sInfoBuffer; 880 /* Reset flag */ 881 Llcp->bFrmrPendingFlag = FALSE; 882 } 883 /* Handle pending service frame */ 884 else if (Llcp->pfSendCB != NULL) 885 { 886 /* Set send params */ 887 psSendHeader = Llcp->psSendHeader; 888 psSendSequence = Llcp->psSendSequence; 889 psSendInfo = Llcp->psSendInfo; 890 /* Reset pending send infos */ 891 Llcp->psSendHeader = NULL; 892 Llcp->psSendSequence = NULL; 893 Llcp->psSendInfo = NULL; 894 bDeallocate = TRUE; 895 } 896 897 /* Perform send, if needed */ 898 if (psSendHeader != NULL) 899 { 900 result = phFriNfc_Llcp_InternalSend(Llcp, psSendHeader, psSendSequence, psSendInfo); 901 if ((result != NFCSTATUS_SUCCESS) && (result != NFCSTATUS_PENDING)) 902 { 903 /* Error: send failed, impossible to recover */ 904 phFriNfc_Llcp_InternalDeactivate(Llcp); 905 } 906 return_value = TRUE; 907 } else if (Llcp->pfSendCB == NULL) { 908 // Nothing to send, send SYMM instead to allow peer to send something 909 // if it wants. 910 phFriNfc_Llcp_SendSymm(Llcp); 911 return_value = TRUE; 912 } 913 914 clean_and_return: 915 if (bDeallocate) 916 { 917 phFriNfc_Llcp_Deallocate(psSendInfo); 918 } 919 920 return return_value; 921 } 922 923 static NFCSTATUS phFriNfc_Llcp_HandleIncomingPacket( phFriNfc_Llcp_t *Llcp, 924 phNfc_sData_t *psPacket ) 925 { 926 NFCSTATUS status = NFCSTATUS_SUCCESS; 927 phFriNfc_Llcp_sPacketHeader_t sHeader; 928 929 /* Parse header */ 930 phFriNfc_Llcp_Buffer2Header(psPacket->buffer, 0, &sHeader); 931 932 /* Check destination */ 933 if (sHeader.dsap == PHFRINFC_LLCP_SAP_LINK) 934 { 935 /* Handle packet as destinated to the Link SAP */ 936 status = phFriNfc_Llcp_HandleLinkPacket(Llcp, psPacket); 937 } 938 else if (sHeader.dsap >= PHFRINFC_LLCP_SAP_NUMBER) 939 { 940 /* NOTE: this cannot happen since "psHeader->dsap" is only 6-bit wide */ 941 status = NFCSTATUS_FAILED; 942 } 943 else 944 { 945 /* Handle packet as destinated to the SDP and transport SAPs */ 946 status = phFriNfc_Llcp_HandleTransportPacket(Llcp, psPacket); 947 } 948 return status; 949 } 950 951 952 static void phFriNfc_Llcp_Receive_CB( void *pContext, 953 NFCSTATUS status, 954 phNfc_sData_t *psData) 955 { 956 /* Get monitor from context */ 957 phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; 958 NFCSTATUS result = NFCSTATUS_SUCCESS; 959 phFriNfc_Llcp_sPacketHeader_t sPacketHeader; 960 961 /* Check reception status and for pending disconnection */ 962 if ((status != NFCSTATUS_SUCCESS) || (Llcp->bDiscPendingFlag == TRUE)) 963 { 964 LLCP_DEBUG("\nReceived LLCP packet error - status = 0x%04x", status); 965 /* Reset disconnection operation */ 966 Llcp->bDiscPendingFlag = FALSE; 967 /* Deactivate the link */ 968 phFriNfc_Llcp_InternalDeactivate(Llcp); 969 return; 970 } 971 972 /* Parse header */ 973 phFriNfc_Llcp_Buffer2Header(psData->buffer, 0, &sPacketHeader); 974 975 if (sPacketHeader.ptype != PHFRINFC_LLCP_PTYPE_SYMM) 976 { 977 LLCP_PRINT_BUFFER("\nReceived LLCP packet :", psData->buffer, psData->length); 978 } 979 else 980 { 981 LLCP_PRINT("?"); 982 } 983 984 985 /* Check new link status */ 986 switch(Llcp->state) 987 { 988 /* Handle packets in PAX-waiting state */ 989 case PHFRINFC_LLCP_STATE_PAX: 990 { 991 /* Check packet type */ 992 if (sPacketHeader.ptype == PHFRINFC_LLCP_PTYPE_PAX) 993 { 994 /* Params exchanged during MAC activation, try LLC activation */ 995 result = phFriNfc_Llcp_InternalActivate(Llcp, psData+PHFRINFC_LLCP_PACKET_HEADER_SIZE); 996 /* If the local LLC is the target, it must answer the PAX */ 997 if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeTarget) 998 { 999 /* Send PAX */ 1000 result = phFriNfc_Llcp_SendPax(Llcp, &Llcp->sLocalParams); 1001 } 1002 } 1003 else 1004 { 1005 /* Warning: Received packet with unhandled type in PAX-waiting state, drop it */ 1006 } 1007 break; 1008 } 1009 1010 /* Handle normal operation packets */ 1011 case PHFRINFC_LLCP_STATE_OPERATION_RECV: 1012 case PHFRINFC_LLCP_STATE_OPERATION_SEND: 1013 { 1014 /* Handle Symmetry procedure by resetting LTO timer */ 1015 phFriNfc_Llcp_ResetLTO(Llcp); 1016 /* Handle packet */ 1017 result = phFriNfc_Llcp_HandleIncomingPacket(Llcp, psData); 1018 if ( (result != NFCSTATUS_SUCCESS) && 1019 (result != NFCSTATUS_PENDING) ) 1020 { 1021 /* TODO: Error: invalid frame */ 1022 } 1023 /* Perform pending send request, if any */ 1024 phFriNfc_Llcp_HandlePendingSend(Llcp); 1025 break; 1026 } 1027 1028 default: 1029 { 1030 /* Warning: Should not receive packets in other states, drop them */ 1031 } 1032 } 1033 1034 /* Restart reception */ 1035 Llcp->sRxBuffer.length = Llcp->nRxBufferLength; 1036 phFriNfc_LlcpMac_Receive(&Llcp->MAC, &Llcp->sRxBuffer, phFriNfc_Llcp_Receive_CB, Llcp); 1037 } 1038 1039 1040 static void phFriNfc_Llcp_Send_CB( void *pContext, 1041 NFCSTATUS status ) 1042 { 1043 /* Get monitor from context */ 1044 phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; 1045 phFriNfc_Llcp_Send_CB_t pfSendCB; 1046 void *pSendContext; 1047 1048 /* Call the upper layer callback if last packet sent was */ 1049 /* NOTE: if Llcp->psSendHeader is not NULL, this means that the send operation is still not initiated */ 1050 if (Llcp->psSendHeader == NULL) 1051 { 1052 if (Llcp->pfSendCB != NULL) 1053 { 1054 /* Get Callback params */ 1055 pfSendCB = Llcp->pfSendCB; 1056 pSendContext = Llcp->pSendContext; 1057 /* Reset callback params */ 1058 Llcp->pfSendCB = NULL; 1059 Llcp->pSendContext = NULL; 1060 /* Call the callback */ 1061 (pfSendCB)(pSendContext, status); 1062 } 1063 } 1064 1065 /* Check reception status */ 1066 if (status != NFCSTATUS_SUCCESS) 1067 { 1068 /* Error: Reception failed, link must be down */ 1069 phFriNfc_Llcp_InternalDeactivate(Llcp); 1070 } 1071 } 1072 1073 1074 static NFCSTATUS phFriNfc_Llcp_InternalSend( phFriNfc_Llcp_t *Llcp, 1075 phFriNfc_Llcp_sPacketHeader_t *psHeader, 1076 phFriNfc_Llcp_sPacketSequence_t *psSequence, 1077 phNfc_sData_t *psInfo ) 1078 { 1079 NFCSTATUS status; 1080 phNfc_sData_t *psRawPacket = &Llcp->sTxBuffer; /* Use internal Tx buffer */ 1081 1082 /* Handle Symmetry procedure */ 1083 phFriNfc_Llcp_ResetLTO(Llcp); 1084 1085 /* Generate raw packet to send (aggregate header + sequence + info fields) */ 1086 psRawPacket->length = 0; 1087 psRawPacket->length += phFriNfc_Llcp_Header2Buffer(psHeader, psRawPacket->buffer, psRawPacket->length); 1088 if (psSequence != NULL) 1089 { 1090 psRawPacket->length += phFriNfc_Llcp_Sequence2Buffer(psSequence, psRawPacket->buffer, psRawPacket->length); 1091 } 1092 if (psInfo != NULL) 1093 { 1094 memcpy(psRawPacket->buffer + psRawPacket->length, psInfo->buffer, psInfo->length); 1095 psRawPacket->length += psInfo->length; 1096 } 1097 1098 if (psHeader->ptype != PHFRINFC_LLCP_PTYPE_SYMM) 1099 { 1100 LLCP_PRINT_BUFFER("\nSending LLCP packet :", psRawPacket->buffer, psRawPacket->length); 1101 } 1102 else 1103 { 1104 LLCP_PRINT("!"); 1105 } 1106 1107 /* Send raw packet */ 1108 status = phFriNfc_LlcpMac_Send ( 1109 &Llcp->MAC, 1110 psRawPacket, 1111 phFriNfc_Llcp_Send_CB, 1112 Llcp ); 1113 1114 return status; 1115 } 1116 1117 /* ---------------------------- Public functions ------------------------------- */ 1118 1119 NFCSTATUS phFriNfc_Llcp_EncodeLinkParams( phNfc_sData_t *psRawBuffer, 1120 phFriNfc_Llcp_sLinkParameters_t *psLinkParams, 1121 uint8_t nVersion ) 1122 { 1123 uint32_t nOffset = 0; 1124 uint16_t miux; 1125 uint16_t wks; 1126 uint8_t pValue[2]; 1127 NFCSTATUS result = NFCSTATUS_SUCCESS; 1128 1129 /* Check parameters */ 1130 if ((psRawBuffer == NULL) || (psLinkParams == NULL)) 1131 { 1132 return NFCSTATUS_INVALID_PARAMETER; 1133 } 1134 1135 /* Encode mandatory VERSION field */ 1136 if (result == NFCSTATUS_SUCCESS) 1137 { 1138 result = phFriNfc_Llcp_EncodeTLV( 1139 psRawBuffer, 1140 &nOffset, 1141 PHFRINFC_LLCP_TLV_TYPE_VERSION, 1142 PHFRINFC_LLCP_TLV_LENGTH_VERSION, 1143 &nVersion); 1144 } 1145 1146 /* Encode mandatory VERSION field */ 1147 if (result == NFCSTATUS_SUCCESS) 1148 { 1149 /* Encode MIUX field, if needed */ 1150 if (psLinkParams->miu != PHFRINFC_LLCP_MIU_DEFAULT) 1151 { 1152 miux = (psLinkParams->miu - PHFRINFC_LLCP_MIU_DEFAULT) & PHFRINFC_LLCP_TLV_MIUX_MASK; 1153 pValue[0] = (miux >> 8) & 0xFF; 1154 pValue[1] = miux & 0xFF; 1155 result = phFriNfc_Llcp_EncodeTLV( 1156 psRawBuffer, 1157 &nOffset, 1158 PHFRINFC_LLCP_TLV_TYPE_MIUX, 1159 PHFRINFC_LLCP_TLV_LENGTH_MIUX, 1160 pValue); 1161 } 1162 } 1163 1164 /* Encode WKS field */ 1165 if (result == NFCSTATUS_SUCCESS) 1166 { 1167 wks = psLinkParams->wks | PHFRINFC_LLCP_TLV_WKS_MASK; 1168 pValue[0] = (wks >> 8) & 0xFF; 1169 pValue[1] = wks & 0xFF; 1170 result = phFriNfc_Llcp_EncodeTLV( 1171 psRawBuffer, 1172 &nOffset, 1173 PHFRINFC_LLCP_TLV_TYPE_WKS, 1174 PHFRINFC_LLCP_TLV_LENGTH_WKS, 1175 pValue); 1176 } 1177 1178 /* Encode LTO field, if needed */ 1179 if (result == NFCSTATUS_SUCCESS) 1180 { 1181 if (psLinkParams->lto != PHFRINFC_LLCP_LTO_DEFAULT) 1182 { 1183 result = phFriNfc_Llcp_EncodeTLV( 1184 psRawBuffer, 1185 &nOffset, 1186 PHFRINFC_LLCP_TLV_TYPE_LTO, 1187 PHFRINFC_LLCP_TLV_LENGTH_LTO, 1188 &psLinkParams->lto); 1189 } 1190 } 1191 1192 /* Encode OPT field, if needed */ 1193 if (result == NFCSTATUS_SUCCESS) 1194 { 1195 if (psLinkParams->option != PHFRINFC_LLCP_OPTION_DEFAULT) 1196 { 1197 result = phFriNfc_Llcp_EncodeTLV( 1198 psRawBuffer, 1199 &nOffset, 1200 PHFRINFC_LLCP_TLV_TYPE_OPT, 1201 PHFRINFC_LLCP_TLV_LENGTH_OPT, 1202 &psLinkParams->option); 1203 } 1204 } 1205 1206 if (result != NFCSTATUS_SUCCESS) 1207 { 1208 /* Error: failed to encode TLV */ 1209 return NFCSTATUS_FAILED; 1210 } 1211 1212 /* Save new buffer size */ 1213 psRawBuffer->length = nOffset; 1214 1215 return result; 1216 } 1217 1218 1219 NFCSTATUS phFriNfc_Llcp_Reset( phFriNfc_Llcp_t *Llcp, 1220 void *LowerDevice, 1221 phFriNfc_Llcp_sLinkParameters_t *psLinkParams, 1222 void *pRxBuffer, 1223 uint16_t nRxBufferLength, 1224 void *pTxBuffer, 1225 uint16_t nTxBufferLength, 1226 phFriNfc_Llcp_LinkStatus_CB_t pfLink_CB, 1227 void *pContext ) 1228 { 1229 const uint16_t nMaxHeaderSize = PHFRINFC_LLCP_PACKET_HEADER_SIZE + 1230 PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE; 1231 NFCSTATUS result; 1232 1233 /* Check parameters presence */ 1234 if ((Llcp == NULL) || (LowerDevice == NULL) || (pfLink_CB == NULL) || 1235 (pRxBuffer == NULL) || (pTxBuffer == NULL) ) 1236 { 1237 return NFCSTATUS_INVALID_PARAMETER; 1238 } 1239 1240 /* Check parameters value */ 1241 if (psLinkParams->miu < PHFRINFC_LLCP_MIU_DEFAULT) 1242 { 1243 return NFCSTATUS_INVALID_PARAMETER; 1244 } 1245 1246 /* Check if buffers are large enough to support minimal MIU */ 1247 if ((nRxBufferLength < (nMaxHeaderSize + PHFRINFC_LLCP_MIU_DEFAULT)) || 1248 (nTxBufferLength < (nMaxHeaderSize + PHFRINFC_LLCP_MIU_DEFAULT)) ) 1249 { 1250 return NFCSTATUS_BUFFER_TOO_SMALL; 1251 } 1252 1253 /* Check compatibility between reception buffer size and announced MIU */ 1254 if (nRxBufferLength < (nMaxHeaderSize + psLinkParams->miu)) 1255 { 1256 return NFCSTATUS_BUFFER_TOO_SMALL; 1257 } 1258 1259 /* Start with a zero-filled monitor */ 1260 memset(Llcp, 0x00, sizeof(phFriNfc_Llcp_t)); 1261 1262 /* Reset the MAC Mapping layer */ 1263 result = phFriNfc_LlcpMac_Reset(&Llcp->MAC, LowerDevice, phFriNfc_Llcp_LinkStatus_CB, Llcp); 1264 if (result != NFCSTATUS_SUCCESS) { 1265 return result; 1266 } 1267 1268 /* Save the working buffers */ 1269 Llcp->sRxBuffer.buffer = pRxBuffer; 1270 Llcp->sRxBuffer.length = nRxBufferLength; 1271 Llcp->nRxBufferLength = nRxBufferLength; 1272 Llcp->sTxBuffer.buffer = pTxBuffer; 1273 Llcp->sTxBuffer.length = nTxBufferLength; 1274 Llcp->nTxBufferLength = nTxBufferLength; 1275 1276 /* Save the link status callback references */ 1277 Llcp->pfLink_CB = pfLink_CB; 1278 Llcp->pLinkContext = pContext; 1279 1280 /* Save the local link parameters */ 1281 memcpy(&Llcp->sLocalParams, psLinkParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); 1282 1283 return NFCSTATUS_SUCCESS; 1284 } 1285 1286 1287 NFCSTATUS phFriNfc_Llcp_ChkLlcp( phFriNfc_Llcp_t *Llcp, 1288 phHal_sRemoteDevInformation_t *psRemoteDevInfo, 1289 phFriNfc_Llcp_Check_CB_t pfCheck_CB, 1290 void *pContext ) 1291 { 1292 /* Check parameters */ 1293 if ( (Llcp == NULL) || (psRemoteDevInfo == NULL) || (pfCheck_CB == NULL) ) 1294 { 1295 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 1296 } 1297 1298 /* Check current state */ 1299 if( Llcp->state != PHFRINFC_LLCP_STATE_RESET_INIT ) { 1300 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE); 1301 } 1302 1303 /* Save the compliance check callback */ 1304 Llcp->pfChk_CB = pfCheck_CB; 1305 Llcp->pChkContext = pContext; 1306 1307 /* Forward check request to MAC layer */ 1308 return phFriNfc_LlcpMac_ChkLlcp(&Llcp->MAC, psRemoteDevInfo, phFriNfc_Llcp_ChkLlcp_CB, (void*)Llcp); 1309 } 1310 1311 1312 NFCSTATUS phFriNfc_Llcp_Activate( phFriNfc_Llcp_t *Llcp ) 1313 { 1314 /* Check parameters */ 1315 if (Llcp == NULL) 1316 { 1317 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 1318 } 1319 1320 /* Check current state */ 1321 if( Llcp->state != PHFRINFC_LLCP_STATE_CHECKED ) { 1322 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE); 1323 } 1324 1325 /* Update state */ 1326 Llcp->state = PHFRINFC_LLCP_STATE_ACTIVATION; 1327 1328 /* Forward check request to MAC layer */ 1329 return phFriNfc_LlcpMac_Activate(&Llcp->MAC); 1330 } 1331 1332 1333 NFCSTATUS phFriNfc_Llcp_Deactivate( phFriNfc_Llcp_t *Llcp ) 1334 { 1335 NFCSTATUS status; 1336 1337 /* Check parameters */ 1338 if (Llcp == NULL) 1339 { 1340 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 1341 } 1342 1343 /* Check current state */ 1344 if( (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_RECV) && 1345 (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND) ) { 1346 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE); 1347 } 1348 1349 /* Send DISC packet */ 1350 status = phFriNfc_Llcp_SendDisconnect(Llcp); 1351 if (status == NFCSTATUS_PENDING) 1352 { 1353 /* Wait for packet to be sent before deactivate link */ 1354 return status; 1355 } 1356 1357 /* Perform actual deactivation */ 1358 return phFriNfc_Llcp_InternalDeactivate(Llcp); 1359 } 1360 1361 1362 NFCSTATUS phFriNfc_Llcp_GetLocalInfo( phFriNfc_Llcp_t *Llcp, 1363 phFriNfc_Llcp_sLinkParameters_t *pParams ) 1364 { 1365 /* Check parameters */ 1366 if ((Llcp == NULL) || (pParams == NULL)) 1367 { 1368 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 1369 } 1370 1371 /* Copy response */ 1372 memcpy(pParams, &Llcp->sLocalParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); 1373 1374 return NFCSTATUS_SUCCESS; 1375 } 1376 1377 1378 NFCSTATUS phFriNfc_Llcp_GetRemoteInfo( phFriNfc_Llcp_t *Llcp, 1379 phFriNfc_Llcp_sLinkParameters_t *pParams ) 1380 { 1381 /* Check parameters */ 1382 if ((Llcp == NULL) || (pParams == NULL)) 1383 { 1384 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 1385 } 1386 1387 /* Copy response */ 1388 memcpy(pParams, &Llcp->sRemoteParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); 1389 1390 return NFCSTATUS_SUCCESS; 1391 } 1392 1393 1394 NFCSTATUS phFriNfc_Llcp_Send( phFriNfc_Llcp_t *Llcp, 1395 phFriNfc_Llcp_sPacketHeader_t *psHeader, 1396 phFriNfc_Llcp_sPacketSequence_t *psSequence, 1397 phNfc_sData_t *psInfo, 1398 phFriNfc_Llcp_Send_CB_t pfSend_CB, 1399 void *pContext ) 1400 { 1401 NFCSTATUS result; 1402 1403 /* Check parameters */ 1404 if ((Llcp == NULL) || (psHeader == NULL) || (pfSend_CB == NULL)) 1405 { 1406 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 1407 } 1408 1409 /* Check if previous phFriNfc_Llcp_Send() has finished */ 1410 if (Llcp->pfSendCB != NULL) 1411 { 1412 /* Error: a send operation is already running */ 1413 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_REJECTED); 1414 } 1415 1416 /* Save the callback parameters */ 1417 Llcp->pfSendCB = pfSend_CB; 1418 Llcp->pSendContext = pContext; 1419 1420 if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND) 1421 { 1422 /* Ready to send */ 1423 result = phFriNfc_Llcp_InternalSend(Llcp, psHeader, psSequence, psInfo); 1424 } 1425 else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) 1426 { 1427 /* Not ready to send, save send params for later use */ 1428 Llcp->psSendHeader = psHeader; 1429 Llcp->psSendSequence = psSequence; 1430 Llcp->psSendInfo = phFriNfc_Llcp_AllocateAndCopy(psInfo); 1431 result = NFCSTATUS_PENDING; 1432 } 1433 else 1434 { 1435 /* Incorrect state for sending ! */ 1436 result = PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);; 1437 } 1438 1439 if (result != NFCSTATUS_PENDING) { 1440 Llcp->pfSendCB = NULL; 1441 } 1442 return result; 1443 } 1444 1445 1446 NFCSTATUS phFriNfc_Llcp_Recv( phFriNfc_Llcp_t *Llcp, 1447 phFriNfc_Llcp_Recv_CB_t pfRecv_CB, 1448 void *pContext ) 1449 { 1450 NFCSTATUS result = NFCSTATUS_SUCCESS; 1451 1452 /* Check parameters */ 1453 if ((Llcp == NULL) || (pfRecv_CB == NULL)) 1454 { 1455 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 1456 } 1457 1458 /* Check if previous phFriNfc_Llcp_Recv() has finished */ 1459 if (Llcp->pfRecvCB != NULL) 1460 { 1461 /* Error: a send operation is already running */ 1462 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_REJECTED); 1463 } 1464 1465 /* Save the callback parameters */ 1466 Llcp->pfRecvCB = pfRecv_CB; 1467 Llcp->pRecvContext = pContext; 1468 1469 /* NOTE: nothing more to do, the receive function is called in background */ 1470 1471 return result; 1472 } 1473