diff options
Diffstat (limited to 'nci/src/com/android/nfc/dhimpl/NativeNfcManager.java')
-rwxr-xr-x | nci/src/com/android/nfc/dhimpl/NativeNfcManager.java | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java b/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java new file mode 100755 index 0000000..1437e5d --- /dev/null +++ b/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java @@ -0,0 +1,378 @@ +/* + * Copyright (C) 2010 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. + */ + +package com.android.nfc.dhimpl; + +import com.android.nfc.DeviceHost; +import com.android.nfc.LlcpException; + +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.content.Context; +import android.content.SharedPreferences; +import android.nfc.ErrorCodes; +import android.nfc.tech.Ndef; +import android.nfc.tech.TagTechnology; +import android.util.Log; + +/** + * Native interface to the NFC Manager functions + */ +public class NativeNfcManager implements DeviceHost { + private static final String TAG = "NativeNfcManager"; + static final String PREF = "NciDeviceHost"; + + static final int DEFAULT_LLCP_MIU = 1980; + static final int DEFAULT_LLCP_RWSIZE = 2; + + static final String DRIVER_NAME = "android-nci"; + + private static final byte[][] EE_WIPE_APDUS = { + {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, + {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, + (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x20, (byte)0x10, (byte)0x00}, + {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00}, + {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, + {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, + (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x30, (byte)0x30, (byte)0x00}, + {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00}, + {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, + }; + + static { + System.loadLibrary("nfc_nci_jni"); + } + + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String INTERNAL_TARGET_DESELECTED_ACTION = "com.android.nfc.action.INTERNAL_TARGET_DESELECTED"; + + /* Native structure */ + private int mNative; + + private final DeviceHostListener mListener; + private final Context mContext; + + public NativeNfcManager(Context context, DeviceHostListener listener) { + mListener = listener; + initializeNativeStructure(); + mContext = context; + } + + public native boolean initializeNativeStructure(); + + private native boolean doDownload(); + + public native int doGetLastError(); + + @Override + public void checkFirmware() { + } + + private native boolean doInitialize(); + + @Override + public boolean initialize() { + SharedPreferences prefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + + if (prefs.getBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false)) { + try { + Thread.sleep (12000); + editor.putBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false); + editor.apply(); + } catch (InterruptedException e) { } + } + + return doInitialize(); + } + + private native boolean doDeinitialize(); + + @Override + public boolean deinitialize() { + SharedPreferences prefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + + editor.putBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false); + editor.apply(); + + return doDeinitialize(); + } + + @Override + public String getName() { + return DRIVER_NAME; + } + + @Override + public native void enableDiscovery(); + + @Override + public native void disableDiscovery(); + + @Override + public native int[] doGetSecureElementList(); + + @Override + public native void doSelectSecureElement(); + + @Override + public native void doDeselectSecureElement(); + + + private native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap, + String sn); + + @Override + public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int nSap, String sn) + throws LlcpException { + LlcpConnectionlessSocket socket = doCreateLlcpConnectionlessSocket(nSap, sn); + if (socket != null) { + return socket; + } else { + /* Get Error Status */ + int error = doGetLastError(); + + Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error)); + + switch (error) { + case ErrorCodes.ERROR_BUFFER_TO_SMALL: + case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: + throw new LlcpException(error); + default: + throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION); + } + } + } + + private native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu, + int rw, int linearBufferLength); + @Override + public LlcpServerSocket createLlcpServerSocket(int nSap, String sn, int miu, + int rw, int linearBufferLength) throws LlcpException { + LlcpServerSocket socket = doCreateLlcpServiceSocket(nSap, sn, miu, rw, linearBufferLength); + if (socket != null) { + return socket; + } else { + /* Get Error Status */ + int error = doGetLastError(); + + Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error)); + + switch (error) { + case ErrorCodes.ERROR_BUFFER_TO_SMALL: + case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: + throw new LlcpException(error); + default: + throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION); + } + } + } + + private native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw, + int linearBufferLength); + @Override + public LlcpSocket createLlcpSocket(int sap, int miu, int rw, + int linearBufferLength) throws LlcpException { + LlcpSocket socket = doCreateLlcpSocket(sap, miu, rw, linearBufferLength); + if (socket != null) { + return socket; + } else { + /* Get Error Status */ + int error = doGetLastError(); + + Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error)); + + switch (error) { + case ErrorCodes.ERROR_BUFFER_TO_SMALL: + case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: + throw new LlcpException(error); + default: + throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION); + } + } + } + + @Override + public native boolean doCheckLlcp(); + + @Override + public native boolean doActivateLlcp(); + + private native void doResetTimeouts(); + + @Override + public void resetTimeouts() { + doResetTimeouts(); + } + + @Override + public native void doAbort(); + + private native boolean doSetTimeout(int tech, int timeout); + @Override + public boolean setTimeout(int tech, int timeout) { + return doSetTimeout(tech, timeout); + } + + private native int doGetTimeout(int tech); + @Override + public int getTimeout(int tech) { + return doGetTimeout(tech); + } + + + @Override + public boolean canMakeReadOnly(int ndefType) { + return (ndefType == Ndef.TYPE_1 || ndefType == Ndef.TYPE_2); + } + + @Override + public int getMaxTransceiveLength(int technology) { + switch (technology) { + case (TagTechnology.NFC_A): + case (TagTechnology.MIFARE_CLASSIC): + case (TagTechnology.MIFARE_ULTRALIGHT): + return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC + case (TagTechnology.NFC_B): + ///////////////////////////////////////////////////////////////// + // Broadcom: Since BCM2079x supports this, set NfcB max size. + //return 0; // PN544 does not support transceive of raw NfcB + return 253; // PN544 does not support transceive of raw NfcB + case (TagTechnology.NFC_V): + return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC + case (TagTechnology.ISO_DEP): + /* The maximum length of a normal IsoDep frame consists of: + * CLA, INS, P1, P2, LC, LE + 255 payload bytes = 261 bytes + * such a frame is supported. Extended length frames however + * are not supported. + */ + return 261; // Will be automatically split in two frames on the RF layer + case (TagTechnology.NFC_F): + return 252; // PN544 RF buffer = 255 bytes, subtract one for SoD, two for CRC + default: + return 0; + } + + } + + private native void doSetP2pInitiatorModes(int modes); + @Override + public void setP2pInitiatorModes(int modes) { + doSetP2pInitiatorModes(modes); + } + + private native void doSetP2pTargetModes(int modes); + @Override + public void setP2pTargetModes(int modes) { + doSetP2pTargetModes(modes); + } + @Override + public boolean getExtendedLengthApdusSupported() { + // TODO check BCM support + return false; + } + + @Override + public boolean enablePN544Quirks() { + return false; + } + + @Override + public byte[][] getWipeApdus() { + return EE_WIPE_APDUS; + } + + @Override + public int getDefaultLlcpMiu() { + return DEFAULT_LLCP_MIU; + } + + @Override + public int getDefaultLlcpRwSize() { + return DEFAULT_LLCP_RWSIZE; + } + + private native String doDump(); + @Override + public String dump() { + return doDump(); + } + + /** + * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered) + */ + private void notifyNdefMessageListeners(NativeNfcTag tag) { + mListener.onRemoteEndpointDiscovered(tag); + } + + /** + * Notifies transaction + */ + private void notifyTargetDeselected() { + mListener.onCardEmulationDeselected(); + } + + /** + * Notifies transaction + */ + private void notifyTransactionListeners(byte[] aid) { + mListener.onCardEmulationAidSelected(aid); + } + + /** + * Notifies P2P Device detected, to activate LLCP link + */ + private void notifyLlcpLinkActivation(NativeP2pDevice device) { + mListener.onLlcpLinkActivated(device); + } + + /** + * Notifies P2P Device detected, to activate LLCP link + */ + private void notifyLlcpLinkDeactivated(NativeP2pDevice device) { + mListener.onLlcpLinkDeactivated(device); + } + + private void notifySeFieldActivated() { + mListener.onRemoteFieldActivated(); + } + + private void notifySeFieldDeactivated() { + mListener.onRemoteFieldDeactivated(); + } + + private void notifySeListenActivated() { + mListener.onSeListenActivated(); + } + + private void notifySeListenDeactivated() { + mListener.onSeListenDeactivated(); + } + + private void notifySeApduReceived(byte[] apdu) { + mListener.onSeApduReceived(apdu); + } + + private void notifySeEmvCardRemoval() { + mListener.onSeEmvCardRemoval(); + } + + private void notifySeMifareAccess(byte[] block) { + mListener.onSeMifareAccess(block); + } + +} |