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 /**
     30  * Native interface to the NFC Manager functions
     31  */
     32 public class NativeNfcManager implements DeviceHost {
     33     private static final String TAG = "NativeNfcManager";
     34     static final String PREF = "NciDeviceHost";
     35 
     36     static final int DEFAULT_LLCP_MIU = 1980;
     37     static final int DEFAULT_LLCP_RWSIZE = 2;
     38 
     39     static final String DRIVER_NAME = "android-nci";
     40 
     41     static {
     42         System.loadLibrary("nfc_nci_jni");
     43     }
     44 
     45 
     46     /* Native structure */
     47     private long mNative;
     48 
     49     private final DeviceHostListener mListener;
     50     private final Context mContext;
     51 
     52 
     53     public NativeNfcManager(Context context, DeviceHostListener listener) {
     54         mListener = listener;
     55         initializeNativeStructure();
     56         mContext = context;
     57     }
     58 
     59     public native boolean initializeNativeStructure();
     60 
     61     private native boolean doDownload();
     62 
     63     public native int doGetLastError();
     64 
     65     @Override
     66     public void checkFirmware() {
     67         doDownload();
     68     }
     69 
     70     private native boolean doInitialize();
     71 
     72     @Override
     73     public boolean initialize() {
     74         return doInitialize();
     75     }
     76 
     77     private native boolean doDeinitialize();
     78 
     79     @Override
     80     public boolean deinitialize() {
     81         return doDeinitialize();
     82     }
     83 
     84     @Override
     85     public String getName() {
     86         return DRIVER_NAME;
     87     }
     88 
     89     @Override
     90     public native boolean sendRawFrame(byte[] data);
     91 
     92     @Override
     93     public native boolean routeAid(byte[] aid, int route);
     94 
     95     @Override
     96     public native boolean unrouteAid(byte[] aid);
     97 
     98     @Override
     99     public native boolean commitRouting();
    100 
    101     private native void doEnableDiscovery(int techMask,
    102                                           boolean enableLowPowerPolling,
    103                                           boolean enableReaderMode,
    104                                           boolean enableHostRouting,
    105                                           boolean enableP2p,
    106                                           boolean restart);
    107     @Override
    108     public void enableDiscovery(NfcDiscoveryParameters params, boolean restart) {
    109         doEnableDiscovery(params.getTechMask(), params.shouldEnableLowPowerDiscovery(),
    110                 params.shouldEnableReaderMode(), params.shouldEnableHostRouting(),
    111                 params.shouldEnableP2p(), restart);
    112     }
    113 
    114     @Override
    115     public native void disableDiscovery();
    116 
    117     private native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap,
    118             String sn);
    119 
    120     @Override
    121     public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int nSap, String sn)
    122             throws LlcpException {
    123         LlcpConnectionlessSocket socket = doCreateLlcpConnectionlessSocket(nSap, sn);
    124         if (socket != null) {
    125             return socket;
    126         } else {
    127             /* Get Error Status */
    128             int error = doGetLastError();
    129 
    130             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
    131 
    132             switch (error) {
    133                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
    134                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
    135                     throw new LlcpException(error);
    136                 default:
    137                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
    138             }
    139         }
    140     }
    141 
    142     private native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu,
    143             int rw, int linearBufferLength);
    144     @Override
    145     public LlcpServerSocket createLlcpServerSocket(int nSap, String sn, int miu,
    146             int rw, int linearBufferLength) throws LlcpException {
    147         LlcpServerSocket socket = doCreateLlcpServiceSocket(nSap, sn, miu, rw, linearBufferLength);
    148         if (socket != null) {
    149             return socket;
    150         } else {
    151             /* Get Error Status */
    152             int error = doGetLastError();
    153 
    154             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
    155 
    156             switch (error) {
    157                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
    158                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
    159                     throw new LlcpException(error);
    160                 default:
    161                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
    162             }
    163         }
    164     }
    165 
    166     private native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw,
    167             int linearBufferLength);
    168     @Override
    169     public LlcpSocket createLlcpSocket(int sap, int miu, int rw,
    170             int linearBufferLength) throws LlcpException {
    171         LlcpSocket socket = doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
    172         if (socket != null) {
    173             return socket;
    174         } else {
    175             /* Get Error Status */
    176             int error = doGetLastError();
    177 
    178             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
    179 
    180             switch (error) {
    181                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
    182                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
    183                     throw new LlcpException(error);
    184                 default:
    185                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
    186             }
    187         }
    188     }
    189 
    190     @Override
    191     public native boolean doCheckLlcp();
    192 
    193     @Override
    194     public native boolean doActivateLlcp();
    195 
    196     private native void doResetTimeouts();
    197 
    198     @Override
    199     public void resetTimeouts() {
    200         doResetTimeouts();
    201     }
    202 
    203     @Override
    204     public native void doAbort();
    205 
    206     private native boolean doSetTimeout(int tech, int timeout);
    207     @Override
    208     public boolean setTimeout(int tech, int timeout) {
    209         return doSetTimeout(tech, timeout);
    210     }
    211 
    212     private native int doGetTimeout(int tech);
    213     @Override
    214     public int getTimeout(int tech) {
    215         return doGetTimeout(tech);
    216     }
    217 
    218 
    219     @Override
    220     public boolean canMakeReadOnly(int ndefType) {
    221         return (ndefType == Ndef.TYPE_1 || ndefType == Ndef.TYPE_2);
    222     }
    223 
    224     @Override
    225     public int getMaxTransceiveLength(int technology) {
    226         switch (technology) {
    227             case (TagTechnology.NFC_A):
    228             case (TagTechnology.MIFARE_CLASSIC):
    229             case (TagTechnology.MIFARE_ULTRALIGHT):
    230                 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
    231             case (TagTechnology.NFC_B):
    232                 /////////////////////////////////////////////////////////////////
    233                 // Broadcom: Since BCM2079x supports this, set NfcB max size.
    234                 //return 0; // PN544 does not support transceive of raw NfcB
    235                 return 253; // PN544 does not support transceive of raw NfcB
    236             case (TagTechnology.NFC_V):
    237                 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
    238             case (TagTechnology.ISO_DEP):
    239                 /* The maximum length of a normal IsoDep frame consists of:
    240                  * CLA, INS, P1, P2, LC, LE + 255 payload bytes = 261 bytes
    241                  * such a frame is supported. Extended length frames however
    242                  * are not supported.
    243                  */
    244                 return 261; // Will be automatically split in two frames on the RF layer
    245             case (TagTechnology.NFC_F):
    246                 return 252; // PN544 RF buffer = 255 bytes, subtract one for SoD, two for CRC
    247             default:
    248                 return 0;
    249         }
    250 
    251     }
    252 
    253     private native void doSetP2pInitiatorModes(int modes);
    254     @Override
    255     public void setP2pInitiatorModes(int modes) {
    256         doSetP2pInitiatorModes(modes);
    257     }
    258 
    259     private native void doSetP2pTargetModes(int modes);
    260     @Override
    261     public void setP2pTargetModes(int modes) {
    262         doSetP2pTargetModes(modes);
    263     }
    264 
    265     @Override
    266     public boolean getExtendedLengthApdusSupported() {
    267         // TODO check BCM support
    268         return false;
    269     }
    270 
    271     @Override
    272     public int getDefaultLlcpMiu() {
    273         return DEFAULT_LLCP_MIU;
    274     }
    275 
    276     @Override
    277     public int getDefaultLlcpRwSize() {
    278         return DEFAULT_LLCP_RWSIZE;
    279     }
    280 
    281     private native String doDump();
    282     @Override
    283     public String dump() {
    284         return doDump();
    285     }
    286 
    287     private native void doEnableScreenOffSuspend();
    288     @Override
    289     public boolean enableScreenOffSuspend() {
    290         doEnableScreenOffSuspend();
    291         return true;
    292     }
    293 
    294     private native void doDisableScreenOffSuspend();
    295     @Override
    296     public boolean disableScreenOffSuspend() {
    297         doDisableScreenOffSuspend();
    298         return true;
    299     }
    300 
    301     /**
    302      * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered)
    303      */
    304     private void notifyNdefMessageListeners(NativeNfcTag tag) {
    305         mListener.onRemoteEndpointDiscovered(tag);
    306     }
    307 
    308     /**
    309      * Notifies P2P Device detected, to activate LLCP link
    310      */
    311     private void notifyLlcpLinkActivation(NativeP2pDevice device) {
    312         mListener.onLlcpLinkActivated(device);
    313     }
    314 
    315     /**
    316      * Notifies P2P Device detected, to activate LLCP link
    317      */
    318     private void notifyLlcpLinkDeactivated(NativeP2pDevice device) {
    319         mListener.onLlcpLinkDeactivated(device);
    320     }
    321 
    322     /**
    323      * Notifies first packet received from remote LLCP
    324      */
    325     private void notifyLlcpLinkFirstPacketReceived(NativeP2pDevice device) {
    326         mListener.onLlcpFirstPacketReceived(device);
    327     }
    328 
    329     private void notifyHostEmuActivated() {
    330         mListener.onHostCardEmulationActivated();
    331     }
    332 
    333     private void notifyHostEmuData(byte[] data) {
    334         mListener.onHostCardEmulationData(data);
    335     }
    336 
    337     private void notifyHostEmuDeactivated() {
    338         mListener.onHostCardEmulationDeactivated();
    339     }
    340 
    341     private void notifyRfFieldActivated() {
    342         mListener.onRemoteFieldActivated();
    343     }
    344 
    345     private void notifyRfFieldDeactivated() {
    346         mListener.onRemoteFieldDeactivated();
    347     }
    348 
    349 }
    350