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