• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
31 /**
32  * Native interface to the NFC Manager functions
33  */
34 public class NativeNfcManager implements DeviceHost {
35     private static final String TAG = "NativeNfcManager";
36     static final String PREF = "NciDeviceHost";
37 
38     static final int DEFAULT_LLCP_MIU = 1980;
39     static final int DEFAULT_LLCP_RWSIZE = 2;
40 
41     static final String DRIVER_NAME = "android-nci";
42 
43     private static final byte[][] EE_WIPE_APDUS = {
44         {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
45         {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00,
46                 (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x20, (byte)0x10, (byte)0x00},
47         {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00},
48         {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
49         {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00,
50                 (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x30, (byte)0x30, (byte)0x00},
51         {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00},
52         {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
53     };
54 
55     static {
56         System.loadLibrary("nfc_nci_jni");
57     }
58 
59     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
60     public static final String INTERNAL_TARGET_DESELECTED_ACTION = "com.android.nfc.action.INTERNAL_TARGET_DESELECTED";
61 
62     /* Native structure */
63     private int mNative;
64 
65     private final DeviceHostListener mListener;
66     private final Context mContext;
67 
NativeNfcManager(Context context, DeviceHostListener listener)68     public NativeNfcManager(Context context, DeviceHostListener listener) {
69         mListener = listener;
70         initializeNativeStructure();
71         mContext = context;
72     }
73 
initializeNativeStructure()74     public native boolean initializeNativeStructure();
75 
doDownload()76     private native boolean doDownload();
77 
doGetLastError()78     public native int doGetLastError();
79 
80     @Override
checkFirmware()81     public void checkFirmware() {
82     }
83 
doInitialize()84     private native boolean doInitialize();
85 
86     @Override
initialize()87     public boolean initialize() {
88         SharedPreferences prefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
89         SharedPreferences.Editor editor = prefs.edit();
90 
91         if (prefs.getBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false)) {
92             try {
93                 Thread.sleep (12000);
94                 editor.putBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false);
95                 editor.apply();
96             } catch (InterruptedException e) { }
97         }
98 
99         return doInitialize();
100     }
101 
doDeinitialize()102     private native boolean doDeinitialize();
103 
104     @Override
deinitialize()105     public boolean deinitialize() {
106         SharedPreferences prefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
107         SharedPreferences.Editor editor = prefs.edit();
108 
109         editor.putBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false);
110         editor.apply();
111 
112         return doDeinitialize();
113     }
114 
115     @Override
getName()116     public String getName() {
117         return DRIVER_NAME;
118     }
119 
120     @Override
enableDiscovery()121     public native void enableDiscovery();
122 
123     @Override
disableDiscovery()124     public native void disableDiscovery();
125 
126     @Override
doGetSecureElementList()127     public native int[] doGetSecureElementList();
128 
129     @Override
doSelectSecureElement()130     public native void doSelectSecureElement();
131 
132     @Override
doDeselectSecureElement()133     public native void doDeselectSecureElement();
134 
135 
doCreateLlcpConnectionlessSocket(int nSap, String sn)136     private native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap,
137             String sn);
138 
139     @Override
createLlcpConnectionlessSocket(int nSap, String sn)140     public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int nSap, String sn)
141             throws LlcpException {
142         LlcpConnectionlessSocket socket = doCreateLlcpConnectionlessSocket(nSap, sn);
143         if (socket != null) {
144             return socket;
145         } else {
146             /* Get Error Status */
147             int error = doGetLastError();
148 
149             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
150 
151             switch (error) {
152                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
153                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
154                     throw new LlcpException(error);
155                 default:
156                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
157             }
158         }
159     }
160 
doCreateLlcpServiceSocket(int nSap, String sn, int miu, int rw, int linearBufferLength)161     private native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu,
162             int rw, int linearBufferLength);
163     @Override
createLlcpServerSocket(int nSap, String sn, int miu, int rw, int linearBufferLength)164     public LlcpServerSocket createLlcpServerSocket(int nSap, String sn, int miu,
165             int rw, int linearBufferLength) throws LlcpException {
166         LlcpServerSocket socket = doCreateLlcpServiceSocket(nSap, sn, miu, rw, linearBufferLength);
167         if (socket != null) {
168             return socket;
169         } else {
170             /* Get Error Status */
171             int error = doGetLastError();
172 
173             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
174 
175             switch (error) {
176                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
177                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
178                     throw new LlcpException(error);
179                 default:
180                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
181             }
182         }
183     }
184 
doCreateLlcpSocket(int sap, int miu, int rw, int linearBufferLength)185     private native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw,
186             int linearBufferLength);
187     @Override
createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)188     public LlcpSocket createLlcpSocket(int sap, int miu, int rw,
189             int linearBufferLength) throws LlcpException {
190         LlcpSocket socket = doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
191         if (socket != null) {
192             return socket;
193         } else {
194             /* Get Error Status */
195             int error = doGetLastError();
196 
197             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
198 
199             switch (error) {
200                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
201                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
202                     throw new LlcpException(error);
203                 default:
204                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
205             }
206         }
207     }
208 
209     @Override
doCheckLlcp()210     public native boolean doCheckLlcp();
211 
212     @Override
doActivateLlcp()213     public native boolean doActivateLlcp();
214 
doResetTimeouts()215     private native void doResetTimeouts();
216 
217     @Override
resetTimeouts()218     public void resetTimeouts() {
219         doResetTimeouts();
220     }
221 
222     @Override
doAbort()223     public native void doAbort();
224 
doSetTimeout(int tech, int timeout)225     private native boolean doSetTimeout(int tech, int timeout);
226     @Override
setTimeout(int tech, int timeout)227     public boolean setTimeout(int tech, int timeout) {
228         return doSetTimeout(tech, timeout);
229     }
230 
doGetTimeout(int tech)231     private native int doGetTimeout(int tech);
232     @Override
getTimeout(int tech)233     public int getTimeout(int tech) {
234         return doGetTimeout(tech);
235     }
236 
237 
238     @Override
canMakeReadOnly(int ndefType)239     public boolean canMakeReadOnly(int ndefType) {
240         return (ndefType == Ndef.TYPE_1 || ndefType == Ndef.TYPE_2);
241     }
242 
243     @Override
getMaxTransceiveLength(int technology)244     public int getMaxTransceiveLength(int technology) {
245         switch (technology) {
246             case (TagTechnology.NFC_A):
247             case (TagTechnology.MIFARE_CLASSIC):
248             case (TagTechnology.MIFARE_ULTRALIGHT):
249                 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
250             case (TagTechnology.NFC_B):
251                 /////////////////////////////////////////////////////////////////
252                 // Broadcom: Since BCM2079x supports this, set NfcB max size.
253                 //return 0; // PN544 does not support transceive of raw NfcB
254                 return 253; // PN544 does not support transceive of raw NfcB
255             case (TagTechnology.NFC_V):
256                 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
257             case (TagTechnology.ISO_DEP):
258                 /* The maximum length of a normal IsoDep frame consists of:
259                  * CLA, INS, P1, P2, LC, LE + 255 payload bytes = 261 bytes
260                  * such a frame is supported. Extended length frames however
261                  * are not supported.
262                  */
263                 return 261; // Will be automatically split in two frames on the RF layer
264             case (TagTechnology.NFC_F):
265                 return 252; // PN544 RF buffer = 255 bytes, subtract one for SoD, two for CRC
266             default:
267                 return 0;
268         }
269 
270     }
271 
doSetP2pInitiatorModes(int modes)272     private native void doSetP2pInitiatorModes(int modes);
273     @Override
setP2pInitiatorModes(int modes)274     public void setP2pInitiatorModes(int modes) {
275         doSetP2pInitiatorModes(modes);
276     }
277 
doSetP2pTargetModes(int modes)278     private native void doSetP2pTargetModes(int modes);
279     @Override
setP2pTargetModes(int modes)280     public void setP2pTargetModes(int modes) {
281         doSetP2pTargetModes(modes);
282     }
283     @Override
getExtendedLengthApdusSupported()284     public boolean getExtendedLengthApdusSupported() {
285         // TODO check BCM support
286         return false;
287     }
288 
289     @Override
enablePN544Quirks()290     public boolean enablePN544Quirks() {
291         return false;
292     }
293 
294     @Override
getWipeApdus()295     public byte[][] getWipeApdus() {
296         return EE_WIPE_APDUS;
297     }
298 
299     @Override
getDefaultLlcpMiu()300     public int getDefaultLlcpMiu() {
301         return DEFAULT_LLCP_MIU;
302     }
303 
304     @Override
getDefaultLlcpRwSize()305     public int getDefaultLlcpRwSize() {
306         return DEFAULT_LLCP_RWSIZE;
307     }
308 
doDump()309     private native String doDump();
310     @Override
dump()311     public String dump() {
312         return doDump();
313     }
314 
315     /**
316      * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered)
317      */
notifyNdefMessageListeners(NativeNfcTag tag)318     private void notifyNdefMessageListeners(NativeNfcTag tag) {
319         mListener.onRemoteEndpointDiscovered(tag);
320     }
321 
322     /**
323      * Notifies transaction
324      */
notifyTargetDeselected()325     private void notifyTargetDeselected() {
326         mListener.onCardEmulationDeselected();
327     }
328 
329     /**
330      * Notifies transaction
331      */
notifyTransactionListeners(byte[] aid)332     private void notifyTransactionListeners(byte[] aid) {
333         mListener.onCardEmulationAidSelected(aid);
334     }
335 
336     /**
337      * Notifies P2P Device detected, to activate LLCP link
338      */
notifyLlcpLinkActivation(NativeP2pDevice device)339     private void notifyLlcpLinkActivation(NativeP2pDevice device) {
340         mListener.onLlcpLinkActivated(device);
341     }
342 
343     /**
344      * Notifies P2P Device detected, to activate LLCP link
345      */
notifyLlcpLinkDeactivated(NativeP2pDevice device)346     private void notifyLlcpLinkDeactivated(NativeP2pDevice device) {
347         mListener.onLlcpLinkDeactivated(device);
348     }
349 
350     /**
351      * Notifies first packet received from remote LLCP
352      */
notifyLlcpLinkFirstPacketReceived(NativeP2pDevice device)353     private void notifyLlcpLinkFirstPacketReceived(NativeP2pDevice device) {
354         mListener.onLlcpFirstPacketReceived(device);
355     }
356 
notifySeFieldActivated()357     private void notifySeFieldActivated() {
358         mListener.onRemoteFieldActivated();
359     }
360 
notifySeFieldDeactivated()361     private void notifySeFieldDeactivated() {
362         mListener.onRemoteFieldDeactivated();
363     }
364 
notifySeListenActivated()365     private void notifySeListenActivated() {
366         mListener.onSeListenActivated();
367     }
368 
notifySeListenDeactivated()369     private void notifySeListenDeactivated() {
370         mListener.onSeListenDeactivated();
371     }
372 
notifySeApduReceived(byte[] apdu)373     private void notifySeApduReceived(byte[] apdu) {
374         mListener.onSeApduReceived(apdu);
375     }
376 
notifySeEmvCardRemoval()377     private void notifySeEmvCardRemoval() {
378         mListener.onSeEmvCardRemoval();
379     }
380 
notifySeMifareAccess(byte[] block)381     private void notifySeMifareAccess(byte[] block) {
382         mListener.onSeMifareAccess(block);
383     }
384 
385 }
386