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 android.content.Context;
     20 import android.nfc.ErrorCodes;
     21 import android.nfc.tech.Ndef;
     22 import android.nfc.tech.TagTechnology;
     23 import android.util.Log;
     24 
     25 import com.android.nfc.DeviceHost;
     26 import com.android.nfc.LlcpException;
     27 import com.android.nfc.NfcDiscoveryParameters;
     28 
     29 import java.util.Arrays;
     30 import java.util.Iterator;
     31 import java.util.HashMap;
     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     static final String PREF = "NciDeviceHost";
     39 
     40     static final int DEFAULT_LLCP_MIU = 1980;
     41     static final int DEFAULT_LLCP_RWSIZE = 2;
     42 
     43     static final String DRIVER_NAME = "android-nci";
     44 
     45     static {
     46         System.loadLibrary("nfc_nci_jni");
     47     }
     48 
     49     /* Native structure */
     50     private long mNative;
     51 
     52     private final DeviceHostListener mListener;
     53     private final Context mContext;
     54 
     55     private final Object mLock = new Object();
     56     private final HashMap<Integer, byte[]> mT3tIdentifiers = new HashMap<Integer, byte[]>();
     57 
     58     public NativeNfcManager(Context context, DeviceHostListener listener) {
     59         mListener = listener;
     60         initializeNativeStructure();
     61         mContext = context;
     62     }
     63 
     64     public native boolean initializeNativeStructure();
     65 
     66     private native boolean doDownload();
     67 
     68     public native int doGetLastError();
     69 
     70     @Override
     71     public void checkFirmware() {
     72         doDownload();
     73     }
     74 
     75     private native boolean doInitialize();
     76 
     77     @Override
     78     public boolean initialize() {
     79         return doInitialize();
     80     }
     81 
     82     private native boolean doDeinitialize();
     83 
     84     @Override
     85     public boolean deinitialize() {
     86         return doDeinitialize();
     87     }
     88 
     89     @Override
     90     public String getName() {
     91         return DRIVER_NAME;
     92     }
     93 
     94     @Override
     95     public native boolean sendRawFrame(byte[] data);
     96 
     97     @Override
     98     public native boolean routeAid(byte[] aid, int route);
     99 
    100     @Override
    101     public native boolean unrouteAid(byte[] aid);
    102 
    103     @Override
    104     public native boolean commitRouting();
    105 
    106     public native int doRegisterT3tIdentifier(byte[] t3tIdentifier);
    107 
    108     @Override
    109     public void registerT3tIdentifier(byte[] t3tIdentifier) {
    110         synchronized (mLock) {
    111             int handle = doRegisterT3tIdentifier(t3tIdentifier);
    112             if (handle != 0xffff) {
    113                 mT3tIdentifiers.put(Integer.valueOf(handle), t3tIdentifier);
    114             }
    115         }
    116     }
    117 
    118     public native void doDeregisterT3tIdentifier(int handle);
    119 
    120     @Override
    121     public void deregisterT3tIdentifier(byte[] t3tIdentifier) {
    122         synchronized (mLock) {
    123             Iterator<Integer> it = mT3tIdentifiers.keySet().iterator();
    124             while (it.hasNext()) {
    125                 int handle = it.next().intValue();
    126                 byte[] value = mT3tIdentifiers.get(handle);
    127                 if (Arrays.equals(value, t3tIdentifier)) {
    128                     doDeregisterT3tIdentifier(handle);
    129                     mT3tIdentifiers.remove(handle);
    130                     break;
    131                 }
    132             }
    133         }
    134     }
    135 
    136     @Override
    137     public void clearT3tIdentifiersCache() {
    138         synchronized (mLock) {
    139             mT3tIdentifiers.clear();
    140         }
    141     }
    142 
    143     @Override
    144     public native int getLfT3tMax();
    145 
    146     private native void doEnableDiscovery(int techMask,
    147                                           boolean enableLowPowerPolling,
    148                                           boolean enableReaderMode,
    149                                           boolean enableHostRouting,
    150                                           boolean enableP2p,
    151                                           boolean restart);
    152     @Override
    153     public void enableDiscovery(NfcDiscoveryParameters params, boolean restart) {
    154         doEnableDiscovery(params.getTechMask(), params.shouldEnableLowPowerDiscovery(),
    155                 params.shouldEnableReaderMode(), params.shouldEnableHostRouting(),
    156                 params.shouldEnableP2p(), restart);
    157     }
    158 
    159     @Override
    160     public native void disableDiscovery();
    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     }
    268 
    269     @Override
    270     public int getMaxTransceiveLength(int technology) {
    271         switch (technology) {
    272             case (TagTechnology.NFC_A):
    273             case (TagTechnology.MIFARE_CLASSIC):
    274             case (TagTechnology.MIFARE_ULTRALIGHT):
    275                 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
    276             case (TagTechnology.NFC_B):
    277                 /////////////////////////////////////////////////////////////////
    278                 // Broadcom: Since BCM2079x supports this, set NfcB max size.
    279                 //return 0; // PN544 does not support transceive of raw NfcB
    280                 return 253; // PN544 does not support transceive of raw NfcB
    281             case (TagTechnology.NFC_V):
    282                 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
    283             case (TagTechnology.ISO_DEP):
    284                 /* The maximum length of a normal IsoDep frame consists of:
    285                  * CLA, INS, P1, P2, LC, LE + 255 payload bytes = 261 bytes
    286                  * such a frame is supported. Extended length frames however
    287                  * are not supported.
    288                  */
    289                 return 261; // Will be automatically split in two frames on the RF layer
    290             case (TagTechnology.NFC_F):
    291                 return 252; // PN544 RF buffer = 255 bytes, subtract one for SoD, two for CRC
    292             default:
    293                 return 0;
    294         }
    295 
    296     }
    297 
    298     private native void doSetP2pInitiatorModes(int modes);
    299     @Override
    300     public void setP2pInitiatorModes(int modes) {
    301         doSetP2pInitiatorModes(modes);
    302     }
    303 
    304     private native void doSetP2pTargetModes(int modes);
    305     @Override
    306     public void setP2pTargetModes(int modes) {
    307         doSetP2pTargetModes(modes);
    308     }
    309 
    310     @Override
    311     public boolean getExtendedLengthApdusSupported() {
    312         // TODO check BCM support
    313         return false;
    314     }
    315 
    316     @Override
    317     public int getDefaultLlcpMiu() {
    318         return DEFAULT_LLCP_MIU;
    319     }
    320 
    321     @Override
    322     public int getDefaultLlcpRwSize() {
    323         return DEFAULT_LLCP_RWSIZE;
    324     }
    325 
    326     private native String doDump();
    327     @Override
    328     public String dump() {
    329         return doDump();
    330     }
    331 
    332     private native void doEnableScreenOffSuspend();
    333     @Override
    334     public boolean enableScreenOffSuspend() {
    335         doEnableScreenOffSuspend();
    336         return true;
    337     }
    338 
    339     private native void doDisableScreenOffSuspend();
    340     @Override
    341     public boolean disableScreenOffSuspend() {
    342         doDisableScreenOffSuspend();
    343         return true;
    344     }
    345 
    346     /**
    347      * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered)
    348      */
    349     private void notifyNdefMessageListeners(NativeNfcTag tag) {
    350         mListener.onRemoteEndpointDiscovered(tag);
    351     }
    352 
    353     /**
    354      * Notifies P2P Device detected, to activate LLCP link
    355      */
    356     private void notifyLlcpLinkActivation(NativeP2pDevice device) {
    357         mListener.onLlcpLinkActivated(device);
    358     }
    359 
    360     /**
    361      * Notifies P2P Device detected, to activate LLCP link
    362      */
    363     private void notifyLlcpLinkDeactivated(NativeP2pDevice device) {
    364         mListener.onLlcpLinkDeactivated(device);
    365     }
    366 
    367     /**
    368      * Notifies first packet received from remote LLCP
    369      */
    370     private void notifyLlcpLinkFirstPacketReceived(NativeP2pDevice device) {
    371         mListener.onLlcpFirstPacketReceived(device);
    372     }
    373 
    374     private void notifyHostEmuActivated(int technology) {
    375         mListener.onHostCardEmulationActivated(technology);
    376     }
    377 
    378     private void notifyHostEmuData(int technology, byte[] data) {
    379         mListener.onHostCardEmulationData(technology, data);
    380     }
    381 
    382     private void notifyHostEmuDeactivated(int technology) {
    383         mListener.onHostCardEmulationDeactivated(technology);
    384     }
    385 
    386     private void notifyRfFieldActivated() {
    387         mListener.onRemoteFieldActivated();
    388     }
    389 
    390     private void notifyRfFieldDeactivated() {
    391         mListener.onRemoteFieldDeactivated();
    392     }
    393 
    394 }
    395