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