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