Home | History | Annotate | Download | only in nxp
      1 /*
      2  * Copyright (C) 2010 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 package com.android.nfc.nxp;
     18 
     19 import com.android.nfc.DeviceHost;
     20 import com.android.nfc.LlcpException;
     21 
     22 import android.annotation.SdkConstant;
     23 import android.annotation.SdkConstant.SdkConstantType;
     24 import android.content.Context;
     25 import android.content.SharedPreferences;
     26 import android.nfc.ErrorCodes;
     27 import android.nfc.tech.Ndef;
     28 import android.nfc.tech.TagTechnology;
     29 import android.util.Log;
     30 
     31 import java.io.File;
     32 
     33 /**
     34  * Native interface to the NFC Manager functions
     35  */
     36 public class NativeNfcManager implements DeviceHost {
     37     private static final String TAG = "NativeNfcManager";
     38 
     39     private static final String NFC_CONTROLLER_FIRMWARE_FILE_NAME = "/vendor/firmware/libpn544_fw.so";
     40 
     41     static final String PREF = "NxpDeviceHost";
     42 
     43     private static final String PREF_FIRMWARE_MODTIME = "firmware_modtime";
     44     private static final long FIRMWARE_MODTIME_DEFAULT = -1;
     45 
     46     static {
     47         System.loadLibrary("nfc_jni");
     48     }
     49 
     50     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     51     public static final String INTERNAL_TARGET_DESELECTED_ACTION = "com.android.nfc.action.INTERNAL_TARGET_DESELECTED";
     52 
     53     /* Native structure */
     54     private int mNative;
     55 
     56     private final DeviceHostListener mListener;
     57     private final Context mContext;
     58 
     59     public NativeNfcManager(Context context, DeviceHostListener listener) {
     60         mListener = listener;
     61         initializeNativeStructure();
     62         mContext = context;
     63     }
     64 
     65     public native boolean initializeNativeStructure();
     66 
     67     private native boolean doDownload();
     68 
     69     public native int doGetLastError();
     70 
     71     @Override
     72     public void checkFirmware() {
     73         // Check that the NFC controller firmware is up to date.  This
     74         // ensures that firmware updates are applied in a timely fashion,
     75         // and makes it much less likely that the user will have to wait
     76         // for a firmware download when they enable NFC in the settings
     77         // app.  Firmware download can take some time, so this should be
     78         // run in a separate thread.
     79 
     80         // check the timestamp of the firmware file
     81         File firmwareFile;
     82         int nbRetry = 0;
     83         try {
     84             firmwareFile = new File(NFC_CONTROLLER_FIRMWARE_FILE_NAME);
     85         } catch(NullPointerException npe) {
     86             Log.e(TAG,"path to firmware file was null");
     87             return;
     88         }
     89 
     90         long modtime = firmwareFile.lastModified();
     91 
     92         SharedPreferences prefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
     93         long prev_fw_modtime = prefs.getLong(PREF_FIRMWARE_MODTIME, FIRMWARE_MODTIME_DEFAULT);
     94         Log.d(TAG,"prev modtime: " + prev_fw_modtime);
     95         Log.d(TAG,"new modtime: " + modtime);
     96         if (prev_fw_modtime == modtime) {
     97             return;
     98         }
     99 
    100         // FW download.
    101         while(nbRetry < 5) {
    102             Log.d(TAG,"Perform Download");
    103             if(doDownload()) {
    104                 Log.d(TAG,"Download Success");
    105                 // Now that we've finished updating the firmware, save the new modtime.
    106                 prefs.edit().putLong(PREF_FIRMWARE_MODTIME, modtime).apply();
    107                 break;
    108             } else {
    109                 Log.d(TAG,"Download Failed");
    110                 nbRetry++;
    111             }
    112         }
    113     }
    114 
    115     private native boolean doInitialize();
    116 
    117     @Override
    118     public boolean initialize() {
    119         SharedPreferences prefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
    120         SharedPreferences.Editor editor = prefs.edit();
    121 
    122         if (prefs.getBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false)) {
    123             try {
    124                 Thread.sleep (12000);
    125                 editor.putBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false);
    126                 editor.apply();
    127             } catch (InterruptedException e) { }
    128         }
    129 
    130         return doInitialize();
    131     }
    132 
    133     private native boolean doDeinitialize();
    134 
    135     @Override
    136     public boolean deinitialize() {
    137         SharedPreferences prefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
    138         SharedPreferences.Editor editor = prefs.edit();
    139 
    140         editor.putBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false);
    141         editor.apply();
    142 
    143         return doDeinitialize();
    144     }
    145 
    146     @Override
    147     public native void enableDiscovery();
    148 
    149     @Override
    150     public native void disableDiscovery();
    151 
    152     @Override
    153     public native int[] doGetSecureElementList();
    154 
    155     @Override
    156     public native void doSelectSecureElement();
    157 
    158     @Override
    159     public native void doDeselectSecureElement();
    160 
    161 
    162     private native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap,
    163             String sn);
    164 
    165     @Override
    166     public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int nSap, String sn)
    167             throws LlcpException {
    168         LlcpConnectionlessSocket socket = doCreateLlcpConnectionlessSocket(nSap, sn);
    169         if (socket != null) {
    170             return socket;
    171         } else {
    172             /* Get Error Status */
    173             int error = doGetLastError();
    174 
    175             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
    176 
    177             switch (error) {
    178                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
    179                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
    180                     throw new LlcpException(error);
    181                 default:
    182                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
    183             }
    184         }
    185     }
    186 
    187     private native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu,
    188             int rw, int linearBufferLength);
    189     @Override
    190     public LlcpServerSocket createLlcpServerSocket(int nSap, String sn, int miu,
    191             int rw, int linearBufferLength) throws LlcpException {
    192         LlcpServerSocket socket = doCreateLlcpServiceSocket(nSap, sn, miu, rw, linearBufferLength);
    193         if (socket != null) {
    194             return socket;
    195         } else {
    196             /* Get Error Status */
    197             int error = doGetLastError();
    198 
    199             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
    200 
    201             switch (error) {
    202                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
    203                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
    204                     throw new LlcpException(error);
    205                 default:
    206                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
    207             }
    208         }
    209     }
    210 
    211     private native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw,
    212             int linearBufferLength);
    213     @Override
    214     public LlcpSocket createLlcpSocket(int sap, int miu, int rw,
    215             int linearBufferLength) throws LlcpException {
    216         LlcpSocket socket = doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
    217         if (socket != null) {
    218             return socket;
    219         } else {
    220             /* Get Error Status */
    221             int error = doGetLastError();
    222 
    223             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
    224 
    225             switch (error) {
    226                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
    227                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
    228                     throw new LlcpException(error);
    229                 default:
    230                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
    231             }
    232         }
    233     }
    234 
    235     @Override
    236     public native boolean doCheckLlcp();
    237 
    238     @Override
    239     public native boolean doActivateLlcp();
    240 
    241     private native void doResetTimeouts();
    242 
    243     @Override
    244     public void resetTimeouts() {
    245         doResetTimeouts();
    246     }
    247 
    248     @Override
    249     public native void doAbort();
    250 
    251     private native boolean doSetTimeout(int tech, int timeout);
    252     @Override
    253     public boolean setTimeout(int tech, int timeout) {
    254         return doSetTimeout(tech, timeout);
    255     }
    256 
    257     private native int doGetTimeout(int tech);
    258     @Override
    259     public int getTimeout(int tech) {
    260         return doGetTimeout(tech);
    261     }
    262 
    263 
    264     @Override
    265     public boolean canMakeReadOnly(int ndefType) {
    266         return (ndefType == Ndef.TYPE_1 || ndefType == Ndef.TYPE_2 ||
    267                 ndefType == Ndef.TYPE_MIFARE_CLASSIC);
    268     }
    269 
    270     @Override
    271     public int getMaxTransceiveLength(int technology) {
    272         switch (technology) {
    273             case (TagTechnology.NFC_A):
    274             case (TagTechnology.MIFARE_CLASSIC):
    275             case (TagTechnology.MIFARE_ULTRALIGHT):
    276                 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
    277             case (TagTechnology.NFC_B):
    278                 return 0; // PN544 does not support transceive of raw NfcB
    279             case (TagTechnology.NFC_V):
    280                 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
    281             case (TagTechnology.ISO_DEP):
    282                 /* The maximum length of a normal IsoDep frame consists of:
    283                  * CLA, INS, P1, P2, LC, LE + 255 payload bytes = 261 bytes
    284                  * such a frame is supported. Extended length frames however
    285                  * are not supported.
    286                  */
    287                 return 261; // Will be automatically split in two frames on the RF layer
    288             case (TagTechnology.NFC_F):
    289                 return 252; // PN544 RF buffer = 255 bytes, subtract one for SoD, two for CRC
    290             default:
    291                 return 0;
    292         }
    293 
    294     }
    295 
    296     private native void doSetP2pInitiatorModes(int modes);
    297     @Override
    298     public void setP2pInitiatorModes(int modes) {
    299         doSetP2pInitiatorModes(modes);
    300     }
    301 
    302     private native void doSetP2pTargetModes(int modes);
    303     @Override
    304     public void setP2pTargetModes(int modes) {
    305         doSetP2pTargetModes(modes);
    306     }
    307 
    308     public boolean getExtendedLengthApdusSupported() {
    309         // Not supported on the PN544
    310         return false;
    311     }
    312 
    313     private native String doDump();
    314     @Override
    315     public String dump() {
    316         return doDump();
    317     }
    318 
    319     /**
    320      * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered)
    321      */
    322     private void notifyNdefMessageListeners(NativeNfcTag tag) {
    323         mListener.onRemoteEndpointDiscovered(tag);
    324     }
    325 
    326     /**
    327      * Notifies transaction
    328      */
    329     private void notifyTargetDeselected() {
    330         mListener.onCardEmulationDeselected();
    331     }
    332 
    333     /**
    334      * Notifies transaction
    335      */
    336     private void notifyTransactionListeners(byte[] aid) {
    337         mListener.onCardEmulationAidSelected(aid);
    338     }
    339 
    340     /**
    341      * Notifies P2P Device detected, to activate LLCP link
    342      */
    343     private void notifyLlcpLinkActivation(NativeP2pDevice device) {
    344         mListener.onLlcpLinkActivated(device);
    345     }
    346 
    347     /**
    348      * Notifies P2P Device detected, to activate LLCP link
    349      */
    350     private void notifyLlcpLinkDeactivated(NativeP2pDevice device) {
    351         mListener.onLlcpLinkDeactivated(device);
    352     }
    353 
    354     private void notifySeFieldActivated() {
    355         mListener.onRemoteFieldActivated();
    356     }
    357 
    358     private void notifySeFieldDeactivated() {
    359         mListener.onRemoteFieldDeactivated();
    360     }
    361 
    362     private void notifySeApduReceived(byte[] apdu) {
    363         mListener.onSeApduReceived(apdu);
    364     }
    365 
    366     private void notifySeEmvCardRemoval() {
    367         mListener.onSeEmvCardRemoval();
    368     }
    369 
    370     private void notifySeMifareAccess(byte[] block) {
    371         mListener.onSeMifareAccess(block);
    372     }
    373 }
    374