Back to project page Android_NFC_FelicaEdit.
The source code is released under:
Apache License
If you think the Android project Android_NFC_FelicaEdit listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * 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.//w ww. j a v a2s. co m */ /* * Changes * * 2011/2/5: k_morishita * ** net.kazzz.felica.lib.FeliCaLib.java ???????????? */ package jp.co.yumemi.nfc; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import android.nfc.Tag; import android.nfc.tech.NfcF; import android.util.Log; import jp.co.yumemi.rd.misc.Util; public class FelicaTag extends NfcTag { private static String TAG = "FelicaTag"; // polling public static final byte COMMAND_POLLING = 0x00; public static final byte RESPONSE_POLLING = 0x01; // request service public static final byte COMMAND_REQUEST_SERVICE = 0x02; public static final byte RESPONSE_REQUEST_SERVICE = 0x03; // request RESPONSE public static final byte COMMAND_REQUEST_RESPONSE = 0x04; public static final byte RESPONSE_REQUEST_RESPONSE = 0x05; // read without encryption public static final byte COMMAND_READ_WO_ENCRYPTION = 0x06; public static final byte RESPONSE_READ_WO_ENCRYPTION = 0x07; // write without encryption public static final byte COMMAND_WRITE_WO_ENCRYPTION = 0x08; public static final byte RESPONSE_WRITE_WO_ENCRYPTION = 0x09; // search service code public static final byte COMMAND_SEARCH_SERVICECODE = 0x0a; public static final byte RESPONSE_SEARCH_SERVICECODE = 0x0b; // request system code public static final byte COMMAND_REQUEST_SYSTEMCODE = 0x0c; public static final byte RESPONSE_REQUEST_SYSTEMCODE = 0x0d; // authentication 1 public static final byte COMMAND_AUTHENTICATION1 = 0x10; public static final byte RESPONSE_AUTHENTICATION1 = 0x11; // authentication 2 public static final byte COMMAND_AUTHENTICATION2 = 0x12; public static final byte RESPONSE_AUTHENTICATION2 = 0x13; // read public static final byte COMMAND_READ = 0x14; public static final byte RESPONSE_READ = 0x15; // write public static final byte COMMAND_WRITE = 0x16; public static final byte RESPONSE_WRITE = 0x17; protected IDm idm; protected final NfcF felicaTag; public IDm getIdm() { return idm; } public FelicaTag(Tag tag) { super(tag); felicaTag = NfcF.get(tag); this.idm = new IDm(getId()); } protected CommandResponse execute(CommandPacket commandPacket) throws NfcException { byte[] result; if (this.felicaTag == null) { throw new NfcException("felicaTag is null!"); } try { if (!felicaTag.isConnected()) { felicaTag.connect(); } result = felicaTag.transceive(commandPacket.getBytes()); } catch (IOException e) { throw new NfcException(e); } return new CommandResponse(result); } /** * Polling?????????????????????????????????????????IDm?????????????????????????? * * @param systemCode * Polling?????????? systemCode * @return ??????????????? IDm ???????????? * @throws NfcException */ public IDm polling(int systemCode) throws NfcException { CommandPacket polling = new CommandPacket(COMMAND_POLLING, new byte[] { (byte) (systemCode >> 8) // ??????? , (byte) (systemCode & 0xff), (byte) 0x01 // ????????????? , (byte) 0x00 }); // ???????}; return doPolling(polling); } /** * @see #polling(int) */ public IDm polling(SystemCode systemCode) throws NfcException { byte bytes[] = systemCode.getBytes(); CommandPacket polling = new CommandPacket(COMMAND_POLLING, new byte[] { (byte) bytes[0] // ??????? , (byte) bytes[1], (byte) 0x01 // ????????????? , (byte) 0x00 }); // ???????}; return doPolling(polling); } private IDm doPolling(CommandPacket polling) throws NfcException { CommandResponse r = execute(polling); PollingResponse pr = new jp.co.yumemi.nfc.PollingResponse(r); this.idm = pr.getIDm(); return idm; } /** * @see #getSystemCodeList(IDm) */ public SystemCode[] getSystemCodeList() throws NfcException { return getSystemCodeList(this.getIdm()); } /** * SystemCode???????????????????? * * @return ????????? SystemCode????????????????? * @throws NfcException */ public SystemCode[] getSystemCodeList(IDm idm) throws NfcException { // request systemCode CommandPacket reqSystemCode = new CommandPacket( COMMAND_REQUEST_SYSTEMCODE, idm); CommandResponse r = execute(reqSystemCode); byte[] retBytes = r.getBytes(); int num = (int) retBytes[10]; Log.d(TAG, "Num SystemCode: " + num); SystemCode retCodeList[] = new SystemCode[num]; for (int i = 0; i < num; i++) { retCodeList[i] = new SystemCode(Arrays.copyOfRange(retBytes, 11 + i * 2, 13 + i * 2)); } return retCodeList; } /** * ??? Polling ??????????????????????????????????????? * ?????????????????????Polling??????????????????????????????????????????? * * ??????ServiceCode?????????????????????????????????????????????????????????????????????????????????????????? * ???????????????????2????????? ServiceCode ?????????????????????????????????????????????????????????????????????? * * @return ????????? ServiceCode ??? List * @throws NfcException */ public List<ServiceCode> getServiceCodeList() throws NfcException { int index = 1; // 0????? root area ???????????????1???????????????? List<ServiceCode> serviceCodeList = new ArrayList<ServiceCode>(); while (true) { byte[] bytes = doSearchServiceCode(idm, index); // 1?1? ????????????????????????? if (bytes.length != 2 && bytes.length != 4) break; // 2 or 4 ?????????????????????????????????????????????????????????????????????????????????????????????? if (bytes.length == 2) { // 2??????? ServiceCode ?????????????????????????? if (bytes[0] == (byte) 0xff && bytes[1] == (byte) 0xff) break; // FFFF ????????????????????? serviceCodeList.add(new ServiceCode(bytes)); } index++; } return serviceCodeList; } /** * COMMAND_SEARCH_SERVICECODE ????????????? ????: * http://wiki.osdev.info/index.php?PaSoRi%2FRC-S320#content_1_25 * * @param idm * ???????????????????????IDm * @param index * ?????? * @return Response?? * @throws NfcException */ public byte[] doSearchServiceCode(IDm idm, int index) throws NfcException { CommandPacket reqServiceCode = new CommandPacket( COMMAND_SEARCH_SERVICECODE, idm, new byte[] { (byte) (index & 0xff), (byte) (index >> 8) }); CommandResponse r = execute(reqServiceCode); byte[] bytes = r.getBytes(); if (bytes[1] != (byte) 0x0b) { // ???????????????? throw new NfcException("ResponseCode is not 0x0b"); } return Arrays.copyOfRange(bytes, 10, bytes.length); } /** * @see #readWithoutEncryption(ServiceCode, byte) */ public byte[] readWithoutEncryption(int serviceCode, byte addr) throws NfcException { return readWithoutEncryption(new ServiceCode(serviceCode), addr); } /** * ??????????????????????????????????????? ???????????????????????????????????? JIS_X_6319_4 * ????????????????????????????????????????? * * @param serviceCode * ??????????????????? * @param addr * ????????????? 0?N * @return ????????????????????Byte????????????????????????????????????????????null???????????? * @throws NfcException */ public byte[] readWithoutEncryption(ServiceCode serviceCode, int addr) throws NfcException { byte[] bytes = serviceCode.getBytes(); CommandPacket readWoEncrypt = new CommandPacket( COMMAND_READ_WO_ENCRYPTION, idm, new byte[] { (byte) 0x01 // ????? , (byte) bytes[0], (byte) bytes[1], (byte) 0x01 // ????????????????? , (byte) 0x80, (byte) addr }); // ??????? CommandResponse r = execute(readWoEncrypt); ReadResponse rr = new ReadResponse(r); if (rr.getStatusFlag1() == 0) { return rr.getBlockData(); } else { return null; // error } } /** * ??????????????????????????????????????????????????????????????????????????? JIS_X_6319_4 * ??????????????????????????????????????? * * @param serviceCode * ?????????? * @param addr * ??????????????????? 0?N * @param buff * ???????????????. 16???????????????????????????? * @return 0: ????, -1: ???? * @throws NfcException */ public int writeWithoutEncryption(ServiceCode serviceCode, int addr, byte[] buff) throws NfcException { if (buff == null || buff.length != 16) { return -1; } byte[] bytes = serviceCode.getBytes(); ByteBuffer b = ByteBuffer.allocate(6 + buff.length); b.put(new byte[] { (byte) 0x01 // Number of Service , (byte) bytes[0] // ??????? (little endian) , (byte) bytes[1], (byte) 1 // ????????????????? , (byte) 0x80, (byte) addr // ??????? }); b.put(buff); // ??????????? CommandPacket writeWoEncrypt = new CommandPacket( COMMAND_WRITE_WO_ENCRYPTION, idm, b.array()); CommandResponse r = execute(writeWoEncrypt); byte[] retBytes = r.getBytes(); if (retBytes != null && retBytes.length > 10 && retBytes[10] == (byte) 0) { return 0; // normal } else { return -1; // error } } /** * @see #writeWithoutEncryption(ServiceCode, byte, byte[]) */ public int writeWithoutEncryption(int serviceCode, byte addr, byte[] buff) throws NfcException { return writeWithoutEncryption(new ServiceCode(serviceCode), addr, buff); } // //////////////////////////////////////////////////////////////////// // ??????????Class // //////////////////////////////////////////////////////////////////// /** * FeliCa ????????????????????????? * * @author Kazzz * @date 2011/01/20 * @since Android API Level 9 */ public static class CommandPacket { protected final byte length; // ????????? protected final byte commandCode;// ??????? protected final IDm idm; // FeliCa IDm protected final byte[] data; // ??????? /** * ??????? * * @param response * ?????????????? */ public CommandPacket(CommandPacket command) { this(command.getBytes()); } /** * ??????? * * @param data * ???????????????????????? * @throws FeliCaException */ public CommandPacket(final byte[] data) { this(data[0], Arrays.copyOfRange(data, 1, data.length)); } /** * ??????? * * @param commandCode * ??????????? * @param data * ??????????? (IDm?????????????) * @throws FeliCaException */ public CommandPacket(byte commandCode, final byte... data) { this.commandCode = commandCode; if (data.length >= 8) { this.idm = new IDm(Arrays.copyOfRange(data, 0, 8)); this.data = Arrays.copyOfRange(data, 8, data.length); } else { this.idm = null; this.data = Arrays.copyOfRange(data, 0, data.length); } this.length = (byte) (data.length + 2); } /** * ??????? * * @param commandCode * ??????????? * @param idm * ??????ID(IDm)???? * @param data * ??????????? * @throws FeliCaException */ public CommandPacket(byte commandCode, IDm idm, final byte... data) { this.commandCode = commandCode; this.idm = idm; this.data = data; this.length = (byte) (idm.getBytes().length + data.length + 2); } /** * ??????? * * @param commandCode * ??????????? * @param idm * ??????ID(IDm)???????????????????????? * @param data * ??????????? * @throws FeliCaException */ public CommandPacket(byte commandCode, byte[] idm, final byte... data) { this.commandCode = commandCode; this.idm = new IDm(idm); this.data = data; this.length = (byte) (idm.length + data.length + 2); } /* * (non-Javadoc) * * @see net.felica.IFeliCaCommand#getIDm() */ public IDm getIDm() { return this.idm; } /** * ???????????????????? * * @return byte[] ???????????????????????????????? */ public byte[] getBytes() { ByteBuffer buff = ByteBuffer.allocate(this.length); if (this.idm != null) { buff.put(this.length).put(this.commandCode).put( this.idm.getBytes()).put(this.data); } else { buff.put(this.length).put(this.commandCode).put(this.data); } return buff.array(); } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("FeliCa ???????? \n"); sb.append(" ???????:" + Util.getHexString(this.commandCode) + "\n"); sb.append(" ????: " + Util.getHexString(this.length) + "\n"); sb.append(" ??????? : " + Util.getHexString(this.commandCode) + "\n"); if (this.idm != null) sb.append(" " + this.idm.toString() + "\n"); sb.append(" ???: " + Util.getHexString(this.data) + "\n"); return sb.toString(); } } /** * FeliCa ??????????????????????????? * * @author Kazz * @since Android API Level 9 */ public static class CommandResponse { protected final byte[] rawData; protected final byte length; // ????????? (FeliCa??????????) protected final byte responseCode;// ?????????????) protected final IDm idm; // FeliCa IDm protected final byte[] data; // ??????? /** * ??????? * * @param response * ?????????????? */ public CommandResponse(CommandResponse response) { this(response.getBytes()); } /** * ??????? * * @param data * ???????????????????????????? */ public CommandResponse(byte[] data) { this.rawData = data; this.length = data[0]; this.responseCode = data[1]; this.idm = new IDm(Arrays.copyOfRange(data, 2, 10)); this.data = Arrays.copyOfRange(data, 10, data.length); } /* * (non-Javadoc) */ public IDm getIDm() { return this.idm; } /** * ???????????????????? * * @return byte[] ???????????????????????????????? */ public byte[] getBytes() { return this.rawData; } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(" \n\n"); sb.append("FeliCa ?????????? \n"); sb.append(" ???????:" + Util.getHexString(this.responseCode) + "\n"); sb.append(" ????: " + Util.getHexString(this.length) + "\n"); sb.append(" ?????????: " + Util.getHexString(this.responseCode) + "\n"); sb.append(" " + this.idm.toString() + "\n"); sb.append(" ???: " + Util.getHexString(this.data) + "\n"); return sb.toString(); } } /** * * FeliCa IDm????????????????? * * @author Kazzz * @date 2011/01/20 * @since Android API Level 9 */ public static class IDm { final byte[] manufactureCode; final byte[] cardIdentification; /** * ??????? * * @param bytes * IDm??????????????????????????????????? */ public IDm(byte[] bytes) { this.manufactureCode = new byte[] { bytes[0], bytes[1] }; this.cardIdentification = new byte[] { bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7] }; } /* * (non-Javadoc) * * @see net.felica.IFeliCaByteData#getBytes() */ public byte[] getBytes() { ByteBuffer buff = ByteBuffer.allocate(this.manufactureCode.length + this.cardIdentification.length); buff.put(this.manufactureCode).put(this.cardIdentification); return buff.array(); } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("IDm (8byte) : " + Util.getHexString(this.getBytes()) + "\n"); sb.append(" ??????: " + Util.getHexString(this.manufactureCode) + "\n"); sb.append(" ?????????:\n"); sb.append(" ???:" + Util.getHexString(this.cardIdentification, 0, 2) + "\n"); sb.append(" ??:" + Util.getHexString(this.cardIdentification, 2, 2) + "\n"); sb.append(" ????:" + Util.getHexString(this.cardIdentification, 4, 2) + "\n"); return sb.toString(); } public String simpleToString() { return Util.getHexString(getBytes()); } } /** * * FeliCa PMm????????????????? * * @author Kazzz * @date 2011/01/20 * @since Android API Level 9 */ public static class PMm { final byte[] icCode; // ROM??, IC?? final byte[] maximumResponseTime; // ?????? /** * ??????? * * @param bytes * ????????? */ public PMm(byte[] bytes) { this.icCode = new byte[] { bytes[0], bytes[1] }; this.maximumResponseTime = new byte[] { bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7] }; } /* * (non-Javadoc) * * @see net.felica.IFeliCaByteData#getBytes() */ public byte[] getBytes() { ByteBuffer buff = ByteBuffer.allocate(this.icCode.length + this.maximumResponseTime.length); buff.put(this.icCode).put(this.maximumResponseTime); return buff.array(); } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("PMm(???????)\n"); sb .append(" IC???(2byte): " + Util.getHexString(this.icCode) + "\n"); sb.append(" ROM??: " + Util.getHexString(this.icCode, 0, 1) + "\n"); sb.append(" IC ??: " + Util.getHexString(this.icCode, 1, 1) + "\n"); sb.append("\n"); sb.append(" ??????????(6byte)\n"); sb.append(" B3(request service):" + Util.getBinString(this.maximumResponseTime, 0, 1) + "\n"); sb.append(" B4(request response):" + Util.getBinString(this.maximumResponseTime, 1, 1) + "\n"); sb.append(" B5(authenticate):" + Util.getBinString(this.maximumResponseTime, 2, 1) + "\n"); sb.append(" B6(read):" + Util.getBinString(this.maximumResponseTime, 3, 1) + "\n"); sb.append(" B7(write):" + Util.getBinString(this.maximumResponseTime, 4, 1) + "\n"); sb.append(" B8():" + Util.getBinString(this.maximumResponseTime, 5, 1) + "\n"); return sb.toString(); } } /** * FeliCa SystemCode????????????????? * * @author Kazzz * @date 2011/01/20 * @since Android API Level 9 */ public static class SystemCode { final byte[] systemCode; /** * ??????? * * @param bytes * ????????? */ public SystemCode(byte[] bytes) { this.systemCode = bytes; } /* * (non-Javadoc) */ public byte[] getBytes() { return this.systemCode; } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("??????? : " + Util.getHexString(this.systemCode)); return sb.toString(); } public String simpleToString() { return Util.getHexString(systemCode); } } /** * FeliCa ServiceCode????????????????? * * @author Kazzz * @date 2011/01/20 * @since Android API Level 9 */ public static class ServiceCode { final byte[] serviceCode; final byte[] serviceCodeLE; // little endian /** * ??????? * * @param bytes * ????????? */ public ServiceCode(byte[] bytes) { this.serviceCode = bytes; if (bytes.length == 2) { this.serviceCodeLE = new byte[] { bytes[1], bytes[0] }; } else { this.serviceCodeLE = null; } } public ServiceCode(int serviceCode) { this(new byte[] { (byte) (serviceCode & 0xff), (byte) (serviceCode >> 8) }); } /* * ????????????????????????????????? * * @return ??????????????????? */ public byte[] getBytes() { return this.serviceCode; } /** * ??????????????????????????????? * * @return ???????True * @author morishita_2 */ public boolean encryptNeeded() { boolean ret = false; if (serviceCodeLE != null) { ret = (serviceCodeLE[1] & 0x1) == 0; } return ret; } /** * ????????????????????????????? * * @return ?????????????True * @author morishita_2 */ public boolean isWritable() { boolean ret = false; if (serviceCodeLE != null) { int accessInfo = serviceCodeLE[1] & 0x3F; // ???6bit????????? ret = (accessInfo & 0x2) == 0 || accessInfo == 0x13 || accessInfo == 0x12; } return ret; } /** * ??????????????????????????JIS_X_6319_4 ?????????????????? * * @author morishita_2 */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(Util.getHexString(serviceCodeLE)); if (serviceCodeLE != null) { int accessInfo = serviceCodeLE[1] & 0x3F; // ???6bit????????? switch (accessInfo) { case 0x09: sb.append(" ???RW"); break; // RW: ReadWrite case 0x0b: sb.append(" ???RO"); break; // RO: ReadOnly case 0x0d: sb.append(" ??RW"); break; case 0x0f: sb.append(" ??RO"); break; case 0x11: sb.append(" ?????"); break; case 0x13: sb.append(" ?????"); break; case 0x15: sb.append(" ?????"); break; case 0x17: sb.append(" ???RO"); break; // case 0x08: sb.append(" ???RW(Locked)"); break; // RW: ReadWrite case 0x0a: sb.append(" ???RO(Locked)"); break; // RO: ReadOnly case 0x0c: sb.append(" ??RW(Locked)"); break; case 0x0e: sb.append(" ??RO(Locked)"); break; case 0x10: sb.append(" ?????(Locked)"); break; case 0x12: sb.append(" ?????(Locked)"); break; case 0x14: sb.append(" ?????(Locked)"); break; case 0x16: sb.append(" ???RO(Locked)"); break; } } // sb.append("\n"); return sb.toString(); } } /** * ???????????????????? */ @Override public String getType() { return TYPE_FELICA; } }