NativeNfcManager.java revision d2604c0544f7bc26e5b2407f0215cccfffedae2c
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 17package com.android.nfc.dhimpl; 18 19import android.annotation.SdkConstant; 20import android.annotation.SdkConstant.SdkConstantType; 21import android.content.Context; 22import android.content.SharedPreferences; 23import android.nfc.ErrorCodes; 24import android.nfc.tech.Ndef; 25import android.nfc.tech.TagTechnology; 26import android.util.Log; 27 28import com.android.nfc.DeviceHost; 29import com.android.nfc.LlcpException; 30 31/** 32 * Native interface to the NFC Manager functions 33 */ 34public class NativeNfcManager implements DeviceHost { 35 private static final String TAG = "NativeNfcManager"; 36 static final String PREF = "NciDeviceHost"; 37 38 static final int DEFAULT_LLCP_MIU = 1980; 39 static final int DEFAULT_LLCP_RWSIZE = 2; 40 41 static final String DRIVER_NAME = "android-nci"; 42 43 private static final byte[][] EE_WIPE_APDUS = { 44 {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 45 {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, 46 (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x20, (byte)0x10, (byte)0x00}, 47 {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00}, 48 {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 49 {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00, 50 (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x30, (byte)0x30, (byte)0x00}, 51 {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00}, 52 {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00}, 53 }; 54 55 static { 56 System.loadLibrary("nfc_nci_jni"); 57 } 58 59 60 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 61 public static final String INTERNAL_TARGET_DESELECTED_ACTION = "com.android.nfc.action.INTERNAL_TARGET_DESELECTED"; 62 63 /* Native structure */ 64 private int mNative; 65 66 private final DeviceHostListener mListener; 67 private final Context mContext; 68 69 70 public NativeNfcManager(Context context, DeviceHostListener listener) { 71 mListener = listener; 72 initializeNativeStructure(); 73 mContext = context; 74 } 75 76 public native boolean initializeNativeStructure(); 77 78 private native boolean doDownload(); 79 80 public native int doGetLastError(); 81 82 @Override 83 public void checkFirmware() { 84 doDownload(); 85 } 86 87 private native boolean doInitialize(boolean enableScreenOffSuspend); 88 89 @Override 90 public boolean initialize(boolean enableScreenOffSuspend) { 91 SharedPreferences prefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE); 92 SharedPreferences.Editor editor = prefs.edit(); 93 94 if (prefs.getBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false)) { 95 try { 96 Thread.sleep (12000); 97 editor.putBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false); 98 editor.apply(); 99 } catch (InterruptedException e) { } 100 } 101 102 return doInitialize(enableScreenOffSuspend); 103 } 104 105 private native boolean doDeinitialize(); 106 107 @Override 108 public boolean deinitialize() { 109 SharedPreferences prefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE); 110 SharedPreferences.Editor editor = prefs.edit(); 111 112 editor.putBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false); 113 editor.apply(); 114 115 return doDeinitialize(); 116 } 117 118 @Override 119 public String getName() { 120 return DRIVER_NAME; 121 } 122 123 @Override 124 public native boolean sendRawFrame(byte[] data); 125 126 @Override 127 public native boolean routeAid(byte[] aid, int route); 128 129 @Override 130 public native boolean unrouteAid(byte[] aid); 131 132 @Override 133 public native void enableDiscovery(int techMask, boolean enableLowPowerDiscovery); 134 135 @Override 136 public native void disableDiscovery(); 137 138 @Override 139 public native void enableRoutingToHost(); 140 141 @Override 142 public native void disableRoutingToHost(); 143 144 @Override 145 public native int[] doGetSecureElementList(); 146 147 @Override 148 public native void doSelectSecureElement(); 149 150 @Override 151 public native void doDeselectSecureElement(); 152 153 154 private native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap, 155 String sn); 156 157 @Override 158 public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int nSap, String sn) 159 throws LlcpException { 160 LlcpConnectionlessSocket socket = doCreateLlcpConnectionlessSocket(nSap, sn); 161 if (socket != null) { 162 return socket; 163 } else { 164 /* Get Error Status */ 165 int error = doGetLastError(); 166 167 Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error)); 168 169 switch (error) { 170 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 171 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 172 throw new LlcpException(error); 173 default: 174 throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION); 175 } 176 } 177 } 178 179 private native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu, 180 int rw, int linearBufferLength); 181 @Override 182 public LlcpServerSocket createLlcpServerSocket(int nSap, String sn, int miu, 183 int rw, int linearBufferLength) throws LlcpException { 184 LlcpServerSocket socket = doCreateLlcpServiceSocket(nSap, sn, miu, rw, linearBufferLength); 185 if (socket != null) { 186 return socket; 187 } else { 188 /* Get Error Status */ 189 int error = doGetLastError(); 190 191 Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error)); 192 193 switch (error) { 194 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 195 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 196 throw new LlcpException(error); 197 default: 198 throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION); 199 } 200 } 201 } 202 203 private native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw, 204 int linearBufferLength); 205 @Override 206 public LlcpSocket createLlcpSocket(int sap, int miu, int rw, 207 int linearBufferLength) throws LlcpException { 208 LlcpSocket socket = doCreateLlcpSocket(sap, miu, rw, linearBufferLength); 209 if (socket != null) { 210 return socket; 211 } else { 212 /* Get Error Status */ 213 int error = doGetLastError(); 214 215 Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error)); 216 217 switch (error) { 218 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 219 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 220 throw new LlcpException(error); 221 default: 222 throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION); 223 } 224 } 225 } 226 227 @Override 228 public native boolean doCheckLlcp(); 229 230 @Override 231 public native boolean doActivateLlcp(); 232 233 private native void doResetTimeouts(); 234 235 @Override 236 public void resetTimeouts() { 237 doResetTimeouts(); 238 } 239 240 @Override 241 public native void doAbort(); 242 243 private native boolean doSetTimeout(int tech, int timeout); 244 @Override 245 public boolean setTimeout(int tech, int timeout) { 246 return doSetTimeout(tech, timeout); 247 } 248 249 private native int doGetTimeout(int tech); 250 @Override 251 public int getTimeout(int tech) { 252 return doGetTimeout(tech); 253 } 254 255 256 @Override 257 public boolean canMakeReadOnly(int ndefType) { 258 return (ndefType == Ndef.TYPE_1 || ndefType == Ndef.TYPE_2); 259 } 260 261 @Override 262 public int getMaxTransceiveLength(int technology) { 263 switch (technology) { 264 case (TagTechnology.NFC_A): 265 case (TagTechnology.MIFARE_CLASSIC): 266 case (TagTechnology.MIFARE_ULTRALIGHT): 267 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC 268 case (TagTechnology.NFC_B): 269 ///////////////////////////////////////////////////////////////// 270 // Broadcom: Since BCM2079x supports this, set NfcB max size. 271 //return 0; // PN544 does not support transceive of raw NfcB 272 return 253; // PN544 does not support transceive of raw NfcB 273 case (TagTechnology.NFC_V): 274 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC 275 case (TagTechnology.ISO_DEP): 276 /* The maximum length of a normal IsoDep frame consists of: 277 * CLA, INS, P1, P2, LC, LE + 255 payload bytes = 261 bytes 278 * such a frame is supported. Extended length frames however 279 * are not supported. 280 */ 281 return 261; // Will be automatically split in two frames on the RF layer 282 case (TagTechnology.NFC_F): 283 return 252; // PN544 RF buffer = 255 bytes, subtract one for SoD, two for CRC 284 default: 285 return 0; 286 } 287 288 } 289 290 private native void doSetP2pInitiatorModes(int modes); 291 @Override 292 public void setP2pInitiatorModes(int modes) { 293 doSetP2pInitiatorModes(modes); 294 } 295 296 private native void doSetP2pTargetModes(int modes); 297 @Override 298 public void setP2pTargetModes(int modes) { 299 doSetP2pTargetModes(modes); 300 } 301 302 @Override 303 public boolean getExtendedLengthApdusSupported() { 304 // TODO check BCM support 305 return false; 306 } 307 308 @Override 309 public boolean enablePN544Quirks() { 310 return false; 311 } 312 313 @Override 314 public byte[][] getWipeApdus() { 315 return EE_WIPE_APDUS; 316 } 317 318 @Override 319 public int getDefaultLlcpMiu() { 320 return DEFAULT_LLCP_MIU; 321 } 322 323 @Override 324 public int getDefaultLlcpRwSize() { 325 return DEFAULT_LLCP_RWSIZE; 326 } 327 328 private native String doDump(); 329 @Override 330 public String dump() { 331 return doDump(); 332 } 333 334 private native void doEnableReaderMode(int technologies); 335 @Override 336 public boolean enableReaderMode(int technologies) { 337 doEnableReaderMode(technologies); 338 return true; 339 } 340 341 private native void doDisableReaderMode(); 342 @Override 343 public boolean disableReaderMode() { 344 doDisableReaderMode(); 345 return true; 346 } 347 348 private native void doEnableScreenOffSuspend(); 349 @Override 350 public boolean enableScreenOffSuspend() { 351 doEnableScreenOffSuspend(); 352 return true; 353 } 354 355 private native void doDisableScreenOffSuspend(); 356 @Override 357 public boolean disableScreenOffSuspend() { 358 doDisableScreenOffSuspend(); 359 return true; 360 } 361 362 /** 363 * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered) 364 */ 365 private void notifyNdefMessageListeners(NativeNfcTag tag) { 366 mListener.onRemoteEndpointDiscovered(tag); 367 } 368 369 /** 370 * Notifies transaction 371 */ 372 private void notifyTargetDeselected() { 373 mListener.onCardEmulationDeselected(); 374 } 375 376 /** 377 * Notifies transaction 378 */ 379 private void notifyTransactionListeners(byte[] aid) { 380 mListener.onCardEmulationAidSelected(aid); 381 } 382 383 /** 384 * Notifies P2P Device detected, to activate LLCP link 385 */ 386 private void notifyLlcpLinkActivation(NativeP2pDevice device) { 387 mListener.onLlcpLinkActivated(device); 388 } 389 390 /** 391 * Notifies P2P Device detected, to activate LLCP link 392 */ 393 private void notifyLlcpLinkDeactivated(NativeP2pDevice device) { 394 mListener.onLlcpLinkDeactivated(device); 395 } 396 397 /** 398 * Notifies first packet received from remote LLCP 399 */ 400 private void notifyLlcpLinkFirstPacketReceived(NativeP2pDevice device) { 401 mListener.onLlcpFirstPacketReceived(device); 402 } 403 404 private void notifySeFieldActivated() { 405 mListener.onRemoteFieldActivated(); 406 } 407 408 private void notifySeFieldDeactivated() { 409 mListener.onRemoteFieldDeactivated(); 410 } 411 412 private void notifySeListenActivated() { 413 mListener.onSeListenActivated(); 414 } 415 416 private void notifySeListenDeactivated() { 417 mListener.onSeListenDeactivated(); 418 } 419 420 private void notifySeApduReceived(byte[] apdu) { 421 mListener.onSeApduReceived(apdu); 422 } 423 424 private void notifySeEmvCardRemoval() { 425 mListener.onSeEmvCardRemoval(); 426 } 427 428 private void notifySeMifareAccess(byte[] block) { 429 mListener.onSeMifareAccess(block); 430 } 431 432 private void notifyHostEmuActivated() { 433 mListener.onHostCardEmulationActivated(); 434 } 435 436 private void notifyHostEmuData(byte[] data) { 437 mListener.onHostCardEmulationData(data); 438 } 439 440 private void notifyHostEmuDeactivated() { 441 mListener.onHostCardEmulationDeactivated(); 442 } 443 444} 445