15d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/* 25d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * Copyright (C) 2010 NXP Semiconductors 35d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * 45d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * Licensed under the Apache License, Version 2.0 (the "License"); 55d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * you may not use this file except in compliance with the License. 65d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * You may obtain a copy of the License at 75d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * 85d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * http://www.apache.org/licenses/LICENSE-2.0 95d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * 105d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * Unless required by applicable law or agreed to in writing, software 115d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * distributed under the License is distributed on an "AS IS" BASIS, 125d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * See the License for the specific language governing permissions and 145d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * limitations under the License. 155d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly */ 165d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 175d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/** 185d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * \file phFriNfc_Llcp.c 195d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * \brief NFC LLCP core 205d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * 215d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * Project: NFC-FRI 225d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * 235d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly */ 245d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 255d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/*include files*/ 265d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly#include <phNfcLlcpTypes.h> 275d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly#include <phOsalNfc_Timer.h> 285d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 295d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly#include <phFriNfc_Llcp.h> 305d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly#include <phFriNfc_LlcpUtils.h> 315d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 325d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/** 335d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * \internal 345d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * \name States of the LLC state machine. 355d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * 365d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly */ 375d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/*@{*/ 385d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly#define PHFRINFC_LLCP_STATE_RESET_INIT 0 /**< \internal Initial state.*/ 395d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly#define PHFRINFC_LLCP_STATE_CHECKED 1 /**< \internal The tag has been checked for LLCP compliance.*/ 405d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly#define PHFRINFC_LLCP_STATE_ACTIVATION 2 /**< \internal The deactivation phase.*/ 415d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly#define PHFRINFC_LLCP_STATE_PAX 3 /**< \internal Parameter exchange phase.*/ 425d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly#define PHFRINFC_LLCP_STATE_OPERATION_RECV 4 /**< \internal Normal operation phase (ready to receive).*/ 435d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly#define PHFRINFC_LLCP_STATE_OPERATION_SEND 5 /**< \internal Normal operation phase (ready to send).*/ 445d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly#define PHFRINFC_LLCP_STATE_DEACTIVATION 6 /**< \internal The deactivation phase.*/ 455d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/*@}*/ 465d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 475d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/** 485d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * \internal 495d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * \name Masks used for VERSION parsing. 505d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * 515d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly */ 525d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/*@{*/ 535d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly#define PHFRINFC_LLCP_VERSION_MAJOR_MASK 0xF0 /**< \internal Mask to apply to get major version number.*/ 545d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly#define PHFRINFC_LLCP_VERSION_MINOR_MASK 0x0F /**< \internal Mask to apply to get major version number.*/ 555d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/*@}*/ 565d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 575d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/** 585d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * \internal 595d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * \name Invalid values for parameters. 605d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * 615d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly */ 625d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/*@{*/ 635d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly#define PHFRINFC_LLCP_INVALID_VERSION 0x00 /**< \internal Invalid VERSION value.*/ 645d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/*@}*/ 655d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 665d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/** 675d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * \internal 685d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * \name Internal constants. 695d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly * 705d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly */ 715d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/*@{*/ 725d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly#define PHFRINFC_LLCP_MAX_PARAM_TLV_LENGTH \ 735d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly (( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_VERSION ) + \ 745d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_MIUX ) + \ 755d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_WKS ) + \ 765d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_LTO ) + \ 775d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_OPT )) /**< \internal Maximum size of link params TLV.*/ 785d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/*@}*/ 795d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 805d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 815d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 825d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/* --------------------------- Internal functions ------------------------------ */ 835d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 845d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic void phFriNfc_Llcp_Receive_CB( void *pContext, 855d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS status, 865d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t *psData); 875d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic NFCSTATUS phFriNfc_Llcp_HandleIncomingPacket( phFriNfc_Llcp_t *Llcp, 885d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t *psPacket ); 895d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic void phFriNfc_Llcp_ResetLTO( phFriNfc_Llcp_t *Llcp ); 905d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic NFCSTATUS phFriNfc_Llcp_InternalSend( phFriNfc_Llcp_t *Llcp, 915d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketHeader_t *psHeader, 925d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketSequence_t *psSequence, 935d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t *psInfo ); 945d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic bool_t phFriNfc_Llcp_HandlePendingSend ( phFriNfc_Llcp_t *Llcp ); 955d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 96d9d57394761c70786f5058f82e7528bfaf1807a0Arnaud Ferirstatic phNfc_sData_t * phFriNfc_Llcp_AllocateAndCopy(phNfc_sData_t * pOrig) 97f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau{ 98f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau phNfc_sData_t * pDest = NULL; 99f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau 100f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau if (pOrig == NULL) 101f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau { 102f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau return NULL; 103f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau } 104f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau 105f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau pDest = phOsalNfc_GetMemory(sizeof(phNfc_sData_t)); 106f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau if (pDest == NULL) 107f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau { 108f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau goto error; 109f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau } 110f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau 111f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau pDest->buffer = phOsalNfc_GetMemory(pOrig->length); 112f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau if (pDest->buffer == NULL) 113f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau { 114f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau goto error; 115f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau } 116f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau 117f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau memcpy(pDest->buffer, pOrig->buffer, pOrig->length); 118f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau pDest->length = pOrig->length; 119f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau 120f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau return pDest; 121f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau 122f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneauerror: 123f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau if (pDest != NULL) 124f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau { 125f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau if (pDest->buffer != NULL) 126f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau { 127f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau phOsalNfc_FreeMemory(pDest->buffer); 128f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau } 129f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau phOsalNfc_FreeMemory(pDest); 130f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau } 131f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau return NULL; 132f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau} 133f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau 134f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneaustatic void phFriNfc_Llcp_Deallocate(phNfc_sData_t * pData) 135f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau{ 136f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau if (pData != NULL) 137f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau { 13840cdab11e00d801c1b9acfdcfe53455059c1b557Arnaud Ferir if (pData->buffer != NULL) 13940cdab11e00d801c1b9acfdcfe53455059c1b557Arnaud Ferir { 14040cdab11e00d801c1b9acfdcfe53455059c1b557Arnaud Ferir phOsalNfc_FreeMemory(pData->buffer); 14140cdab11e00d801c1b9acfdcfe53455059c1b557Arnaud Ferir } 14240cdab11e00d801c1b9acfdcfe53455059c1b557Arnaud Ferir else 14340cdab11e00d801c1b9acfdcfe53455059c1b557Arnaud Ferir { 14440cdab11e00d801c1b9acfdcfe53455059c1b557Arnaud Ferir LLCP_PRINT("Warning, deallocating empty buffer"); 14540cdab11e00d801c1b9acfdcfe53455059c1b557Arnaud Ferir } 146f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau phOsalNfc_FreeMemory(pData); 147f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau } 148f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau} 149f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau 1505d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic NFCSTATUS phFriNfc_Llcp_InternalDeactivate( phFriNfc_Llcp_t *Llcp ) 1515d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 1521ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir phFriNfc_Llcp_Send_CB_t pfSendCB; 1531ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir void * pSendContext; 1545d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if ((Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) || 1555d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND) || 1565d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly (Llcp->state == PHFRINFC_LLCP_STATE_PAX) || 1575d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly (Llcp->state == PHFRINFC_LLCP_STATE_ACTIVATION)) 1585d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 1595d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Update state */ 1605d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->state = PHFRINFC_LLCP_STATE_DEACTIVATION; 1615d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 1625d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Stop timer */ 1635d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phOsalNfc_Timer_Stop(Llcp->hSymmTimer); 1645d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 1653cbab5882f6d89a52068a3fa72a7223971d6b7fdMartijn Coenen Llcp->psSendHeader = NULL; 1663cbab5882f6d89a52068a3fa72a7223971d6b7fdMartijn Coenen Llcp->psSendSequence = NULL; 1671ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir /* Return delayed send operation in error, in any */ 1681ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir if (Llcp->psSendInfo != NULL) 1691ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir { 1701ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir phFriNfc_Llcp_Deallocate(Llcp->psSendInfo); 17140cdab11e00d801c1b9acfdcfe53455059c1b557Arnaud Ferir Llcp->psSendInfo = NULL; 1721ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir } 1731ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir if (Llcp->pfSendCB != NULL) 1741ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir { 1751ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir /* Get Callback params */ 1761ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir pfSendCB = Llcp->pfSendCB; 1771ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir pSendContext = Llcp->pSendContext; 1781ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir /* Reset callback params */ 1791ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir Llcp->pfSendCB = NULL; 1801ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir Llcp->pSendContext = NULL; 1811ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir /* Call the callback */ 1821ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir (pfSendCB)(pSendContext, NFCSTATUS_FAILED); 1831ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir } 1841ec4ace9cd3079abd7c0b30d0976591c8c0f441eArnaud Ferir 1855d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Notify service layer */ 1865d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkDeactivated); 1875d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 1885d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Forward check request to MAC layer */ 1895d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return phFriNfc_LlcpMac_Deactivate(&Llcp->MAC); 1905d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 1915d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 1925d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_SUCCESS; 1935d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 1945d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 1955d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 1965d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic NFCSTATUS phFriNfc_Llcp_SendSymm( phFriNfc_Llcp_t *Llcp ) 1975d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 1985d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketHeader_t sHeader; 1995d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 20054b847c7f7a5bc2e36ebe877ce832cdfefabc733Martijn Coenen sHeader.dsap = PHFRINFC_LLCP_SAP_LINK; 20154b847c7f7a5bc2e36ebe877ce832cdfefabc733Martijn Coenen sHeader.ssap = PHFRINFC_LLCP_SAP_LINK; 20254b847c7f7a5bc2e36ebe877ce832cdfefabc733Martijn Coenen sHeader.ptype = PHFRINFC_LLCP_PTYPE_SYMM; 20354b847c7f7a5bc2e36ebe877ce832cdfefabc733Martijn Coenen return phFriNfc_Llcp_InternalSend(Llcp, &sHeader, NULL, NULL); 2045d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 2055d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 2065d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 2075d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic NFCSTATUS phFriNfc_Llcp_SendPax( phFriNfc_Llcp_t *Llcp, phFriNfc_Llcp_sLinkParameters_t *psLinkParams) 2085d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 2095d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t pTLVBuffer[PHFRINFC_LLCP_MAX_PARAM_TLV_LENGTH]; 2105d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t sParamsTLV; 2115d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketHeader_t sHeader; 2125d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS result; 2135d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 2145d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Prepare link parameters TLV */ 2155d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sParamsTLV.buffer = pTLVBuffer; 2165d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sParamsTLV.length = PHFRINFC_LLCP_MAX_PARAM_TLV_LENGTH; 2175d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = phFriNfc_Llcp_EncodeLinkParams(&sParamsTLV, psLinkParams, PHFRINFC_LLCP_VERSION); 2185d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (result != NFCSTATUS_SUCCESS) 2195d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 2205d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error while encoding */ 2215d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_FAILED; 2225d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 2235d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 2245d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check if ready to send */ 2255d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND) 2265d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 2275d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* No send pending, send the PAX packet */ 2285d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sHeader.dsap = PHFRINFC_LLCP_SAP_LINK; 2295d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sHeader.ssap = PHFRINFC_LLCP_SAP_LINK; 2305d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sHeader.ptype = PHFRINFC_LLCP_PTYPE_PAX; 2315d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return phFriNfc_Llcp_InternalSend(Llcp, &sHeader, NULL, &sParamsTLV); 2325d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 2335d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else 2345d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 2355d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error: A send is already pending, cannot send PAX */ 2365d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* NOTE: this should not happen since PAX are sent before any other packet ! */ 2375d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_FAILED; 2385d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 2395d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 2405d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 2415d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 2425d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic NFCSTATUS phFriNfc_Llcp_SendDisconnect( phFriNfc_Llcp_t *Llcp ) 2435d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 2445d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketHeader_t sHeader; 2455d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 2465d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check if ready to send */ 2475d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND) 2485d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 2495d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* No send pending, send the DISC packet */ 2505d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sHeader.dsap = PHFRINFC_LLCP_SAP_LINK; 2515d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sHeader.ssap = PHFRINFC_LLCP_SAP_LINK; 2525d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sHeader.ptype = PHFRINFC_LLCP_PTYPE_DISC; 2535d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return phFriNfc_Llcp_InternalSend(Llcp, &sHeader, NULL, NULL); 2545d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 2555d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else 2565d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 2575d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* A send is already pending, raise a flag to send DISC as soon as possible */ 2585d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->bDiscPendingFlag = TRUE; 2595d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_PENDING; 2605d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 2615d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 2625d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 2635d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 2645d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic void phFriNfc_Llcp_Timer_CB(uint32_t TimerId, void *pContext) 2655d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 2665d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; 2675d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 2685d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly PHNFC_UNUSED_VARIABLE(TimerId); 2695d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 2705d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check current state */ 2715d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) 2725d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 2735d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* No data is coming before LTO, disconnecting */ 2745d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_InternalDeactivate(Llcp); 2755d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 2765d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND) 2775d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 2785d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Send SYMM */ 2795d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_SendSymm(Llcp); 2805d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 2815d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else 2825d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 2835d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Nothing to do if not in Normal Operation state */ 2845d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 2855d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 2865d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 2875d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 2885d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic NFCSTATUS phFriNfc_Llcp_HandleAggregatedPacket( phFriNfc_Llcp_t *Llcp, 2895d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t *psRawPacket ) 2905d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 2915d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t sInfo; 292b7e67c8dbd4aa5892815bfed4e7ff934cf49b904Sylvain Fonteneau phNfc_sData_t sCurrentInfo; 2935d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint16_t length; 2945d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS status; 2955d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 2965d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Get info field */ 2975d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sInfo.buffer = psRawPacket->buffer + PHFRINFC_LLCP_PACKET_HEADER_SIZE; 2985d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sInfo.length = psRawPacket->length - PHFRINFC_LLCP_PACKET_HEADER_SIZE; 2995d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 3005d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check for empty info field */ 3015d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (sInfo.length == 0) 3025d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 3035d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_FAILED; 3045d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 3055d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 3065d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check consistency */ 3075d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly while (sInfo.length != 0) 3085d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 3095d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check if enough room to read length */ 3105d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (sInfo.length < sizeof(sInfo.length)) 3115d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 3125d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_FAILED; 3135d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 3145d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Read length */ 3155d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly length = (sInfo.buffer[0] << 8) | sInfo.buffer[1]; 3165d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Update info buffer */ 317b7e67c8dbd4aa5892815bfed4e7ff934cf49b904Sylvain Fonteneau sInfo.buffer += 2; /*Size of length field is 2*/ 318b7e67c8dbd4aa5892815bfed4e7ff934cf49b904Sylvain Fonteneau sInfo.length -= 2; /*Size of length field is 2*/ 3195d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check if declared length fits in remaining space */ 3205d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (length > sInfo.length) 3215d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 3225d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_FAILED; 3235d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 3245d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Update info buffer */ 3255d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sInfo.buffer += length; 3265d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sInfo.length -= length; 3275d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 3285d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 3295d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Get info field */ 3305d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sInfo.buffer = psRawPacket->buffer + PHFRINFC_LLCP_PACKET_HEADER_SIZE; 3315d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sInfo.length = psRawPacket->length - PHFRINFC_LLCP_PACKET_HEADER_SIZE; 3325d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 3335d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle aggregated packets */ 3345d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly while (sInfo.length != 0) 3355d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 3365d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Read length */ 3375d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly length = (sInfo.buffer[0] << 8) | sInfo.buffer[1]; 3385d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Update info buffer */ 339b7e67c8dbd4aa5892815bfed4e7ff934cf49b904Sylvain Fonteneau sInfo.buffer += 2; /* Size of length field is 2 */ 340b7e67c8dbd4aa5892815bfed4e7ff934cf49b904Sylvain Fonteneau sInfo.length -= 2; /*Size of length field is 2*/ 3415d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle aggregated packet */ 342b7e67c8dbd4aa5892815bfed4e7ff934cf49b904Sylvain Fonteneau sCurrentInfo.buffer=sInfo.buffer; 343b7e67c8dbd4aa5892815bfed4e7ff934cf49b904Sylvain Fonteneau sCurrentInfo.length=length; 344b7e67c8dbd4aa5892815bfed4e7ff934cf49b904Sylvain Fonteneau status = phFriNfc_Llcp_HandleIncomingPacket(Llcp, &sCurrentInfo); 3455d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if ( (status != NFCSTATUS_SUCCESS) && 3465d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly (status != NFCSTATUS_PENDING) ) 3475d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 3485d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* TODO: Error: invalid frame */ 3495d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 3505d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Update info buffer */ 3515d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sInfo.buffer += length; 3525d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sInfo.length -= length; 3535d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 3545d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_SUCCESS; 3555d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 3565d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 3575d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 3585d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic NFCSTATUS phFriNfc_Llcp_ParseLinkParams( phNfc_sData_t *psParamsTLV, 3595d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sLinkParameters_t *psParsedParams, 3605d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t *pnParsedVersion ) 3615d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 3625d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS status; 3635d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t type; 3645d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sLinkParameters_t sParams; 3655d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t sValueBuffer; 3665d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint32_t offset = 0; 3675d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t version = PHFRINFC_LLCP_INVALID_VERSION; 3685d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 3695d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check for NULL pointers */ 3705d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if ((psParamsTLV == NULL) || (psParsedParams == NULL) || (pnParsedVersion == NULL)) 3715d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 3725d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 3735d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 3745d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 3755d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Prepare default param structure */ 3765d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sParams.miu = PHFRINFC_LLCP_MIU_DEFAULT; 3775d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sParams.wks = PHFRINFC_LLCP_WKS_DEFAULT; 3785d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sParams.lto = PHFRINFC_LLCP_LTO_DEFAULT; 3795d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sParams.option = PHFRINFC_LLCP_OPTION_DEFAULT; 3805d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 3815d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Decode TLV */ 3825d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly while (offset < psParamsTLV->length) 3835d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 3845d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly status = phFriNfc_Llcp_DecodeTLV(psParamsTLV, &offset, &type, &sValueBuffer); 3855d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (status != NFCSTATUS_SUCCESS) 3865d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 3875d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error: Ill-formed TLV */ 3885d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return status; 3895d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 3905d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly switch(type) 3915d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 3925d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case PHFRINFC_LLCP_TLV_TYPE_VERSION: 3935d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 3945d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check length */ 3955d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_VERSION) 3965d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 3975d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error : Ill-formed VERSION parameter TLV */ 39846dbed4e11700226e9b43ca17e5ad6f3d192bf63Sylvain Fonteneau break; 3995d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4005d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Get VERSION */ 4015d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly version = sValueBuffer.buffer[0]; 4025d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 4035d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4045d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case PHFRINFC_LLCP_TLV_TYPE_MIUX: 4055d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 4065d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check length */ 4075d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_MIUX) 4085d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 4095d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error : Ill-formed MIUX parameter TLV */ 41046dbed4e11700226e9b43ca17e5ad6f3d192bf63Sylvain Fonteneau break; 4115d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4125d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Get MIU */ 41334ff48f6cd6595a899e05fbd56f4c84891840d3fNick Pelly sParams.miu = (PHFRINFC_LLCP_MIU_DEFAULT + ((sValueBuffer.buffer[0] << 8) | sValueBuffer.buffer[1])) & PHFRINFC_LLCP_TLV_MIUX_MASK; 4145d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 4155d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4165d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case PHFRINFC_LLCP_TLV_TYPE_WKS: 4175d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 4185d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check length */ 4195d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_WKS) 4205d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 4215d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error : Ill-formed MIUX parameter TLV */ 42246dbed4e11700226e9b43ca17e5ad6f3d192bf63Sylvain Fonteneau break; 4235d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4245d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Get WKS */ 4255d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sParams.wks = (sValueBuffer.buffer[0] << 8) | sValueBuffer.buffer[1]; 4265d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Ignored bits must always be set */ 4275d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sParams.wks |= PHFRINFC_LLCP_TLV_WKS_MASK; 4285d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 4295d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4305d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case PHFRINFC_LLCP_TLV_TYPE_LTO: 4315d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 4325d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check length */ 4335d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_LTO) 4345d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 4355d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error : Ill-formed LTO parameter TLV */ 43646dbed4e11700226e9b43ca17e5ad6f3d192bf63Sylvain Fonteneau break; 4375d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4385d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Get LTO */ 4395d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sParams.lto = sValueBuffer.buffer[0]; 4405d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 4415d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4425d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case PHFRINFC_LLCP_TLV_TYPE_OPT: 4435d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 4445d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check length */ 4455d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_OPT) 4465d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 4475d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error : Ill-formed OPT parameter TLV */ 44846dbed4e11700226e9b43ca17e5ad6f3d192bf63Sylvain Fonteneau break;; 4495d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4505d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Get OPT */ 4515d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sParams.option = sValueBuffer.buffer[0] & PHFRINFC_LLCP_TLV_OPT_MASK; 4525d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 4535d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4545d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly default: 4555d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 4565d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error : Unknown Type */ 45746dbed4e11700226e9b43ca17e5ad6f3d192bf63Sylvain Fonteneau break; 4585d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4595d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4605d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4615d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 4625d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check if a VERSION parameter has been provided */ 4635d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (version == PHFRINFC_LLCP_INVALID_VERSION) 4645d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 4655d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error : Mandatory VERSION parameter not provided */ 4665d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 4675d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4685d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 4695d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Save response */ 4705d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly *pnParsedVersion = version; 4715d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly memcpy(psParsedParams, &sParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); 4725d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 4735d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_SUCCESS; 4745d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 4755d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 4765d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 4775d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic NFCSTATUS phFriNfc_Llcp_VersionAgreement( uint8_t localVersion, 4785d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t remoteVersion, 4795d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t *pNegociatedVersion ) 4805d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 4815d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t localMajor = localVersion & PHFRINFC_LLCP_VERSION_MAJOR_MASK; 4825d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t localMinor = localVersion & PHFRINFC_LLCP_VERSION_MINOR_MASK; 4835d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t remoteMajor = remoteVersion & PHFRINFC_LLCP_VERSION_MAJOR_MASK; 4845d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t remoteMinor = remoteVersion & PHFRINFC_LLCP_VERSION_MINOR_MASK; 4855d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t negociatedVersion; 4865d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 4875d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check for NULL pointers */ 4885d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (pNegociatedVersion == NULL) 4895d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 4905d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 4915d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4925d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 4935d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Compare Major numbers */ 4945d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (localMajor == remoteMajor) 4955d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 4965d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Version agreement succeed : use lowest version */ 4975d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly negociatedVersion = localMajor | ((remoteMinor<localMinor)?remoteMinor:localMinor); 4985d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 4995d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else if (localMajor > remoteMajor) 5005d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 5015d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Decide if versions are compatible */ 5025d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Currently, there is no backward compatibility to handle */ 5035d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_FAILED; 5045d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 5055d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else /* if (localMajor < remoteMajor) */ 5065d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 5075d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* It is up to the remote host to decide if versions are compatible */ 5085d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Set negociated version to our local version, the remote will 5095d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly deacivate the link if its own version agreement fails */ 5105d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly negociatedVersion = localVersion; 5115d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 5125d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 5135d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Save response */ 5145d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly *pNegociatedVersion = negociatedVersion; 5155d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 5165d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_SUCCESS; 5175d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 5185d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 5195d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 5205d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic NFCSTATUS phFriNfc_Llcp_InternalActivate( phFriNfc_Llcp_t *Llcp, 5215d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t *psParamsTLV) 5225d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 5235d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS status; 5245d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sLinkParameters_t sRemoteParams; 5255d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t remoteVersion; 5265d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t negociatedVersion; 5275d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly const uint16_t nMaxHeaderSize = PHFRINFC_LLCP_PACKET_HEADER_SIZE + 5285d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE; 5295d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 5305d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Parse parameters */ 5315d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly status = phFriNfc_Llcp_ParseLinkParams(psParamsTLV, &sRemoteParams, &remoteVersion); 5325d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (status != NFCSTATUS_SUCCESS) 5335d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 5345d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error: invalid parameters TLV */ 5355d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly status = NFCSTATUS_FAILED; 5365d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 5375d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else 5385d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 5395d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Version agreement procedure */ 5405d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly status = phFriNfc_Llcp_VersionAgreement(PHFRINFC_LLCP_VERSION , remoteVersion, &negociatedVersion); 5415d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (status != NFCSTATUS_SUCCESS) 5425d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 5435d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error: version agreement failed */ 5445d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly status = NFCSTATUS_FAILED; 5455d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 5465d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else 5475d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 5485d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Save parameters */ 5495d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->version = negociatedVersion; 5505d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly memcpy(&Llcp->sRemoteParams, &sRemoteParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); 5515d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 5525d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Update remote MIU to match local Tx buffer size */ 5535d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->nTxBufferLength < (Llcp->sRemoteParams.miu + nMaxHeaderSize)) 5545d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 5555d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->sRemoteParams.miu = Llcp->nTxBufferLength - nMaxHeaderSize; 5565d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 5575d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 5585d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Initiate Symmetry procedure by resetting LTO timer */ 5595d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* NOTE: this also updates current state */ 5605d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_ResetLTO(Llcp); 5615d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 5625d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 5635d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Notify upper layer, if Activation failed CB called by Deactivate */ 5645d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (status == NFCSTATUS_SUCCESS) 5655d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 5665d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Link activated ! */ 5675d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkActivated); 5685d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 5695d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 5705d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return status; 5715d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 5725d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 5735d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 5745d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic NFCSTATUS phFriNfc_Llcp_HandleMACLinkActivated( phFriNfc_Llcp_t *Llcp, 5755d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t *psParamsTLV) 5765d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 5775d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS status = NFCSTATUS_SUCCESS; 5785d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 5795d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Create the timer */ 5805d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->hSymmTimer = phOsalNfc_Timer_Create(); 5815d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->hSymmTimer == PH_OSALNFC_INVALID_TIMER_ID) 5825d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 5835d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error: unable to create timer */ 5845d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_INSUFFICIENT_RESOURCES; 5855d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 5865d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 5875d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check if params received from MAC activation procedure */ 5885d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (psParamsTLV == NULL) 5895d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 5905d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* No params with selected MAC mapping, enter PAX mode for parameter exchange */ 5915d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->state = PHFRINFC_LLCP_STATE_PAX; 5925d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Set default MIU for PAX exchange */ 5935d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->sRemoteParams.miu = PHFRINFC_LLCP_MIU_DEFAULT; 5945d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* If the local device is the initiator, it must initiate PAX exchange */ 5955d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeInitiator) 5965d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 5975d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Send PAX */ 5985d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly status = phFriNfc_Llcp_SendPax(Llcp, &Llcp->sLocalParams); 5995d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 6005d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 6015d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else 6025d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 6035d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Params exchanged during MAX activation, try LLC activation */ 6045d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly status = phFriNfc_Llcp_InternalActivate(Llcp, psParamsTLV); 6055d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 6065d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 6075d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (status == NFCSTATUS_SUCCESS) 6085d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 6095d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Start listening for incoming packets */ 6105d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->sRxBuffer.length = Llcp->nRxBufferLength; 6115d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_LlcpMac_Receive(&Llcp->MAC, &Llcp->sRxBuffer, phFriNfc_Llcp_Receive_CB, Llcp); 6125d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 6135d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 6145d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return status; 6155d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 6165d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 6175d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 6185d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic void phFriNfc_Llcp_HandleMACLinkDeactivated( phFriNfc_Llcp_t *Llcp ) 6195d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 6205d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t state = Llcp->state; 6215d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 6225d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Delete the timer */ 6235d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->hSymmTimer != PH_OSALNFC_INVALID_TIMER_ID) 6245d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 6255d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phOsalNfc_Timer_Delete(Llcp->hSymmTimer); 6265d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 6275d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 6285d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Reset state */ 6296bd5058796097ae40ed41c283a69e7874f2e9db2Martijn Coenen Llcp->state = PHFRINFC_LLCP_STATE_RESET_INIT; 6305d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 6315d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly switch (state) 6325d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 6335d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case PHFRINFC_LLCP_STATE_DEACTIVATION: 6345d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 6355d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* The service layer has already been notified, nothing more to do */ 6365d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 6375d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 6385d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly default: 6395d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 6405d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Notify service layer of link failure */ 6415d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkDeactivated); 6425d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 6435d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 6445d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 6455d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 6465d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 6475d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 6485d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic void phFriNfc_Llcp_ChkLlcp_CB( void *pContext, 6495d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS status ) 6505d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 6515d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Get monitor from context */ 6525d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; 6535d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 6545d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Update state */ 6555d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->state = PHFRINFC_LLCP_STATE_CHECKED; 6565d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 6575d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Invoke callback */ 6585d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pfChk_CB(Llcp->pChkContext, status); 6595d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 6605d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 6615d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic void phFriNfc_Llcp_LinkStatus_CB( void *pContext, 6625d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_LlcpMac_eLinkStatus_t eLinkStatus, 6635d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t *psParamsTLV, 66434ff48f6cd6595a899e05fbd56f4c84891840d3fNick Pelly phFriNfc_LlcpMac_ePeerType_t PeerRemoteDevType) 6655d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 6665d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS status; 6675d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 6685d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Get monitor from context */ 6695d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; 6705d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 6715d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Save the local peer role (initiator/target) */ 6725d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->eRole = PeerRemoteDevType; 6735d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 6745d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check new link status */ 6755d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly switch(eLinkStatus) 6765d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 6775d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case phFriNfc_LlcpMac_eLinkActivated: 6785d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 6795d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle MAC link activation */ 6805d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly status = phFriNfc_Llcp_HandleMACLinkActivated(Llcp, psParamsTLV); 6815d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (status != NFCSTATUS_SUCCESS) 6825d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 6835d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error: LLC link activation procedure failed, deactivate MAC link */ 6845d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly status = phFriNfc_Llcp_InternalDeactivate(Llcp); 6855d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 6865d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 6875d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 6885d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case phFriNfc_LlcpMac_eLinkDeactivated: 6895d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 6905d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle MAC link deactivation (cannot fail) */ 6915d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_HandleMACLinkDeactivated(Llcp); 6925d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 6935d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 6945d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly default: 6955d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 6965d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Warning: Unknown link status, should not happen */ 6975d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 6985d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 6995d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 7005d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 7015d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 7025d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic void phFriNfc_Llcp_ResetLTO( phFriNfc_Llcp_t *Llcp ) 7035d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 70465e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen uint32_t nDuration = 0; 70565e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen uint8_t bIsReset = 0; 7065d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 7075d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Stop timer */ 7085d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phOsalNfc_Timer_Stop(Llcp->hSymmTimer); 7095d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 7105d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 7115d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Update state */ 7125d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) 7135d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 7145d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_SEND; 7155d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 7165d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND) 7175d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 7185d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_RECV; 7195d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 7206bd5058796097ae40ed41c283a69e7874f2e9db2Martijn Coenen else if (Llcp->state != PHFRINFC_LLCP_STATE_DEACTIVATION && 7216bd5058796097ae40ed41c283a69e7874f2e9db2Martijn Coenen Llcp->state != PHFRINFC_LLCP_STATE_RESET_INIT) 7225d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 72365e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen bIsReset = 1; 7245d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Not yet in OPERATION state, perform first reset */ 7255d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeInitiator) 7265d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 7275d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_SEND; 7285d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 7295d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else 7305d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 7315d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_RECV; 7325d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 7335d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 7345d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 7355d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Calculate timer duration */ 7365d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* NOTE: nDuration is in 1/100s, and timer system takes values in 1/1000s */ 7375d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) 7385d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 7395d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Response must be received before LTO announced by remote peer */ 7405d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly nDuration = Llcp->sRemoteParams.lto * 10; 7415d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 7425d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else 7435d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 74465e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen if (bIsReset) 74565e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen { 74665e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen /* Immediately bounce SYMM back - it'll take 74765e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen * a while for the host to come up with something, 74865e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen * and maybe the remote is faster. 74965e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen */ 75065e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen nDuration = 1; 75165e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen } 75265e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen else 75365e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen { 75465e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen /* Must answer before the local announced LTO */ 75565e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen /* NOTE: to ensure the answer is completely sent before LTO, the 75665e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen timer is triggered _before_ LTO expiration */ 75765e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen /* TODO: make sure time scope is enough, and avoid use of magic number */ 75865e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen nDuration = (Llcp->sLocalParams.lto * 10) / 2; 75965e86fce1fe9e3f9aff98861c5e1e9d9ba6df9d5Martijn Coenen } 7605d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 7615d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 76257d24648f73cfface7409e664fe56d38f38636dfJeff Hamilton LLCP_DEBUG("Starting LLCP timer with duration %d", nDuration); 76357d24648f73cfface7409e664fe56d38f38636dfJeff Hamilton 7645d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Restart timer */ 7655d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phOsalNfc_Timer_Start( 7665d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->hSymmTimer, 7675d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly nDuration, 7685d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_Timer_CB, 7695d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp); 7705d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 7715d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 7725d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 7735d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic NFCSTATUS phFriNfc_Llcp_HandleLinkPacket( phFriNfc_Llcp_t *Llcp, 7745d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t *psPacket ) 7755d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 7765d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS result; 7775d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketHeader_t sHeader; 7785d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 7795d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Parse header */ 7805d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_Buffer2Header(psPacket->buffer, 0, &sHeader); 7815d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 7825d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check packet type */ 7835d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly switch (sHeader.ptype) 7845d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 7855d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case PHFRINFC_LLCP_PTYPE_SYMM: 7865d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 7875d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Nothing to do, the LTO is handled upon all packet reception */ 7885d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = NFCSTATUS_SUCCESS; 7895d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 7905d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 7915d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 7925d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case PHFRINFC_LLCP_PTYPE_AGF: 7935d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 7945d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle the aggregated packet */ 7955d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = phFriNfc_Llcp_HandleAggregatedPacket(Llcp, psPacket); 7965d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (result != NFCSTATUS_SUCCESS) 7975d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 7985d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error: invalid info field, dropping frame */ 7995d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 8005d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 8015d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 8025d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 8035d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case PHFRINFC_LLCP_PTYPE_DISC: 8045d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 8055d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle link disconnection request */ 8065d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = phFriNfc_Llcp_InternalDeactivate(Llcp); 8075d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 8085d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 8095d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 8105d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 8115d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case PHFRINFC_LLCP_PTYPE_FRMR: 8125d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 8135d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* TODO: what to do upon reception of FRMR on Link SAP ? */ 8145d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = NFCSTATUS_SUCCESS; 8155d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 8165d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 8175d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 8185d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case PHFRINFC_LLCP_PTYPE_PAX: 8195d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 8205d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Ignore PAX when in Normal Operation */ 8215d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = NFCSTATUS_SUCCESS; 8225d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 8235d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 8245d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 8255d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly default: 8265d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 8275d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error: invalid ptype field, dropping packet */ 8285d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 8295d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 8305d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 8315d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 8325d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return result; 8335d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 8345d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 8355d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 8365d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic NFCSTATUS phFriNfc_Llcp_HandleTransportPacket( phFriNfc_Llcp_t *Llcp, 8375d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t *psPacket ) 8385d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 8395d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_Recv_CB_t pfRecvCB; 8405d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly void *pContext; 8415d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS result = NFCSTATUS_SUCCESS; 8425d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketHeader_t sHeader; 8435d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 8445d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Forward to upper layer */ 8455d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->pfRecvCB != NULL) 8465d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 8475d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Get callback details */ 8485d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly pfRecvCB = Llcp->pfRecvCB; 8495d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly pContext = Llcp->pRecvContext; 8505d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Reset callback details */ 8515d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pfRecvCB = NULL; 8525d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pRecvContext = NULL; 8535d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Call the callback */ 8545d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly (pfRecvCB)(pContext, psPacket, NFCSTATUS_SUCCESS); 8555d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 8565d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 8575d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return result; 8585d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 8595d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 8605d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 8615d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic bool_t phFriNfc_Llcp_HandlePendingSend ( phFriNfc_Llcp_t *Llcp ) 8625d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 8635d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketHeader_t sHeader; 8645d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t sInfoBuffer; 8655d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketHeader_t *psSendHeader = NULL; 8665d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketSequence_t *psSendSequence = NULL; 8675d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t *psSendInfo = NULL; 8685d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS result; 869f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau uint8_t bDeallocate = FALSE; 870f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau uint8_t return_value = FALSE; 8715d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle pending disconnection request */ 8725d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->bDiscPendingFlag == TRUE) 8735d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 8745d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Last send si acheived, send the pending DISC packet */ 8755d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sHeader.dsap = PHFRINFC_LLCP_SAP_LINK; 8765d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sHeader.ssap = PHFRINFC_LLCP_SAP_LINK; 8775d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sHeader.ptype = PHFRINFC_LLCP_PTYPE_DISC; 8785d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Set send params */ 8795d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psSendHeader = &sHeader; 8805d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Reset flag */ 8815d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->bDiscPendingFlag = FALSE; 8825d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 8835d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle pending frame reject request */ 8845d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else if (Llcp->bFrmrPendingFlag == TRUE) 8855d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 8865d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Last send si acheived, send the pending FRMR packet */ 8875d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sInfoBuffer.buffer = Llcp->pFrmrInfo; 8885d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly sInfoBuffer.length = sizeof(Llcp->pFrmrInfo); 8895d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Set send params */ 8905d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psSendHeader = &Llcp->sFrmrHeader; 8915d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psSendInfo = &sInfoBuffer; 8925d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Reset flag */ 8935d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->bFrmrPendingFlag = FALSE; 8945d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 8955d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle pending service frame */ 8965d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else if (Llcp->pfSendCB != NULL) 8975d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 8985d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Set send params */ 8995d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psSendHeader = Llcp->psSendHeader; 9005d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psSendSequence = Llcp->psSendSequence; 9015d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psSendInfo = Llcp->psSendInfo; 9025d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Reset pending send infos */ 9035d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->psSendHeader = NULL; 9045d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->psSendSequence = NULL; 9055d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->psSendInfo = NULL; 906f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau bDeallocate = TRUE; 9075d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 9085d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 9095d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Perform send, if needed */ 9105d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (psSendHeader != NULL) 9115d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 9125d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = phFriNfc_Llcp_InternalSend(Llcp, psSendHeader, psSendSequence, psSendInfo); 9135d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if ((result != NFCSTATUS_SUCCESS) && (result != NFCSTATUS_PENDING)) 9145d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 9155d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error: send failed, impossible to recover */ 9165d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_InternalDeactivate(Llcp); 9175d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 918f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau return_value = TRUE; 91954b847c7f7a5bc2e36ebe877ce832cdfefabc733Martijn Coenen } else if (Llcp->pfSendCB == NULL) { 92054b847c7f7a5bc2e36ebe877ce832cdfefabc733Martijn Coenen // Nothing to send, send SYMM instead to allow peer to send something 92154b847c7f7a5bc2e36ebe877ce832cdfefabc733Martijn Coenen // if it wants. 92254b847c7f7a5bc2e36ebe877ce832cdfefabc733Martijn Coenen phFriNfc_Llcp_SendSymm(Llcp); 92354b847c7f7a5bc2e36ebe877ce832cdfefabc733Martijn Coenen return_value = TRUE; 924f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau } 925f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau 926f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneauclean_and_return: 927f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau if (bDeallocate) 928f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau { 929f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau phFriNfc_Llcp_Deallocate(psSendInfo); 9305d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 9315d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 932f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau return return_value; 9335d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 9345d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 9355d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic NFCSTATUS phFriNfc_Llcp_HandleIncomingPacket( phFriNfc_Llcp_t *Llcp, 9365d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t *psPacket ) 9375d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 9385d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS status = NFCSTATUS_SUCCESS; 9395d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketHeader_t sHeader; 9405d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 9415d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Parse header */ 9425d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_Buffer2Header(psPacket->buffer, 0, &sHeader); 9435d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 9445d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check destination */ 9455d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (sHeader.dsap == PHFRINFC_LLCP_SAP_LINK) 9465d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 9475d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle packet as destinated to the Link SAP */ 9485d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly status = phFriNfc_Llcp_HandleLinkPacket(Llcp, psPacket); 9495d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 9505d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else if (sHeader.dsap >= PHFRINFC_LLCP_SAP_NUMBER) 9515d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 9525d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* NOTE: this cannot happen since "psHeader->dsap" is only 6-bit wide */ 9535d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly status = NFCSTATUS_FAILED; 9545d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 9555d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else 9565d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 9575d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle packet as destinated to the SDP and transport SAPs */ 9585d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly status = phFriNfc_Llcp_HandleTransportPacket(Llcp, psPacket); 9595d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 9605d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return status; 9615d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 9625d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 9635d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 9645d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic void phFriNfc_Llcp_Receive_CB( void *pContext, 9655d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS status, 9665d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t *psData) 9675d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 9685d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Get monitor from context */ 9695d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; 9705d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS result = NFCSTATUS_SUCCESS; 9715d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketHeader_t sPacketHeader; 9725d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 9735d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check reception status and for pending disconnection */ 9745d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if ((status != NFCSTATUS_SUCCESS) || (Llcp->bDiscPendingFlag == TRUE)) 9755d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 976bf52196cdecd0decc2f8deabb19bf5877794bc31daniel_Tomas LLCP_DEBUG("\nReceived LLCP packet error - status = 0x%04x", status); 9775d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Reset disconnection operation */ 9785d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->bDiscPendingFlag = FALSE; 9795d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Deactivate the link */ 9805d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_InternalDeactivate(Llcp); 9815d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return; 9825d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 9835d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 98435a9f321a9cb5db0e65b9579d11bee2ac9bb1c54Sylvain Fonteneau /* Parse header */ 98535a9f321a9cb5db0e65b9579d11bee2ac9bb1c54Sylvain Fonteneau phFriNfc_Llcp_Buffer2Header(psData->buffer, 0, &sPacketHeader); 98635a9f321a9cb5db0e65b9579d11bee2ac9bb1c54Sylvain Fonteneau 987bf52196cdecd0decc2f8deabb19bf5877794bc31daniel_Tomas if (sPacketHeader.ptype != PHFRINFC_LLCP_PTYPE_SYMM) 988bf52196cdecd0decc2f8deabb19bf5877794bc31daniel_Tomas { 989bf52196cdecd0decc2f8deabb19bf5877794bc31daniel_Tomas LLCP_PRINT_BUFFER("\nReceived LLCP packet :", psData->buffer, psData->length); 990bf52196cdecd0decc2f8deabb19bf5877794bc31daniel_Tomas } 991bf52196cdecd0decc2f8deabb19bf5877794bc31daniel_Tomas else 992bf52196cdecd0decc2f8deabb19bf5877794bc31daniel_Tomas { 993bf52196cdecd0decc2f8deabb19bf5877794bc31daniel_Tomas LLCP_PRINT("?"); 994bf52196cdecd0decc2f8deabb19bf5877794bc31daniel_Tomas } 995bf52196cdecd0decc2f8deabb19bf5877794bc31daniel_Tomas 996bf52196cdecd0decc2f8deabb19bf5877794bc31daniel_Tomas 9975d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check new link status */ 9985d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly switch(Llcp->state) 9995d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 10005d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle packets in PAX-waiting state */ 10015d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case PHFRINFC_LLCP_STATE_PAX: 10025d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 10035d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check packet type */ 10045d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (sPacketHeader.ptype == PHFRINFC_LLCP_PTYPE_PAX) 10055d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 10065d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Params exchanged during MAC activation, try LLC activation */ 10075d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = phFriNfc_Llcp_InternalActivate(Llcp, psData+PHFRINFC_LLCP_PACKET_HEADER_SIZE); 10085d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* If the local LLC is the target, it must answer the PAX */ 10095d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeTarget) 10105d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 10115d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Send PAX */ 10125d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = phFriNfc_Llcp_SendPax(Llcp, &Llcp->sLocalParams); 10135d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 10145d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 10155d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else 10165d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 10175d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Warning: Received packet with unhandled type in PAX-waiting state, drop it */ 10185d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 10195d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 10205d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 10215d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 10225d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle normal operation packets */ 10235d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case PHFRINFC_LLCP_STATE_OPERATION_RECV: 10245d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly case PHFRINFC_LLCP_STATE_OPERATION_SEND: 10255d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 10265d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle Symmetry procedure by resetting LTO timer */ 10275d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_ResetLTO(Llcp); 10285d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle packet */ 10295d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = phFriNfc_Llcp_HandleIncomingPacket(Llcp, psData); 10305d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if ( (result != NFCSTATUS_SUCCESS) && 10315d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly (result != NFCSTATUS_PENDING) ) 10325d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 10335d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* TODO: Error: invalid frame */ 10345d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 10355d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Perform pending send request, if any */ 10365d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_HandlePendingSend(Llcp); 10375d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly break; 10385d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 10395d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 10405d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly default: 10415d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 10425d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Warning: Should not receive packets in other states, drop them */ 10435d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 10445d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 10455d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 10465d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Restart reception */ 10475d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->sRxBuffer.length = Llcp->nRxBufferLength; 10485d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_LlcpMac_Receive(&Llcp->MAC, &Llcp->sRxBuffer, phFriNfc_Llcp_Receive_CB, Llcp); 10495d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 10505d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 10515d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 10525d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic void phFriNfc_Llcp_Send_CB( void *pContext, 10535d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS status ) 10545d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 10555d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Get monitor from context */ 10565d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext; 10575d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_Send_CB_t pfSendCB; 10585d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly void *pSendContext; 10595d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 10605d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Call the upper layer callback if last packet sent was */ 10615d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* NOTE: if Llcp->psSendHeader is not NULL, this means that the send operation is still not initiated */ 10625d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->psSendHeader == NULL) 10635d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 10645d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->pfSendCB != NULL) 10655d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 10665d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Get Callback params */ 10675d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly pfSendCB = Llcp->pfSendCB; 10685d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly pSendContext = Llcp->pSendContext; 10695d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Reset callback params */ 10705d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pfSendCB = NULL; 10715d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pSendContext = NULL; 10725d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Call the callback */ 10735d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly (pfSendCB)(pSendContext, status); 10745d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 10755d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 107628ab3385d05d10437c6b1f0168bab6ed71bf4bfdSylvain Fonteneau 107728ab3385d05d10437c6b1f0168bab6ed71bf4bfdSylvain Fonteneau /* Check reception status */ 107828ab3385d05d10437c6b1f0168bab6ed71bf4bfdSylvain Fonteneau if (status != NFCSTATUS_SUCCESS) 107928ab3385d05d10437c6b1f0168bab6ed71bf4bfdSylvain Fonteneau { 108028ab3385d05d10437c6b1f0168bab6ed71bf4bfdSylvain Fonteneau /* Error: Reception failed, link must be down */ 108128ab3385d05d10437c6b1f0168bab6ed71bf4bfdSylvain Fonteneau phFriNfc_Llcp_InternalDeactivate(Llcp); 108228ab3385d05d10437c6b1f0168bab6ed71bf4bfdSylvain Fonteneau } 10835d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 10845d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 10855d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 10865d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pellystatic NFCSTATUS phFriNfc_Llcp_InternalSend( phFriNfc_Llcp_t *Llcp, 10875d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketHeader_t *psHeader, 10885d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketSequence_t *psSequence, 10895d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t *psInfo ) 10905d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 10915d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS status; 10925d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t *psRawPacket = &Llcp->sTxBuffer; /* Use internal Tx buffer */ 10935d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 10945d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Handle Symmetry procedure */ 10955d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_ResetLTO(Llcp); 10965d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 10975d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Generate raw packet to send (aggregate header + sequence + info fields) */ 10985d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psRawPacket->length = 0; 10995d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psRawPacket->length += phFriNfc_Llcp_Header2Buffer(psHeader, psRawPacket->buffer, psRawPacket->length); 11005d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (psSequence != NULL) 11015d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 11025d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psRawPacket->length += phFriNfc_Llcp_Sequence2Buffer(psSequence, psRawPacket->buffer, psRawPacket->length); 11035d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 11045d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (psInfo != NULL) 11055d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 11065d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly memcpy(psRawPacket->buffer + psRawPacket->length, psInfo->buffer, psInfo->length); 11075d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psRawPacket->length += psInfo->length; 11085d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 11095d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 11105d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (psHeader->ptype != PHFRINFC_LLCP_PTYPE_SYMM) 11115d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 11125d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly LLCP_PRINT_BUFFER("\nSending LLCP packet :", psRawPacket->buffer, psRawPacket->length); 11135d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 11145d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else 11155d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 11165d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly LLCP_PRINT("!"); 11175d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 11185d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 11195d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Send raw packet */ 11205d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly status = phFriNfc_LlcpMac_Send ( 11215d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly &Llcp->MAC, 11225d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psRawPacket, 11235d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_Send_CB, 11245d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp ); 11255d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 11265d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return status; 11275d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 11285d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 11295d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly/* ---------------------------- Public functions ------------------------------- */ 11305d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 11315d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick PellyNFCSTATUS phFriNfc_Llcp_EncodeLinkParams( phNfc_sData_t *psRawBuffer, 11325d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sLinkParameters_t *psLinkParams, 11335d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t nVersion ) 11345d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 11355d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint32_t nOffset = 0; 11365d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint16_t miux; 11375d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint16_t wks; 11385d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint8_t pValue[2]; 11395d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS result = NFCSTATUS_SUCCESS; 11405d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 11415d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check parameters */ 11425d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if ((psRawBuffer == NULL) || (psLinkParams == NULL)) 11435d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 11445d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_INVALID_PARAMETER; 11455d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 11465d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 11475d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Encode mandatory VERSION field */ 11485d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (result == NFCSTATUS_SUCCESS) 11495d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 11505d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = phFriNfc_Llcp_EncodeTLV( 11515d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psRawBuffer, 11525d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly &nOffset, 11535d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly PHFRINFC_LLCP_TLV_TYPE_VERSION, 11545d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly PHFRINFC_LLCP_TLV_LENGTH_VERSION, 11555d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly &nVersion); 11565d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 11575d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 11585d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Encode mandatory VERSION field */ 11595d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (result == NFCSTATUS_SUCCESS) 11605d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 11615d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Encode MIUX field, if needed */ 11625d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (psLinkParams->miu != PHFRINFC_LLCP_MIU_DEFAULT) 11635d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 11645d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly miux = (psLinkParams->miu - PHFRINFC_LLCP_MIU_DEFAULT) & PHFRINFC_LLCP_TLV_MIUX_MASK; 11655d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly pValue[0] = (miux >> 8) & 0xFF; 11665d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly pValue[1] = miux & 0xFF; 11675d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = phFriNfc_Llcp_EncodeTLV( 11685d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psRawBuffer, 11695d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly &nOffset, 11705d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly PHFRINFC_LLCP_TLV_TYPE_MIUX, 11715d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly PHFRINFC_LLCP_TLV_LENGTH_MIUX, 11725d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly pValue); 11735d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 11745d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 11755d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 11765d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Encode WKS field */ 11775d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (result == NFCSTATUS_SUCCESS) 11785d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 11795d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly wks = psLinkParams->wks | PHFRINFC_LLCP_TLV_WKS_MASK; 11805d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly pValue[0] = (wks >> 8) & 0xFF; 11815d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly pValue[1] = wks & 0xFF; 11825d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = phFriNfc_Llcp_EncodeTLV( 11835d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psRawBuffer, 11845d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly &nOffset, 11855d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly PHFRINFC_LLCP_TLV_TYPE_WKS, 11865d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly PHFRINFC_LLCP_TLV_LENGTH_WKS, 11875d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly pValue); 11885d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 11895d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 11905d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Encode LTO field, if needed */ 11915d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (result == NFCSTATUS_SUCCESS) 11925d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 11935d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (psLinkParams->lto != PHFRINFC_LLCP_LTO_DEFAULT) 11945d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 11955d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = phFriNfc_Llcp_EncodeTLV( 11965d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psRawBuffer, 11975d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly &nOffset, 11985d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly PHFRINFC_LLCP_TLV_TYPE_LTO, 11995d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly PHFRINFC_LLCP_TLV_LENGTH_LTO, 12005d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly &psLinkParams->lto); 12015d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 12025d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 12035d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12045d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Encode OPT field, if needed */ 12055d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (result == NFCSTATUS_SUCCESS) 12065d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 12075d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (psLinkParams->option != PHFRINFC_LLCP_OPTION_DEFAULT) 12085d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 12095d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = phFriNfc_Llcp_EncodeTLV( 12105d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psRawBuffer, 12115d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly &nOffset, 12125d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly PHFRINFC_LLCP_TLV_TYPE_OPT, 12135d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly PHFRINFC_LLCP_TLV_LENGTH_OPT, 12145d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly &psLinkParams->option); 12155d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 12165d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 12175d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12185d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (result != NFCSTATUS_SUCCESS) 12195d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 12205d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error: failed to encode TLV */ 12215d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_FAILED; 12225d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 12235d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12245d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Save new buffer size */ 12255d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly psRawBuffer->length = nOffset; 12265d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12275d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return result; 12285d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 12295d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12305d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12315d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick PellyNFCSTATUS phFriNfc_Llcp_Reset( phFriNfc_Llcp_t *Llcp, 12325d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly void *LowerDevice, 12335d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sLinkParameters_t *psLinkParams, 12345d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly void *pRxBuffer, 12355d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint16_t nRxBufferLength, 12365d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly void *pTxBuffer, 12375d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly uint16_t nTxBufferLength, 12385d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_LinkStatus_CB_t pfLink_CB, 12395d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly void *pContext ) 12405d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 12415d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly const uint16_t nMaxHeaderSize = PHFRINFC_LLCP_PACKET_HEADER_SIZE + 12425d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE; 12435d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS result; 12445d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12455d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check parameters presence */ 12465d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if ((Llcp == NULL) || (LowerDevice == NULL) || (pfLink_CB == NULL) || 12475d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly (pRxBuffer == NULL) || (pTxBuffer == NULL) ) 12485d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 12495d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_INVALID_PARAMETER; 12505d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 12515d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12525d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check parameters value */ 12535d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (psLinkParams->miu < PHFRINFC_LLCP_MIU_DEFAULT) 12545d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 12555d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_INVALID_PARAMETER; 12565d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 12575d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12585d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check if buffers are large enough to support minimal MIU */ 12595d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if ((nRxBufferLength < (nMaxHeaderSize + PHFRINFC_LLCP_MIU_DEFAULT)) || 12605d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly (nTxBufferLength < (nMaxHeaderSize + PHFRINFC_LLCP_MIU_DEFAULT)) ) 12615d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 12625d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_BUFFER_TOO_SMALL; 12635d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 12645d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12655d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check compatibility between reception buffer size and announced MIU */ 12665d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (nRxBufferLength < (nMaxHeaderSize + psLinkParams->miu)) 12675d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 12685d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_BUFFER_TOO_SMALL; 12695d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 12705d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12715d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Start with a zero-filled monitor */ 12725d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly memset(Llcp, 0x00, sizeof(phFriNfc_Llcp_t)); 12735d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12745d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Reset the MAC Mapping layer */ 12755d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = phFriNfc_LlcpMac_Reset(&Llcp->MAC, LowerDevice, phFriNfc_Llcp_LinkStatus_CB, Llcp); 12765d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (result != NFCSTATUS_SUCCESS) { 12775d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return result; 12785d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 12795d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12805d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Save the working buffers */ 12815d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->sRxBuffer.buffer = pRxBuffer; 12825d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->sRxBuffer.length = nRxBufferLength; 12835d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->nRxBufferLength = nRxBufferLength; 12845d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->sTxBuffer.buffer = pTxBuffer; 12855d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->sTxBuffer.length = nTxBufferLength; 12865d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->nTxBufferLength = nTxBufferLength; 12875d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12885d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Save the link status callback references */ 12895d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pfLink_CB = pfLink_CB; 12905d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pLinkContext = pContext; 12915d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12925d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Save the local link parameters */ 12935d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly memcpy(&Llcp->sLocalParams, psLinkParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); 12945d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12955d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_SUCCESS; 12965d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 12975d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12985d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 12995d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick PellyNFCSTATUS phFriNfc_Llcp_ChkLlcp( phFriNfc_Llcp_t *Llcp, 13005d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phHal_sRemoteDevInformation_t *psRemoteDevInfo, 13015d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_Check_CB_t pfCheck_CB, 13025d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly void *pContext ) 13035d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 13045d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check parameters */ 13055d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if ( (Llcp == NULL) || (psRemoteDevInfo == NULL) || (pfCheck_CB == NULL) ) 13065d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 13075d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 13085d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 13095d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13105d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check current state */ 13115d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if( Llcp->state != PHFRINFC_LLCP_STATE_RESET_INIT ) { 13125d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE); 13135d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 13145d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13155d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Save the compliance check callback */ 13165d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pfChk_CB = pfCheck_CB; 13175d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pChkContext = pContext; 13185d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13195d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Forward check request to MAC layer */ 13205d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return phFriNfc_LlcpMac_ChkLlcp(&Llcp->MAC, psRemoteDevInfo, phFriNfc_Llcp_ChkLlcp_CB, (void*)Llcp); 13215d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 13225d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13235d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13245d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick PellyNFCSTATUS phFriNfc_Llcp_Activate( phFriNfc_Llcp_t *Llcp ) 13255d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 13265d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check parameters */ 13275d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp == NULL) 13285d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 13295d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 13305d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 13315d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13325d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check current state */ 13335d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if( Llcp->state != PHFRINFC_LLCP_STATE_CHECKED ) { 13345d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE); 13355d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 13365d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13375d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Update state */ 13385d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->state = PHFRINFC_LLCP_STATE_ACTIVATION; 13395d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13403cbab5882f6d89a52068a3fa72a7223971d6b7fdMartijn Coenen /* Reset any headers to send */ 13413cbab5882f6d89a52068a3fa72a7223971d6b7fdMartijn Coenen Llcp->psSendHeader = NULL; 13423cbab5882f6d89a52068a3fa72a7223971d6b7fdMartijn Coenen Llcp->psSendSequence = NULL; 13433cbab5882f6d89a52068a3fa72a7223971d6b7fdMartijn Coenen 13445d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Forward check request to MAC layer */ 13455d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return phFriNfc_LlcpMac_Activate(&Llcp->MAC); 13465d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 13475d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13485d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13495d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick PellyNFCSTATUS phFriNfc_Llcp_Deactivate( phFriNfc_Llcp_t *Llcp ) 13505d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 13515d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS status; 13525d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13535d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check parameters */ 13545d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp == NULL) 13555d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 13565d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 13575d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 13585d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13595d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check current state */ 13605d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if( (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_RECV) && 13615d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND) ) { 13625d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE); 13635d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 13645d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13655d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Send DISC packet */ 13665d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly status = phFriNfc_Llcp_SendDisconnect(Llcp); 13675d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (status == NFCSTATUS_PENDING) 13685d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 13695d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Wait for packet to be sent before deactivate link */ 13705d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return status; 13715d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 13725d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13735d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Perform actual deactivation */ 13745d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return phFriNfc_Llcp_InternalDeactivate(Llcp); 13755d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 13765d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13775d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13785d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick PellyNFCSTATUS phFriNfc_Llcp_GetLocalInfo( phFriNfc_Llcp_t *Llcp, 13795d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sLinkParameters_t *pParams ) 13805d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 13815d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check parameters */ 13825d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if ((Llcp == NULL) || (pParams == NULL)) 13835d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 13845d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 13855d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 13865d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13875d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Copy response */ 13885d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly memcpy(pParams, &Llcp->sLocalParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); 13895d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13905d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_SUCCESS; 13915d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 13925d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13935d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 13945d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick PellyNFCSTATUS phFriNfc_Llcp_GetRemoteInfo( phFriNfc_Llcp_t *Llcp, 13955d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sLinkParameters_t *pParams ) 13965d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 13975d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check parameters */ 13985d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if ((Llcp == NULL) || (pParams == NULL)) 13995d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 14005d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 14015d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 14025d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 14035d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Copy response */ 14045d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly memcpy(pParams, &Llcp->sRemoteParams, sizeof(phFriNfc_Llcp_sLinkParameters_t)); 14055d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 14065d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return NFCSTATUS_SUCCESS; 14075d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 14085d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 14095d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 14105d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick PellyNFCSTATUS phFriNfc_Llcp_Send( phFriNfc_Llcp_t *Llcp, 14115d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketHeader_t *psHeader, 14125d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_sPacketSequence_t *psSequence, 14135d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phNfc_sData_t *psInfo, 14145d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_Send_CB_t pfSend_CB, 14155d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly void *pContext ) 14165d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 14175d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS result; 14185d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check parameters */ 14195d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if ((Llcp == NULL) || (psHeader == NULL) || (pfSend_CB == NULL)) 14205d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 14215d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 14225d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 14235d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 14245d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check if previous phFriNfc_Llcp_Send() has finished */ 14255d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->pfSendCB != NULL) 14265d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 14275d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error: a send operation is already running */ 14285d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_REJECTED); 14295d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 14305d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 14315d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Save the callback parameters */ 14325d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pfSendCB = pfSend_CB; 14335d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pSendContext = pContext; 14345d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 14351927b9d35c5efe26676c1dae78e3d1ab906f7586Sylvain Fonteneau if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND) 14361927b9d35c5efe26676c1dae78e3d1ab906f7586Sylvain Fonteneau { 14371927b9d35c5efe26676c1dae78e3d1ab906f7586Sylvain Fonteneau /* Ready to send */ 14381927b9d35c5efe26676c1dae78e3d1ab906f7586Sylvain Fonteneau result = phFriNfc_Llcp_InternalSend(Llcp, psHeader, psSequence, psInfo); 14391927b9d35c5efe26676c1dae78e3d1ab906f7586Sylvain Fonteneau } 14401927b9d35c5efe26676c1dae78e3d1ab906f7586Sylvain Fonteneau else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) 14415d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 14425d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Not ready to send, save send params for later use */ 14435d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->psSendHeader = psHeader; 14445d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->psSendSequence = psSequence; 1445f3fc813f66fba3a24ca96007507073c045e17c4bSylvain Fonteneau Llcp->psSendInfo = phFriNfc_Llcp_AllocateAndCopy(psInfo); 14465d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly result = NFCSTATUS_PENDING; 14475d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 14485d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly else 14495d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 14501927b9d35c5efe26676c1dae78e3d1ab906f7586Sylvain Fonteneau /* Incorrect state for sending ! */ 14511927b9d35c5efe26676c1dae78e3d1ab906f7586Sylvain Fonteneau result = PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);; 14525d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 145345101265f65461385bd7c81db0bfc84b334df8e0Martijn Coenen 145445101265f65461385bd7c81db0bfc84b334df8e0Martijn Coenen if (result != NFCSTATUS_PENDING) { 145545101265f65461385bd7c81db0bfc84b334df8e0Martijn Coenen Llcp->pfSendCB = NULL; 145645101265f65461385bd7c81db0bfc84b334df8e0Martijn Coenen } 14575d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return result; 14585d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 14595d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 14605d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 14615d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick PellyNFCSTATUS phFriNfc_Llcp_Recv( phFriNfc_Llcp_t *Llcp, 14625d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly phFriNfc_Llcp_Recv_CB_t pfRecv_CB, 14635d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly void *pContext ) 14645d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly{ 14655d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly NFCSTATUS result = NFCSTATUS_SUCCESS; 14665d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 14675d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check parameters */ 14685d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if ((Llcp == NULL) || (pfRecv_CB == NULL)) 14695d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 14705d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER); 14715d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 14725d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 14735d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Check if previous phFriNfc_Llcp_Recv() has finished */ 14745d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly if (Llcp->pfRecvCB != NULL) 14755d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly { 14765d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Error: a send operation is already running */ 14775d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_REJECTED); 14785d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly } 14795d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 14805d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* Save the callback parameters */ 14815d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pfRecvCB = pfRecv_CB; 14825d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly Llcp->pRecvContext = pContext; 14835d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 14845d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly /* NOTE: nothing more to do, the receive function is called in background */ 14855d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly 14865d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly return result; 14875d9927ba30ba449badb9f6df0fbeb4d6aedc6e2aNick Pelly} 1488