Home | History | Annotate | Download | only in dhimpl
      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.dhimpl;
     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 import com.android.nfc.NfcDiscoveryParameters;
     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     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 final String DRIVER_NAME = "nxp";
     48 
     49     static final int DEFAULT_LLCP_MIU = 128;
     50     static final int DEFAULT_LLCP_RWSIZE = 1;
     51 
     52     static {
     53         System.loadLibrary("nfc_jni");
     54     }
     55 
     56     /* Native structure */
     57     private long mNative;
     58 
     59     private final DeviceHostListener mListener;
     60     private final Context mContext;
     61 
     62     public NativeNfcManager(Context context, DeviceHostListener listener) {
     63         mListener = listener;
     64         initializeNativeStructure();
     65         mContext = context;
     66     }
     67 
     68     public native boolean initializeNativeStructure();
     69 
     70     private native boolean doDownload();
     71 
     72     public native int doGetLastError();
     73 
     74     @Override
     75     public void checkFirmware() {
     76         // Check that the NFC controller firmware is up to date.  This
     77         // ensures that firmware updates are applied in a timely fashion,
     78         // and makes it much less likely that the user will have to wait
     79         // for a firmware download when they enable NFC in the settings
     80         // app.  Firmware download can take some time, so this should be
     81         // run in a separate thread.
     82 
     83         // check the timestamp of the firmware file
     84         File firmwareFile;
     85         int nbRetry = 0;
     86         try {
     87             firmwareFile = new File(NFC_CONTROLLER_FIRMWARE_FILE_NAME);
     88         } catch(NullPointerException npe) {
     89             Log.e(TAG,"path to firmware file was null");
     90             return;
     91         }
     92 
     93         long modtime = firmwareFile.lastModified();
     94 
     95         SharedPreferences prefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
     96         long prev_fw_modtime = prefs.getLong(PREF_FIRMWARE_MODTIME, FIRMWARE_MODTIME_DEFAULT);
     97         Log.d(TAG,"prev modtime: " + prev_fw_modtime);
     98         Log.d(TAG,"new modtime: " + modtime);
     99         if (prev_fw_modtime == modtime) {
    100             return;
    101         }
    102 
    103         // FW download.
    104         while(nbRetry < 5) {
    105             Log.d(TAG,"Perform Download");
    106             if(doDownload()) {
    107                 Log.d(TAG,"Download Success");
    108                 // Now that we've finished updating the firmware, save the new modtime.
    109                 prefs.edit().putLong(PREF_FIRMWARE_MODTIME, modtime).apply();
    110                 break;
    111             } else {
    112                 Log.d(TAG,"Download Failed");
    113                 nbRetry++;
    114             }
    115         }
    116     }
    117 
    118     private native boolean doInitialize();
    119 
    120     @Override
    121     public boolean initialize() {
    122         return doInitialize();
    123     }
    124 
    125     private native boolean doDeinitialize();
    126 
    127     @Override
    128     public boolean deinitialize() {
    129         return doDeinitialize();
    130     }
    131 
    132     @Override
    133     public String getName() {
    134         return DRIVER_NAME;
    135     }
    136 
    137     @Override
    138     public boolean sendRawFrame(byte[] data) {
    139         return false;
    140     }
    141 
    142     @Override
    143     public boolean routeAid(byte[] aid, int route) {
    144         return false;
    145     }
    146 
    147     @Override
    148     public boolean unrouteAid(byte[] aid) {
    149        return false;
    150     }
    151 
    152     @Override
    153     public boolean commitRouting() {
    154         return false;
    155     }
    156 
    157     @Override
    158     public void registerT3tIdentifier(byte[] t3tIdentifier) {
    159         return;
    160     }
    161 
    162     @Override
    163     public void deregisterT3tIdentifier(byte[] t3tIdentifier) {
    164         return;
    165     }
    166 
    167     @Override
    168     public void clearT3tIdentifiersCache() {
    169         return;
    170     }
    171 
    172     @Override
    173     public int getLfT3tMax() {
    174         return 0;
    175     }
    176 
    177     private native void doEnableDiscovery(int techMask,
    178                                           boolean enableLowPowerPolling,
    179                                           boolean enableReaderMode,
    180                                           boolean enableP2p,
    181                                           boolean restart);
    182     @Override
    183     public void enableDiscovery(NfcDiscoveryParameters params, boolean restart) {
    184         doEnableDiscovery(params.getTechMask(), params.shouldEnableLowPowerDiscovery(),
    185                 params.shouldEnableReaderMode(), params.shouldEnableP2p(), restart);
    186     }
    187 
    188     @Override
    189     public native void disableDiscovery();
    190 
    191     private native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap,
    192             String sn);
    193 
    194     @Override
    195     public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int nSap, String sn)
    196             throws LlcpException {
    197         LlcpConnectionlessSocket socket = doCreateLlcpConnectionlessSocket(nSap, sn);
    198         if (socket != null) {
    199             return socket;
    200         } else {
    201             /* Get Error Status */
    202             int error = doGetLastError();
    203 
    204             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
    205 
    206             switch (error) {
    207                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
    208                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
    209                     throw new LlcpException(error);
    210                 default:
    211                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
    212             }
    213         }
    214     }
    215 
    216     private native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu,
    217             int rw, int linearBufferLength);
    218     @Override
    219     public LlcpServerSocket createLlcpServerSocket(int nSap, String sn, int miu,
    220             int rw, int linearBufferLength) throws LlcpException {
    221         LlcpServerSocket socket = doCreateLlcpServiceSocket(nSap, sn, miu, rw, linearBufferLength);
    222         if (socket != null) {
    223             return socket;
    224         } else {
    225             /* Get Error Status */
    226             int error = doGetLastError();
    227 
    228             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
    229 
    230             switch (error) {
    231                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
    232                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
    233                     throw new LlcpException(error);
    234                 default:
    235                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
    236             }
    237         }
    238     }
    239 
    240     private native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw,
    241             int linearBufferLength);
    242     @Override
    243     public LlcpSocket createLlcpSocket(int sap, int miu, int rw,
    244             int linearBufferLength) throws LlcpException {
    245         LlcpSocket socket = doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
    246         if (socket != null) {
    247             return socket;
    248         } else {
    249             /* Get Error Status */
    250             int error = doGetLastError();
    251 
    252             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
    253 
    254             switch (error) {
    255                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
    256                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
    257                     throw new LlcpException(error);
    258                 default:
    259                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
    260             }
    261         }
    262     }
    263 
    264     @Override
    265     public native boolean doCheckLlcp();
    266 
    267     @Override
    268     public native boolean doActivateLlcp();
    269 
    270     private native void doResetTimeouts();
    271 
    272     @Override
    273     public void resetTimeouts() {
    274         doResetTimeouts();
    275     }
    276 
    277     @Override
    278     public native void doAbort();
    279 
    280     private native boolean doSetTimeout(int tech, int timeout);
    281     @Override
    282     public boolean setTimeout(int tech, int timeout) {
    283         return doSetTimeout(tech, timeout);
    284     }
    285 
    286     private native int doGetTimeout(int tech);
    287     @Override
    288     public int getTimeout(int tech) {
    289         return doGetTimeout(tech);
    290     }
    291 
    292 
    293     @Override
    294     public boolean canMakeReadOnly(int ndefType) {
    295         return (ndefType == Ndef.TYPE_1 || ndefType == Ndef.TYPE_2 ||
    296                 ndefType == Ndef.TYPE_MIFARE_CLASSIC);
    297     }
    298 
    299     @Override
    300     public int getMaxTransceiveLength(int technology) {
    301         switch (technology) {
    302             case (TagTechnology.NFC_A):
    303             case (TagTechnology.MIFARE_CLASSIC):
    304             case (TagTechnology.MIFARE_ULTRALIGHT):
    305                 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
    306             case (TagTechnology.NFC_B):
    307                 return 0; // PN544 does not support transceive of raw NfcB
    308             case (TagTechnology.NFC_V):
    309                 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
    310             case (TagTechnology.ISO_DEP):
    311                 /* The maximum length of a normal IsoDep frame consists of:
    312                  * CLA, INS, P1, P2, LC, LE + 255 payload bytes = 261 bytes
    313                  * such a frame is supported. Extended length frames however
    314                  * are not supported.
    315                  */
    316                 return 261; // Will be automatically split in two frames on the RF layer
    317             case (TagTechnology.NFC_F):
    318                 return 252; // PN544 RF buffer = 255 bytes, subtract one for SoD, two for CRC
    319             default:
    320                 return 0;
    321         }
    322 
    323     }
    324 
    325     private native void doSetP2pInitiatorModes(int modes);
    326     @Override
    327     public void setP2pInitiatorModes(int modes) {
    328         doSetP2pInitiatorModes(modes);
    329     }
    330 
    331     private native void doSetP2pTargetModes(int modes);
    332     @Override
    333     public void setP2pTargetModes(int modes) {
    334         doSetP2pTargetModes(modes);
    335     }
    336 
    337     @Override
    338     public boolean enableScreenOffSuspend() {
    339         // Snooze mode not supported on NXP silicon
    340         Log.i(TAG, "Snooze mode is not supported on NXP NFCC");
    341         return false;
    342     }
    343 
    344     @Override
    345     public boolean disableScreenOffSuspend() {
    346         // Snooze mode not supported on NXP silicon
    347         Log.i(TAG, "Snooze mode is not supported on NXP NFCC");
    348         return true;
    349     }
    350 
    351     @Override
    352     public boolean getExtendedLengthApdusSupported() {
    353         // Not supported on the PN544
    354         return false;
    355     }
    356 
    357     @Override
    358     public int getDefaultLlcpMiu() {
    359         return DEFAULT_LLCP_MIU;
    360     }
    361 
    362     @Override
    363     public int getDefaultLlcpRwSize() {
    364         return DEFAULT_LLCP_RWSIZE;
    365     }
    366 
    367     private native String doDump();
    368     @Override
    369     public String dump() {
    370         return doDump();
    371     }
    372 
    373     /**
    374      * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered)
    375      */
    376     private void notifyNdefMessageListeners(NativeNfcTag tag) {
    377         mListener.onRemoteEndpointDiscovered(tag);
    378     }
    379 
    380     /**
    381      * Notifies P2P Device detected, to activate LLCP link
    382      */
    383     private void notifyLlcpLinkActivation(NativeP2pDevice device) {
    384         mListener.onLlcpLinkActivated(device);
    385     }
    386 
    387     /**
    388      * Notifies P2P Device detected, to activate LLCP link
    389      */
    390     private void notifyLlcpLinkDeactivated(NativeP2pDevice device) {
    391         mListener.onLlcpLinkDeactivated(device);
    392     }
    393 
    394     private void notifyHostEmuActivated(int technology) {
    395         mListener.onHostCardEmulationActivated(technology);
    396     }
    397 
    398     private void notifyHostEmuData(int technology, byte[] data) {
    399         mListener.onHostCardEmulationData(technology, data);
    400     }
    401 
    402     private void notifyHostEmuDeactivated(int technology) {
    403         mListener.onHostCardEmulationDeactivated(technology);
    404     }
    405 
    406     private void notifyRfFieldActivated() {
    407         mListener.onRemoteFieldActivated();
    408     }
    409 
    410     private void notifyRfFieldDeactivated() {
    411         mListener.onRemoteFieldDeactivated();
    412     }
    413 }
    414