/* ******************************************************************************* * BTChip Bitcoin Hardware Wallet Java API * (c) 2014 BTChip - 1BTChip7VfTnrPra5jqci7ejnMguuHogTn * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************** */ package com.btchip.comm.android; import java.util.concurrent.Future; import nordpol.android.AndroidCard; import android.util.Log; import com.btchip.BTChipException; import com.btchip.comm.BTChipTransport; import com.btchip.utils.Dump; import com.btchip.utils.FutureUtils; public class BTChipTransportAndroidNFC implements BTChipTransport { public static final int DEFAULT_TIMEOUT = 30000; private static final byte DEFAULT_AID[] = Dump.hexToBin("a0000006170054bf6aa94901"); private AndroidCard card; private int timeout; private boolean debug; private byte[] aid; private boolean selected; public BTChipTransportAndroidNFC(AndroidCard card, int timeout) { this.card = card; this.timeout = timeout; card.setTimeout(timeout); aid = DEFAULT_AID; } public BTChipTransportAndroidNFC(AndroidCard card) { this(card, DEFAULT_TIMEOUT); } public void setAID(byte[] aid) { this.aid = aid; } @Override public Future<byte[]> exchange(byte[] command) throws BTChipException { if (!selected) { byte[] selectCommand = new byte[aid.length + 5]; selectCommand[0] = (byte)0x00; selectCommand[1] = (byte)0xA4; selectCommand[2] = (byte)0x04; selectCommand[3] = (byte)0x00; selectCommand[4] = (byte)aid.length; System.arraycopy(aid, 0, selectCommand, 5, aid.length); try { exchangeInternal(selectCommand); } catch(Exception e) { } selected = true; } return exchangeInternal(command); } public Future<byte[]> exchangeInternal(byte[] command) throws BTChipException { try { if (!card.isConnected()) { card.connect(); card.setTimeout(timeout); if (debug) { Log.d(BTChipTransportAndroid.LOG_STRING, "Connected"); } } if (debug) { Log.d(BTChipTransportAndroid.LOG_STRING, "=> " + Dump.dump(command)); } byte[] commandLe = new byte[command.length + 1]; System.arraycopy(command, 0, commandLe, 0, command.length); byte[] response = card.transceive(commandLe); if (debug) { Log.d(BTChipTransportAndroid.LOG_STRING, "<= " + Dump.dump(response)); } return FutureUtils.getDummyFuture(response); } catch(Exception e) { try { card.close(); } catch(Exception e1) { } throw new BTChipException("I/O error", e); } } @Override public void close() throws BTChipException { try { if (card.isConnected()) { card.close(); } } catch(Exception e) { } } @Override public void setDebug(boolean debugFlag) { this.debug = debugFlag; } }