2 * Copyright (C) 2010 NXP Semiconductors
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
18 * \file phFriNfc_Llcp.c
\r
19 * \brief NFC LLCP core
\r
26 #include <phNfcLlcpTypes.h>
\r
27 #include <phOsalNfc_Timer.h>
\r
29 #include <phFriNfc_Llcp.h>
\r
30 #include <phFriNfc_LlcpUtils.h>
\r
34 * \name States of the LLC state machine.
\r
38 #define PHFRINFC_LLCP_STATE_RESET_INIT 0 /**< \internal Initial state.*/
\r
39 #define PHFRINFC_LLCP_STATE_CHECKED 1 /**< \internal The tag has been checked for LLCP compliance.*/
\r
40 #define PHFRINFC_LLCP_STATE_ACTIVATION 2 /**< \internal The deactivation phase.*/
\r
41 #define PHFRINFC_LLCP_STATE_PAX 3 /**< \internal Parameter exchange phase.*/
\r
42 #define PHFRINFC_LLCP_STATE_OPERATION_RECV 4 /**< \internal Normal operation phase (ready to receive).*/
\r
43 #define PHFRINFC_LLCP_STATE_OPERATION_SEND 5 /**< \internal Normal operation phase (ready to send).*/
\r
44 #define PHFRINFC_LLCP_STATE_DEACTIVATION 6 /**< \internal The deactivation phase.*/
\r
49 * \name Masks used for VERSION parsing.
\r
53 #define PHFRINFC_LLCP_VERSION_MAJOR_MASK 0xF0 /**< \internal Mask to apply to get major version number.*/
\r
54 #define PHFRINFC_LLCP_VERSION_MINOR_MASK 0x0F /**< \internal Mask to apply to get major version number.*/
\r
59 * \name Invalid values for parameters.
\r
63 #define PHFRINFC_LLCP_INVALID_VERSION 0x00 /**< \internal Invalid VERSION value.*/
\r
68 * \name Internal constants.
\r
72 #define PHFRINFC_LLCP_MAX_PARAM_TLV_LENGTH \
\r
73 (( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_VERSION ) + \
\r
74 ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_MIUX ) + \
\r
75 ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_WKS ) + \
\r
76 ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_LTO ) + \
\r
77 ( PHFRINFC_LLCP_TLV_LENGTH_HEADER + PHFRINFC_LLCP_TLV_LENGTH_OPT )) /**< \internal Maximum size of link params TLV.*/
\r
82 /* --------------------------- Internal functions ------------------------------ */
\r
84 static void phFriNfc_Llcp_Receive_CB( void *pContext,
\r
86 phNfc_sData_t *psData);
\r
87 static NFCSTATUS phFriNfc_Llcp_HandleIncomingPacket( phFriNfc_Llcp_t *Llcp,
\r
88 phNfc_sData_t *psPacket );
\r
89 static void phFriNfc_Llcp_ResetLTO( phFriNfc_Llcp_t *Llcp );
\r
90 static NFCSTATUS phFriNfc_Llcp_InternalSend( phFriNfc_Llcp_t *Llcp,
\r
91 phFriNfc_Llcp_sPacketHeader_t *psHeader,
\r
92 phFriNfc_Llcp_sPacketSequence_t *psSequence,
\r
93 phNfc_sData_t *psInfo );
\r
94 static bool_t phFriNfc_Llcp_HandlePendingSend ( phFriNfc_Llcp_t *Llcp );
\r
96 static phNfc_sData_t * phFriNfc_Llcp_AllocateAndCopy(phNfc_sData_t * pOrig)
\r
98 phNfc_sData_t * pDest = NULL;
\r
105 pDest = phOsalNfc_GetMemory(sizeof(phNfc_sData_t));
\r
111 pDest->buffer = phOsalNfc_GetMemory(pOrig->length);
\r
112 if (pDest->buffer == NULL)
\r
117 memcpy(pDest->buffer, pOrig->buffer, pOrig->length);
\r
118 pDest->length = pOrig->length;
\r
125 if (pDest->buffer != NULL)
\r
127 phOsalNfc_FreeMemory(pDest->buffer);
\r
129 phOsalNfc_FreeMemory(pDest);
\r
134 static void phFriNfc_Llcp_Deallocate(phNfc_sData_t * pData)
\r
138 if (pData->buffer != NULL)
\r
140 phOsalNfc_FreeMemory(pData->buffer);
\r
144 LLCP_PRINT("Warning, deallocating empty buffer");
\r
146 phOsalNfc_FreeMemory(pData);
\r
150 static NFCSTATUS phFriNfc_Llcp_InternalDeactivate( phFriNfc_Llcp_t *Llcp )
\r
152 phFriNfc_Llcp_Send_CB_t pfSendCB;
\r
153 void * pSendContext;
\r
154 if ((Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV) ||
\r
155 (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND) ||
\r
156 (Llcp->state == PHFRINFC_LLCP_STATE_PAX) ||
\r
157 (Llcp->state == PHFRINFC_LLCP_STATE_ACTIVATION))
\r
160 Llcp->state = PHFRINFC_LLCP_STATE_DEACTIVATION;
\r
163 phOsalNfc_Timer_Stop(Llcp->hSymmTimer);
\r
165 /* Return delayed send operation in error, in any */
\r
166 if (Llcp->psSendInfo != NULL)
\r
168 phFriNfc_Llcp_Deallocate(Llcp->psSendInfo);
\r
169 Llcp->psSendInfo = NULL;
\r
170 Llcp->psSendHeader = NULL;
\r
171 Llcp->psSendSequence = NULL;
\r
173 if (Llcp->pfSendCB != NULL)
\r
175 /* Get Callback params */
\r
176 pfSendCB = Llcp->pfSendCB;
\r
177 pSendContext = Llcp->pSendContext;
\r
178 /* Reset callback params */
\r
179 Llcp->pfSendCB = NULL;
\r
180 Llcp->pSendContext = NULL;
\r
181 /* Call the callback */
\r
182 (pfSendCB)(pSendContext, NFCSTATUS_FAILED);
\r
185 /* Notify service layer */
\r
186 Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkDeactivated);
\r
188 /* Forward check request to MAC layer */
\r
189 return phFriNfc_LlcpMac_Deactivate(&Llcp->MAC);
\r
192 return NFCSTATUS_SUCCESS;
\r
196 static NFCSTATUS phFriNfc_Llcp_SendSymm( phFriNfc_Llcp_t *Llcp )
\r
198 phFriNfc_Llcp_sPacketHeader_t sHeader;
\r
200 sHeader.dsap = PHFRINFC_LLCP_SAP_LINK;
\r
201 sHeader.ssap = PHFRINFC_LLCP_SAP_LINK;
\r
202 sHeader.ptype = PHFRINFC_LLCP_PTYPE_SYMM;
\r
203 return phFriNfc_Llcp_InternalSend(Llcp, &sHeader, NULL, NULL);
\r
207 static NFCSTATUS phFriNfc_Llcp_SendPax( phFriNfc_Llcp_t *Llcp, phFriNfc_Llcp_sLinkParameters_t *psLinkParams)
\r
209 uint8_t pTLVBuffer[PHFRINFC_LLCP_MAX_PARAM_TLV_LENGTH];
\r
210 phNfc_sData_t sParamsTLV;
\r
211 phFriNfc_Llcp_sPacketHeader_t sHeader;
\r
214 /* Prepare link parameters TLV */
\r
215 sParamsTLV.buffer = pTLVBuffer;
\r
216 sParamsTLV.length = PHFRINFC_LLCP_MAX_PARAM_TLV_LENGTH;
\r
217 result = phFriNfc_Llcp_EncodeLinkParams(&sParamsTLV, psLinkParams, PHFRINFC_LLCP_VERSION);
\r
218 if (result != NFCSTATUS_SUCCESS)
\r
220 /* Error while encoding */
\r
221 return NFCSTATUS_FAILED;
\r
224 /* Check if ready to send */
\r
225 if (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND)
\r
227 /* No send pending, send the PAX packet */
\r
228 sHeader.dsap = PHFRINFC_LLCP_SAP_LINK;
\r
229 sHeader.ssap = PHFRINFC_LLCP_SAP_LINK;
\r
230 sHeader.ptype = PHFRINFC_LLCP_PTYPE_PAX;
\r
231 return phFriNfc_Llcp_InternalSend(Llcp, &sHeader, NULL, &sParamsTLV);
\r
235 /* Error: A send is already pending, cannot send PAX */
\r
236 /* NOTE: this should not happen since PAX are sent before any other packet ! */
\r
237 return NFCSTATUS_FAILED;
\r
242 static NFCSTATUS phFriNfc_Llcp_SendDisconnect( phFriNfc_Llcp_t *Llcp )
\r
244 phFriNfc_Llcp_sPacketHeader_t sHeader;
\r
246 /* Check if ready to send */
\r
247 if (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND)
\r
249 /* No send pending, send the DISC packet */
\r
250 sHeader.dsap = PHFRINFC_LLCP_SAP_LINK;
\r
251 sHeader.ssap = PHFRINFC_LLCP_SAP_LINK;
\r
252 sHeader.ptype = PHFRINFC_LLCP_PTYPE_DISC;
\r
253 return phFriNfc_Llcp_InternalSend(Llcp, &sHeader, NULL, NULL);
\r
257 /* A send is already pending, raise a flag to send DISC as soon as possible */
\r
258 Llcp->bDiscPendingFlag = TRUE;
\r
259 return NFCSTATUS_PENDING;
\r
264 static void phFriNfc_Llcp_Timer_CB(uint32_t TimerId, void *pContext)
\r
266 phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext;
\r
268 PHNFC_UNUSED_VARIABLE(TimerId);
\r
270 /* Check current state */
\r
271 if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV)
\r
273 /* No data is coming before LTO, disconnecting */
\r
274 phFriNfc_Llcp_InternalDeactivate(Llcp);
\r
276 else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND)
\r
279 phFriNfc_Llcp_SendSymm(Llcp);
\r
283 /* Nothing to do if not in Normal Operation state */
\r
288 static NFCSTATUS phFriNfc_Llcp_HandleAggregatedPacket( phFriNfc_Llcp_t *Llcp,
\r
289 phNfc_sData_t *psRawPacket )
\r
291 phNfc_sData_t sInfo;
\r
292 phNfc_sData_t sCurrentInfo;
\r
296 /* Get info field */
\r
297 sInfo.buffer = psRawPacket->buffer + PHFRINFC_LLCP_PACKET_HEADER_SIZE;
\r
298 sInfo.length = psRawPacket->length - PHFRINFC_LLCP_PACKET_HEADER_SIZE;
\r
300 /* Check for empty info field */
\r
301 if (sInfo.length == 0)
\r
303 return NFCSTATUS_FAILED;
\r
306 /* Check consistency */
\r
307 while (sInfo.length != 0)
\r
309 /* Check if enough room to read length */
\r
310 if (sInfo.length < sizeof(sInfo.length))
\r
312 return NFCSTATUS_FAILED;
\r
315 length = (sInfo.buffer[0] << 8) | sInfo.buffer[1];
\r
316 /* Update info buffer */
\r
317 sInfo.buffer += 2; /*Size of length field is 2*/
\r
318 sInfo.length -= 2; /*Size of length field is 2*/
\r
319 /* Check if declared length fits in remaining space */
\r
320 if (length > sInfo.length)
\r
322 return NFCSTATUS_FAILED;
\r
324 /* Update info buffer */
\r
325 sInfo.buffer += length;
\r
326 sInfo.length -= length;
\r
329 /* Get info field */
\r
330 sInfo.buffer = psRawPacket->buffer + PHFRINFC_LLCP_PACKET_HEADER_SIZE;
\r
331 sInfo.length = psRawPacket->length - PHFRINFC_LLCP_PACKET_HEADER_SIZE;
\r
333 /* Handle aggregated packets */
\r
334 while (sInfo.length != 0)
\r
337 length = (sInfo.buffer[0] << 8) | sInfo.buffer[1];
\r
338 /* Update info buffer */
\r
339 sInfo.buffer += 2; /* Size of length field is 2 */
\r
340 sInfo.length -= 2; /*Size of length field is 2*/
\r
341 /* Handle aggregated packet */
\r
342 sCurrentInfo.buffer=sInfo.buffer;
\r
343 sCurrentInfo.length=length;
\r
344 status = phFriNfc_Llcp_HandleIncomingPacket(Llcp, &sCurrentInfo);
\r
345 if ( (status != NFCSTATUS_SUCCESS) &&
\r
346 (status != NFCSTATUS_PENDING) )
\r
348 /* TODO: Error: invalid frame */
\r
350 /* Update info buffer */
\r
351 sInfo.buffer += length;
\r
352 sInfo.length -= length;
\r
354 return NFCSTATUS_SUCCESS;
\r
358 static NFCSTATUS phFriNfc_Llcp_ParseLinkParams( phNfc_sData_t *psParamsTLV,
\r
359 phFriNfc_Llcp_sLinkParameters_t *psParsedParams,
\r
360 uint8_t *pnParsedVersion )
\r
364 phFriNfc_Llcp_sLinkParameters_t sParams;
\r
365 phNfc_sData_t sValueBuffer;
\r
366 uint32_t offset = 0;
\r
367 uint8_t version = PHFRINFC_LLCP_INVALID_VERSION;
\r
369 /* Check for NULL pointers */
\r
370 if ((psParamsTLV == NULL) || (psParsedParams == NULL) || (pnParsedVersion == NULL))
\r
372 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
\r
375 /* Prepare default param structure */
\r
376 sParams.miu = PHFRINFC_LLCP_MIU_DEFAULT;
\r
377 sParams.wks = PHFRINFC_LLCP_WKS_DEFAULT;
\r
378 sParams.lto = PHFRINFC_LLCP_LTO_DEFAULT;
\r
379 sParams.option = PHFRINFC_LLCP_OPTION_DEFAULT;
\r
382 while (offset < psParamsTLV->length)
\r
384 status = phFriNfc_Llcp_DecodeTLV(psParamsTLV, &offset, &type, &sValueBuffer);
\r
385 if (status != NFCSTATUS_SUCCESS)
\r
387 /* Error: Ill-formed TLV */
\r
392 case PHFRINFC_LLCP_TLV_TYPE_VERSION:
\r
395 if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_VERSION)
\r
397 /* Error : Ill-formed VERSION parameter TLV */
\r
401 version = sValueBuffer.buffer[0];
\r
404 case PHFRINFC_LLCP_TLV_TYPE_MIUX:
\r
407 if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_MIUX)
\r
409 /* Error : Ill-formed MIUX parameter TLV */
\r
413 sParams.miu = (PHFRINFC_LLCP_MIU_DEFAULT + ((sValueBuffer.buffer[0] << 8) | sValueBuffer.buffer[1])) & PHFRINFC_LLCP_TLV_MIUX_MASK;
\r
416 case PHFRINFC_LLCP_TLV_TYPE_WKS:
\r
419 if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_WKS)
\r
421 /* Error : Ill-formed MIUX parameter TLV */
\r
425 sParams.wks = (sValueBuffer.buffer[0] << 8) | sValueBuffer.buffer[1];
\r
426 /* Ignored bits must always be set */
\r
427 sParams.wks |= PHFRINFC_LLCP_TLV_WKS_MASK;
\r
430 case PHFRINFC_LLCP_TLV_TYPE_LTO:
\r
433 if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_LTO)
\r
435 /* Error : Ill-formed LTO parameter TLV */
\r
439 sParams.lto = sValueBuffer.buffer[0];
\r
442 case PHFRINFC_LLCP_TLV_TYPE_OPT:
\r
445 if (sValueBuffer.length != PHFRINFC_LLCP_TLV_LENGTH_OPT)
\r
447 /* Error : Ill-formed OPT parameter TLV */
\r
451 sParams.option = sValueBuffer.buffer[0] & PHFRINFC_LLCP_TLV_OPT_MASK;
\r
456 /* Error : Unknown Type */
\r
462 /* Check if a VERSION parameter has been provided */
\r
463 if (version == PHFRINFC_LLCP_INVALID_VERSION)
\r
465 /* Error : Mandatory VERSION parameter not provided */
\r
466 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
\r
469 /* Save response */
\r
470 *pnParsedVersion = version;
\r
471 memcpy(psParsedParams, &sParams, sizeof(phFriNfc_Llcp_sLinkParameters_t));
\r
473 return NFCSTATUS_SUCCESS;
\r
477 static NFCSTATUS phFriNfc_Llcp_VersionAgreement( uint8_t localVersion,
\r
478 uint8_t remoteVersion,
\r
479 uint8_t *pNegociatedVersion )
\r
481 uint8_t localMajor = localVersion & PHFRINFC_LLCP_VERSION_MAJOR_MASK;
\r
482 uint8_t localMinor = localVersion & PHFRINFC_LLCP_VERSION_MINOR_MASK;
\r
483 uint8_t remoteMajor = remoteVersion & PHFRINFC_LLCP_VERSION_MAJOR_MASK;
\r
484 uint8_t remoteMinor = remoteVersion & PHFRINFC_LLCP_VERSION_MINOR_MASK;
\r
485 uint8_t negociatedVersion;
\r
487 /* Check for NULL pointers */
\r
488 if (pNegociatedVersion == NULL)
\r
490 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
\r
493 /* Compare Major numbers */
\r
494 if (localMajor == remoteMajor)
\r
496 /* Version agreement succeed : use lowest version */
\r
497 negociatedVersion = localMajor | ((remoteMinor<localMinor)?remoteMinor:localMinor);
\r
499 else if (localMajor > remoteMajor)
\r
501 /* Decide if versions are compatible */
\r
502 /* Currently, there is no backward compatibility to handle */
\r
503 return NFCSTATUS_FAILED;
\r
505 else /* if (localMajor < remoteMajor) */
\r
507 /* It is up to the remote host to decide if versions are compatible */
\r
508 /* Set negociated version to our local version, the remote will
\r
509 deacivate the link if its own version agreement fails */
\r
510 negociatedVersion = localVersion;
\r
513 /* Save response */
\r
514 *pNegociatedVersion = negociatedVersion;
\r
516 return NFCSTATUS_SUCCESS;
\r
520 static NFCSTATUS phFriNfc_Llcp_InternalActivate( phFriNfc_Llcp_t *Llcp,
\r
521 phNfc_sData_t *psParamsTLV)
\r
524 phFriNfc_Llcp_sLinkParameters_t sRemoteParams;
\r
525 uint8_t remoteVersion;
\r
526 uint8_t negociatedVersion;
\r
527 const uint16_t nMaxHeaderSize = PHFRINFC_LLCP_PACKET_HEADER_SIZE +
\r
528 PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE;
\r
530 /* Parse parameters */
\r
531 status = phFriNfc_Llcp_ParseLinkParams(psParamsTLV, &sRemoteParams, &remoteVersion);
\r
532 if (status != NFCSTATUS_SUCCESS)
\r
534 /* Error: invalid parameters TLV */
\r
535 status = NFCSTATUS_FAILED;
\r
539 /* Version agreement procedure */
\r
540 status = phFriNfc_Llcp_VersionAgreement(PHFRINFC_LLCP_VERSION , remoteVersion, &negociatedVersion);
\r
541 if (status != NFCSTATUS_SUCCESS)
\r
543 /* Error: version agreement failed */
\r
544 status = NFCSTATUS_FAILED;
\r
548 /* Save parameters */
\r
549 Llcp->version = negociatedVersion;
\r
550 memcpy(&Llcp->sRemoteParams, &sRemoteParams, sizeof(phFriNfc_Llcp_sLinkParameters_t));
\r
552 /* Update remote MIU to match local Tx buffer size */
\r
553 if (Llcp->nTxBufferLength < (Llcp->sRemoteParams.miu + nMaxHeaderSize))
\r
555 Llcp->sRemoteParams.miu = Llcp->nTxBufferLength - nMaxHeaderSize;
\r
558 /* Initiate Symmetry procedure by resetting LTO timer */
\r
559 /* NOTE: this also updates current state */
\r
560 phFriNfc_Llcp_ResetLTO(Llcp);
\r
564 /* Notify upper layer, if Activation failed CB called by Deactivate */
\r
565 if (status == NFCSTATUS_SUCCESS)
\r
567 /* Link activated ! */
\r
568 Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkActivated);
\r
575 static NFCSTATUS phFriNfc_Llcp_HandleMACLinkActivated( phFriNfc_Llcp_t *Llcp,
\r
576 phNfc_sData_t *psParamsTLV)
\r
578 NFCSTATUS status = NFCSTATUS_SUCCESS;
\r
580 /* Create the timer */
\r
581 Llcp->hSymmTimer = phOsalNfc_Timer_Create();
\r
582 if (Llcp->hSymmTimer == PH_OSALNFC_INVALID_TIMER_ID)
\r
584 /* Error: unable to create timer */
\r
585 return NFCSTATUS_INSUFFICIENT_RESOURCES;
\r
588 /* Check if params received from MAC activation procedure */
\r
589 if (psParamsTLV == NULL)
\r
591 /* No params with selected MAC mapping, enter PAX mode for parameter exchange */
\r
592 Llcp->state = PHFRINFC_LLCP_STATE_PAX;
\r
593 /* Set default MIU for PAX exchange */
\r
594 Llcp->sRemoteParams.miu = PHFRINFC_LLCP_MIU_DEFAULT;
\r
595 /* If the local device is the initiator, it must initiate PAX exchange */
\r
596 if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeInitiator)
\r
599 status = phFriNfc_Llcp_SendPax(Llcp, &Llcp->sLocalParams);
\r
604 /* Params exchanged during MAX activation, try LLC activation */
\r
605 status = phFriNfc_Llcp_InternalActivate(Llcp, psParamsTLV);
\r
608 if (status == NFCSTATUS_SUCCESS)
\r
610 /* Start listening for incoming packets */
\r
611 Llcp->sRxBuffer.length = Llcp->nRxBufferLength;
\r
612 phFriNfc_LlcpMac_Receive(&Llcp->MAC, &Llcp->sRxBuffer, phFriNfc_Llcp_Receive_CB, Llcp);
\r
619 static void phFriNfc_Llcp_HandleMACLinkDeactivated( phFriNfc_Llcp_t *Llcp )
\r
621 uint8_t state = Llcp->state;
\r
623 /* Delete the timer */
\r
624 if (Llcp->hSymmTimer != PH_OSALNFC_INVALID_TIMER_ID)
\r
626 phOsalNfc_Timer_Delete(Llcp->hSymmTimer);
\r
630 Llcp->state = PHFRINFC_LLCP_STATE_CHECKED;
\r
634 case PHFRINFC_LLCP_STATE_DEACTIVATION:
\r
636 /* The service layer has already been notified, nothing more to do */
\r
641 /* Notify service layer of link failure */
\r
642 Llcp->pfLink_CB(Llcp->pLinkContext, phFriNfc_LlcpMac_eLinkDeactivated);
\r
649 static void phFriNfc_Llcp_ChkLlcp_CB( void *pContext,
\r
652 /* Get monitor from context */
\r
653 phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext;
\r
656 Llcp->state = PHFRINFC_LLCP_STATE_CHECKED;
\r
658 /* Invoke callback */
\r
659 Llcp->pfChk_CB(Llcp->pChkContext, status);
\r
662 static void phFriNfc_Llcp_LinkStatus_CB( void *pContext,
\r
663 phFriNfc_LlcpMac_eLinkStatus_t eLinkStatus,
\r
664 phNfc_sData_t *psParamsTLV,
\r
665 phFriNfc_LlcpMac_ePeerType_t PeerRemoteDevType)
\r
669 /* Get monitor from context */
\r
670 phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext;
\r
672 /* Save the local peer role (initiator/target) */
\r
673 Llcp->eRole = PeerRemoteDevType;
\r
675 /* Check new link status */
\r
676 switch(eLinkStatus)
\r
678 case phFriNfc_LlcpMac_eLinkActivated:
\r
680 /* Handle MAC link activation */
\r
681 status = phFriNfc_Llcp_HandleMACLinkActivated(Llcp, psParamsTLV);
\r
682 if (status != NFCSTATUS_SUCCESS)
\r
684 /* Error: LLC link activation procedure failed, deactivate MAC link */
\r
685 status = phFriNfc_Llcp_InternalDeactivate(Llcp);
\r
689 case phFriNfc_LlcpMac_eLinkDeactivated:
\r
691 /* Handle MAC link deactivation (cannot fail) */
\r
692 phFriNfc_Llcp_HandleMACLinkDeactivated(Llcp);
\r
697 /* Warning: Unknown link status, should not happen */
\r
703 static void phFriNfc_Llcp_ResetLTO( phFriNfc_Llcp_t *Llcp )
\r
705 uint32_t nDuration;
\r
708 phOsalNfc_Timer_Stop(Llcp->hSymmTimer);
\r
712 if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV)
\r
714 Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_SEND;
\r
716 else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND)
\r
718 Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_RECV;
\r
722 /* Not yet in OPERATION state, perform first reset */
\r
723 if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeInitiator)
\r
725 Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_SEND;
\r
729 Llcp->state = PHFRINFC_LLCP_STATE_OPERATION_RECV;
\r
733 /* Calculate timer duration */
\r
734 /* NOTE: nDuration is in 1/100s, and timer system takes values in 1/1000s */
\r
735 if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV)
\r
737 /* Response must be received before LTO announced by remote peer */
\r
738 nDuration = Llcp->sRemoteParams.lto * 10;
\r
742 /* Must answer before the local announced LTO */
\r
743 /* NOTE: to ensure the answer is completely sent before LTO, the
\r
744 timer is triggered _before_ LTO expiration */
\r
745 /* TODO: make sure time scope is enough, and avoid use of magic number */
\r
746 nDuration = (Llcp->sLocalParams.lto * 10) / 2;
\r
749 LLCP_DEBUG("Starting LLCP timer with duration %d", nDuration);
\r
751 /* Restart timer */
\r
752 phOsalNfc_Timer_Start(
\r
755 phFriNfc_Llcp_Timer_CB,
\r
760 static NFCSTATUS phFriNfc_Llcp_HandleLinkPacket( phFriNfc_Llcp_t *Llcp,
\r
761 phNfc_sData_t *psPacket )
\r
764 phFriNfc_Llcp_sPacketHeader_t sHeader;
\r
767 phFriNfc_Llcp_Buffer2Header(psPacket->buffer, 0, &sHeader);
\r
769 /* Check packet type */
\r
770 switch (sHeader.ptype)
\r
772 case PHFRINFC_LLCP_PTYPE_SYMM:
\r
774 /* Nothing to do, the LTO is handled upon all packet reception */
\r
775 result = NFCSTATUS_SUCCESS;
\r
779 case PHFRINFC_LLCP_PTYPE_AGF:
\r
781 /* Handle the aggregated packet */
\r
782 result = phFriNfc_Llcp_HandleAggregatedPacket(Llcp, psPacket);
\r
783 if (result != NFCSTATUS_SUCCESS)
\r
785 /* Error: invalid info field, dropping frame */
\r
790 case PHFRINFC_LLCP_PTYPE_DISC:
\r
792 /* Handle link disconnection request */
\r
793 result = phFriNfc_Llcp_InternalDeactivate(Llcp);
\r
798 case PHFRINFC_LLCP_PTYPE_FRMR:
\r
800 /* TODO: what to do upon reception of FRMR on Link SAP ? */
\r
801 result = NFCSTATUS_SUCCESS;
\r
805 case PHFRINFC_LLCP_PTYPE_PAX:
\r
807 /* Ignore PAX when in Normal Operation */
\r
808 result = NFCSTATUS_SUCCESS;
\r
814 /* Error: invalid ptype field, dropping packet */
\r
823 static NFCSTATUS phFriNfc_Llcp_HandleTransportPacket( phFriNfc_Llcp_t *Llcp,
\r
824 phNfc_sData_t *psPacket )
\r
826 phFriNfc_Llcp_Recv_CB_t pfRecvCB;
\r
828 NFCSTATUS result = NFCSTATUS_SUCCESS;
\r
829 phFriNfc_Llcp_sPacketHeader_t sHeader;
\r
831 /* Forward to upper layer */
\r
832 if (Llcp->pfRecvCB != NULL)
\r
834 /* Get callback details */
\r
835 pfRecvCB = Llcp->pfRecvCB;
\r
836 pContext = Llcp->pRecvContext;
\r
837 /* Reset callback details */
\r
838 Llcp->pfRecvCB = NULL;
\r
839 Llcp->pRecvContext = NULL;
\r
840 /* Call the callback */
\r
841 (pfRecvCB)(pContext, psPacket, NFCSTATUS_SUCCESS);
\r
848 static bool_t phFriNfc_Llcp_HandlePendingSend ( phFriNfc_Llcp_t *Llcp )
\r
850 phFriNfc_Llcp_sPacketHeader_t sHeader;
\r
851 phNfc_sData_t sInfoBuffer;
\r
852 phFriNfc_Llcp_sPacketHeader_t *psSendHeader = NULL;
\r
853 phFriNfc_Llcp_sPacketSequence_t *psSendSequence = NULL;
\r
854 phNfc_sData_t *psSendInfo = NULL;
\r
856 uint8_t bDeallocate = FALSE;
\r
857 uint8_t return_value = FALSE;
\r
859 /* Handle pending disconnection request */
\r
860 if (Llcp->bDiscPendingFlag == TRUE)
\r
862 /* Last send si acheived, send the pending DISC packet */
\r
863 sHeader.dsap = PHFRINFC_LLCP_SAP_LINK;
\r
864 sHeader.ssap = PHFRINFC_LLCP_SAP_LINK;
\r
865 sHeader.ptype = PHFRINFC_LLCP_PTYPE_DISC;
\r
866 /* Set send params */
\r
867 psSendHeader = &sHeader;
\r
869 Llcp->bDiscPendingFlag = FALSE;
\r
871 /* Handle pending frame reject request */
\r
872 else if (Llcp->bFrmrPendingFlag == TRUE)
\r
874 /* Last send si acheived, send the pending FRMR packet */
\r
875 sInfoBuffer.buffer = Llcp->pFrmrInfo;
\r
876 sInfoBuffer.length = sizeof(Llcp->pFrmrInfo);
\r
877 /* Set send params */
\r
878 psSendHeader = &Llcp->sFrmrHeader;
\r
879 psSendInfo = &sInfoBuffer;
\r
881 Llcp->bFrmrPendingFlag = FALSE;
\r
883 /* Handle pending service frame */
\r
884 else if (Llcp->pfSendCB != NULL)
\r
886 /* Set send params */
\r
887 psSendHeader = Llcp->psSendHeader;
\r
888 psSendSequence = Llcp->psSendSequence;
\r
889 psSendInfo = Llcp->psSendInfo;
\r
890 /* Reset pending send infos */
\r
891 Llcp->psSendHeader = NULL;
\r
892 Llcp->psSendSequence = NULL;
\r
893 Llcp->psSendInfo = NULL;
\r
894 bDeallocate = TRUE;
\r
897 /* Perform send, if needed */
\r
898 if (psSendHeader != NULL)
\r
900 result = phFriNfc_Llcp_InternalSend(Llcp, psSendHeader, psSendSequence, psSendInfo);
\r
901 if ((result != NFCSTATUS_SUCCESS) && (result != NFCSTATUS_PENDING))
\r
903 /* Error: send failed, impossible to recover */
\r
904 phFriNfc_Llcp_InternalDeactivate(Llcp);
\r
906 return_value = TRUE;
\r
907 } else if (Llcp->pfSendCB == NULL) {
\r
908 // Nothing to send, send SYMM instead to allow peer to send something
\r
910 phFriNfc_Llcp_SendSymm(Llcp);
\r
911 return_value = TRUE;
\r
917 phFriNfc_Llcp_Deallocate(psSendInfo);
\r
920 return return_value;
\r
923 static NFCSTATUS phFriNfc_Llcp_HandleIncomingPacket( phFriNfc_Llcp_t *Llcp,
\r
924 phNfc_sData_t *psPacket )
\r
926 NFCSTATUS status = NFCSTATUS_SUCCESS;
\r
927 phFriNfc_Llcp_sPacketHeader_t sHeader;
\r
930 phFriNfc_Llcp_Buffer2Header(psPacket->buffer, 0, &sHeader);
\r
932 /* Check destination */
\r
933 if (sHeader.dsap == PHFRINFC_LLCP_SAP_LINK)
\r
935 /* Handle packet as destinated to the Link SAP */
\r
936 status = phFriNfc_Llcp_HandleLinkPacket(Llcp, psPacket);
\r
938 else if (sHeader.dsap >= PHFRINFC_LLCP_SAP_NUMBER)
\r
940 /* NOTE: this cannot happen since "psHeader->dsap" is only 6-bit wide */
\r
941 status = NFCSTATUS_FAILED;
\r
945 /* Handle packet as destinated to the SDP and transport SAPs */
\r
946 status = phFriNfc_Llcp_HandleTransportPacket(Llcp, psPacket);
\r
952 static void phFriNfc_Llcp_Receive_CB( void *pContext,
\r
954 phNfc_sData_t *psData)
\r
956 /* Get monitor from context */
\r
957 phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext;
\r
958 NFCSTATUS result = NFCSTATUS_SUCCESS;
\r
959 phFriNfc_Llcp_sPacketHeader_t sPacketHeader;
\r
961 /* Check reception status and for pending disconnection */
\r
962 if ((status != NFCSTATUS_SUCCESS) || (Llcp->bDiscPendingFlag == TRUE))
\r
964 LLCP_DEBUG("\nReceived LLCP packet error - status = 0x%04x", status);
\r
965 /* Reset disconnection operation */
\r
966 Llcp->bDiscPendingFlag = FALSE;
\r
967 /* Deactivate the link */
\r
968 phFriNfc_Llcp_InternalDeactivate(Llcp);
\r
973 phFriNfc_Llcp_Buffer2Header(psData->buffer, 0, &sPacketHeader);
\r
975 if (sPacketHeader.ptype != PHFRINFC_LLCP_PTYPE_SYMM)
\r
977 LLCP_PRINT_BUFFER("\nReceived LLCP packet :", psData->buffer, psData->length);
\r
985 /* Check new link status */
\r
986 switch(Llcp->state)
\r
988 /* Handle packets in PAX-waiting state */
\r
989 case PHFRINFC_LLCP_STATE_PAX:
\r
991 /* Check packet type */
\r
992 if (sPacketHeader.ptype == PHFRINFC_LLCP_PTYPE_PAX)
\r
994 /* Params exchanged during MAC activation, try LLC activation */
\r
995 result = phFriNfc_Llcp_InternalActivate(Llcp, psData+PHFRINFC_LLCP_PACKET_HEADER_SIZE);
\r
996 /* If the local LLC is the target, it must answer the PAX */
\r
997 if (Llcp->eRole == phFriNfc_LlcpMac_ePeerTypeTarget)
\r
1000 result = phFriNfc_Llcp_SendPax(Llcp, &Llcp->sLocalParams);
\r
1005 /* Warning: Received packet with unhandled type in PAX-waiting state, drop it */
\r
1010 /* Handle normal operation packets */
\r
1011 case PHFRINFC_LLCP_STATE_OPERATION_RECV:
\r
1012 case PHFRINFC_LLCP_STATE_OPERATION_SEND:
\r
1014 /* Handle Symmetry procedure by resetting LTO timer */
\r
1015 phFriNfc_Llcp_ResetLTO(Llcp);
\r
1016 /* Handle packet */
\r
1017 result = phFriNfc_Llcp_HandleIncomingPacket(Llcp, psData);
\r
1018 if ( (result != NFCSTATUS_SUCCESS) &&
\r
1019 (result != NFCSTATUS_PENDING) )
\r
1021 /* TODO: Error: invalid frame */
\r
1023 /* Perform pending send request, if any */
\r
1024 phFriNfc_Llcp_HandlePendingSend(Llcp);
\r
1030 /* Warning: Should not receive packets in other states, drop them */
\r
1034 /* Restart reception */
\r
1035 Llcp->sRxBuffer.length = Llcp->nRxBufferLength;
\r
1036 phFriNfc_LlcpMac_Receive(&Llcp->MAC, &Llcp->sRxBuffer, phFriNfc_Llcp_Receive_CB, Llcp);
\r
1040 static void phFriNfc_Llcp_Send_CB( void *pContext,
\r
1041 NFCSTATUS status )
\r
1043 /* Get monitor from context */
\r
1044 phFriNfc_Llcp_t *Llcp = (phFriNfc_Llcp_t*)pContext;
\r
1045 phFriNfc_Llcp_Send_CB_t pfSendCB;
\r
1046 void *pSendContext;
\r
1048 /* Call the upper layer callback if last packet sent was */
\r
1049 /* NOTE: if Llcp->psSendHeader is not NULL, this means that the send operation is still not initiated */
\r
1050 if (Llcp->psSendHeader == NULL)
\r
1052 if (Llcp->pfSendCB != NULL)
\r
1054 /* Get Callback params */
\r
1055 pfSendCB = Llcp->pfSendCB;
\r
1056 pSendContext = Llcp->pSendContext;
\r
1057 /* Reset callback params */
\r
1058 Llcp->pfSendCB = NULL;
\r
1059 Llcp->pSendContext = NULL;
\r
1060 /* Call the callback */
\r
1061 (pfSendCB)(pSendContext, status);
\r
1065 /* Check reception status */
\r
1066 if (status != NFCSTATUS_SUCCESS)
\r
1068 /* Error: Reception failed, link must be down */
\r
1069 phFriNfc_Llcp_InternalDeactivate(Llcp);
\r
1074 static NFCSTATUS phFriNfc_Llcp_InternalSend( phFriNfc_Llcp_t *Llcp,
\r
1075 phFriNfc_Llcp_sPacketHeader_t *psHeader,
\r
1076 phFriNfc_Llcp_sPacketSequence_t *psSequence,
\r
1077 phNfc_sData_t *psInfo )
\r
1080 phNfc_sData_t *psRawPacket = &Llcp->sTxBuffer; /* Use internal Tx buffer */
\r
1082 /* Handle Symmetry procedure */
\r
1083 phFriNfc_Llcp_ResetLTO(Llcp);
\r
1085 /* Generate raw packet to send (aggregate header + sequence + info fields) */
\r
1086 psRawPacket->length = 0;
\r
1087 psRawPacket->length += phFriNfc_Llcp_Header2Buffer(psHeader, psRawPacket->buffer, psRawPacket->length);
\r
1088 if (psSequence != NULL)
\r
1090 psRawPacket->length += phFriNfc_Llcp_Sequence2Buffer(psSequence, psRawPacket->buffer, psRawPacket->length);
\r
1092 if (psInfo != NULL)
\r
1094 memcpy(psRawPacket->buffer + psRawPacket->length, psInfo->buffer, psInfo->length);
\r
1095 psRawPacket->length += psInfo->length;
\r
1098 if (psHeader->ptype != PHFRINFC_LLCP_PTYPE_SYMM)
\r
1100 LLCP_PRINT_BUFFER("\nSending LLCP packet :", psRawPacket->buffer, psRawPacket->length);
\r
1107 /* Send raw packet */
\r
1108 status = phFriNfc_LlcpMac_Send (
\r
1111 phFriNfc_Llcp_Send_CB,
\r
1117 /* ---------------------------- Public functions ------------------------------- */
\r
1119 NFCSTATUS phFriNfc_Llcp_EncodeLinkParams( phNfc_sData_t *psRawBuffer,
\r
1120 phFriNfc_Llcp_sLinkParameters_t *psLinkParams,
\r
1121 uint8_t nVersion )
\r
1123 uint32_t nOffset = 0;
\r
1126 uint8_t pValue[2];
\r
1127 NFCSTATUS result = NFCSTATUS_SUCCESS;
\r
1129 /* Check parameters */
\r
1130 if ((psRawBuffer == NULL) || (psLinkParams == NULL))
\r
1132 return NFCSTATUS_INVALID_PARAMETER;
\r
1135 /* Encode mandatory VERSION field */
\r
1136 if (result == NFCSTATUS_SUCCESS)
\r
1138 result = phFriNfc_Llcp_EncodeTLV(
\r
1141 PHFRINFC_LLCP_TLV_TYPE_VERSION,
\r
1142 PHFRINFC_LLCP_TLV_LENGTH_VERSION,
\r
1146 /* Encode mandatory VERSION field */
\r
1147 if (result == NFCSTATUS_SUCCESS)
\r
1149 /* Encode MIUX field, if needed */
\r
1150 if (psLinkParams->miu != PHFRINFC_LLCP_MIU_DEFAULT)
\r
1152 miux = (psLinkParams->miu - PHFRINFC_LLCP_MIU_DEFAULT) & PHFRINFC_LLCP_TLV_MIUX_MASK;
\r
1153 pValue[0] = (miux >> 8) & 0xFF;
\r
1154 pValue[1] = miux & 0xFF;
\r
1155 result = phFriNfc_Llcp_EncodeTLV(
\r
1158 PHFRINFC_LLCP_TLV_TYPE_MIUX,
\r
1159 PHFRINFC_LLCP_TLV_LENGTH_MIUX,
\r
1164 /* Encode WKS field */
\r
1165 if (result == NFCSTATUS_SUCCESS)
\r
1167 wks = psLinkParams->wks | PHFRINFC_LLCP_TLV_WKS_MASK;
\r
1168 pValue[0] = (wks >> 8) & 0xFF;
\r
1169 pValue[1] = wks & 0xFF;
\r
1170 result = phFriNfc_Llcp_EncodeTLV(
\r
1173 PHFRINFC_LLCP_TLV_TYPE_WKS,
\r
1174 PHFRINFC_LLCP_TLV_LENGTH_WKS,
\r
1178 /* Encode LTO field, if needed */
\r
1179 if (result == NFCSTATUS_SUCCESS)
\r
1181 if (psLinkParams->lto != PHFRINFC_LLCP_LTO_DEFAULT)
\r
1183 result = phFriNfc_Llcp_EncodeTLV(
\r
1186 PHFRINFC_LLCP_TLV_TYPE_LTO,
\r
1187 PHFRINFC_LLCP_TLV_LENGTH_LTO,
\r
1188 &psLinkParams->lto);
\r
1192 /* Encode OPT field, if needed */
\r
1193 if (result == NFCSTATUS_SUCCESS)
\r
1195 if (psLinkParams->option != PHFRINFC_LLCP_OPTION_DEFAULT)
\r
1197 result = phFriNfc_Llcp_EncodeTLV(
\r
1200 PHFRINFC_LLCP_TLV_TYPE_OPT,
\r
1201 PHFRINFC_LLCP_TLV_LENGTH_OPT,
\r
1202 &psLinkParams->option);
\r
1206 if (result != NFCSTATUS_SUCCESS)
\r
1208 /* Error: failed to encode TLV */
\r
1209 return NFCSTATUS_FAILED;
\r
1212 /* Save new buffer size */
\r
1213 psRawBuffer->length = nOffset;
\r
1219 NFCSTATUS phFriNfc_Llcp_Reset( phFriNfc_Llcp_t *Llcp,
\r
1220 void *LowerDevice,
\r
1221 phFriNfc_Llcp_sLinkParameters_t *psLinkParams,
\r
1223 uint16_t nRxBufferLength,
\r
1225 uint16_t nTxBufferLength,
\r
1226 phFriNfc_Llcp_LinkStatus_CB_t pfLink_CB,
\r
1229 const uint16_t nMaxHeaderSize = PHFRINFC_LLCP_PACKET_HEADER_SIZE +
\r
1230 PHFRINFC_LLCP_PACKET_SEQUENCE_SIZE;
\r
1233 /* Check parameters presence */
\r
1234 if ((Llcp == NULL) || (LowerDevice == NULL) || (pfLink_CB == NULL) ||
\r
1235 (pRxBuffer == NULL) || (pTxBuffer == NULL) )
\r
1237 return NFCSTATUS_INVALID_PARAMETER;
\r
1240 /* Check parameters value */
\r
1241 if (psLinkParams->miu < PHFRINFC_LLCP_MIU_DEFAULT)
\r
1243 return NFCSTATUS_INVALID_PARAMETER;
\r
1246 /* Check if buffers are large enough to support minimal MIU */
\r
1247 if ((nRxBufferLength < (nMaxHeaderSize + PHFRINFC_LLCP_MIU_DEFAULT)) ||
\r
1248 (nTxBufferLength < (nMaxHeaderSize + PHFRINFC_LLCP_MIU_DEFAULT)) )
\r
1250 return NFCSTATUS_BUFFER_TOO_SMALL;
\r
1253 /* Check compatibility between reception buffer size and announced MIU */
\r
1254 if (nRxBufferLength < (nMaxHeaderSize + psLinkParams->miu))
\r
1256 return NFCSTATUS_BUFFER_TOO_SMALL;
\r
1259 /* Start with a zero-filled monitor */
\r
1260 memset(Llcp, 0x00, sizeof(phFriNfc_Llcp_t));
\r
1262 /* Reset the MAC Mapping layer */
\r
1263 result = phFriNfc_LlcpMac_Reset(&Llcp->MAC, LowerDevice, phFriNfc_Llcp_LinkStatus_CB, Llcp);
\r
1264 if (result != NFCSTATUS_SUCCESS) {
\r
1268 /* Save the working buffers */
\r
1269 Llcp->sRxBuffer.buffer = pRxBuffer;
\r
1270 Llcp->sRxBuffer.length = nRxBufferLength;
\r
1271 Llcp->nRxBufferLength = nRxBufferLength;
\r
1272 Llcp->sTxBuffer.buffer = pTxBuffer;
\r
1273 Llcp->sTxBuffer.length = nTxBufferLength;
\r
1274 Llcp->nTxBufferLength = nTxBufferLength;
\r
1276 /* Save the link status callback references */
\r
1277 Llcp->pfLink_CB = pfLink_CB;
\r
1278 Llcp->pLinkContext = pContext;
\r
1280 /* Save the local link parameters */
\r
1281 memcpy(&Llcp->sLocalParams, psLinkParams, sizeof(phFriNfc_Llcp_sLinkParameters_t));
\r
1283 return NFCSTATUS_SUCCESS;
\r
1287 NFCSTATUS phFriNfc_Llcp_ChkLlcp( phFriNfc_Llcp_t *Llcp,
\r
1288 phHal_sRemoteDevInformation_t *psRemoteDevInfo,
\r
1289 phFriNfc_Llcp_Check_CB_t pfCheck_CB,
\r
1292 /* Check parameters */
\r
1293 if ( (Llcp == NULL) || (psRemoteDevInfo == NULL) || (pfCheck_CB == NULL) )
\r
1295 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
\r
1298 /* Check current state */
\r
1299 if( Llcp->state != PHFRINFC_LLCP_STATE_RESET_INIT ) {
\r
1300 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);
\r
1303 /* Save the compliance check callback */
\r
1304 Llcp->pfChk_CB = pfCheck_CB;
\r
1305 Llcp->pChkContext = pContext;
\r
1307 /* Forward check request to MAC layer */
\r
1308 return phFriNfc_LlcpMac_ChkLlcp(&Llcp->MAC, psRemoteDevInfo, phFriNfc_Llcp_ChkLlcp_CB, (void*)Llcp);
\r
1312 NFCSTATUS phFriNfc_Llcp_Activate( phFriNfc_Llcp_t *Llcp )
\r
1314 /* Check parameters */
\r
1317 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
\r
1320 /* Check current state */
\r
1321 if( Llcp->state != PHFRINFC_LLCP_STATE_CHECKED ) {
\r
1322 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);
\r
1325 /* Update state */
\r
1326 Llcp->state = PHFRINFC_LLCP_STATE_ACTIVATION;
\r
1328 /* Forward check request to MAC layer */
\r
1329 return phFriNfc_LlcpMac_Activate(&Llcp->MAC);
\r
1333 NFCSTATUS phFriNfc_Llcp_Deactivate( phFriNfc_Llcp_t *Llcp )
\r
1337 /* Check parameters */
\r
1340 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
\r
1343 /* Check current state */
\r
1344 if( (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_RECV) &&
\r
1345 (Llcp->state != PHFRINFC_LLCP_STATE_OPERATION_SEND) ) {
\r
1346 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);
\r
1349 /* Send DISC packet */
\r
1350 status = phFriNfc_Llcp_SendDisconnect(Llcp);
\r
1351 if (status == NFCSTATUS_PENDING)
\r
1353 /* Wait for packet to be sent before deactivate link */
\r
1357 /* Perform actual deactivation */
\r
1358 return phFriNfc_Llcp_InternalDeactivate(Llcp);
\r
1362 NFCSTATUS phFriNfc_Llcp_GetLocalInfo( phFriNfc_Llcp_t *Llcp,
\r
1363 phFriNfc_Llcp_sLinkParameters_t *pParams )
\r
1365 /* Check parameters */
\r
1366 if ((Llcp == NULL) || (pParams == NULL))
\r
1368 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
\r
1371 /* Copy response */
\r
1372 memcpy(pParams, &Llcp->sLocalParams, sizeof(phFriNfc_Llcp_sLinkParameters_t));
\r
1374 return NFCSTATUS_SUCCESS;
\r
1378 NFCSTATUS phFriNfc_Llcp_GetRemoteInfo( phFriNfc_Llcp_t *Llcp,
\r
1379 phFriNfc_Llcp_sLinkParameters_t *pParams )
\r
1381 /* Check parameters */
\r
1382 if ((Llcp == NULL) || (pParams == NULL))
\r
1384 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
\r
1387 /* Copy response */
\r
1388 memcpy(pParams, &Llcp->sRemoteParams, sizeof(phFriNfc_Llcp_sLinkParameters_t));
\r
1390 return NFCSTATUS_SUCCESS;
\r
1394 NFCSTATUS phFriNfc_Llcp_Send( phFriNfc_Llcp_t *Llcp,
\r
1395 phFriNfc_Llcp_sPacketHeader_t *psHeader,
\r
1396 phFriNfc_Llcp_sPacketSequence_t *psSequence,
\r
1397 phNfc_sData_t *psInfo,
\r
1398 phFriNfc_Llcp_Send_CB_t pfSend_CB,
\r
1403 /* Check parameters */
\r
1404 if ((Llcp == NULL) || (psHeader == NULL) || (pfSend_CB == NULL))
\r
1406 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
\r
1409 /* Check if previous phFriNfc_Llcp_Send() has finished */
\r
1410 if (Llcp->pfSendCB != NULL)
\r
1412 /* Error: a send operation is already running */
\r
1413 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_REJECTED);
\r
1416 /* Save the callback parameters */
\r
1417 Llcp->pfSendCB = pfSend_CB;
\r
1418 Llcp->pSendContext = pContext;
\r
1420 if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_SEND)
\r
1422 /* Ready to send */
\r
1423 result = phFriNfc_Llcp_InternalSend(Llcp, psHeader, psSequence, psInfo);
\r
1425 else if (Llcp->state == PHFRINFC_LLCP_STATE_OPERATION_RECV)
\r
1427 /* Not ready to send, save send params for later use */
\r
1428 Llcp->psSendHeader = psHeader;
\r
1429 Llcp->psSendSequence = psSequence;
\r
1430 Llcp->psSendInfo = phFriNfc_Llcp_AllocateAndCopy(psInfo);
\r
1431 result = NFCSTATUS_PENDING;
\r
1435 /* Incorrect state for sending ! */
\r
1436 result = PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_STATE);;
\r
1439 if (result != NFCSTATUS_PENDING) {
\r
1440 Llcp->pfSendCB = NULL;
\r
1446 NFCSTATUS phFriNfc_Llcp_Recv( phFriNfc_Llcp_t *Llcp,
\r
1447 phFriNfc_Llcp_Recv_CB_t pfRecv_CB,
\r
1450 NFCSTATUS result = NFCSTATUS_SUCCESS;
\r
1452 /* Check parameters */
\r
1453 if ((Llcp == NULL) || (pfRecv_CB == NULL))
\r
1455 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_INVALID_PARAMETER);
\r
1458 /* Check if previous phFriNfc_Llcp_Recv() has finished */
\r
1459 if (Llcp->pfRecvCB != NULL)
\r
1461 /* Error: a send operation is already running */
\r
1462 return PHNFCSTVAL(CID_FRI_NFC_LLCP, NFCSTATUS_REJECTED);
\r
1465 /* Save the callback parameters */
\r
1466 Llcp->pfRecvCB = pfRecv_CB;
\r
1467 Llcp->pRecvContext = pContext;
\r
1469 /* NOTE: nothing more to do, the receive function is called in background */
\r