1/*
2 * Copyright (C) 2015 The Android Open Source Project
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#ifdef ESE_NFC_SYNCHRONIZATION
18#include <linux/ese-nfc-sync.h>
19#endif
20#include <fcntl.h>
21#include <sys/ioctl.h>
22#include <sys/time.h>
23
24#include <phNxpExtns_MifareStd.h>
25#include <phNxpLog.h>
26#include <phNxpConfig.h>
27
28phNxpExtns_Context_t         gphNxpExtns_Context;
29extern phFriNfc_NdefMap_t    *NdefMap;
30extern phNci_mfc_auth_cmd_t  gAuthCmdBuf;
31
32static NFCSTATUS phNxpExtns_ProcessSysMessage (phLibNfc_Message_t *msg);
33static NFCSTATUS phNxpExtns_SendMsg (phLibNfc_Message_t *sysmsg);
34
35#ifdef ESE_NFC_SYNCHRONIZATION
36/* timing calculation structure*/
37typedef struct time_cal
38{
39    struct timeval tv1;
40    struct timeval tv2;
41} TimeCal;
42static int fd_ese_nfc_sync; /*file descriptor to hold sync driver handle*/
43#endif
44
45/*******************************************************************************
46**
47** Function         EXTNS_Init
48**
49** Description      This function Initializes Mifare Classic Extns. Allocates
50**                  required memory and initializes the Mifare Classic Vars
51**
52** Returns          NFCSTATUS_SUCCESS if successfully initialized
53**                  NFCSTATUS_FAILED otherwise
54**
55*******************************************************************************/
56NFCSTATUS EXTNS_Init (tNFA_DM_CBACK        *p_nfa_dm_cback,
57                     tNFA_CONN_CBACK      *p_nfa_conn_cback)
58{
59    NFCSTATUS status = NFCSTATUS_FAILED;
60
61    /* reset config cache */
62    resetNxpConfig ();
63
64    /* Initialize Log level */
65    phNxpLog_InitializeLogLevel ();
66
67    /* Validate parameters */
68    if ((!p_nfa_dm_cback) || (!p_nfa_conn_cback))
69    {
70        NXPLOG_EXTNS_E ("EXTNS_Init(): error null callback");
71        goto clean_and_return;
72    }
73
74    gphNxpExtns_Context.p_dm_cback = p_nfa_dm_cback;
75    gphNxpExtns_Context.p_conn_cback = p_nfa_conn_cback;
76
77    if (NFCSTATUS_SUCCESS != phNxpExtns_MfcModuleInit ())
78    {
79       NXPLOG_EXTNS_E ("ERROR: MFC Module Init Failed");
80       goto clean_and_return;
81    }
82    gphNxpExtns_Context.Extns_status = EXTNS_STATUS_OPEN;
83
84    status = NFCSTATUS_SUCCESS;
85    return status;
86
87clean_and_return:
88    gphNxpExtns_Context.Extns_status = EXTNS_STATUS_CLOSE;
89    return status;
90}
91
92/*******************************************************************************
93**
94** Function         EXTNS_Close
95**
96** Description      This function de-initializes Mifare Classic Extns.
97**                  De-allocates memory
98**
99** Returns          None
100**
101*******************************************************************************/
102void EXTNS_Close (void)
103{
104    gphNxpExtns_Context.Extns_status = EXTNS_STATUS_CLOSE;
105    phNxpExtns_MfcModuleDeInit ();
106    return;
107}
108
109/*******************************************************************************
110**
111** Function         EXTNS_MfcCallBack
112**
113** Description      Decodes Mifare Classic Tag Response
114**                  This is called from NFA_SendRaw Callback
115**
116** Returns:
117**                  NFCSTATUS_SUCCESS if successfully initiated
118**                  NFCSTATUS_FAILED otherwise
119**
120*******************************************************************************/
121NFCSTATUS EXTNS_MfcCallBack (uint8_t *buf, uint32_t buflen)
122{
123    NFCSTATUS status = NFCSTATUS_SUCCESS;
124
125    phLibNfc_Message_t msg;
126
127    msg.eMsgType = PH_NXPEXTNS_RX_DATA;
128    msg.pMsgData = buf;
129    msg.Size = buflen;
130
131    status = phNxpExtns_SendMsg (&msg);
132    if (NFCSTATUS_SUCCESS != status)
133    {
134        NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread");
135    }
136    return status;
137}
138
139/*******************************************************************************
140**
141** Function         EXTNS_MfcCheckNDef
142**
143** Description      Performs NDEF detection for Mifare Classic Tag
144**
145**                  Upon successful completion of NDEF detection, a
146**                  NFA_NDEF_DETECT_EVT will be sent, to notify the application
147**                  of the NDEF attributes (NDEF total memory size, current
148**                  size, etc.).
149**
150** Returns:
151**                  NFCSTATUS_SUCCESS if successfully initiated
152**                  NFCSTATUS_FAILED otherwise
153**
154*******************************************************************************/
155NFCSTATUS EXTNS_MfcCheckNDef (void)
156{
157    NFCSTATUS status = NFCSTATUS_SUCCESS;
158    phLibNfc_Message_t msg;
159
160    msg.eMsgType = PH_NXPEXTNS_MIFARE_CHECK_NDEF;
161    msg.pMsgData = NULL;
162    msg.Size = 0;
163
164    status = phNxpExtns_SendMsg (&msg);
165    if (NFCSTATUS_SUCCESS != status)
166    {
167        NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread");
168    }
169
170    return status;
171}
172
173/*******************************************************************************
174**
175** Function         EXTNS_MfcReadNDef
176**
177** Description      Reads NDEF message from Mifare Classic Tag.
178**
179**                  Upon receiving the NDEF message, the message will be sent to
180**                  the handler registered with EXTNS_MfcRegisterNDefTypeHandler.
181**
182** Returns:
183**                  NFCSTATUS_SUCCESS if successfully initiated
184**                  NFCSTATUS_FAILED otherwise
185**
186*******************************************************************************/
187NFCSTATUS EXTNS_MfcReadNDef (void)
188{
189    NFCSTATUS status = NFCSTATUS_SUCCESS;
190
191    phLibNfc_Message_t msg;
192
193    msg.eMsgType = PH_NXPEXTNS_MIFARE_READ_NDEF;
194    msg.pMsgData = NULL;
195    msg.Size = 0;
196
197    status = phNxpExtns_SendMsg (&msg);
198    if (NFCSTATUS_SUCCESS != status)
199    {
200        NXPLOG_EXTNS_E("Error Sending msg to Extension Thread");
201    }
202
203    return status;
204}
205/*******************************************************************************
206**
207** Function         EXTNS_MfcPresenceCheck
208**
209** Description      Do the check presence for Mifare Classic Tag.
210**
211**
212** Returns:
213**                  NFCSTATUS_SUCCESS if successfully initiated
214**                  NFCSTATUS_FAILED otherwise
215**
216*******************************************************************************/
217NFCSTATUS EXTNS_MfcPresenceCheck (void)
218{
219    NFCSTATUS status = NFCSTATUS_SUCCESS;
220
221    phLibNfc_Message_t msg;
222
223    msg.eMsgType = PH_NXPEXTNS_MIFARE_PRESENCE_CHECK;
224    msg.pMsgData = NULL;
225    msg.Size = 0;
226
227    gAuthCmdBuf.status = NFCSTATUS_FAILED;
228    if (sem_init (&gAuthCmdBuf.semPresenceCheck, 0, 0) == -1)
229    {
230        ALOGE ("%s: semaphore creation failed (errno=0x%08x)", __FUNCTION__, errno);
231        return NFCSTATUS_FAILED;
232    }
233
234    status = phNxpExtns_SendMsg (&msg);
235    if (NFCSTATUS_SUCCESS != status)
236    {
237        NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread");
238        sem_destroy (&gAuthCmdBuf.semPresenceCheck);
239    }
240
241    return status;
242}
243
244/*******************************************************************************
245**
246** Function        EXTNS_MfcSetReadOnly
247**
248**
249** Description:
250**      Sets tag as read only.
251**
252**      When tag is set as read only, or if an error occurs, the app will be
253**      notified with NFA_SET_TAG_RO_EVT.
254**
255** Returns:
256**                  NFCSTATUS_SUCCESS if successfully initiated
257**                  NFCSTATUS_FAILED otherwise
258**
259*******************************************************************************/
260NFCSTATUS EXTNS_MfcSetReadOnly (uint8_t *key, uint8_t len)
261{
262    NFCSTATUS status = NFCSTATUS_SUCCESS;
263
264    phLibNfc_Message_t msg;
265
266    msg.eMsgType = PH_NXPEXTNS_MIFARE_READ_ONLY;
267    msg.pMsgData = key;
268    msg.Size = len;
269
270    status = phNxpExtns_SendMsg (&msg);
271    if (NFCSTATUS_SUCCESS != status)
272    {
273        NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread");
274    }
275
276    return status;
277}
278
279/*******************************************************************************
280**
281** Function         EXTNS_MfcWriteNDef
282**
283** Description      Writes NDEF data to Mifare Classic Tag.
284**
285**                  When the entire message has been written, or if an error
286**                  occurs, the app will be notified with NFA_WRITE_CPLT_EVT.
287**
288**                  p_data needs to be persistent until NFA_WRITE_CPLT_EVT
289**
290** Returns:
291**                  NFCSTATUS_SUCCESS if successfully initiated
292**                  NFCSTATUS_FAILED otherwise
293**
294*******************************************************************************/
295NFCSTATUS EXTNS_MfcWriteNDef (uint8_t *p_data, uint32_t len)
296{
297    NFCSTATUS status = NFCSTATUS_SUCCESS;
298
299    phLibNfc_Message_t msg;
300
301    msg.eMsgType = PH_NXPEXTNS_MIFARE_WRITE_NDEF;
302    msg.pMsgData = p_data;
303    msg.Size = len;
304
305    status = phNxpExtns_SendMsg (&msg);
306    if (NFCSTATUS_SUCCESS != status)
307    {
308        NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread");
309    }
310
311    return status;
312}
313
314/*****************************************************************************
315**
316** Function         EXTNS_MfcFormatTag
317**
318** Description      Formats Mifare Classic Tag.
319**
320**                  The NFA_RW_FORMAT_CPLT_EVT, status is used to
321**                  indicate if tag is successfully formated or not
322**
323** Returns
324**                  NFCSTATUS_SUCCESS if successfully initiated
325**                  NFCSTATUS_FAILED otherwise
326**
327*****************************************************************************/
328NFCSTATUS EXTNS_MfcFormatTag (uint8_t *key, uint8_t len)
329{
330    NFCSTATUS status = NFCSTATUS_SUCCESS;
331
332    phLibNfc_Message_t msg;
333
334    msg.eMsgType = PH_NXPEXTNS_MIFARE_FORMAT_NDEF;
335    msg.pMsgData = key;
336    msg.Size = len;
337
338    status = phNxpExtns_SendMsg (&msg);
339    if (NFCSTATUS_SUCCESS != status)
340    {
341        NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread");
342    }
343
344    return status;
345}
346
347/*****************************************************************************
348**
349** Function         EXTNS_MfcDisconnect
350**
351** Description      Disconnects Mifare Classic Tag.
352**
353** Returns
354**                  NFCSTATUS_SUCCESS if successfully initiated
355**                  NFCSTATUS_FAILED otherwise
356**
357*****************************************************************************/
358NFCSTATUS EXTNS_MfcDisconnect (void)
359{
360    NFCSTATUS status = NFCSTATUS_SUCCESS;
361
362    phLibNfc_Message_t msg;
363
364    msg.eMsgType = PH_NXPEXTNS_DISCONNECT;
365    msg.pMsgData = NULL;
366    msg.Size = 0;
367
368    status = phNxpExtns_SendMsg (&msg);
369    if (NFCSTATUS_SUCCESS != status)
370    {
371        NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread");
372    }
373
374    return status;
375}
376
377/*****************************************************************************
378**
379** Function         EXTNS_MfcActivated
380**
381** Description      Activates Mifare Classic Tag.
382**
383** Returns
384**                  NFCSTATUS_SUCCESS if successfully initiated
385**                  NFCSTATUS_FAILED otherwise
386**
387*****************************************************************************/
388NFCSTATUS EXTNS_MfcActivated (void)
389{
390    NFCSTATUS status = NFCSTATUS_SUCCESS;
391    phLibNfc_Message_t msg;
392
393    msg.eMsgType = PH_NXPEXTNS_ACTIVATED;
394    msg.pMsgData = NULL;
395    msg.Size = 0;
396
397    status = phNxpExtns_SendMsg (&msg);
398    if (NFCSTATUS_SUCCESS != status)
399    {
400        NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread");
401    }
402
403    return status;
404}
405
406/*******************************************************************************
407**
408** Function         EXTNS_MfcTransceive
409**
410** Description      Sends raw frame to Mifare Classic Tag.
411**
412** Returns          NFCSTATUS_SUCCESS if successfully initiated
413**                  NFCSTATUS_FAILED otherwise
414**
415*******************************************************************************/
416NFCSTATUS EXTNS_MfcTransceive (uint8_t *p_data, uint32_t len)
417{
418    NFCSTATUS status = NFCSTATUS_SUCCESS;
419
420    phLibNfc_Message_t msg;
421
422    msg.eMsgType = PH_NXPEXTNS_MIFARE_TRANSCEIVE;
423    msg.pMsgData = p_data;
424    msg.Size = len;
425
426    status = phNxpExtns_SendMsg (&msg);
427    if (NFCSTATUS_SUCCESS != status)
428    {
429        NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread");
430    }
431
432    return status;
433}
434
435/*******************************************************************************
436**
437** Function         EXTNS_MfcInit
438**
439** Description      This function is used to Init Mifare Classic Extns.
440**                  This function should be called when the tag detected is
441**                  Mifare Classic.
442**
443** Returns          NFCSTATUS_SUCCESS
444**
445*******************************************************************************/
446NFCSTATUS EXTNS_MfcInit (tNFA_ACTIVATED activationData)
447{
448    tNFC_ACTIVATE_DEVT rfDetail = activationData.activate_ntf;
449
450    NdefMap->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak     = rfDetail.rf_tech_param.param.pa.sel_rsp;
451    NdefMap->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA [0] = rfDetail.rf_tech_param.param.pa.sens_res[0];
452    NdefMap->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA [1] = rfDetail.rf_tech_param.param.pa.sens_res[1];
453
454    return NFCSTATUS_SUCCESS;
455}
456
457/*******************************************************************************
458**
459** Function         phNxpExtns_ProcessSysMessage
460**
461** Description      Internal function to route the request from JNI and Callback
462**                  from NFA_SendRawFrame to right function
463**
464** Returns          NFCSTATUS_SUCCESS if valid request
465**                  NFCSTATUS_FAILED otherwise
466**
467*******************************************************************************/
468static NFCSTATUS phNxpExtns_ProcessSysMessage (phLibNfc_Message_t *msg)
469{
470    NFCSTATUS status = NFCSTATUS_SUCCESS;
471
472    if (gphNxpExtns_Context.Extns_status == EXTNS_STATUS_CLOSE)
473    {
474        return NFCSTATUS_FAILED;
475    }
476
477    switch (msg->eMsgType)
478    {
479        case PH_NXPEXTNS_RX_DATA:
480            status = Mfc_RecvPacket (msg->pMsgData, msg->Size);
481            break;
482
483        case PH_NXPEXTNS_MIFARE_CHECK_NDEF:
484            pthread_mutex_init (&gAuthCmdBuf.syncmutex, NULL);
485            pthread_mutex_lock (&gAuthCmdBuf.syncmutex);
486            status = Mfc_CheckNdef ();
487            pthread_mutex_unlock (&gAuthCmdBuf.syncmutex);
488            pthread_mutex_destroy (&gAuthCmdBuf.syncmutex);
489            break;
490
491        case PH_NXPEXTNS_MIFARE_READ_NDEF:
492            status = Mfc_ReadNdef ();
493            break;
494
495        case PH_NXPEXTNS_MIFARE_WRITE_NDEF:
496            status = Mfc_WriteNdef (msg->pMsgData, msg->Size);
497            break;
498
499        case PH_NXPEXTNS_MIFARE_FORMAT_NDEF:
500            status = Mfc_FormatNdef (msg->pMsgData, msg->Size);
501            break;
502
503        case PH_NXPEXTNS_DISCONNECT:
504            Mfc_DeactivateCbackSelect ();
505            break;
506
507        case PH_NXPEXTNS_ACTIVATED:
508            Mfc_ActivateCback ();
509            break;
510
511        case PH_NXPEXTNS_MIFARE_TRANSCEIVE:
512            status = Mfc_Transceive (msg->pMsgData, msg->Size);
513            break;
514
515        case PH_NXPEXTNS_MIFARE_READ_ONLY:
516            status = Mfc_SetReadOnly (msg->pMsgData, msg->Size);
517            break;
518        case PH_NXPEXTNS_MIFARE_PRESENCE_CHECK:
519            pthread_mutex_init (&gAuthCmdBuf.syncmutex, NULL);
520            pthread_mutex_lock (&gAuthCmdBuf.syncmutex);
521            status = Mfc_PresenceCheck ();
522            pthread_mutex_unlock (&gAuthCmdBuf.syncmutex);
523            pthread_mutex_destroy (&gAuthCmdBuf.syncmutex);
524            break;
525        default:
526            status = NFCSTATUS_FAILED;
527            NXPLOG_EXTNS_E ("Illegal Command for Extension");
528            break;
529        }
530
531    return status;
532}
533
534/*******************************************************************************
535**
536** Function         phNxpExtns_SendMsg
537**
538** Description      unlocks phNxpExtns_ProcessSysMessage with a valid message
539**
540** Returns          NFCSTATUS_SUCCESS if successfully initiated
541**                  NFCSTATUS_FAILED otherwise
542**
543*******************************************************************************/
544static NFCSTATUS phNxpExtns_SendMsg (phLibNfc_Message_t *sysmsg)
545{
546    NFCSTATUS status = NFCSTATUS_SUCCESS;
547
548    status = phNxpExtns_ProcessSysMessage (sysmsg);
549
550    return status;
551}
552
553/*******************************************************************************
554**
555** Function         EXTNS_MfcRegisterNDefTypeHandler
556**
557** Description      This function allows the applications to register for
558**                  specific types of NDEF records.
559**
560**                  For records types which were not registered, the record will
561**                  be sent to the default handler.
562**
563** Returns          NFCSTATUS_SUCCESS
564**
565*******************************************************************************/
566NFCSTATUS EXTNS_MfcRegisterNDefTypeHandler (tNFA_NDEF_CBACK *ndefHandlerCallback)
567{
568
569    NFCSTATUS status = NFCSTATUS_FAILED;
570    if (NULL != ndefHandlerCallback)
571    {
572        gphNxpExtns_Context.p_ndef_cback = ndefHandlerCallback;
573        status = NFCSTATUS_SUCCESS;
574    }
575
576    return status;
577}
578
579/*******************************************************************************
580**                     Synchronizing Functions                                **
581**            Synchronizes Callback in JNI and MFC Extns                      **
582*******************************************************************************/
583
584bool_t EXTNS_GetConnectFlag (void)
585{
586    return (gphNxpExtns_Context.ExtnsConnect);
587}
588
589void EXTNS_SetConnectFlag (bool_t flagval)
590{
591    gphNxpExtns_Context.ExtnsConnect = flagval;
592}
593
594bool_t EXTNS_GetDeactivateFlag (void)
595{
596    return (gphNxpExtns_Context.ExtnsDeactivate);
597}
598
599void EXTNS_SetDeactivateFlag (bool_t flagval)
600{
601    gphNxpExtns_Context.ExtnsDeactivate = flagval;
602}
603
604bool_t EXTNS_GetCallBackFlag (void)
605{
606    return (gphNxpExtns_Context.ExtnsCallBack);
607}
608
609void EXTNS_SetCallBackFlag (bool_t flagval)
610{
611    gphNxpExtns_Context.ExtnsCallBack = flagval;
612
613}
614NFCSTATUS EXTNS_GetPresenceCheckStatus (void)
615{
616    struct timespec ts;
617
618    clock_gettime (CLOCK_REALTIME, &ts);
619    ts.tv_sec += 0;
620    ts.tv_nsec += 100*1000*1000; // 100 milisec
621    if (ts.tv_nsec >= 1000 * 1000 * 1000)
622    {
623        ts.tv_sec += 1;
624        ts.tv_nsec = ts.tv_nsec - (1000 * 1000 * 1000);
625    }
626
627    if (sem_timedwait (&gAuthCmdBuf.semPresenceCheck, &ts))
628    {
629        ALOGE ("%s: failed to wait (errno=0x%08x)", __FUNCTION__, errno);
630        sem_destroy (&gAuthCmdBuf.semPresenceCheck);
631        gAuthCmdBuf.auth_sent = FALSE;
632        return NFCSTATUS_FAILED;
633    }
634    if (sem_destroy (&gAuthCmdBuf.semPresenceCheck))
635    {
636        ALOGE ("Failed to destroy check Presence semaphore (errno=0x%08x)", errno);
637    }
638    return gAuthCmdBuf.status;
639}
640
641void MfcPresenceCheckResult (NFCSTATUS status)
642{
643    gAuthCmdBuf.status = status;
644    EXTNS_SetCallBackFlag (TRUE);
645    sem_post (&gAuthCmdBuf.semPresenceCheck);
646}
647void MfcResetPresenceCheckStatus (void)
648{
649    gAuthCmdBuf.auth_sent = FALSE;
650}
651/*******************************************************************************
652**
653** Function         EXTNS_CheckMfcResponse
654**
655** Description      This function is called from JNI Transceive for Mifare
656**                  Classic Tag status interpretation and to send the required
657**                  status to application
658**
659** Returns          NFCSTATUS_SUCCESS
660**                  NFCSTATUS_FAILED
661**
662*******************************************************************************/
663NFCSTATUS EXTNS_CheckMfcResponse (uint8_t** sTransceiveData, uint32_t *sTransceiveDataLen)
664{
665    NFCSTATUS status = NFCSTATUS_SUCCESS;
666
667    if (*sTransceiveDataLen == 3)
668    {
669        if((*sTransceiveData) [0] == 0x10 && (*sTransceiveData) [1] != 0x0A)
670        {
671            NXPLOG_EXTNS_E ("Mifare Error in payload response");
672            *sTransceiveDataLen = 0x1;
673            *sTransceiveData += 1;
674            return NFCSTATUS_FAILED;
675        }
676    }
677    if ((*sTransceiveData) [0] == 0x40)
678    {
679        *sTransceiveData += 1;
680        *sTransceiveDataLen = 0x01;
681        if((*sTransceiveData) [0] == 0x03)
682        {
683            *sTransceiveDataLen = 0x00;
684            status = NFCSTATUS_FAILED;
685        }
686    }
687    else if ((*sTransceiveData) [0] == 0x10)
688    {
689        *sTransceiveData += 1;
690        *sTransceiveDataLen = 0x10;
691    }
692
693    return status;
694}
695
696