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 native void enableDiscovery(); 172 173 @Override 174 public native void disableDiscovery(); 175 176 @Override 177 public native int[] doGetSecureElementList(); 178 179 @Override 180 public native void doSelectSecureElement(); 181 182 @Override 183 public native void doDeselectSecureElement(); 184 185 186 private native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap, 187 String sn); 188 189 @Override 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 211 private native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu, 212 int rw, int linearBufferLength); 213 @Override 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 235 private native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw, 236 int linearBufferLength); 237 @Override 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 260 public native boolean doCheckLlcp(); 261 262 @Override 263 public native boolean doActivateLlcp(); 264 265 private native void doResetTimeouts(); 266 267 @Override 268 public void resetTimeouts() { 269 doResetTimeouts(); 270 } 271 272 @Override 273 public native void doAbort(); 274 275 private native boolean doSetTimeout(int tech, int timeout); 276 @Override 277 public boolean setTimeout(int tech, int timeout) { 278 return doSetTimeout(tech, timeout); 279 } 280 281 private native int doGetTimeout(int tech); 282 @Override 283 public int getTimeout(int tech) { 284 return doGetTimeout(tech); 285 } 286 287 288 @Override 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 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 320 private native void doSetP2pInitiatorModes(int modes); 321 @Override 322 public void setP2pInitiatorModes(int modes) { 323 doSetP2pInitiatorModes(modes); 324 } 325 326 private native void doSetP2pTargetModes(int modes); 327 @Override 328 public void setP2pTargetModes(int modes) { 329 doSetP2pTargetModes(modes); 330 } 331 332 @Override 333 public boolean getExtendedLengthApdusSupported() { 334 // Not supported on the PN544 335 return false; 336 } 337 338 @Override 339 public boolean enablePN544Quirks() { 340 return true; 341 } 342 343 @Override 344 public byte[][] getWipeApdus() { 345 return EE_WIPE_APDUS; 346 } 347 348 @Override 349 public int getDefaultLlcpMiu() { 350 return DEFAULT_LLCP_MIU; 351 } 352 353 @Override 354 public int getDefaultLlcpRwSize() { 355 return DEFAULT_LLCP_RWSIZE; 356 } 357 358 private native String doDump(); 359 @Override 360 public String dump() { 361 return doDump(); 362 } 363 364 /** 365 * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered) 366 */ 367 private void notifyNdefMessageListeners(NativeNfcTag tag) { 368 mListener.onRemoteEndpointDiscovered(tag); 369 } 370 371 /** 372 * Notifies transaction 373 */ 374 private void notifyTargetDeselected() { 375 mListener.onCardEmulationDeselected(); 376 } 377 378 /** 379 * Notifies transaction 380 */ 381 private void notifyTransactionListeners(byte[] aid) { 382 mListener.onCardEmulationAidSelected(aid); 383 } 384 385 /** 386 * Notifies P2P Device detected, to activate LLCP link 387 */ 388 private void notifyLlcpLinkActivation(NativeP2pDevice device) { 389 mListener.onLlcpLinkActivated(device); 390 } 391 392 /** 393 * Notifies P2P Device detected, to activate LLCP link 394 */ 395 private void notifyLlcpLinkDeactivated(NativeP2pDevice device) { 396 mListener.onLlcpLinkDeactivated(device); 397 } 398 399 private void notifySeFieldActivated() { 400 mListener.onRemoteFieldActivated(); 401 } 402 403 private void notifySeFieldDeactivated() { 404 mListener.onRemoteFieldDeactivated(); 405 } 406 407 private void notifySeApduReceived(byte[] apdu) { 408 mListener.onSeApduReceived(apdu); 409 } 410 411 private void notifySeEmvCardRemoval() { 412 mListener.onSeEmvCardRemoval(); 413 } 414 415 private void notifySeMifareAccess(byte[] block) { 416 mListener.onSeMifareAccess(block); 417 } 418 419 } 420