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