Support Mifare DESFire tag format

Support Mifare DESFire tag format

Change-Id: I362dc5c539ea7e5c749ca677f88d859d489a74d8
diff --git a/nci/jni/NativeNfcTag.cpp b/nci/jni/NativeNfcTag.cpp
index 268c1f6..7b51d93 100755
--- a/nci/jni/NativeNfcTag.cpp
+++ b/nci/jni/NativeNfcTag.cpp
@@ -1288,8 +1288,8 @@
 ** Returns:         True if formattable.
 **
 *******************************************************************************/
-static jboolean nativeNfcTag_doIsNdefFormatable (JNIEnv*,
-        jobject, jint /*libNfcType*/, jbyteArray, jbyteArray,
+static jboolean nativeNfcTag_doIsNdefFormatable (JNIEnv* e,
+        jobject o, jint /*libNfcType*/, jbyteArray, jbyteArray,
         jbyteArray)
 {
     jboolean isFormattable = JNI_FALSE;
@@ -1309,6 +1309,42 @@
                           NfcTag::getInstance().isKovioType2Tag() )
                         ? JNI_TRUE : JNI_FALSE;
     }
+    else if (NFA_PROTOCOL_ISO_DEP == protocol)
+    {
+        /**
+         * Determines whether this is a formatable IsoDep tag - currectly only NXP DESFire
+         * is supported.
+         */
+        uint8_t cmd[] = {0x90, 0x60, 0x00, 0x00, 0x00};
+
+        if (NfcTag::getInstance ().isMifareDESFire ())
+        {
+            /* Identifies as DESfire, use get version cmd to be sure */
+            jbyteArray versionCmd = e->NewByteArray (5);
+            e->SetByteArrayRegion (versionCmd, 0, 5, (jbyte*) cmd);
+            jbyteArray respBytes = nativeNfcTag_doTransceive(e, o, versionCmd, JNI_TRUE, NULL);
+            if (respBytes != NULL)
+            {
+                // Check whether the response matches a typical DESfire
+                // response.
+                // libNFC even does more advanced checking than we do
+                // here, and will only format DESfire's with a certain
+                // major/minor sw version and NXP as a manufacturer.
+                // We don't want to do such checking here, to avoid
+                // having to change code in multiple places.
+                // A succesful (wrapped) DESFire getVersion command returns
+                // 9 bytes, with byte 7 0x91 and byte 8 having status
+                // code 0xAF (these values are fixed and well-known).
+                int respLength = e->GetArrayLength (respBytes);
+                uint8_t* resp = (uint8_t*) e->GetByteArrayElements (respBytes, NULL);
+                if (respLength == 9 && resp[7] == 0x91 && resp[8] == 0xAF)
+                {
+                    isFormattable = JNI_TRUE;
+                }
+                e->ReleaseByteArrayElements (respBytes, (jbyte *) resp, JNI_ABORT);
+            }
+        }
+    }
 
     ALOGD("%s: is formattable=%u", __FUNCTION__, isFormattable);
     return isFormattable;
@@ -1350,7 +1386,7 @@
 ** Returns:         True if ok.
 **
 *******************************************************************************/
-static jboolean nativeNfcTag_doNdefFormat (JNIEnv*, jobject, jbyteArray)
+static jboolean nativeNfcTag_doNdefFormat (JNIEnv *e, jobject o, jbyteArray)
 {
     ALOGD ("%s: enter", __FUNCTION__);
     tNFA_STATUS status = NFA_STATUS_OK;
@@ -1375,6 +1411,11 @@
         ALOGE ("%s: error status=%u", __FUNCTION__, status);
     sem_destroy (&sFormatSem);
 
+    if (NfcTag::getInstance ().mTechLibNfcTypes[0] == NFA_PROTOCOL_ISO_DEP)
+    {
+        int retCode = NFCSTATUS_SUCCESS;
+        retCode = nativeNfcTag_doReconnect (e, o);
+    }
     ALOGD ("%s: exit", __FUNCTION__);
     return (status == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
 }
diff --git a/nci/jni/NfcTag.cpp b/nci/jni/NfcTag.cpp
index d394806..c5eadd3 100755
--- a/nci/jni/NfcTag.cpp
+++ b/nci/jni/NfcTag.cpp
@@ -1082,7 +1082,7 @@
 {
     static const char fn [] = "NfcTag::resetTechnologies";
     ALOGD ("%s", fn);
-   	mNumTechList = 0;
+    mNumTechList = 0;
     memset (mTechList, 0, sizeof(mTechList));
     memset (mTechHandles, 0, sizeof(mTechHandles));
     memset (mTechLibNfcTypes, 0, sizeof(mTechLibNfcTypes));
@@ -1235,6 +1235,42 @@
 
 /*******************************************************************************
 **
+** Function:        isMifareDESFire
+**
+** Description:     Whether the currently activated tag is Mifare DESFire.
+**
+** Returns:         True if tag is Mifare DESFire.
+**
+*******************************************************************************/
+bool NfcTag::isMifareDESFire ()
+{
+    static const char fn [] = "NfcTag::isMifareDESFire";
+    bool retval = false;
+
+    for (int i =0; i < mNumTechList; i++)
+    {
+        if ( (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) ||
+             (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_A) ||
+             (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_A_ACTIVE) )
+        {
+            /* DESfire has one sak byte and 2 ATQA bytes */
+            if ( (mTechParams[i].param.pa.sens_res[0] == 0x44) &&
+                 (mTechParams[i].param.pa.sens_res[1] == 0x03) &&
+                 (mTechParams[i].param.pa.sel_rsp == 0x20) )
+            {
+                retval = true;
+            }
+            break;
+        }
+    }
+
+    ALOGD ("%s: return=%u", fn, retval);
+    return retval;
+}
+
+
+/*******************************************************************************
+**
 ** Function:        isFelicaLite
 **
 ** Description:     Whether the currently activated tag is Felica Lite.
@@ -1408,7 +1444,7 @@
 {
     mTechnologyTimeoutsTable [TARGET_TYPE_ISO14443_3A] = 618; //NfcA
     mTechnologyTimeoutsTable [TARGET_TYPE_ISO14443_3B] = 1000; //NfcB
-    mTechnologyTimeoutsTable [TARGET_TYPE_ISO14443_4] = 309; //ISO-DEP
+    mTechnologyTimeoutsTable [TARGET_TYPE_ISO14443_4] = 618; //ISO-DEP
     mTechnologyTimeoutsTable [TARGET_TYPE_FELICA] = 255; //Felica
     mTechnologyTimeoutsTable [TARGET_TYPE_ISO15693] = 1000;//NfcV
     mTechnologyTimeoutsTable [TARGET_TYPE_NDEF] = 1000;
diff --git a/nci/jni/NfcTag.h b/nci/jni/NfcTag.h
index d3e399f..df7ce0c 100755
--- a/nci/jni/NfcTag.h
+++ b/nci/jni/NfcTag.h
@@ -222,6 +222,18 @@
 
     /*******************************************************************************
     **
+    ** Function:        isMifareDESFire
+    **
+    ** Description:     Whether the currently activated tag is Mifare DESFire.
+    **
+    ** Returns:         True if tag is Mifare DESFire.
+    **
+    *******************************************************************************/
+    bool isMifareDESFire ();
+
+
+    /*******************************************************************************
+    **
     ** Function:        isFelicaLite
     **
     ** Description:     Whether the currently activated tag is Felica Lite.