• 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 android.annotation.SdkConstant;
20 import android.annotation.SdkConstant.SdkConstantType;
21 import android.content.Context;
22 import android.content.SharedPreferences;
23 import android.nfc.ErrorCodes;
24 import android.nfc.tech.Ndef;
25 import android.nfc.tech.TagTechnology;
26 import android.util.Log;
27 
28 import com.android.nfc.DeviceHost;
29 import com.android.nfc.LlcpException;
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         doDownload();
83     }
84 
doInitialize()85     private native boolean doInitialize();
86 
87     @Override
initialize()88     public boolean initialize() {
89         SharedPreferences prefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
90         SharedPreferences.Editor editor = prefs.edit();
91 
92         if (prefs.getBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false)) {
93             try {
94                 Thread.sleep (12000);
95                 editor.putBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false);
96                 editor.apply();
97             } catch (InterruptedException e) { }
98         }
99 
100         return doInitialize();
101     }
102 
doDeinitialize()103     private native boolean doDeinitialize();
104 
105     @Override
deinitialize()106     public boolean deinitialize() {
107         SharedPreferences prefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
108         SharedPreferences.Editor editor = prefs.edit();
109 
110         editor.putBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false);
111         editor.apply();
112 
113         return doDeinitialize();
114     }
115 
116     @Override
getName()117     public String getName() {
118         return DRIVER_NAME;
119     }
120 
121     @Override
sendRawFrame(byte[] data)122     public native boolean sendRawFrame(byte[] data);
123 
124     @Override
routeAid(byte[] aid, int route)125     public native boolean routeAid(byte[] aid, int route);
126 
127     @Override
unrouteAid(byte[] aid)128     public native boolean unrouteAid(byte[] aid);
129 
130     @Override
enableDiscovery()131     public native void enableDiscovery();
132 
133     @Override
disableDiscovery()134     public native void disableDiscovery();
135 
136     @Override
enableRoutingToHost()137     public native void enableRoutingToHost();
138 
139     @Override
disableRoutingToHost()140     public native void disableRoutingToHost();
141 
142     @Override
doGetSecureElementList()143     public native int[] doGetSecureElementList();
144 
145     @Override
doSelectSecureElement()146     public native void doSelectSecureElement();
147 
148     @Override
doDeselectSecureElement()149     public native void doDeselectSecureElement();
150 
151 
doCreateLlcpConnectionlessSocket(int nSap, String sn)152     private native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap,
153             String sn);
154 
155     @Override
createLlcpConnectionlessSocket(int nSap, String sn)156     public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int nSap, String sn)
157             throws LlcpException {
158         LlcpConnectionlessSocket socket = doCreateLlcpConnectionlessSocket(nSap, sn);
159         if (socket != null) {
160             return socket;
161         } else {
162             /* Get Error Status */
163             int error = doGetLastError();
164 
165             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
166 
167             switch (error) {
168                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
169                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
170                     throw new LlcpException(error);
171                 default:
172                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
173             }
174         }
175     }
176 
doCreateLlcpServiceSocket(int nSap, String sn, int miu, int rw, int linearBufferLength)177     private native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu,
178             int rw, int linearBufferLength);
179     @Override
createLlcpServerSocket(int nSap, String sn, int miu, int rw, int linearBufferLength)180     public LlcpServerSocket createLlcpServerSocket(int nSap, String sn, int miu,
181             int rw, int linearBufferLength) throws LlcpException {
182         LlcpServerSocket socket = doCreateLlcpServiceSocket(nSap, sn, miu, rw, linearBufferLength);
183         if (socket != null) {
184             return socket;
185         } else {
186             /* Get Error Status */
187             int error = doGetLastError();
188 
189             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
190 
191             switch (error) {
192                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
193                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
194                     throw new LlcpException(error);
195                 default:
196                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
197             }
198         }
199     }
200 
doCreateLlcpSocket(int sap, int miu, int rw, int linearBufferLength)201     private native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw,
202             int linearBufferLength);
203     @Override
createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)204     public LlcpSocket createLlcpSocket(int sap, int miu, int rw,
205             int linearBufferLength) throws LlcpException {
206         LlcpSocket socket = doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
207         if (socket != null) {
208             return socket;
209         } else {
210             /* Get Error Status */
211             int error = doGetLastError();
212 
213             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
214 
215             switch (error) {
216                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
217                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
218                     throw new LlcpException(error);
219                 default:
220                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
221             }
222         }
223     }
224 
225     @Override
doCheckLlcp()226     public native boolean doCheckLlcp();
227 
228     @Override
doActivateLlcp()229     public native boolean doActivateLlcp();
230 
doResetTimeouts()231     private native void doResetTimeouts();
232 
233     @Override
resetTimeouts()234     public void resetTimeouts() {
235         doResetTimeouts();
236     }
237 
238     @Override
doAbort()239     public native void doAbort();
240 
doSetTimeout(int tech, int timeout)241     private native boolean doSetTimeout(int tech, int timeout);
242     @Override
setTimeout(int tech, int timeout)243     public boolean setTimeout(int tech, int timeout) {
244         return doSetTimeout(tech, timeout);
245     }
246 
doGetTimeout(int tech)247     private native int doGetTimeout(int tech);
248     @Override
getTimeout(int tech)249     public int getTimeout(int tech) {
250         return doGetTimeout(tech);
251     }
252 
253 
254     @Override
canMakeReadOnly(int ndefType)255     public boolean canMakeReadOnly(int ndefType) {
256         return (ndefType == Ndef.TYPE_1 || ndefType == Ndef.TYPE_2);
257     }
258 
259     @Override
getMaxTransceiveLength(int technology)260     public int getMaxTransceiveLength(int technology) {
261         switch (technology) {
262             case (TagTechnology.NFC_A):
263             case (TagTechnology.MIFARE_CLASSIC):
264             case (TagTechnology.MIFARE_ULTRALIGHT):
265                 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
266             case (TagTechnology.NFC_B):
267                 /////////////////////////////////////////////////////////////////
268                 // Broadcom: Since BCM2079x supports this, set NfcB max size.
269                 //return 0; // PN544 does not support transceive of raw NfcB
270                 return 253; // PN544 does not support transceive of raw NfcB
271             case (TagTechnology.NFC_V):
272                 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
273             case (TagTechnology.ISO_DEP):
274                 /* The maximum length of a normal IsoDep frame consists of:
275                  * CLA, INS, P1, P2, LC, LE + 255 payload bytes = 261 bytes
276                  * such a frame is supported. Extended length frames however
277                  * are not supported.
278                  */
279                 return 261; // Will be automatically split in two frames on the RF layer
280             case (TagTechnology.NFC_F):
281                 return 252; // PN544 RF buffer = 255 bytes, subtract one for SoD, two for CRC
282             default:
283                 return 0;
284         }
285 
286     }
287 
doSetP2pInitiatorModes(int modes)288     private native void doSetP2pInitiatorModes(int modes);
289     @Override
setP2pInitiatorModes(int modes)290     public void setP2pInitiatorModes(int modes) {
291         doSetP2pInitiatorModes(modes);
292     }
293 
doSetP2pTargetModes(int modes)294     private native void doSetP2pTargetModes(int modes);
295     @Override
setP2pTargetModes(int modes)296     public void setP2pTargetModes(int modes) {
297         doSetP2pTargetModes(modes);
298     }
299 
300     @Override
getExtendedLengthApdusSupported()301     public boolean getExtendedLengthApdusSupported() {
302         // TODO check BCM support
303         return false;
304     }
305 
306     @Override
enablePN544Quirks()307     public boolean enablePN544Quirks() {
308         return false;
309     }
310 
311     @Override
getWipeApdus()312     public byte[][] getWipeApdus() {
313         return EE_WIPE_APDUS;
314     }
315 
316     @Override
getDefaultLlcpMiu()317     public int getDefaultLlcpMiu() {
318         return DEFAULT_LLCP_MIU;
319     }
320 
321     @Override
getDefaultLlcpRwSize()322     public int getDefaultLlcpRwSize() {
323         return DEFAULT_LLCP_RWSIZE;
324     }
325 
doDump()326     private native String doDump();
327     @Override
dump()328     public String dump() {
329         return doDump();
330     }
331 
doEnableReaderMode(int technologies)332     private native void doEnableReaderMode(int technologies);
333     @Override
enableReaderMode(int technologies)334     public boolean enableReaderMode(int technologies) {
335         doEnableReaderMode(technologies);
336         return true;
337     }
338 
doDisableReaderMode()339     private native void doDisableReaderMode();
340     @Override
disableReaderMode()341     public boolean disableReaderMode() {
342         doDisableReaderMode();
343         return true;
344     }
345 
346     /**
347      * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered)
348      */
notifyNdefMessageListeners(NativeNfcTag tag)349     private void notifyNdefMessageListeners(NativeNfcTag tag) {
350         mListener.onRemoteEndpointDiscovered(tag);
351     }
352 
353     /**
354      * Notifies transaction
355      */
notifyTargetDeselected()356     private void notifyTargetDeselected() {
357         mListener.onCardEmulationDeselected();
358     }
359 
360     /**
361      * Notifies transaction
362      */
notifyTransactionListeners(byte[] aid)363     private void notifyTransactionListeners(byte[] aid) {
364         mListener.onCardEmulationAidSelected(aid);
365     }
366 
367     /**
368      * Notifies P2P Device detected, to activate LLCP link
369      */
notifyLlcpLinkActivation(NativeP2pDevice device)370     private void notifyLlcpLinkActivation(NativeP2pDevice device) {
371         mListener.onLlcpLinkActivated(device);
372     }
373 
374     /**
375      * Notifies P2P Device detected, to activate LLCP link
376      */
notifyLlcpLinkDeactivated(NativeP2pDevice device)377     private void notifyLlcpLinkDeactivated(NativeP2pDevice device) {
378         mListener.onLlcpLinkDeactivated(device);
379     }
380 
381     /**
382      * Notifies first packet received from remote LLCP
383      */
notifyLlcpLinkFirstPacketReceived(NativeP2pDevice device)384     private void notifyLlcpLinkFirstPacketReceived(NativeP2pDevice device) {
385         mListener.onLlcpFirstPacketReceived(device);
386     }
387 
notifySeFieldActivated()388     private void notifySeFieldActivated() {
389         mListener.onRemoteFieldActivated();
390     }
391 
notifySeFieldDeactivated()392     private void notifySeFieldDeactivated() {
393         mListener.onRemoteFieldDeactivated();
394     }
395 
notifySeListenActivated()396     private void notifySeListenActivated() {
397         mListener.onSeListenActivated();
398     }
399 
notifySeListenDeactivated()400     private void notifySeListenDeactivated() {
401         mListener.onSeListenDeactivated();
402     }
403 
notifySeApduReceived(byte[] apdu)404     private void notifySeApduReceived(byte[] apdu) {
405         mListener.onSeApduReceived(apdu);
406     }
407 
notifySeEmvCardRemoval()408     private void notifySeEmvCardRemoval() {
409         mListener.onSeEmvCardRemoval();
410     }
411 
notifySeMifareAccess(byte[] block)412     private void notifySeMifareAccess(byte[] block) {
413         mListener.onSeMifareAccess(block);
414     }
415 
notifyHostEmuActivated()416     private void notifyHostEmuActivated() {
417         mListener.onHostCardEmulationActivated();
418     }
419 
notifyHostEmuData(byte[] data)420     private void notifyHostEmuData(byte[] data) {
421         mListener.onHostCardEmulationData(data);
422     }
423 
notifyHostEmuDeactivated()424     private void notifyHostEmuDeactivated() {
425         mListener.onHostCardEmulationDeactivated();
426     }
427 
428 }
429