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 53 public NativeNfcManager(Context context, DeviceHostListener listener) { 54 mListener = listener; 55 initializeNativeStructure(); 56 mContext = context; 57 } 58 59 public native boolean initializeNativeStructure(); 60 61 private native boolean doDownload(); 62 63 public native int doGetLastError(); 64 65 @Override 66 public void checkFirmware() { 67 doDownload(); 68 } 69 70 private native boolean doInitialize(); 71 72 @Override 73 public boolean initialize() { 74 return doInitialize(); 75 } 76 77 private native boolean doDeinitialize(); 78 79 @Override 80 public boolean deinitialize() { 81 return doDeinitialize(); 82 } 83 84 @Override 85 public String getName() { 86 return DRIVER_NAME; 87 } 88 89 @Override 90 public native boolean sendRawFrame(byte[] data); 91 92 @Override 93 public native boolean routeAid(byte[] aid, int route); 94 95 @Override 96 public native boolean unrouteAid(byte[] aid); 97 98 @Override 99 public native boolean commitRouting(); 100 101 private native void doEnableDiscovery(int techMask, 102 boolean enableLowPowerPolling, 103 boolean enableReaderMode, 104 boolean enableHostRouting, 105 boolean enableP2p, 106 boolean restart); 107 @Override 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 115 public native void disableDiscovery(); 116 117 private native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap, 118 String sn); 119 120 @Override 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 142 private native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu, 143 int rw, int linearBufferLength); 144 @Override 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 166 private native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw, 167 int linearBufferLength); 168 @Override 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 191 public native boolean doCheckLlcp(); 192 193 @Override 194 public native boolean doActivateLlcp(); 195 196 private native void doResetTimeouts(); 197 198 @Override 199 public void resetTimeouts() { 200 doResetTimeouts(); 201 } 202 203 @Override 204 public native void doAbort(); 205 206 private native boolean doSetTimeout(int tech, int timeout); 207 @Override 208 public boolean setTimeout(int tech, int timeout) { 209 return doSetTimeout(tech, timeout); 210 } 211 212 private native int doGetTimeout(int tech); 213 @Override 214 public int getTimeout(int tech) { 215 return doGetTimeout(tech); 216 } 217 218 219 @Override 220 public boolean canMakeReadOnly(int ndefType) { 221 return (ndefType == Ndef.TYPE_1 || ndefType == Ndef.TYPE_2); 222 } 223 224 @Override 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 253 private native void doSetP2pInitiatorModes(int modes); 254 @Override 255 public void setP2pInitiatorModes(int modes) { 256 doSetP2pInitiatorModes(modes); 257 } 258 259 private native void doSetP2pTargetModes(int modes); 260 @Override 261 public void setP2pTargetModes(int modes) { 262 doSetP2pTargetModes(modes); 263 } 264 265 @Override 266 public boolean getExtendedLengthApdusSupported() { 267 // TODO check BCM support 268 return false; 269 } 270 271 @Override 272 public int getDefaultLlcpMiu() { 273 return DEFAULT_LLCP_MIU; 274 } 275 276 @Override 277 public int getDefaultLlcpRwSize() { 278 return DEFAULT_LLCP_RWSIZE; 279 } 280 281 private native String doDump(); 282 @Override 283 public String dump() { 284 return doDump(); 285 } 286 287 private native void doEnableScreenOffSuspend(); 288 @Override 289 public boolean enableScreenOffSuspend() { 290 doEnableScreenOffSuspend(); 291 return true; 292 } 293 294 private native void doDisableScreenOffSuspend(); 295 @Override 296 public boolean disableScreenOffSuspend() { 297 doDisableScreenOffSuspend(); 298 return true; 299 } 300 301 /** 302 * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered) 303 */ 304 private void notifyNdefMessageListeners(NativeNfcTag tag) { 305 mListener.onRemoteEndpointDiscovered(tag); 306 } 307 308 /** 309 * Notifies P2P Device detected, to activate LLCP link 310 */ 311 private void notifyLlcpLinkActivation(NativeP2pDevice device) { 312 mListener.onLlcpLinkActivated(device); 313 } 314 315 /** 316 * Notifies P2P Device detected, to activate LLCP link 317 */ 318 private void notifyLlcpLinkDeactivated(NativeP2pDevice device) { 319 mListener.onLlcpLinkDeactivated(device); 320 } 321 322 /** 323 * Notifies first packet received from remote LLCP 324 */ 325 private void notifyLlcpLinkFirstPacketReceived(NativeP2pDevice device) { 326 mListener.onLlcpFirstPacketReceived(device); 327 } 328 329 private void notifyHostEmuActivated() { 330 mListener.onHostCardEmulationActivated(); 331 } 332 333 private void notifyHostEmuData(byte[] data) { 334 mListener.onHostCardEmulationData(data); 335 } 336 337 private void notifyHostEmuDeactivated() { 338 mListener.onHostCardEmulationDeactivated(); 339 } 340 341 private void notifyRfFieldActivated() { 342 mListener.onRemoteFieldActivated(); 343 } 344 345 private void notifyRfFieldDeactivated() { 346 mListener.onRemoteFieldDeactivated(); 347 } 348 349 } 350