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