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 /** 30 * Native interface to the NFC Manager functions 31 */ 32 public class NativeNfcManager implements DeviceHost { 33 private static final String TAG = "NativeNfcManager"; 34 static final String PREF = "NciDeviceHost"; 35 36 static final int DEFAULT_LLCP_MIU = 1980; 37 static final int DEFAULT_LLCP_RWSIZE = 2; 38 39 static final String DRIVER_NAME = "android-nci"; 40 41 static { 42 System.loadLibrary("nfc_nci_jni"); 43 } 44 45 46 /* Native structure */ 47 private long mNative; 48 49 private final DeviceHostListener mListener; 50 private final Context mContext; 51 52 NativeNfcManager(Context context, DeviceHostListener listener)53 public NativeNfcManager(Context context, DeviceHostListener listener) { 54 mListener = listener; 55 initializeNativeStructure(); 56 mContext = context; 57 } 58 initializeNativeStructure()59 public native boolean initializeNativeStructure(); 60 doDownload()61 private native boolean doDownload(); 62 doGetLastError()63 public native int doGetLastError(); 64 65 @Override checkFirmware()66 public void checkFirmware() { 67 doDownload(); 68 } 69 doInitialize()70 private native boolean doInitialize(); 71 72 @Override initialize()73 public boolean initialize() { 74 return doInitialize(); 75 } 76 doDeinitialize()77 private native boolean doDeinitialize(); 78 79 @Override deinitialize()80 public boolean deinitialize() { 81 return doDeinitialize(); 82 } 83 84 @Override getName()85 public String getName() { 86 return DRIVER_NAME; 87 } 88 89 @Override sendRawFrame(byte[] data)90 public native boolean sendRawFrame(byte[] data); 91 92 @Override routeAid(byte[] aid, int route)93 public native boolean routeAid(byte[] aid, int route); 94 95 @Override unrouteAid(byte[] aid)96 public native boolean unrouteAid(byte[] aid); 97 98 @Override commitRouting()99 public native boolean commitRouting(); 100 doEnableDiscovery(int techMask, boolean enableLowPowerPolling, boolean enableReaderMode, boolean enableHostRouting, boolean enableP2p, boolean restart)101 private native void doEnableDiscovery(int techMask, 102 boolean enableLowPowerPolling, 103 boolean enableReaderMode, 104 boolean enableHostRouting, 105 boolean enableP2p, 106 boolean restart); 107 @Override enableDiscovery(NfcDiscoveryParameters params, boolean restart)108 public void enableDiscovery(NfcDiscoveryParameters params, boolean restart) { 109 doEnableDiscovery(params.getTechMask(), params.shouldEnableLowPowerDiscovery(), 110 params.shouldEnableReaderMode(), params.shouldEnableHostRouting(), 111 params.shouldEnableP2p(), restart); 112 } 113 114 @Override disableDiscovery()115 public native void disableDiscovery(); 116 doCreateLlcpConnectionlessSocket(int nSap, String sn)117 private native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap, 118 String sn); 119 120 @Override createLlcpConnectionlessSocket(int nSap, String sn)121 public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int nSap, String sn) 122 throws LlcpException { 123 LlcpConnectionlessSocket socket = doCreateLlcpConnectionlessSocket(nSap, sn); 124 if (socket != null) { 125 return socket; 126 } else { 127 /* Get Error Status */ 128 int error = doGetLastError(); 129 130 Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error)); 131 132 switch (error) { 133 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 134 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 135 throw new LlcpException(error); 136 default: 137 throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION); 138 } 139 } 140 } 141 doCreateLlcpServiceSocket(int nSap, String sn, int miu, int rw, int linearBufferLength)142 private native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu, 143 int rw, int linearBufferLength); 144 @Override createLlcpServerSocket(int nSap, String sn, int miu, int rw, int linearBufferLength)145 public LlcpServerSocket createLlcpServerSocket(int nSap, String sn, int miu, 146 int rw, int linearBufferLength) throws LlcpException { 147 LlcpServerSocket socket = doCreateLlcpServiceSocket(nSap, sn, miu, rw, linearBufferLength); 148 if (socket != null) { 149 return socket; 150 } else { 151 /* Get Error Status */ 152 int error = doGetLastError(); 153 154 Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error)); 155 156 switch (error) { 157 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 158 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 159 throw new LlcpException(error); 160 default: 161 throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION); 162 } 163 } 164 } 165 doCreateLlcpSocket(int sap, int miu, int rw, int linearBufferLength)166 private native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw, 167 int linearBufferLength); 168 @Override createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)169 public LlcpSocket createLlcpSocket(int sap, int miu, int rw, 170 int linearBufferLength) throws LlcpException { 171 LlcpSocket socket = doCreateLlcpSocket(sap, miu, rw, linearBufferLength); 172 if (socket != null) { 173 return socket; 174 } else { 175 /* Get Error Status */ 176 int error = doGetLastError(); 177 178 Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error)); 179 180 switch (error) { 181 case ErrorCodes.ERROR_BUFFER_TO_SMALL: 182 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 183 throw new LlcpException(error); 184 default: 185 throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION); 186 } 187 } 188 } 189 190 @Override doCheckLlcp()191 public native boolean doCheckLlcp(); 192 193 @Override doActivateLlcp()194 public native boolean doActivateLlcp(); 195 doResetTimeouts()196 private native void doResetTimeouts(); 197 198 @Override resetTimeouts()199 public void resetTimeouts() { 200 doResetTimeouts(); 201 } 202 203 @Override doAbort()204 public native void doAbort(); 205 doSetTimeout(int tech, int timeout)206 private native boolean doSetTimeout(int tech, int timeout); 207 @Override setTimeout(int tech, int timeout)208 public boolean setTimeout(int tech, int timeout) { 209 return doSetTimeout(tech, timeout); 210 } 211 doGetTimeout(int tech)212 private native int doGetTimeout(int tech); 213 @Override getTimeout(int tech)214 public int getTimeout(int tech) { 215 return doGetTimeout(tech); 216 } 217 218 219 @Override canMakeReadOnly(int ndefType)220 public boolean canMakeReadOnly(int ndefType) { 221 return (ndefType == Ndef.TYPE_1 || ndefType == Ndef.TYPE_2); 222 } 223 224 @Override getMaxTransceiveLength(int technology)225 public int getMaxTransceiveLength(int technology) { 226 switch (technology) { 227 case (TagTechnology.NFC_A): 228 case (TagTechnology.MIFARE_CLASSIC): 229 case (TagTechnology.MIFARE_ULTRALIGHT): 230 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC 231 case (TagTechnology.NFC_B): 232 ///////////////////////////////////////////////////////////////// 233 // Broadcom: Since BCM2079x supports this, set NfcB max size. 234 //return 0; // PN544 does not support transceive of raw NfcB 235 return 253; // PN544 does not support transceive of raw NfcB 236 case (TagTechnology.NFC_V): 237 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC 238 case (TagTechnology.ISO_DEP): 239 /* The maximum length of a normal IsoDep frame consists of: 240 * CLA, INS, P1, P2, LC, LE + 255 payload bytes = 261 bytes 241 * such a frame is supported. Extended length frames however 242 * are not supported. 243 */ 244 return 261; // Will be automatically split in two frames on the RF layer 245 case (TagTechnology.NFC_F): 246 return 252; // PN544 RF buffer = 255 bytes, subtract one for SoD, two for CRC 247 default: 248 return 0; 249 } 250 251 } 252 doSetP2pInitiatorModes(int modes)253 private native void doSetP2pInitiatorModes(int modes); 254 @Override setP2pInitiatorModes(int modes)255 public void setP2pInitiatorModes(int modes) { 256 doSetP2pInitiatorModes(modes); 257 } 258 doSetP2pTargetModes(int modes)259 private native void doSetP2pTargetModes(int modes); 260 @Override setP2pTargetModes(int modes)261 public void setP2pTargetModes(int modes) { 262 doSetP2pTargetModes(modes); 263 } 264 265 @Override getExtendedLengthApdusSupported()266 public boolean getExtendedLengthApdusSupported() { 267 // TODO check BCM support 268 return false; 269 } 270 271 @Override getDefaultLlcpMiu()272 public int getDefaultLlcpMiu() { 273 return DEFAULT_LLCP_MIU; 274 } 275 276 @Override getDefaultLlcpRwSize()277 public int getDefaultLlcpRwSize() { 278 return DEFAULT_LLCP_RWSIZE; 279 } 280 doDump()281 private native String doDump(); 282 @Override dump()283 public String dump() { 284 return doDump(); 285 } 286 doEnableScreenOffSuspend()287 private native void doEnableScreenOffSuspend(); 288 @Override enableScreenOffSuspend()289 public boolean enableScreenOffSuspend() { 290 doEnableScreenOffSuspend(); 291 return true; 292 } 293 doDisableScreenOffSuspend()294 private native void doDisableScreenOffSuspend(); 295 @Override disableScreenOffSuspend()296 public boolean disableScreenOffSuspend() { 297 doDisableScreenOffSuspend(); 298 return true; 299 } 300 301 /** 302 * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered) 303 */ notifyNdefMessageListeners(NativeNfcTag tag)304 private void notifyNdefMessageListeners(NativeNfcTag tag) { 305 mListener.onRemoteEndpointDiscovered(tag); 306 } 307 308 /** 309 * Notifies P2P Device detected, to activate LLCP link 310 */ notifyLlcpLinkActivation(NativeP2pDevice device)311 private void notifyLlcpLinkActivation(NativeP2pDevice device) { 312 mListener.onLlcpLinkActivated(device); 313 } 314 315 /** 316 * Notifies P2P Device detected, to activate LLCP link 317 */ notifyLlcpLinkDeactivated(NativeP2pDevice device)318 private void notifyLlcpLinkDeactivated(NativeP2pDevice device) { 319 mListener.onLlcpLinkDeactivated(device); 320 } 321 322 /** 323 * Notifies first packet received from remote LLCP 324 */ notifyLlcpLinkFirstPacketReceived(NativeP2pDevice device)325 private void notifyLlcpLinkFirstPacketReceived(NativeP2pDevice device) { 326 mListener.onLlcpFirstPacketReceived(device); 327 } 328 notifyHostEmuActivated()329 private void notifyHostEmuActivated() { 330 mListener.onHostCardEmulationActivated(); 331 } 332 notifyHostEmuData(byte[] data)333 private void notifyHostEmuData(byte[] data) { 334 mListener.onHostCardEmulationData(data); 335 } 336 notifyHostEmuDeactivated()337 private void notifyHostEmuDeactivated() { 338 mListener.onHostCardEmulationDeactivated(); 339 } 340 notifyRfFieldActivated()341 private void notifyRfFieldActivated() { 342 mListener.onRemoteFieldActivated(); 343 } 344 notifyRfFieldDeactivated()345 private void notifyRfFieldDeactivated() { 346 mListener.onRemoteFieldDeactivated(); 347 } 348 349 } 350