/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef ESE_NFC_SYNCHRONIZATION #include #endif #include #include #include #include #include #include phNxpExtns_Context_t gphNxpExtns_Context; extern phFriNfc_NdefMap_t *NdefMap; extern phNci_mfc_auth_cmd_t gAuthCmdBuf; static NFCSTATUS phNxpExtns_ProcessSysMessage (phLibNfc_Message_t *msg); static NFCSTATUS phNxpExtns_SendMsg (phLibNfc_Message_t *sysmsg); #ifdef ESE_NFC_SYNCHRONIZATION /* timing calculation structure*/ typedef struct time_cal { struct timeval tv1; struct timeval tv2; } TimeCal; static int fd_ese_nfc_sync; /*file descriptor to hold sync driver handle*/ #endif /******************************************************************************* ** ** Function EXTNS_Init ** ** Description This function Initializes Mifare Classic Extns. Allocates ** required memory and initializes the Mifare Classic Vars ** ** Returns NFCSTATUS_SUCCESS if successfully initialized ** NFCSTATUS_FAILED otherwise ** *******************************************************************************/ NFCSTATUS EXTNS_Init (tNFA_DM_CBACK *p_nfa_dm_cback, tNFA_CONN_CBACK *p_nfa_conn_cback) { NFCSTATUS status = NFCSTATUS_FAILED; /* reset config cache */ resetNxpConfig (); /* Initialize Log level */ phNxpLog_InitializeLogLevel (); /* Validate parameters */ if ((!p_nfa_dm_cback) || (!p_nfa_conn_cback)) { NXPLOG_EXTNS_E ("EXTNS_Init(): error null callback"); goto clean_and_return; } gphNxpExtns_Context.p_dm_cback = p_nfa_dm_cback; gphNxpExtns_Context.p_conn_cback = p_nfa_conn_cback; if (NFCSTATUS_SUCCESS != phNxpExtns_MfcModuleInit ()) { NXPLOG_EXTNS_E ("ERROR: MFC Module Init Failed"); goto clean_and_return; } gphNxpExtns_Context.Extns_status = EXTNS_STATUS_OPEN; status = NFCSTATUS_SUCCESS; return status; clean_and_return: gphNxpExtns_Context.Extns_status = EXTNS_STATUS_CLOSE; return status; } /******************************************************************************* ** ** Function EXTNS_Close ** ** Description This function de-initializes Mifare Classic Extns. ** De-allocates memory ** ** Returns None ** *******************************************************************************/ void EXTNS_Close (void) { gphNxpExtns_Context.Extns_status = EXTNS_STATUS_CLOSE; phNxpExtns_MfcModuleDeInit (); return; } /******************************************************************************* ** ** Function EXTNS_MfcCallBack ** ** Description Decodes Mifare Classic Tag Response ** This is called from NFA_SendRaw Callback ** ** Returns: ** NFCSTATUS_SUCCESS if successfully initiated ** NFCSTATUS_FAILED otherwise ** *******************************************************************************/ NFCSTATUS EXTNS_MfcCallBack (uint8_t *buf, uint32_t buflen) { NFCSTATUS status = NFCSTATUS_SUCCESS; phLibNfc_Message_t msg; msg.eMsgType = PH_NXPEXTNS_RX_DATA; msg.pMsgData = buf; msg.Size = buflen; status = phNxpExtns_SendMsg (&msg); if (NFCSTATUS_SUCCESS != status) { NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread"); } return status; } /******************************************************************************* ** ** Function EXTNS_MfcCheckNDef ** ** Description Performs NDEF detection for Mifare Classic Tag ** ** Upon successful completion of NDEF detection, a ** NFA_NDEF_DETECT_EVT will be sent, to notify the application ** of the NDEF attributes (NDEF total memory size, current ** size, etc.). ** ** Returns: ** NFCSTATUS_SUCCESS if successfully initiated ** NFCSTATUS_FAILED otherwise ** *******************************************************************************/ NFCSTATUS EXTNS_MfcCheckNDef (void) { NFCSTATUS status = NFCSTATUS_SUCCESS; phLibNfc_Message_t msg; msg.eMsgType = PH_NXPEXTNS_MIFARE_CHECK_NDEF; msg.pMsgData = NULL; msg.Size = 0; status = phNxpExtns_SendMsg (&msg); if (NFCSTATUS_SUCCESS != status) { NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread"); } return status; } /******************************************************************************* ** ** Function EXTNS_MfcReadNDef ** ** Description Reads NDEF message from Mifare Classic Tag. ** ** Upon receiving the NDEF message, the message will be sent to ** the handler registered with EXTNS_MfcRegisterNDefTypeHandler. ** ** Returns: ** NFCSTATUS_SUCCESS if successfully initiated ** NFCSTATUS_FAILED otherwise ** *******************************************************************************/ NFCSTATUS EXTNS_MfcReadNDef (void) { NFCSTATUS status = NFCSTATUS_SUCCESS; phLibNfc_Message_t msg; msg.eMsgType = PH_NXPEXTNS_MIFARE_READ_NDEF; msg.pMsgData = NULL; msg.Size = 0; status = phNxpExtns_SendMsg (&msg); if (NFCSTATUS_SUCCESS != status) { NXPLOG_EXTNS_E("Error Sending msg to Extension Thread"); } return status; } /******************************************************************************* ** ** Function EXTNS_MfcPresenceCheck ** ** Description Do the check presence for Mifare Classic Tag. ** ** ** Returns: ** NFCSTATUS_SUCCESS if successfully initiated ** NFCSTATUS_FAILED otherwise ** *******************************************************************************/ NFCSTATUS EXTNS_MfcPresenceCheck (void) { NFCSTATUS status = NFCSTATUS_SUCCESS; phLibNfc_Message_t msg; msg.eMsgType = PH_NXPEXTNS_MIFARE_PRESENCE_CHECK; msg.pMsgData = NULL; msg.Size = 0; gAuthCmdBuf.status = NFCSTATUS_FAILED; if (sem_init (&gAuthCmdBuf.semPresenceCheck, 0, 0) == -1) { ALOGE ("%s: semaphore creation failed (errno=0x%08x)", __FUNCTION__, errno); return NFCSTATUS_FAILED; } status = phNxpExtns_SendMsg (&msg); if (NFCSTATUS_SUCCESS != status) { NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread"); sem_destroy (&gAuthCmdBuf.semPresenceCheck); } return status; } /******************************************************************************* ** ** Function EXTNS_MfcSetReadOnly ** ** ** Description: ** Sets tag as read only. ** ** When tag is set as read only, or if an error occurs, the app will be ** notified with NFA_SET_TAG_RO_EVT. ** ** Returns: ** NFCSTATUS_SUCCESS if successfully initiated ** NFCSTATUS_FAILED otherwise ** *******************************************************************************/ NFCSTATUS EXTNS_MfcSetReadOnly (uint8_t *key, uint8_t len) { NFCSTATUS status = NFCSTATUS_SUCCESS; phLibNfc_Message_t msg; msg.eMsgType = PH_NXPEXTNS_MIFARE_READ_ONLY; msg.pMsgData = key; msg.Size = len; status = phNxpExtns_SendMsg (&msg); if (NFCSTATUS_SUCCESS != status) { NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread"); } return status; } /******************************************************************************* ** ** Function EXTNS_MfcWriteNDef ** ** Description Writes NDEF data to Mifare Classic Tag. ** ** When the entire message has been written, or if an error ** occurs, the app will be notified with NFA_WRITE_CPLT_EVT. ** ** p_data needs to be persistent until NFA_WRITE_CPLT_EVT ** ** Returns: ** NFCSTATUS_SUCCESS if successfully initiated ** NFCSTATUS_FAILED otherwise ** *******************************************************************************/ NFCSTATUS EXTNS_MfcWriteNDef (uint8_t *p_data, uint32_t len) { NFCSTATUS status = NFCSTATUS_SUCCESS; phLibNfc_Message_t msg; msg.eMsgType = PH_NXPEXTNS_MIFARE_WRITE_NDEF; msg.pMsgData = p_data; msg.Size = len; status = phNxpExtns_SendMsg (&msg); if (NFCSTATUS_SUCCESS != status) { NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread"); } return status; } /***************************************************************************** ** ** Function EXTNS_MfcFormatTag ** ** Description Formats Mifare Classic Tag. ** ** The NFA_RW_FORMAT_CPLT_EVT, status is used to ** indicate if tag is successfully formated or not ** ** Returns ** NFCSTATUS_SUCCESS if successfully initiated ** NFCSTATUS_FAILED otherwise ** *****************************************************************************/ NFCSTATUS EXTNS_MfcFormatTag (uint8_t *key, uint8_t len) { NFCSTATUS status = NFCSTATUS_SUCCESS; phLibNfc_Message_t msg; msg.eMsgType = PH_NXPEXTNS_MIFARE_FORMAT_NDEF; msg.pMsgData = key; msg.Size = len; status = phNxpExtns_SendMsg (&msg); if (NFCSTATUS_SUCCESS != status) { NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread"); } return status; } /***************************************************************************** ** ** Function EXTNS_MfcDisconnect ** ** Description Disconnects Mifare Classic Tag. ** ** Returns ** NFCSTATUS_SUCCESS if successfully initiated ** NFCSTATUS_FAILED otherwise ** *****************************************************************************/ NFCSTATUS EXTNS_MfcDisconnect (void) { NFCSTATUS status = NFCSTATUS_SUCCESS; phLibNfc_Message_t msg; msg.eMsgType = PH_NXPEXTNS_DISCONNECT; msg.pMsgData = NULL; msg.Size = 0; status = phNxpExtns_SendMsg (&msg); if (NFCSTATUS_SUCCESS != status) { NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread"); } return status; } /***************************************************************************** ** ** Function EXTNS_MfcActivated ** ** Description Activates Mifare Classic Tag. ** ** Returns ** NFCSTATUS_SUCCESS if successfully initiated ** NFCSTATUS_FAILED otherwise ** *****************************************************************************/ NFCSTATUS EXTNS_MfcActivated (void) { NFCSTATUS status = NFCSTATUS_SUCCESS; phLibNfc_Message_t msg; msg.eMsgType = PH_NXPEXTNS_ACTIVATED; msg.pMsgData = NULL; msg.Size = 0; status = phNxpExtns_SendMsg (&msg); if (NFCSTATUS_SUCCESS != status) { NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread"); } return status; } /******************************************************************************* ** ** Function EXTNS_MfcTransceive ** ** Description Sends raw frame to Mifare Classic Tag. ** ** Returns NFCSTATUS_SUCCESS if successfully initiated ** NFCSTATUS_FAILED otherwise ** *******************************************************************************/ NFCSTATUS EXTNS_MfcTransceive (uint8_t *p_data, uint32_t len) { NFCSTATUS status = NFCSTATUS_SUCCESS; phLibNfc_Message_t msg; msg.eMsgType = PH_NXPEXTNS_MIFARE_TRANSCEIVE; msg.pMsgData = p_data; msg.Size = len; status = phNxpExtns_SendMsg (&msg); if (NFCSTATUS_SUCCESS != status) { NXPLOG_EXTNS_E ("Error Sending msg to Extension Thread"); } return status; } /******************************************************************************* ** ** Function EXTNS_MfcInit ** ** Description This function is used to Init Mifare Classic Extns. ** This function should be called when the tag detected is ** Mifare Classic. ** ** Returns NFCSTATUS_SUCCESS ** *******************************************************************************/ NFCSTATUS EXTNS_MfcInit (tNFA_ACTIVATED activationData) { tNFC_ACTIVATE_DEVT rfDetail = activationData.activate_ntf; NdefMap->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.Sak = rfDetail.rf_tech_param.param.pa.sel_rsp; NdefMap->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA [0] = rfDetail.rf_tech_param.param.pa.sens_res[0]; NdefMap->psRemoteDevInfo->RemoteDevInfo.Iso14443A_Info.AtqA [1] = rfDetail.rf_tech_param.param.pa.sens_res[1]; return NFCSTATUS_SUCCESS; } /******************************************************************************* ** ** Function phNxpExtns_ProcessSysMessage ** ** Description Internal function to route the request from JNI and Callback ** from NFA_SendRawFrame to right function ** ** Returns NFCSTATUS_SUCCESS if valid request ** NFCSTATUS_FAILED otherwise ** *******************************************************************************/ static NFCSTATUS phNxpExtns_ProcessSysMessage (phLibNfc_Message_t *msg) { NFCSTATUS status = NFCSTATUS_SUCCESS; if (gphNxpExtns_Context.Extns_status == EXTNS_STATUS_CLOSE) { return NFCSTATUS_FAILED; } switch (msg->eMsgType) { case PH_NXPEXTNS_RX_DATA: status = Mfc_RecvPacket (msg->pMsgData, msg->Size); break; case PH_NXPEXTNS_MIFARE_CHECK_NDEF: pthread_mutex_init (&gAuthCmdBuf.syncmutex, NULL); pthread_mutex_lock (&gAuthCmdBuf.syncmutex); status = Mfc_CheckNdef (); pthread_mutex_unlock (&gAuthCmdBuf.syncmutex); pthread_mutex_destroy (&gAuthCmdBuf.syncmutex); break; case PH_NXPEXTNS_MIFARE_READ_NDEF: status = Mfc_ReadNdef (); break; case PH_NXPEXTNS_MIFARE_WRITE_NDEF: status = Mfc_WriteNdef (msg->pMsgData, msg->Size); break; case PH_NXPEXTNS_MIFARE_FORMAT_NDEF: status = Mfc_FormatNdef (msg->pMsgData, msg->Size); break; case PH_NXPEXTNS_DISCONNECT: Mfc_DeactivateCbackSelect (); break; case PH_NXPEXTNS_ACTIVATED: Mfc_ActivateCback (); break; case PH_NXPEXTNS_MIFARE_TRANSCEIVE: status = Mfc_Transceive (msg->pMsgData, msg->Size); break; case PH_NXPEXTNS_MIFARE_READ_ONLY: status = Mfc_SetReadOnly (msg->pMsgData, msg->Size); break; case PH_NXPEXTNS_MIFARE_PRESENCE_CHECK: pthread_mutex_init (&gAuthCmdBuf.syncmutex, NULL); pthread_mutex_lock (&gAuthCmdBuf.syncmutex); status = Mfc_PresenceCheck (); pthread_mutex_unlock (&gAuthCmdBuf.syncmutex); pthread_mutex_destroy (&gAuthCmdBuf.syncmutex); break; default: status = NFCSTATUS_FAILED; NXPLOG_EXTNS_E ("Illegal Command for Extension"); break; } return status; } /******************************************************************************* ** ** Function phNxpExtns_SendMsg ** ** Description unlocks phNxpExtns_ProcessSysMessage with a valid message ** ** Returns NFCSTATUS_SUCCESS if successfully initiated ** NFCSTATUS_FAILED otherwise ** *******************************************************************************/ static NFCSTATUS phNxpExtns_SendMsg (phLibNfc_Message_t *sysmsg) { NFCSTATUS status = NFCSTATUS_SUCCESS; status = phNxpExtns_ProcessSysMessage (sysmsg); return status; } /******************************************************************************* ** ** Function EXTNS_MfcRegisterNDefTypeHandler ** ** Description This function allows the applications to register for ** specific types of NDEF records. ** ** For records types which were not registered, the record will ** be sent to the default handler. ** ** Returns NFCSTATUS_SUCCESS ** *******************************************************************************/ NFCSTATUS EXTNS_MfcRegisterNDefTypeHandler (tNFA_NDEF_CBACK *ndefHandlerCallback) { NFCSTATUS status = NFCSTATUS_FAILED; if (NULL != ndefHandlerCallback) { gphNxpExtns_Context.p_ndef_cback = ndefHandlerCallback; status = NFCSTATUS_SUCCESS; } return status; } /******************************************************************************* ** Synchronizing Functions ** ** Synchronizes Callback in JNI and MFC Extns ** *******************************************************************************/ bool_t EXTNS_GetConnectFlag (void) { return (gphNxpExtns_Context.ExtnsConnect); } void EXTNS_SetConnectFlag (bool_t flagval) { gphNxpExtns_Context.ExtnsConnect = flagval; } bool_t EXTNS_GetDeactivateFlag (void) { return (gphNxpExtns_Context.ExtnsDeactivate); } void EXTNS_SetDeactivateFlag (bool_t flagval) { gphNxpExtns_Context.ExtnsDeactivate = flagval; } bool_t EXTNS_GetCallBackFlag (void) { return (gphNxpExtns_Context.ExtnsCallBack); } void EXTNS_SetCallBackFlag (bool_t flagval) { gphNxpExtns_Context.ExtnsCallBack = flagval; } NFCSTATUS EXTNS_GetPresenceCheckStatus (void) { struct timespec ts; clock_gettime (CLOCK_REALTIME, &ts); ts.tv_sec += 0; ts.tv_nsec += 100*1000*1000; // 100 milisec if (ts.tv_nsec >= 1000 * 1000 * 1000) { ts.tv_sec += 1; ts.tv_nsec = ts.tv_nsec - (1000 * 1000 * 1000); } if (sem_timedwait (&gAuthCmdBuf.semPresenceCheck, &ts)) { ALOGE ("%s: failed to wait (errno=0x%08x)", __FUNCTION__, errno); sem_destroy (&gAuthCmdBuf.semPresenceCheck); gAuthCmdBuf.auth_sent = FALSE; return NFCSTATUS_FAILED; } if (sem_destroy (&gAuthCmdBuf.semPresenceCheck)) { ALOGE ("Failed to destroy check Presence semaphore (errno=0x%08x)", errno); } return gAuthCmdBuf.status; } void MfcPresenceCheckResult (NFCSTATUS status) { gAuthCmdBuf.status = status; EXTNS_SetCallBackFlag (TRUE); sem_post (&gAuthCmdBuf.semPresenceCheck); } void MfcResetPresenceCheckStatus (void) { gAuthCmdBuf.auth_sent = FALSE; } /******************************************************************************* ** ** Function EXTNS_CheckMfcResponse ** ** Description This function is called from JNI Transceive for Mifare ** Classic Tag status interpretation and to send the required ** status to application ** ** Returns NFCSTATUS_SUCCESS ** NFCSTATUS_FAILED ** *******************************************************************************/ NFCSTATUS EXTNS_CheckMfcResponse (uint8_t** sTransceiveData, uint32_t *sTransceiveDataLen) { NFCSTATUS status = NFCSTATUS_SUCCESS; if (*sTransceiveDataLen == 3) { if((*sTransceiveData) [0] == 0x10 && (*sTransceiveData) [1] != 0x0A) { NXPLOG_EXTNS_E ("Mifare Error in payload response"); *sTransceiveDataLen = 0x1; *sTransceiveData += 1; return NFCSTATUS_FAILED; } } if ((*sTransceiveData) [0] == 0x40) { *sTransceiveData += 1; *sTransceiveDataLen = 0x01; if((*sTransceiveData) [0] == 0x03) { *sTransceiveDataLen = 0x00; status = NFCSTATUS_FAILED; } } else if ((*sTransceiveData) [0] == 0x10) { *sTransceiveData += 1; *sTransceiveDataLen = 0x10; } return status; }