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 78 public NativeNfcManager(Context context, DeviceHostListener listener) { 79 mListener = listener; 80 initializeNativeStructure(); 81 mContext = context; 82 } 83 84 public native boolean initializeNativeStructure(); 85 86 private native boolean doDownload(); 87 88 public native int doGetLastError(); 89 90 @Override 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 134 private native boolean doInitialize(); 135 136 @Override 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 152 private native boolean doDeinitialize(); 153 154 @Override 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 166 public String getName() { 167 return DRIVER_NAME; 168 } 169 170 @Override 171 public boolean sendRawFrame(byte[] data) 172 { 173 return false; 174 } 175 176 @Override 177 public boolean routeAid(byte[] aid, int route) 178 { 179 return false; 180 } 181 182 @Override 183 public boolean unrouteAid(byte[] aid) 184 { 185 return false; 186 } 187 188 @Override 189 public native void enableDiscovery(); 190 191 @Override 192 public native void disableDiscovery(); 193 194 @Override 195 public void enableRoutingToHost() 196 { 197 198 } 199 200 @Override 201 public void disableRoutingToHost() 202 { 203 204 } 205 206 @Override 207 public native int[] doGetSecureElementList(); 208 209 @Override 210 public native void doSelectSecureElement(); 211 212 @Override 213 public native void doDeselectSecureElement(); 214 215 216 private native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap, 217 String sn); 218 219 @Override 220 public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int nSap, String sn) 221 throws LlcpException { 222 LlcpConnectionlessSocket socket = doCreateLlcpConnectionlessSocket(nSap, sn); 223 if (socket != null) { 224 return socket; 225 } else { 226 /* Get Error Status */ 227 int error = doGetLastError(); 228 229 Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error)); 230 231 switch (error) { 232 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 233 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 234 throw new LlcpException(error); 235 default: 236 throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION); 237 } 238 } 239 } 240 241 private native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu, 242 int rw, int linearBufferLength); 243 @Override 244 public LlcpServerSocket createLlcpServerSocket(int nSap, String sn, int miu, 245 int rw, int linearBufferLength) throws LlcpException { 246 LlcpServerSocket socket = doCreateLlcpServiceSocket(nSap, sn, miu, rw, linearBufferLength); 247 if (socket != null) { 248 return socket; 249 } else { 250 /* Get Error Status */ 251 int error = doGetLastError(); 252 253 Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error)); 254 255 switch (error) { 256 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 257 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 258 throw new LlcpException(error); 259 default: 260 throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION); 261 } 262 } 263 } 264 265 private native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw, 266 int linearBufferLength); 267 @Override 268 public LlcpSocket createLlcpSocket(int sap, int miu, int rw, 269 int linearBufferLength) throws LlcpException { 270 LlcpSocket socket = doCreateLlcpSocket(sap, miu, rw, linearBufferLength); 271 if (socket != null) { 272 return socket; 273 } else { 274 /* Get Error Status */ 275 int error = doGetLastError(); 276 277 Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error)); 278 279 switch (error) { 280 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 281 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 282 throw new LlcpException(error); 283 default: 284 throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION); 285 } 286 } 287 } 288 289 @Override 290 public native boolean doCheckLlcp(); 291 292 @Override 293 public native boolean doActivateLlcp(); 294 295 private native void doResetTimeouts(); 296 297 @Override 298 public void resetTimeouts() { 299 doResetTimeouts(); 300 } 301 302 @Override 303 public native void doAbort(); 304 305 private native boolean doSetTimeout(int tech, int timeout); 306 @Override 307 public boolean setTimeout(int tech, int timeout) { 308 return doSetTimeout(tech, timeout); 309 } 310 311 private native int doGetTimeout(int tech); 312 @Override 313 public int getTimeout(int tech) { 314 return doGetTimeout(tech); 315 } 316 317 318 @Override 319 public boolean canMakeReadOnly(int ndefType) { 320 return (ndefType == Ndef.TYPE_1 || ndefType == Ndef.TYPE_2 || 321 ndefType == Ndef.TYPE_MIFARE_CLASSIC); 322 } 323 324 @Override 325 public int getMaxTransceiveLength(int technology) { 326 switch (technology) { 327 case (TagTechnology.NFC_A): 328 case (TagTechnology.MIFARE_CLASSIC): 329 case (TagTechnology.MIFARE_ULTRALIGHT): 330 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC 331 case (TagTechnology.NFC_B): 332 return 0; // PN544 does not support transceive of raw NfcB 333 case (TagTechnology.NFC_V): 334 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC 335 case (TagTechnology.ISO_DEP): 336 /* The maximum length of a normal IsoDep frame consists of: 337 * CLA, INS, P1, P2, LC, LE + 255 payload bytes = 261 bytes 338 * such a frame is supported. Extended length frames however 339 * are not supported. 340 */ 341 return 261; // Will be automatically split in two frames on the RF layer 342 case (TagTechnology.NFC_F): 343 return 252; // PN544 RF buffer = 255 bytes, subtract one for SoD, two for CRC 344 default: 345 return 0; 346 } 347 348 } 349 350 private native void doSetP2pInitiatorModes(int modes); 351 @Override 352 public void setP2pInitiatorModes(int modes) { 353 doSetP2pInitiatorModes(modes); 354 } 355 356 private native void doSetP2pTargetModes(int modes); 357 @Override 358 public void setP2pTargetModes(int modes) { 359 doSetP2pTargetModes(modes); 360 } 361 362 private native void doEnableReaderMode(int technologies); 363 public boolean enableReaderMode(int technologies) { 364 doEnableReaderMode(technologies); 365 return true; 366 } 367 368 private native void doDisableReaderMode(); 369 public boolean disableReaderMode() { 370 doDisableReaderMode(); 371 return true; 372 } 373 374 @Override 375 public boolean getExtendedLengthApdusSupported() { 376 // Not supported on the PN544 377 return false; 378 } 379 380 @Override 381 public boolean enablePN544Quirks() { 382 return true; 383 } 384 385 @Override 386 public byte[][] getWipeApdus() { 387 return EE_WIPE_APDUS; 388 } 389 390 @Override 391 public int getDefaultLlcpMiu() { 392 return DEFAULT_LLCP_MIU; 393 } 394 395 @Override 396 public int getDefaultLlcpRwSize() { 397 return DEFAULT_LLCP_RWSIZE; 398 } 399 400 private native String doDump(); 401 @Override 402 public String dump() { 403 return doDump(); 404 } 405 406 /** 407 * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered) 408 */ 409 private void notifyNdefMessageListeners(NativeNfcTag tag) { 410 mListener.onRemoteEndpointDiscovered(tag); 411 } 412 413 /** 414 * Notifies transaction 415 */ 416 private void notifyTargetDeselected() { 417 mListener.onCardEmulationDeselected(); 418 } 419 420 /** 421 * Notifies transaction 422 */ 423 private void notifyTransactionListeners(byte[] aid) { 424 mListener.onCardEmulationAidSelected(aid); 425 } 426 427 /** 428 * Notifies P2P Device detected, to activate LLCP link 429 */ 430 private void notifyLlcpLinkActivation(NativeP2pDevice device) { 431 mListener.onLlcpLinkActivated(device); 432 } 433 434 /** 435 * Notifies P2P Device detected, to activate LLCP link 436 */ 437 private void notifyLlcpLinkDeactivated(NativeP2pDevice device) { 438 mListener.onLlcpLinkDeactivated(device); 439 } 440 441 private void notifySeFieldActivated() { 442 mListener.onRemoteFieldActivated(); 443 } 444 445 private void notifySeFieldDeactivated() { 446 mListener.onRemoteFieldDeactivated(); 447 } 448 449 private void notifySeApduReceived(byte[] apdu) { 450 mListener.onSeApduReceived(apdu); 451 } 452 453 private void notifySeEmvCardRemoval() { 454 mListener.onSeEmvCardRemoval(); 455 } 456 457 private void notifySeMifareAccess(byte[] block) { 458 mListener.onSeMifareAccess(block); 459 } 460 461 } 462