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