• 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 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 
NativeNfcManager(Context context, DeviceHostListener listener)62     public NativeNfcManager(Context context, DeviceHostListener listener) {
63         mListener = listener;
64         initializeNativeStructure();
65         mContext = context;
66     }
67 
initializeNativeStructure()68     public native boolean initializeNativeStructure();
69 
doDownload()70     private native boolean doDownload();
71 
doGetLastError()72     public native int doGetLastError();
73 
74     @Override
checkFirmware()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 
doInitialize()118     private native boolean doInitialize();
119 
120     @Override
initialize()121     public boolean initialize() {
122         return doInitialize();
123     }
124 
doDeinitialize()125     private native boolean doDeinitialize();
126 
127     @Override
deinitialize()128     public boolean deinitialize() {
129         return doDeinitialize();
130     }
131 
132     @Override
getName()133     public String getName() {
134         return DRIVER_NAME;
135     }
136 
137     @Override
sendRawFrame(byte[] data)138     public boolean sendRawFrame(byte[] data) {
139         return false;
140     }
141 
142     @Override
routeAid(byte[] aid, int route)143     public boolean routeAid(byte[] aid, int route) {
144         return false;
145     }
146 
147     @Override
unrouteAid(byte[] aid)148     public boolean unrouteAid(byte[] aid) {
149        return false;
150     }
151 
152     @Override
commitRouting()153     public boolean commitRouting() {
154         return false;
155     }
156 
157     @Override
registerT3tIdentifier(byte[] t3tIdentifier)158     public void registerT3tIdentifier(byte[] t3tIdentifier) {
159         return;
160     }
161 
162     @Override
deregisterT3tIdentifier(byte[] t3tIdentifier)163     public void deregisterT3tIdentifier(byte[] t3tIdentifier) {
164         return;
165     }
166 
167     @Override
clearT3tIdentifiersCache()168     public void clearT3tIdentifiersCache() {
169         return;
170     }
171 
172     @Override
getLfT3tMax()173     public int getLfT3tMax() {
174         return 0;
175     }
176 
doEnableDiscovery(int techMask, boolean enableLowPowerPolling, boolean enableReaderMode, boolean enableP2p, boolean restart)177     private native void doEnableDiscovery(int techMask,
178                                           boolean enableLowPowerPolling,
179                                           boolean enableReaderMode,
180                                           boolean enableP2p,
181                                           boolean restart);
182     @Override
enableDiscovery(NfcDiscoveryParameters params, boolean restart)183     public void enableDiscovery(NfcDiscoveryParameters params, boolean restart) {
184         doEnableDiscovery(params.getTechMask(), params.shouldEnableLowPowerDiscovery(),
185                 params.shouldEnableReaderMode(), params.shouldEnableP2p(), restart);
186     }
187 
188     @Override
disableDiscovery()189     public native void disableDiscovery();
190 
doCreateLlcpConnectionlessSocket(int nSap, String sn)191     private native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap,
192             String sn);
193 
194     @Override
createLlcpConnectionlessSocket(int nSap, String sn)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 
doCreateLlcpServiceSocket(int nSap, String sn, int miu, int rw, int linearBufferLength)216     private native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu,
217             int rw, int linearBufferLength);
218     @Override
createLlcpServerSocket(int nSap, String sn, int miu, int rw, int linearBufferLength)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 
doCreateLlcpSocket(int sap, int miu, int rw, int linearBufferLength)240     private native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw,
241             int linearBufferLength);
242     @Override
createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)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
doCheckLlcp()265     public native boolean doCheckLlcp();
266 
267     @Override
doActivateLlcp()268     public native boolean doActivateLlcp();
269 
doResetTimeouts()270     private native void doResetTimeouts();
271 
272     @Override
resetTimeouts()273     public void resetTimeouts() {
274         doResetTimeouts();
275     }
276 
277     @Override
doAbort()278     public native void doAbort();
279 
doSetTimeout(int tech, int timeout)280     private native boolean doSetTimeout(int tech, int timeout);
281     @Override
setTimeout(int tech, int timeout)282     public boolean setTimeout(int tech, int timeout) {
283         return doSetTimeout(tech, timeout);
284     }
285 
doGetTimeout(int tech)286     private native int doGetTimeout(int tech);
287     @Override
getTimeout(int tech)288     public int getTimeout(int tech) {
289         return doGetTimeout(tech);
290     }
291 
292 
293     @Override
canMakeReadOnly(int ndefType)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
getMaxTransceiveLength(int technology)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 
doSetP2pInitiatorModes(int modes)325     private native void doSetP2pInitiatorModes(int modes);
326     @Override
setP2pInitiatorModes(int modes)327     public void setP2pInitiatorModes(int modes) {
328         doSetP2pInitiatorModes(modes);
329     }
330 
doSetP2pTargetModes(int modes)331     private native void doSetP2pTargetModes(int modes);
332     @Override
setP2pTargetModes(int modes)333     public void setP2pTargetModes(int modes) {
334         doSetP2pTargetModes(modes);
335     }
336 
337     @Override
enableScreenOffSuspend()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
disableScreenOffSuspend()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
getExtendedLengthApdusSupported()352     public boolean getExtendedLengthApdusSupported() {
353         // Not supported on the PN544
354         return false;
355     }
356 
357     @Override
getDefaultLlcpMiu()358     public int getDefaultLlcpMiu() {
359         return DEFAULT_LLCP_MIU;
360     }
361 
362     @Override
getDefaultLlcpRwSize()363     public int getDefaultLlcpRwSize() {
364         return DEFAULT_LLCP_RWSIZE;
365     }
366 
doDump()367     private native String doDump();
368     @Override
dump()369     public String dump() {
370         return doDump();
371     }
372 
373     /**
374      * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered)
375      */
notifyNdefMessageListeners(NativeNfcTag tag)376     private void notifyNdefMessageListeners(NativeNfcTag tag) {
377         mListener.onRemoteEndpointDiscovered(tag);
378     }
379 
380     /**
381      * Notifies P2P Device detected, to activate LLCP link
382      */
notifyLlcpLinkActivation(NativeP2pDevice device)383     private void notifyLlcpLinkActivation(NativeP2pDevice device) {
384         mListener.onLlcpLinkActivated(device);
385     }
386 
387     /**
388      * Notifies P2P Device detected, to activate LLCP link
389      */
notifyLlcpLinkDeactivated(NativeP2pDevice device)390     private void notifyLlcpLinkDeactivated(NativeP2pDevice device) {
391         mListener.onLlcpLinkDeactivated(device);
392     }
393 
notifyHostEmuActivated(int technology)394     private void notifyHostEmuActivated(int technology) {
395         mListener.onHostCardEmulationActivated(technology);
396     }
397 
notifyHostEmuData(int technology, byte[] data)398     private void notifyHostEmuData(int technology, byte[] data) {
399         mListener.onHostCardEmulationData(technology, data);
400     }
401 
notifyHostEmuDeactivated(int technology)402     private void notifyHostEmuDeactivated(int technology) {
403         mListener.onHostCardEmulationDeactivated(technology);
404     }
405 
notifyRfFieldActivated()406     private void notifyRfFieldActivated() {
407         mListener.onRemoteFieldActivated();
408     }
409 
notifyRfFieldDeactivated()410     private void notifyRfFieldDeactivated() {
411         mListener.onRemoteFieldDeactivated();
412     }
413 }
414