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