diff options
-rw-r--r-- | jni/com_android_nfc.cpp | 114 | ||||
-rw-r--r-- | jni/com_android_nfc.h | 4 | ||||
-rw-r--r-- | jni/com_android_nfc_NativeNfcManager.cpp | 6 | ||||
-rwxr-xr-x | jni/com_android_nfc_NativeNfcSecureElement.cpp | 8 | ||||
-rw-r--r-- | jni/com_android_nfc_NativeNfcTag.cpp | 29 | ||||
-rwxr-xr-x | src/com/android/nfc/NativeNfcTag.java | 33 | ||||
-rwxr-xr-x | src/com/android/nfc/NfcService.java | 2 |
7 files changed, 126 insertions, 70 deletions
diff --git a/jni/com_android_nfc.cpp b/jni/com_android_nfc.cpp index 2bf9685..a46168c 100644 --- a/jni/com_android_nfc.cpp +++ b/jni/com_android_nfc.cpp @@ -267,6 +267,29 @@ jint nfc_jni_get_connected_technology(JNIEnv *e, jobject o) } +jint nfc_jni_get_connected_technology_libnfc_type(JNIEnv *e, jobject o) +{ + jclass c; + jfieldID f; + jint connectedLibNfcType = -1; + + int connectedTechIndex = nfc_jni_get_connected_tech_index(e,o); + c = e->GetObjectClass(o); + f = e->GetFieldID(c, "mTechLibNfcTypes", "[I"); + jintArray libNfcTypes = (jintArray) e->GetObjectField(o, f); + + if ((connectedTechIndex != -1) && (libNfcTypes != NULL) && + (connectedTechIndex < e->GetArrayLength(libNfcTypes))) { + jint* types = e->GetIntArrayElements(libNfcTypes, 0); + if (types != NULL) { + connectedLibNfcType = types[connectedTechIndex]; + e->ReleaseIntArrayElements(libNfcTypes, types, JNI_ABORT); + } + } + return connectedLibNfcType; + +} + phLibNfc_Handle nfc_jni_get_connected_handle(JNIEnv *e, jobject o) { jclass c; @@ -384,8 +407,8 @@ const char* nfc_jni_get_status_name(NFCSTATUS status) return "UNKNOWN"; } -int addTechIfNeeded(int *techList, int* handleList, int listSize, int maxListSize, - int techToAdd, int handleToAdd) { +int addTechIfNeeded(int *techList, int* handleList, int* typeList, int listSize, + int maxListSize, int techToAdd, int handleToAdd, int typeToAdd) { bool found = false; for (int i = 0; i < listSize; i++) { if (techList[i] == techToAdd) { @@ -396,6 +419,7 @@ int addTechIfNeeded(int *techList, int* handleList, int listSize, int maxListSiz if (!found && listSize < maxListSize) { techList[listSize] = techToAdd; handleList[listSize] = handleToAdd; + typeList[listSize] = typeToAdd; return listSize + 1; } else { @@ -410,10 +434,13 @@ int addTechIfNeeded(int *techList, int* handleList, int listSize, int maxListSiz * Utility to get a technology tree and a corresponding handle list from a detected tag. */ void nfc_jni_get_technology_tree(JNIEnv* e, phLibNfc_RemoteDevList_t* devList, - uint8_t count, jintArray* techList, jintArray* handleList) + uint8_t count, jintArray* techList, jintArray* handleList, + jintArray* libnfcTypeList) { int technologies[MAX_NUM_TECHNOLOGIES]; int handles[MAX_NUM_TECHNOLOGIES]; + int libnfctypes[MAX_NUM_TECHNOLOGIES]; + int index = 0; // TODO: This counts from up to down because on multi-protocols, the // ISO handle is usually the second, and we prefer the ISO. Should implement @@ -427,41 +454,40 @@ void nfc_jni_get_technology_tree(JNIEnv* e, phLibNfc_RemoteDevList_t* devList, case phNfc_eISO14443_A_PICC: case phNfc_eISO14443_4A_PICC: { - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_ISO14443_4, handle); - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_ISO14443_3A, handle); - - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_NDEF_FORMATABLE, handle); + index = addTechIfNeeded(technologies, handles, libnfctypes, index, + MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_4, handle, type); + index = addTechIfNeeded(technologies, handles, libnfctypes, index, + MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3A, handle, type); + index = addTechIfNeeded(technologies, handles, libnfctypes, + index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_NDEF_FORMATABLE, handle, type); break; } case phNfc_eISO14443_4B_PICC: { - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_ISO14443_4, handle); - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_ISO14443_3B, handle); + index = addTechIfNeeded(technologies, handles, libnfctypes, index, + MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_4, handle, type); + index = addTechIfNeeded(technologies, handles, libnfctypes, index, + MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3B, handle, type); }break; case phNfc_eISO14443_3A_PICC: { - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_ISO14443_3A, handle); + index = addTechIfNeeded(technologies, handles, libnfctypes, + index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3A, handle, type); }break; case phNfc_eISO14443_B_PICC: { // TODO a bug in libnfc will cause 14443-3B only cards // to be returned as this type as well, but these cards // are very rare. Hence assume it's -4B - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_ISO14443_4, handle); - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_ISO14443_3B, handle); + index = addTechIfNeeded(technologies, handles, libnfctypes, + index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_4, handle, type); + index = addTechIfNeeded(technologies, handles, libnfctypes, + index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3B, handle, type); }break; case phNfc_eISO15693_PICC: { - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_ISO15693, handle); + index = addTechIfNeeded(technologies, handles, libnfctypes, + index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO15693, handle, type); }break; case phNfc_eMifare_PICC: { @@ -474,55 +500,57 @@ void nfc_jni_get_technology_tree(JNIEnv* e, phLibNfc_RemoteDevList_t* devList, { case 0x00: // could be UL or UL-C - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_MIFARE_UL, handle); - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_ISO14443_3A, handle); - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_NDEF_FORMATABLE, handle); + index = addTechIfNeeded(technologies, handles, libnfctypes, + index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_MIFARE_UL, handle, type); + index = addTechIfNeeded(technologies, handles, libnfctypes, + index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3A, handle, type); + index = addTechIfNeeded(technologies, handles, libnfctypes, + index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_NDEF_FORMATABLE, handle, type); break; default: - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_MIFARE_CLASSIC, handle); - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_ISO14443_3A, handle); - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_NDEF_FORMATABLE, handle); + index = addTechIfNeeded(technologies, handles, libnfctypes, + index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_MIFARE_CLASSIC, handle, type); + index = addTechIfNeeded(technologies, handles, libnfctypes, + index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3A, handle, type); + index = addTechIfNeeded(technologies, handles, libnfctypes, + index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_NDEF_FORMATABLE, handle, type); break; } }break; case phNfc_eFelica_PICC: { - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_FELICA, handle); + index = addTechIfNeeded(technologies, handles, libnfctypes, + index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_FELICA, handle, type); }break; case phNfc_eJewel_PICC: { -// TODO expose Jewel in the Java APIs -// index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, -// TARGET_TYPE_JEWEL, handle); - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_ISO14443_3A, handle); + // Jewel represented as NfcA + index = addTechIfNeeded(technologies, handles, libnfctypes, + index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_ISO14443_3A, handle, type); }break; default: { - index = addTechIfNeeded(technologies, handles, index, MAX_NUM_TECHNOLOGIES, - TARGET_TYPE_UNKNOWN, handle); + index = addTechIfNeeded(technologies, handles, libnfctypes, + index, MAX_NUM_TECHNOLOGIES, TARGET_TYPE_UNKNOWN, handle, type); } } } // Build the Java arrays *techList = e->NewIntArray(index); *handleList = e->NewIntArray(index); + *libnfcTypeList = e->NewIntArray(index); jint* techItems = e->GetIntArrayElements(*techList, NULL); jint* handleItems = e->GetIntArrayElements(*handleList, NULL); + jint* typeItems = e->GetIntArrayElements(*libnfcTypeList, NULL); for (int i = 0; i < index; i++) { techItems[i] = technologies[i]; handleItems[i] = handles[i]; + typeItems[i] = libnfctypes[i]; } e->ReleaseIntArrayElements(*techList, techItems, 0); e->ReleaseIntArrayElements(*handleList, handleItems, 0); + e->ReleaseIntArrayElements(*libnfcTypeList, typeItems, 0); } diff --git a/jni/com_android_nfc.h b/jni/com_android_nfc.h index 8e67d04..035e7d0 100644 --- a/jni/com_android_nfc.h +++ b/jni/com_android_nfc.h @@ -187,7 +187,8 @@ nfc_jni_native_monitor_t* nfc_jni_get_monitor(void); int get_technology_type(phNfc_eRemDevType_t type, uint8_t sak); void nfc_jni_get_technology_tree(JNIEnv* e, phLibNfc_RemoteDevList_t* devList, - uint8_t count, jintArray* techList, jintArray* handleList); + uint8_t count, jintArray* techList, jintArray* handleList, + jintArray* typeList); /* P2P */ phLibNfc_Handle nfc_jni_get_p2p_device_handle(JNIEnv *e, jobject o); @@ -195,6 +196,7 @@ jshort nfc_jni_get_p2p_device_mode(JNIEnv *e, jobject o); /* TAG */ jint nfc_jni_get_connected_technology(JNIEnv *e, jobject o); +jint nfc_jni_get_connected_technology_libnfc_type(JNIEnv *e, jobject o); phLibNfc_Handle nfc_jni_get_connected_handle(JNIEnv *e, jobject o); jintArray nfc_jni_get_nfc_tag_type(JNIEnv *e, jobject o); diff --git a/jni/com_android_nfc_NativeNfcManager.cpp b/jni/com_android_nfc_NativeNfcManager.cpp index 5789811..fb943a1 100644 --- a/jni/com_android_nfc_NativeNfcManager.cpp +++ b/jni/com_android_nfc_NativeNfcManager.cpp @@ -953,9 +953,10 @@ static void nfc_jni_Discovery_notification_callback(void *pContext, /* Generate technology list */ jintArray techList; jintArray handleList; + jintArray typeList; nfc_jni_get_technology_tree(e, psRemoteDevList, multi_protocol ? uNofRemoteDev : 1, - &techList, &handleList); + &techList, &handleList, &typeList); /* Push the technology list into the java object */ f = e->GetFieldID(tag_cls, "mTechList", "[I"); @@ -964,6 +965,9 @@ static void nfc_jni_Discovery_notification_callback(void *pContext, f = e->GetFieldID(tag_cls, "mTechHandles", "[I"); e->SetObjectField(tag, f, handleList); + f = e->GetFieldID(tag_cls, "mTechLibNfcTypes", "[I"); + e->SetObjectField(tag, f, typeList); + f = e->GetFieldID(tag_cls, "mConnectedTechnology", "I"); e->SetIntField(tag, f,(jint)-1); } diff --git a/jni/com_android_nfc_NativeNfcSecureElement.cpp b/jni/com_android_nfc_NativeNfcSecureElement.cpp index cd5e181..aec9d2d 100755 --- a/jni/com_android_nfc_NativeNfcSecureElement.cpp +++ b/jni/com_android_nfc_NativeNfcSecureElement.cpp @@ -129,7 +129,9 @@ static void com_android_nfc_jni_open_secure_element_notification_callback(void * /* Set type name */ jintArray techList; jintArray handleList; - nfc_jni_get_technology_tree(e, psRemoteDevList,uNofRemoteDev, &techList, &handleList); + jintArray typeList; + nfc_jni_get_technology_tree(e, psRemoteDevList,uNofRemoteDev, &techList, + &handleList, &typeList); // TODO: Should use the "connected" technology, for now use the first if (e->GetArrayLength(techList) > 0) { jint* technologies = e->GetIntArrayElements(techList, 0); @@ -153,7 +155,9 @@ static void com_android_nfc_jni_open_secure_element_notification_callback(void * /* Set type name */ jintArray techList; jintArray handleList; - nfc_jni_get_technology_tree(e, psRemoteDevList,uNofRemoteDev, &techList, &handleList); + jintArray typeList; + nfc_jni_get_technology_tree(e, psRemoteDevList,uNofRemoteDev, &techList, + &handleList, &typeList); // TODO: Should use the "connected" technology, for now use the first if ((techList != NULL) && e->GetArrayLength(techList) > 0) { diff --git a/jni/com_android_nfc_NativeNfcTag.cpp b/jni/com_android_nfc_NativeNfcTag.cpp index 79737b9..8eb3354 100644 --- a/jni/com_android_nfc_NativeNfcTag.cpp +++ b/jni/com_android_nfc_NativeNfcTag.cpp @@ -517,11 +517,11 @@ static jboolean com_android_nfc_NativeNfcTag_doReconnect(JNIEnv *e, { // Reconnect is provided by libnfc by just calling connect again // on the same handle. - // Note that some tag types are stateless, hence we do not reconnect - // those. Currently those are the Jewel and Iso15693 technologies. - int selectedTech = nfc_jni_get_connected_technology(e, o); - if (selectedTech != -1) { - if (selectedTech != TARGET_TYPE_ISO15693) { + int libNfcType = nfc_jni_get_connected_technology_libnfc_type(e, o); + if (libNfcType != -1) { + // Note that some tag types are stateless, hence we do not reconnect + // those. Currently those are the Jewel and Iso15693 technologies. + if ((libNfcType != phNfc_eJewel_PICC) && (libNfcType != phNfc_eISO15693_PICC)) { phLibNfc_Handle handle = nfc_jni_get_connected_handle(e,o); return com_android_nfc_NativeNfcTag_doConnect(e, o, handle); } @@ -697,6 +697,7 @@ static jbyteArray com_android_nfc_NativeNfcTag_doTransceive(JNIEnv *e, NFCSTATUS status; struct nfc_jni_callback_data cb_data; int selectedTech = 0; + int selectedLibNfcType = 0; jint* technologies = NULL; bool checkResponseCrc = false; @@ -710,17 +711,12 @@ static jbyteArray com_android_nfc_NativeNfcTag_doTransceive(JNIEnv *e, } selectedTech = nfc_jni_get_connected_technology(e, o); + selectedLibNfcType = nfc_jni_get_connected_technology_libnfc_type(e, o); buf = outbuf = (uint8_t *)e->GetByteArrayElements(data, NULL); buflen = outlen = (uint32_t)e->GetArrayLength(data); switch (selectedTech) { -/* TODO figure out how to pipe Jewel commands through from Java - case TARGET_TYPE_JEWEL: - transceive_info.cmd.JewelCmd = phNfc_eJewel_Raw; - transceive_info.addr = 0; - break; -*/ case TARGET_TYPE_FELICA: transceive_info.cmd.FelCmd = phNfc_eFelica_Raw; transceive_info.addr = 0; @@ -744,7 +740,12 @@ static jbyteArray com_android_nfc_NativeNfcTag_doTransceive(JNIEnv *e, } break; case TARGET_TYPE_ISO14443_3A: - if (raw) { + // Check which libnfc type + if (selectedLibNfcType == phNfc_eJewel_PICC) { + // For the Jewel pipe, CRC is automatically computed + transceive_info.cmd.JewelCmd = phNfc_eJewel_Raw; + transceive_info.addr = 0; + } else { transceive_info.cmd.MfCmd = phHal_eMifareRaw; transceive_info.addr = 0; // Need to add in the crc here @@ -754,10 +755,6 @@ static jbyteArray com_android_nfc_NativeNfcTag_doTransceive(JNIEnv *e, nfc_insert_crc_a(outbuf, buflen); checkResponseCrc = true; - } else { - offset = 2; - transceive_info.cmd.MfCmd = (phNfc_eMifareCmdList_t)buf[0]; - transceive_info.addr = (uint8_t)buf[1]; } break; case TARGET_TYPE_ISO14443_4: diff --git a/src/com/android/nfc/NativeNfcTag.java b/src/com/android/nfc/NativeNfcTag.java index 5995ea8..c9a2ee7 100755 --- a/src/com/android/nfc/NativeNfcTag.java +++ b/src/com/android/nfc/NativeNfcTag.java @@ -34,6 +34,7 @@ public class NativeNfcTag { private int[] mTechList; private int[] mTechHandles; + private int[] mTechLibNfcTypes; private Bundle[] mTechExtras; private byte[][] mTechPollBytes; private byte[][] mTechActBytes; @@ -83,12 +84,16 @@ public class NativeNfcTag { boolean isSuccess = false; for (int i = 0; i < mTechList.length; i++) { if (mTechList[i] == technology) { - // Get the handle and connect - isSuccess = doConnect(mTechHandles[i]); - if (isSuccess) { - mConnectedTechnology = i; - mWatchdog = new PresenceCheckWatchdog(); - mWatchdog.start(); + // Get the handle and connect, if not already connected + if (mConnectedTechnology != i) { + isSuccess = doConnect(mTechHandles[i]); + if (isSuccess) { + mConnectedTechnology = i; + mWatchdog = new PresenceCheckWatchdog(); + mWatchdog.start(); + } + } else { + isSuccess = true; // Already connect to this tech } break; } @@ -208,12 +213,21 @@ public class NativeNfcTag { return 0; } } + + public int getConnectedLibNfcType() { + if (mConnectedTechnology != -1 && mConnectedTechnology < mTechLibNfcTypes.length) { + return mTechLibNfcTypes[mConnectedTechnology]; + } else { + return 0; + } + } // This method exists to "patch in" the ndef technologies, // which is done inside Java instead of the native JNI code. // To not create some nasty dependencies on the order on which things // are called (most notably getTechExtras()), it needs some additional // checking. - public void addNdefTechnology(NdefMessage msg, int handle, int maxLength, int cardState) { + public void addNdefTechnology(NdefMessage msg, int handle, int libnfctype, + int maxLength, int cardState) { synchronized (this) { int[] mNewTechList = new int[mTechList.length + 1]; System.arraycopy(mTechList, 0, mNewTechList, 0, mTechList.length); @@ -225,6 +239,11 @@ public class NativeNfcTag { mNewHandleList[mTechHandles.length] = handle; mTechHandles = mNewHandleList; + int[] mNewTypeList = new int[mTechLibNfcTypes.length + 1]; + System.arraycopy(mTechLibNfcTypes, 0, mNewTypeList, 0, mTechLibNfcTypes.length); + mNewTypeList[mTechLibNfcTypes.length] = handle; + mTechLibNfcTypes = mNewTypeList; + Bundle extras = new Bundle(); extras.putParcelable(Ndef.EXTRA_NDEF_MSG, msg); extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, maxLength); diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java index 66e6f54..3457583 100755 --- a/src/com/android/nfc/NfcService.java +++ b/src/com/android/nfc/NfcService.java @@ -2501,6 +2501,7 @@ public class NfcService extends Application { ndefMsgs[0] = new NdefMessage(buff); nativeTag.addNdefTechnology(ndefMsgs[0], nativeTag.getConnectedHandle(), + nativeTag.getConnectedLibNfcType(), supportedNdefLength, cardState); nativeTag.reconnect(); } catch (FormatException e) { @@ -2515,6 +2516,7 @@ public class NfcService extends Application { ndefMsgs = new NdefMessage[] { }; nativeTag.addNdefTechnology(null, nativeTag.getConnectedHandle(), + nativeTag.getConnectedLibNfcType(), supportedNdefLength, cardState); nativeTag.reconnect(); } |