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