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