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