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