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