• 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     {
140         return false;
141     }
142 
143     @Override
routeAid(byte[] aid, int route)144     public boolean routeAid(byte[] aid, int route)
145     {
146         return false;
147     }
148 
149     @Override
unrouteAid(byte[] aid)150     public boolean unrouteAid(byte[] aid)
151     {
152        return false;
153     }
154 
155     @Override
commitRouting()156     public boolean commitRouting()
157     {
158         return false;
159     }
160 
doEnableDiscovery(int techMask, boolean enableLowPowerPolling, boolean enableReaderMode, boolean enableP2p, boolean restart)161     private native void doEnableDiscovery(int techMask,
162                                           boolean enableLowPowerPolling,
163                                           boolean enableReaderMode,
164                                           boolean enableP2p,
165                                           boolean restart);
166     @Override
enableDiscovery(NfcDiscoveryParameters params, boolean restart)167     public void enableDiscovery(NfcDiscoveryParameters params, boolean restart) {
168         doEnableDiscovery(params.getTechMask(), params.shouldEnableLowPowerDiscovery(),
169                 params.shouldEnableReaderMode(), params.shouldEnableP2p(), restart);
170     }
171 
172     @Override
disableDiscovery()173     public native void disableDiscovery();
174 
doCreateLlcpConnectionlessSocket(int nSap, String sn)175     private native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap,
176             String sn);
177 
178     @Override
createLlcpConnectionlessSocket(int nSap, String sn)179     public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int nSap, String sn)
180             throws LlcpException {
181         LlcpConnectionlessSocket socket = doCreateLlcpConnectionlessSocket(nSap, sn);
182         if (socket != null) {
183             return socket;
184         } else {
185             /* Get Error Status */
186             int error = doGetLastError();
187 
188             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
189 
190             switch (error) {
191                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
192                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
193                     throw new LlcpException(error);
194                 default:
195                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
196             }
197         }
198     }
199 
doCreateLlcpServiceSocket(int nSap, String sn, int miu, int rw, int linearBufferLength)200     private native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu,
201             int rw, int linearBufferLength);
202     @Override
createLlcpServerSocket(int nSap, String sn, int miu, int rw, int linearBufferLength)203     public LlcpServerSocket createLlcpServerSocket(int nSap, String sn, int miu,
204             int rw, int linearBufferLength) throws LlcpException {
205         LlcpServerSocket socket = doCreateLlcpServiceSocket(nSap, sn, miu, rw, linearBufferLength);
206         if (socket != null) {
207             return socket;
208         } else {
209             /* Get Error Status */
210             int error = doGetLastError();
211 
212             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
213 
214             switch (error) {
215                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
216                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
217                     throw new LlcpException(error);
218                 default:
219                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
220             }
221         }
222     }
223 
doCreateLlcpSocket(int sap, int miu, int rw, int linearBufferLength)224     private native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw,
225             int linearBufferLength);
226     @Override
createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)227     public LlcpSocket createLlcpSocket(int sap, int miu, int rw,
228             int linearBufferLength) throws LlcpException {
229         LlcpSocket socket = doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
230         if (socket != null) {
231             return socket;
232         } else {
233             /* Get Error Status */
234             int error = doGetLastError();
235 
236             Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
237 
238             switch (error) {
239                 case ErrorCodes.ERROR_BUFFER_TO_SMALL:
240                 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
241                     throw new LlcpException(error);
242                 default:
243                     throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
244             }
245         }
246     }
247 
248     @Override
doCheckLlcp()249     public native boolean doCheckLlcp();
250 
251     @Override
doActivateLlcp()252     public native boolean doActivateLlcp();
253 
doResetTimeouts()254     private native void doResetTimeouts();
255 
256     @Override
resetTimeouts()257     public void resetTimeouts() {
258         doResetTimeouts();
259     }
260 
261     @Override
doAbort()262     public native void doAbort();
263 
doSetTimeout(int tech, int timeout)264     private native boolean doSetTimeout(int tech, int timeout);
265     @Override
setTimeout(int tech, int timeout)266     public boolean setTimeout(int tech, int timeout) {
267         return doSetTimeout(tech, timeout);
268     }
269 
doGetTimeout(int tech)270     private native int doGetTimeout(int tech);
271     @Override
getTimeout(int tech)272     public int getTimeout(int tech) {
273         return doGetTimeout(tech);
274     }
275 
276 
277     @Override
canMakeReadOnly(int ndefType)278     public boolean canMakeReadOnly(int ndefType) {
279         return (ndefType == Ndef.TYPE_1 || ndefType == Ndef.TYPE_2 ||
280                 ndefType == Ndef.TYPE_MIFARE_CLASSIC);
281     }
282 
283     @Override
getMaxTransceiveLength(int technology)284     public int getMaxTransceiveLength(int technology) {
285         switch (technology) {
286             case (TagTechnology.NFC_A):
287             case (TagTechnology.MIFARE_CLASSIC):
288             case (TagTechnology.MIFARE_ULTRALIGHT):
289                 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
290             case (TagTechnology.NFC_B):
291                 return 0; // PN544 does not support transceive of raw NfcB
292             case (TagTechnology.NFC_V):
293                 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
294             case (TagTechnology.ISO_DEP):
295                 /* The maximum length of a normal IsoDep frame consists of:
296                  * CLA, INS, P1, P2, LC, LE + 255 payload bytes = 261 bytes
297                  * such a frame is supported. Extended length frames however
298                  * are not supported.
299                  */
300                 return 261; // Will be automatically split in two frames on the RF layer
301             case (TagTechnology.NFC_F):
302                 return 252; // PN544 RF buffer = 255 bytes, subtract one for SoD, two for CRC
303             default:
304                 return 0;
305         }
306 
307     }
308 
doSetP2pInitiatorModes(int modes)309     private native void doSetP2pInitiatorModes(int modes);
310     @Override
setP2pInitiatorModes(int modes)311     public void setP2pInitiatorModes(int modes) {
312         doSetP2pInitiatorModes(modes);
313     }
314 
doSetP2pTargetModes(int modes)315     private native void doSetP2pTargetModes(int modes);
316     @Override
setP2pTargetModes(int modes)317     public void setP2pTargetModes(int modes) {
318         doSetP2pTargetModes(modes);
319     }
320 
321     @Override
enableScreenOffSuspend()322     public boolean enableScreenOffSuspend() {
323         // Snooze mode not supported on NXP silicon
324         Log.i(TAG, "Snooze mode is not supported on NXP NFCC");
325         return false;
326     }
327 
328     @Override
disableScreenOffSuspend()329     public boolean disableScreenOffSuspend() {
330         // Snooze mode not supported on NXP silicon
331         Log.i(TAG, "Snooze mode is not supported on NXP NFCC");
332         return true;
333     }
334 
335     @Override
getExtendedLengthApdusSupported()336     public boolean getExtendedLengthApdusSupported() {
337         // Not supported on the PN544
338         return false;
339     }
340 
341     @Override
getDefaultLlcpMiu()342     public int getDefaultLlcpMiu() {
343         return DEFAULT_LLCP_MIU;
344     }
345 
346     @Override
getDefaultLlcpRwSize()347     public int getDefaultLlcpRwSize() {
348         return DEFAULT_LLCP_RWSIZE;
349     }
350 
doDump()351     private native String doDump();
352     @Override
dump()353     public String dump() {
354         return doDump();
355     }
356 
357     /**
358      * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered)
359      */
notifyNdefMessageListeners(NativeNfcTag tag)360     private void notifyNdefMessageListeners(NativeNfcTag tag) {
361         mListener.onRemoteEndpointDiscovered(tag);
362     }
363 
364     /**
365      * Notifies P2P Device detected, to activate LLCP link
366      */
notifyLlcpLinkActivation(NativeP2pDevice device)367     private void notifyLlcpLinkActivation(NativeP2pDevice device) {
368         mListener.onLlcpLinkActivated(device);
369     }
370 
371     /**
372      * Notifies P2P Device detected, to activate LLCP link
373      */
notifyLlcpLinkDeactivated(NativeP2pDevice device)374     private void notifyLlcpLinkDeactivated(NativeP2pDevice device) {
375         mListener.onLlcpLinkDeactivated(device);
376     }
377 
notifyRfFieldActivated()378     private void notifyRfFieldActivated() {
379         mListener.onRemoteFieldActivated();
380     }
381 
notifyRfFieldDeactivated()382     private void notifyRfFieldDeactivated() {
383         mListener.onRemoteFieldDeactivated();
384     }
385 }
386