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.content.Context; 20 import android.nfc.ErrorCodes; 21 import android.nfc.tech.Ndef; 22 import android.nfc.tech.TagTechnology; 23 import android.util.Log; 24 25 import com.android.nfc.DeviceHost; 26 import com.android.nfc.LlcpException; 27 import com.android.nfc.NfcDiscoveryParameters; 28 29 import java.io.FileDescriptor; 30 import java.util.Arrays; 31 import java.util.Iterator; 32 import java.util.HashMap; 33 34 /** 35 * Native interface to the NFC Manager functions 36 */ 37 public class NativeNfcManager implements DeviceHost { 38 private static final String TAG = "NativeNfcManager"; 39 static final String PREF = "NciDeviceHost"; 40 41 static final int DEFAULT_LLCP_MIU = 1980; 42 static final int DEFAULT_LLCP_RWSIZE = 2; 43 44 static final String DRIVER_NAME = "android-nci"; 45 46 static { 47 System.loadLibrary("nfc_nci_jni"); 48 } 49 50 /* Native structure */ 51 private long mNative; 52 53 private int mIsoDepMaxTransceiveLength; 54 private final DeviceHostListener mListener; 55 private final Context mContext; 56 57 private final Object mLock = new Object(); 58 private final HashMap<Integer, byte[]> mT3tIdentifiers = new HashMap<Integer, byte[]>(); 59 NativeNfcManager(Context context, DeviceHostListener listener)60 public NativeNfcManager(Context context, DeviceHostListener listener) { 61 mListener = listener; 62 initializeNativeStructure(); 63 mContext = context; 64 } 65 initializeNativeStructure()66 public native boolean initializeNativeStructure(); 67 doDownload()68 private native boolean doDownload(); 69 doGetLastError()70 public native int doGetLastError(); 71 72 @Override checkFirmware()73 public boolean checkFirmware() { 74 return doDownload(); 75 } 76 doInitialize()77 private native boolean doInitialize(); 78 getIsoDepMaxTransceiveLength()79 private native int getIsoDepMaxTransceiveLength(); 80 81 @Override initialize()82 public boolean initialize() { 83 boolean ret = doInitialize(); 84 mIsoDepMaxTransceiveLength = getIsoDepMaxTransceiveLength(); 85 return ret; 86 } 87 doEnableDtaMode()88 private native void doEnableDtaMode(); 89 90 @Override enableDtaMode()91 public void enableDtaMode() { 92 doEnableDtaMode(); 93 } 94 doDisableDtaMode()95 private native void doDisableDtaMode(); 96 97 @Override disableDtaMode()98 public void disableDtaMode() { 99 Log.d(TAG,"disableDtaMode : entry"); 100 doDisableDtaMode(); 101 } 102 doFactoryReset()103 private native void doFactoryReset(); 104 105 @Override factoryReset()106 public void factoryReset() { 107 doFactoryReset(); 108 } 109 doShutdown()110 private native void doShutdown(); 111 112 @Override shutdown()113 public void shutdown() { 114 doShutdown(); 115 } 116 doDeinitialize()117 private native boolean doDeinitialize(); 118 119 @Override deinitialize()120 public boolean deinitialize() { 121 return doDeinitialize(); 122 } 123 124 @Override getName()125 public String getName() { 126 return DRIVER_NAME; 127 } 128 129 @Override sendRawFrame(byte[] data)130 public native boolean sendRawFrame(byte[] data); 131 132 @Override routeAid(byte[] aid, int route, int aidInfo)133 public native boolean routeAid(byte[] aid, int route, int aidInfo); 134 135 @Override unrouteAid(byte[] aid)136 public native boolean unrouteAid(byte[] aid); 137 138 @Override commitRouting()139 public native boolean commitRouting(); 140 doRegisterT3tIdentifier(byte[] t3tIdentifier)141 public native int doRegisterT3tIdentifier(byte[] t3tIdentifier); 142 143 @Override registerT3tIdentifier(byte[] t3tIdentifier)144 public void registerT3tIdentifier(byte[] t3tIdentifier) { 145 synchronized (mLock) { 146 int handle = doRegisterT3tIdentifier(t3tIdentifier); 147 if (handle != 0xffff) { 148 mT3tIdentifiers.put(Integer.valueOf(handle), t3tIdentifier); 149 } 150 } 151 } 152 doDeregisterT3tIdentifier(int handle)153 public native void doDeregisterT3tIdentifier(int handle); 154 155 @Override deregisterT3tIdentifier(byte[] t3tIdentifier)156 public void deregisterT3tIdentifier(byte[] t3tIdentifier) { 157 synchronized (mLock) { 158 Iterator<Integer> it = mT3tIdentifiers.keySet().iterator(); 159 while (it.hasNext()) { 160 int handle = it.next().intValue(); 161 byte[] value = mT3tIdentifiers.get(handle); 162 if (Arrays.equals(value, t3tIdentifier)) { 163 doDeregisterT3tIdentifier(handle); 164 mT3tIdentifiers.remove(handle); 165 break; 166 } 167 } 168 } 169 } 170 171 @Override clearT3tIdentifiersCache()172 public void clearT3tIdentifiersCache() { 173 synchronized (mLock) { 174 mT3tIdentifiers.clear(); 175 } 176 } 177 178 @Override getLfT3tMax()179 public native int getLfT3tMax(); 180 181 @Override doSetScreenState(int screen_state_mask)182 public native void doSetScreenState(int screen_state_mask); 183 184 @Override getNciVersion()185 public native int getNciVersion(); 186 doEnableDiscovery(int techMask, boolean enableLowPowerPolling, boolean enableReaderMode, boolean enableHostRouting, boolean enableP2p, boolean restart)187 private native void doEnableDiscovery(int techMask, 188 boolean enableLowPowerPolling, 189 boolean enableReaderMode, 190 boolean enableHostRouting, 191 boolean enableP2p, 192 boolean restart); 193 @Override enableDiscovery(NfcDiscoveryParameters params, boolean restart)194 public void enableDiscovery(NfcDiscoveryParameters params, boolean restart) { 195 doEnableDiscovery(params.getTechMask(), params.shouldEnableLowPowerDiscovery(), 196 params.shouldEnableReaderMode(), params.shouldEnableHostRouting(), 197 params.shouldEnableP2p(), restart); 198 } 199 200 @Override disableDiscovery()201 public native void disableDiscovery(); 202 doCreateLlcpConnectionlessSocket(int nSap, String sn)203 private native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap, 204 String sn); 205 206 @Override createLlcpConnectionlessSocket(int nSap, String sn)207 public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int nSap, String sn) 208 throws LlcpException { 209 LlcpConnectionlessSocket socket = doCreateLlcpConnectionlessSocket(nSap, sn); 210 if (socket != null) { 211 return socket; 212 } else { 213 /* Get Error Status */ 214 int error = doGetLastError(); 215 216 Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error)); 217 218 switch (error) { 219 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 220 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 221 throw new LlcpException(error); 222 default: 223 throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION); 224 } 225 } 226 } 227 doCreateLlcpServiceSocket(int nSap, String sn, int miu, int rw, int linearBufferLength)228 private native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu, 229 int rw, int linearBufferLength); 230 @Override createLlcpServerSocket(int nSap, String sn, int miu, int rw, int linearBufferLength)231 public LlcpServerSocket createLlcpServerSocket(int nSap, String sn, int miu, 232 int rw, int linearBufferLength) throws LlcpException { 233 LlcpServerSocket socket = doCreateLlcpServiceSocket(nSap, sn, miu, rw, linearBufferLength); 234 if (socket != null) { 235 return socket; 236 } else { 237 /* Get Error Status */ 238 int error = doGetLastError(); 239 240 Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error)); 241 242 switch (error) { 243 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 244 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 245 throw new LlcpException(error); 246 default: 247 throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION); 248 } 249 } 250 } 251 doCreateLlcpSocket(int sap, int miu, int rw, int linearBufferLength)252 private native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw, 253 int linearBufferLength); 254 @Override createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)255 public LlcpSocket createLlcpSocket(int sap, int miu, int rw, 256 int linearBufferLength) throws LlcpException { 257 LlcpSocket socket = doCreateLlcpSocket(sap, miu, rw, linearBufferLength); 258 if (socket != null) { 259 return socket; 260 } else { 261 /* Get Error Status */ 262 int error = doGetLastError(); 263 264 Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error)); 265 266 switch (error) { 267 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 268 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 269 throw new LlcpException(error); 270 default: 271 throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION); 272 } 273 } 274 } 275 276 @Override doCheckLlcp()277 public native boolean doCheckLlcp(); 278 279 @Override doActivateLlcp()280 public native boolean doActivateLlcp(); 281 doResetTimeouts()282 private native void doResetTimeouts(); 283 284 @Override resetTimeouts()285 public void resetTimeouts() { 286 doResetTimeouts(); 287 } 288 289 @Override doAbort(String msg)290 public native void doAbort(String msg); 291 doSetTimeout(int tech, int timeout)292 private native boolean doSetTimeout(int tech, int timeout); 293 @Override setTimeout(int tech, int timeout)294 public boolean setTimeout(int tech, int timeout) { 295 return doSetTimeout(tech, timeout); 296 } 297 doGetTimeout(int tech)298 private native int doGetTimeout(int tech); 299 @Override getTimeout(int tech)300 public int getTimeout(int tech) { 301 return doGetTimeout(tech); 302 } 303 304 305 @Override canMakeReadOnly(int ndefType)306 public boolean canMakeReadOnly(int ndefType) { 307 return (ndefType == Ndef.TYPE_1 || ndefType == Ndef.TYPE_2); 308 } 309 310 @Override getMaxTransceiveLength(int technology)311 public int getMaxTransceiveLength(int technology) { 312 switch (technology) { 313 case (TagTechnology.NFC_A): 314 case (TagTechnology.MIFARE_CLASSIC): 315 case (TagTechnology.MIFARE_ULTRALIGHT): 316 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC 317 case (TagTechnology.NFC_B): 318 ///////////////////////////////////////////////////////////////// 319 // Broadcom: Since BCM2079x supports this, set NfcB max size. 320 //return 0; // PN544 does not support transceive of raw NfcB 321 return 253; // PN544 does not support transceive of raw NfcB 322 case (TagTechnology.NFC_V): 323 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC 324 case (TagTechnology.ISO_DEP): 325 return mIsoDepMaxTransceiveLength; 326 case (TagTechnology.NFC_F): 327 return 255; 328 default: 329 return 0; 330 } 331 332 } 333 getAidTableSize()334 public native int getAidTableSize(); 335 doSetP2pInitiatorModes(int modes)336 private native void doSetP2pInitiatorModes(int modes); 337 @Override setP2pInitiatorModes(int modes)338 public void setP2pInitiatorModes(int modes) { 339 doSetP2pInitiatorModes(modes); 340 } 341 doSetP2pTargetModes(int modes)342 private native void doSetP2pTargetModes(int modes); 343 @Override setP2pTargetModes(int modes)344 public void setP2pTargetModes(int modes) { 345 doSetP2pTargetModes(modes); 346 } 347 348 @Override getExtendedLengthApdusSupported()349 public boolean getExtendedLengthApdusSupported() { 350 /* 261 is the default size if extended length frames aren't supported */ 351 if (getMaxTransceiveLength(TagTechnology.ISO_DEP) > 261) 352 return true; 353 return false; 354 } 355 356 @Override getDefaultLlcpMiu()357 public int getDefaultLlcpMiu() { 358 return DEFAULT_LLCP_MIU; 359 } 360 361 @Override getDefaultLlcpRwSize()362 public int getDefaultLlcpRwSize() { 363 return DEFAULT_LLCP_RWSIZE; 364 } 365 doDump(FileDescriptor fd)366 private native void doDump(FileDescriptor fd); 367 @Override dump(FileDescriptor fd)368 public void dump(FileDescriptor fd) { 369 doDump(fd); 370 } 371 doEnableScreenOffSuspend()372 private native void doEnableScreenOffSuspend(); 373 @Override enableScreenOffSuspend()374 public boolean enableScreenOffSuspend() { 375 doEnableScreenOffSuspend(); 376 return true; 377 } 378 doDisableScreenOffSuspend()379 private native void doDisableScreenOffSuspend(); 380 @Override disableScreenOffSuspend()381 public boolean disableScreenOffSuspend() { 382 doDisableScreenOffSuspend(); 383 return true; 384 } 385 doSetNfcSecure(boolean enable)386 private native boolean doSetNfcSecure(boolean enable); 387 @Override setNfcSecure(boolean enable)388 public boolean setNfcSecure(boolean enable) { 389 return doSetNfcSecure(enable); 390 } 391 392 @Override getNfaStorageDir()393 public native String getNfaStorageDir(); 394 395 /** 396 * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered) 397 */ notifyNdefMessageListeners(NativeNfcTag tag)398 private void notifyNdefMessageListeners(NativeNfcTag tag) { 399 mListener.onRemoteEndpointDiscovered(tag); 400 } 401 402 /** 403 * Notifies P2P Device detected, to activate LLCP link 404 */ notifyLlcpLinkActivation(NativeP2pDevice device)405 private void notifyLlcpLinkActivation(NativeP2pDevice device) { 406 mListener.onLlcpLinkActivated(device); 407 } 408 409 /** 410 * Notifies P2P Device detected, to activate LLCP link 411 */ notifyLlcpLinkDeactivated(NativeP2pDevice device)412 private void notifyLlcpLinkDeactivated(NativeP2pDevice device) { 413 mListener.onLlcpLinkDeactivated(device); 414 } 415 416 /** 417 * Notifies first packet received from remote LLCP 418 */ notifyLlcpLinkFirstPacketReceived(NativeP2pDevice device)419 private void notifyLlcpLinkFirstPacketReceived(NativeP2pDevice device) { 420 mListener.onLlcpFirstPacketReceived(device); 421 } 422 notifyHostEmuActivated(int technology)423 private void notifyHostEmuActivated(int technology) { 424 mListener.onHostCardEmulationActivated(technology); 425 } 426 notifyHostEmuData(int technology, byte[] data)427 private void notifyHostEmuData(int technology, byte[] data) { 428 mListener.onHostCardEmulationData(technology, data); 429 } 430 notifyHostEmuDeactivated(int technology)431 private void notifyHostEmuDeactivated(int technology) { 432 mListener.onHostCardEmulationDeactivated(technology); 433 } 434 notifyRfFieldActivated()435 private void notifyRfFieldActivated() { 436 mListener.onRemoteFieldActivated(); 437 } 438 notifyRfFieldDeactivated()439 private void notifyRfFieldDeactivated() { 440 mListener.onRemoteFieldDeactivated(); 441 } 442 notifyTransactionListeners(byte[] aid, byte[] data, String evtSrc)443 private void notifyTransactionListeners(byte[] aid, byte[] data, String evtSrc) { 444 mListener.onNfcTransactionEvent(aid, data, evtSrc); 445 } 446 notifyEeUpdated()447 private void notifyEeUpdated() { 448 mListener.onEeUpdated(); 449 } 450 } 451