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/**
19 * \file  phFriNfc_LlcpMacNfcip.c
20 * \brief NFC LLCP MAC Mappings For Different RF Technologies.
21 *
22 * Project: NFC-FRI
23 *
24 */
25
26
27/*include files*/
28#include <phFriNfc_LlcpMac.h>
29#include <phLibNfcStatus.h>
30#include <phLibNfc.h>
31#include <phLibNfc_Internal.h>
32#include <stdio.h>
33#include <string.h>
34
35static NFCSTATUS phFriNfc_LlcpMac_Nfcip_Send(phFriNfc_LlcpMac_t               *LlcpMac,
36                                             phNfc_sData_t                    *psData,
37                                             phFriNfc_LlcpMac_Send_CB_t       LlcpMacSend_Cb,
38                                             void                             *pContext);
39
40
41static void phFriNfc_LlcpMac_Nfcip_TriggerRecvCb(phFriNfc_LlcpMac_t  *LlcpMac,
42                                                 NFCSTATUS           status)
43{
44   phFriNfc_LlcpMac_Reveive_CB_t pfReceiveCB;
45   void                          *pReceiveContext;
46
47   if (LlcpMac->MacReceive_Cb != NULL)
48   {
49      /* Save callback params */
50      pfReceiveCB = LlcpMac->MacReceive_Cb;
51      pReceiveContext = LlcpMac->MacReceive_Context;
52
53      /* Reset the pointer to the Receive Callback and Context*/
54      LlcpMac->MacReceive_Cb = NULL;
55      LlcpMac->MacReceive_Context = NULL;
56
57      /* Call the receive callback */
58      pfReceiveCB(pReceiveContext, status, LlcpMac->psReceiveBuffer);
59   }
60}
61
62static void phFriNfc_LlcpMac_Nfcip_TriggerSendCb(phFriNfc_LlcpMac_t  *LlcpMac,
63                                                 NFCSTATUS           status)
64{
65   phFriNfc_LlcpMac_Send_CB_t pfSendCB;
66   void                       *pSendContext;
67
68   if (LlcpMac->MacSend_Cb != NULL)
69   {
70      /* Save context in local variables */
71      pfSendCB     = LlcpMac->MacSend_Cb;
72      pSendContext = LlcpMac->MacSend_Context;
73
74      /* Reset the pointer to the Send Callback */
75      LlcpMac->MacSend_Cb = NULL;
76      LlcpMac->MacSend_Context = NULL;
77
78      /* Call Send callback */
79      pfSendCB(pSendContext, status);
80   }
81}
82
83static NFCSTATUS phFriNfc_LlcpMac_Nfcip_Chk(phFriNfc_LlcpMac_t                   *LlcpMac,
84                                            phFriNfc_LlcpMac_Chk_CB_t            ChkLlcpMac_Cb,
85                                            void                                 *pContext)
86{
87   NFCSTATUS status = NFCSTATUS_SUCCESS;
88   uint8_t Llcp_Magic_Number[] = {0x46,0x66,0x6D};
89
90   if(NULL == LlcpMac || NULL == ChkLlcpMac_Cb || NULL == pContext)
91   {
92      status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_PARAMETER);
93   }
94   else
95   {
96      status = (NFCSTATUS)memcmp(Llcp_Magic_Number,LlcpMac->psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo,3);
97      if(!status)
98      {
99         LlcpMac->sConfigParam.buffer = &LlcpMac->psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo[3] ;
100         LlcpMac->sConfigParam.length = (LlcpMac->psRemoteDevInfo->RemoteDevInfo.NfcIP_Info.ATRInfo_Length - 3);
101         status = NFCSTATUS_SUCCESS;
102      }
103      else
104      {
105         status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_FAILED);
106      }
107      ChkLlcpMac_Cb(pContext,status);
108   }
109
110   return status;
111}
112
113static NFCSTATUS phFriNfc_LlcpMac_Nfcip_Activate (phFriNfc_LlcpMac_t   *LlcpMac)
114{
115   NFCSTATUS status  = NFCSTATUS_SUCCESS;
116
117   if(LlcpMac == NULL)
118   {
119      status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_PARAMETER);
120   }
121   else
122   {
123      LlcpMac->LinkState = phFriNfc_LlcpMac_eLinkActivated;
124      LlcpMac->LinkStatus_Cb(LlcpMac->LinkStatus_Context,
125                             LlcpMac->LinkState,
126                             &LlcpMac->sConfigParam,
127                             LlcpMac->PeerRemoteDevType);
128   }
129
130   return status;
131}
132
133static NFCSTATUS phFriNfc_LlcpMac_Nfcip_Deactivate (phFriNfc_LlcpMac_t   *LlcpMac)
134{
135   NFCSTATUS status  = NFCSTATUS_SUCCESS;
136
137   if(NULL == LlcpMac)
138   {
139      status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_PARAMETER);
140   }
141   else
142   {
143      /* Set the flag of LinkStatus to deactivate */
144      LlcpMac->LinkState = phFriNfc_LlcpMac_eLinkDeactivated;
145
146      if (LlcpMac->SendPending)
147      {
148         /* Reset Flag */
149         LlcpMac->SendPending = FALSE;
150         phFriNfc_LlcpMac_Nfcip_TriggerSendCb(LlcpMac, NFCSTATUS_FAILED);
151      }
152
153      if (LlcpMac->RecvPending)
154      {
155         /* Reset Flag */
156         LlcpMac->RecvPending = FALSE;
157         phFriNfc_LlcpMac_Nfcip_TriggerRecvCb(LlcpMac, NFCSTATUS_FAILED);
158      }
159
160      LlcpMac->LinkStatus_Cb(LlcpMac->LinkStatus_Context,
161                             LlcpMac->LinkState,
162                             NULL,
163                             LlcpMac->PeerRemoteDevType);
164   }
165
166   return status;
167}
168
169static void phFriNfc_LlcpMac_Nfcip_Send_Cb(void       *pContext,
170                                           NFCSTATUS   Status)
171{
172   phFriNfc_LlcpMac_t            *LlcpMac = (phFriNfc_LlcpMac_t *)pContext;
173
174#ifdef LLCP_CHANGES
175   if(gpphLibContext->LibNfcState.next_state
176                               == eLibNfcHalStateShutdown)
177   {
178      phLibNfc_Pending_Shutdown();
179      Status = NFCSTATUS_SHUTDOWN;
180   }
181#endif /* #ifdef LLCP_CHANGES */
182
183   /* Reset Send and Receive Flag */
184   LlcpMac->SendPending = FALSE;
185   LlcpMac->RecvPending = FALSE;
186
187   phFriNfc_LlcpMac_Nfcip_TriggerSendCb(LlcpMac, Status);
188
189}
190
191static void phFriNfc_LlcpMac_Nfcip_Receive_Cb(void       *pContext,
192                                              NFCSTATUS   Status)
193{
194   phFriNfc_LlcpMac_t               *LlcpMac = (phFriNfc_LlcpMac_t *)pContext;
195#ifdef LLCP_CHANGES
196
197   phFriNfc_LlcpMac_Send_CB_t       pfSendCB;
198   void                             *pSendContext;
199
200
201   if(gpphLibContext->LibNfcState.next_state
202                               == eLibNfcHalStateShutdown)
203   {
204      phLibNfc_Pending_Shutdown();
205      Status = NFCSTATUS_SHUTDOWN;
206   }
207
208   if (NFCSTATUS_SHUTDOWN == Status)
209   {
210      /* Save context in local variables */
211      pfSendCB = LlcpMac->MacSend_Cb;
212      pSendContext = LlcpMac->MacSend_Context;
213
214      /* Reset the pointer to the Send Callback */
215      LlcpMac->MacSend_Cb = NULL;
216      LlcpMac->MacSend_Context = NULL;
217
218      /* Reset Send and Receive Flag */
219      LlcpMac->SendPending = FALSE;
220      LlcpMac->RecvPending = FALSE;
221   }
222
223#endif /* #ifdef LLCP_CHANGES */
224
225   phFriNfc_LlcpMac_Nfcip_TriggerRecvCb(LlcpMac, Status);
226
227#ifdef LLCP_CHANGES
228
229   if (NFCSTATUS_SHUTDOWN == Status)
230   {
231       if ((LlcpMac->SendPending) && (NULL != pfSendCB))
232       {
233           pfSendCB(pSendContext, Status);
234      }
235   }
236   else
237
238#endif /* #ifdef LLCP_CHANGES */
239   {
240   /* Test if a send is pending */
241   if(LlcpMac->SendPending)
242   {
243      Status = phFriNfc_LlcpMac_Nfcip_Send(LlcpMac,LlcpMac->psSendBuffer,LlcpMac->MacSend_Cb,LlcpMac->MacSend_Context);
244   }
245}
246}
247
248static void phFriNfc_LlcpMac_Nfcip_Transceive_Cb(void       *pContext,
249                                                 NFCSTATUS   Status)
250{
251   phFriNfc_LlcpMac_t               *LlcpMac = (phFriNfc_LlcpMac_t *)pContext;
252
253#ifdef LLCP_CHANGES
254   if(gpphLibContext->LibNfcState.next_state
255                               == eLibNfcHalStateShutdown)
256   {
257      phLibNfc_Pending_Shutdown();
258      Status = NFCSTATUS_SHUTDOWN;
259   }
260#endif /* #ifdef LLCP_CHANGES */
261
262   /* Reset Send and Receive Flag */
263   LlcpMac->SendPending = FALSE;
264   LlcpMac->RecvPending = FALSE;
265
266   /* Call the callbacks */
267   phFriNfc_LlcpMac_Nfcip_TriggerSendCb(LlcpMac, Status);
268   phFriNfc_LlcpMac_Nfcip_TriggerRecvCb(LlcpMac, Status);
269}
270
271static NFCSTATUS phFriNfc_LlcpMac_Nfcip_Send(phFriNfc_LlcpMac_t               *LlcpMac,
272                                             phNfc_sData_t                    *psData,
273                                             phFriNfc_LlcpMac_Send_CB_t       LlcpMacSend_Cb,
274                                             void                             *pContext)
275{
276   NFCSTATUS status = NFCSTATUS_SUCCESS;
277
278   if(NULL == LlcpMac || NULL == psData || NULL == LlcpMacSend_Cb || NULL == pContext)
279   {
280      status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_PARAMETER);
281   }
282   else if(LlcpMac->MacSend_Cb != NULL && LlcpMac->PeerRemoteDevType == phFriNfc_LlcpMac_ePeerTypeInitiator)
283   {
284      /*Previous callback is pending */
285      status = NFCSTATUS_REJECTED;
286   }
287   else
288   {
289      /* Save the LlcpMacSend_Cb */
290      LlcpMac->MacSend_Cb = LlcpMacSend_Cb;
291      LlcpMac->MacSend_Context = pContext;
292
293      switch(LlcpMac->PeerRemoteDevType)
294      {
295      case phFriNfc_LlcpMac_ePeerTypeInitiator:
296         {
297            if(LlcpMac->RecvPending)
298            {
299               /*set the completion routines for the LLCP Transceive function*/
300                LlcpMac->MacCompletionInfo.CompletionRoutine = phFriNfc_LlcpMac_Nfcip_Transceive_Cb;
301                LlcpMac->MacCompletionInfo.Context = LlcpMac;
302
303                /* set the command type*/
304                LlcpMac->Cmd.NfcIP1Cmd = phHal_eNfcIP1_Raw;
305
306                /* set the Additional Info*/
307                LlcpMac->psDepAdditionalInfo.DepFlags.MetaChaining = 0;
308                LlcpMac->psDepAdditionalInfo.DepFlags.NADPresent = 0;
309                LlcpMac->SendPending = TRUE;
310
311                status = phFriNfc_OvrHal_Transceive(LlcpMac->LowerDevice,
312                                                    &LlcpMac->MacCompletionInfo,
313                                                    LlcpMac->psRemoteDevInfo,
314                                                    LlcpMac->Cmd,
315                                                    &LlcpMac->psDepAdditionalInfo,
316                                                    psData->buffer,
317                                                    (uint16_t)psData->length,
318                                                    LlcpMac->psReceiveBuffer->buffer,
319                                                    (uint16_t*)&LlcpMac->psReceiveBuffer->length);
320            }
321            else
322            {
323               LlcpMac->SendPending = TRUE;
324               LlcpMac->psSendBuffer = psData;
325               return status = NFCSTATUS_PENDING;
326            }
327         }break;
328      case phFriNfc_LlcpMac_ePeerTypeTarget:
329         {
330            if(!LlcpMac->RecvPending)
331            {
332               LlcpMac->SendPending = TRUE;
333               LlcpMac->psSendBuffer = psData;
334               return status = NFCSTATUS_PENDING;
335            }
336            else
337            {
338               /*set the completion routines for the LLCP Send function*/
339               LlcpMac->MacCompletionInfo.CompletionRoutine = phFriNfc_LlcpMac_Nfcip_Send_Cb;
340               LlcpMac->MacCompletionInfo.Context = LlcpMac;
341               status = phFriNfc_OvrHal_Send(LlcpMac->LowerDevice,
342                                             &LlcpMac->MacCompletionInfo,
343                                             LlcpMac->psRemoteDevInfo,
344                                             psData->buffer,
345                                             (uint16_t)psData->length);
346            }
347         }break;
348      default:
349         {
350            status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_DEVICE);
351         }break;
352      }
353   }
354   return status;
355}
356
357static NFCSTATUS phFriNfc_LlcpMac_Nfcip_Receive(phFriNfc_LlcpMac_t               *LlcpMac,
358                                                phNfc_sData_t                    *psData,
359                                                phFriNfc_LlcpMac_Reveive_CB_t    LlcpMacReceive_Cb,
360                                                void                             *pContext)
361{
362   NFCSTATUS status = NFCSTATUS_SUCCESS;
363   if(NULL == LlcpMac || NULL==psData || NULL == LlcpMacReceive_Cb || NULL == pContext)
364   {
365      status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_PARAMETER);
366   }
367   else if(LlcpMac->MacReceive_Cb != NULL)
368   {
369      /*Previous callback is pending */
370      status = NFCSTATUS_REJECTED;
371   }
372   else
373   {
374      /* Save the LlcpMacReceive_Cb */
375      LlcpMac->MacReceive_Cb = LlcpMacReceive_Cb;
376      LlcpMac->MacReceive_Context = pContext;
377
378      /* Save the pointer to the receive buffer */
379      LlcpMac->psReceiveBuffer= psData;
380
381      switch(LlcpMac->PeerRemoteDevType)
382      {
383      case phFriNfc_LlcpMac_ePeerTypeInitiator:
384         {
385            if(LlcpMac->SendPending)
386            {
387               /*set the completion routines for the LLCP Transceive function*/
388               LlcpMac->MacCompletionInfo.CompletionRoutine = phFriNfc_LlcpMac_Nfcip_Transceive_Cb;
389               LlcpMac->MacCompletionInfo.Context = LlcpMac;
390               /* set the command type*/
391               LlcpMac->Cmd.NfcIP1Cmd = phHal_eNfcIP1_Raw;
392               /* set the Additional Info*/
393               LlcpMac->psDepAdditionalInfo.DepFlags.MetaChaining = 0;
394               LlcpMac->psDepAdditionalInfo.DepFlags.NADPresent = 0;
395               LlcpMac->RecvPending = TRUE;
396
397               status = phFriNfc_OvrHal_Transceive(LlcpMac->LowerDevice,
398                                                   &LlcpMac->MacCompletionInfo,
399                                                   LlcpMac->psRemoteDevInfo,
400                                                   LlcpMac->Cmd,
401                                                   &LlcpMac->psDepAdditionalInfo,
402                                                   LlcpMac->psSendBuffer->buffer,
403                                                   (uint16_t)LlcpMac->psSendBuffer->length,
404                                                   psData->buffer,
405                                                   (uint16_t*)&psData->length);
406            }
407            else
408            {
409               LlcpMac->RecvPending = TRUE;
410               return status = NFCSTATUS_PENDING;
411            }
412         }break;
413      case phFriNfc_LlcpMac_ePeerTypeTarget:
414         {
415             /*set the completion routines for the LLCP Receive function*/
416            LlcpMac->MacCompletionInfo.CompletionRoutine = phFriNfc_LlcpMac_Nfcip_Receive_Cb;
417            /* save the context of LlcpMacNfcip */
418            LlcpMac->MacCompletionInfo.Context = LlcpMac;
419            LlcpMac->RecvPending = TRUE;
420
421            status = phFriNfc_OvrHal_Receive(LlcpMac->LowerDevice,
422                                             &LlcpMac->MacCompletionInfo,
423                                             LlcpMac->psRemoteDevInfo,
424                                             LlcpMac->psReceiveBuffer->buffer,
425                                             (uint16_t*)&LlcpMac->psReceiveBuffer->length);
426         }break;
427      default:
428         {
429            status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_INVALID_DEVICE);
430         }break;
431      }
432   }
433   return status;
434}
435
436
437NFCSTATUS phFriNfc_LlcpMac_Nfcip_Register (phFriNfc_LlcpMac_t *LlcpMac)
438{
439   NFCSTATUS status = NFCSTATUS_SUCCESS;
440
441   if(NULL != LlcpMac)
442   {
443      LlcpMac->LlcpMacInterface.chk = phFriNfc_LlcpMac_Nfcip_Chk;
444      LlcpMac->LlcpMacInterface.activate   = phFriNfc_LlcpMac_Nfcip_Activate;
445      LlcpMac->LlcpMacInterface.deactivate = phFriNfc_LlcpMac_Nfcip_Deactivate;
446      LlcpMac->LlcpMacInterface.send = phFriNfc_LlcpMac_Nfcip_Send;
447      LlcpMac->LlcpMacInterface.receive = phFriNfc_LlcpMac_Nfcip_Receive;
448
449      return NFCSTATUS_SUCCESS;
450   }
451   else
452   {
453      return status = PHNFCSTVAL(CID_FRI_NFC_LLCP_MAC, NFCSTATUS_FAILED);
454   }
455}
456