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