[JAVA] Ich habe versucht, mit HCE-F von Android eine Funktion zu implementieren, die Felica Lite entspricht

Einführung

Ich habe eine Funktion implementiert, die Felica Lite mit HCE-F von Android entspricht. Der Einfachheit halber wird im Gegensatz zu Felica Lite beim Lesen jedoch nur ein Block akzeptiert. Da ich die Szene, in der die Abfrage erneut durchgeführt wurde, nicht reproduzieren konnte, habe ich auch keine Abfrage implementiert.

IDm wird als zufällig angenommen, daher reagiert es unabhängig von IDm als Karte dieses IDm. (Es gibt Einschränkungen. Weitere Informationen finden Sie in den ** Host-basierten Kartenemulationen von Sony für Richtlinien zur Entwicklung von NFC-F-Anwendungen **.)

image.png

Servicequelle

Weitere Teile als HCEFService.java finden Sie im Folgenden. Hinweise und Beispielquellen zur Untersuchung von HCE-F unter Android

** Klicken Sie hier, um die Verwendung zu vereinfachen **

HCEFService.java


/*
zlib License
Copyright (c) 2018 GPS_NMEA_JP

This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/

package com.example.gpsnmeajp.hce_test;

import android.nfc.cardemulation.HostNfcFService;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

public class HCEFService extends HostNfcFService {

    final int PACKET_LENGTH_POS = 0;
    final int PACKET_LENGTH_SIZE = 1;

    final int COMMAND_TYPE_POS = 1;
    final int COMMAND_TYPE_SIZE = 1;

    final int IDM_POS = 2;
    final int IDM_SIZE = 8;

    final int RESPONSE_SIZE = 1;
    final int STATUS_FLAG1_SIZE = 1;
    final int STATUS_FLAG2_SIZE = 1;

    final int BLOCK_NUM_SIZE = 1;
    final int BLOCK_SIZE = 16;

    final int ONE_BLOCK = 1;

    //---
    final byte CMD_POLLING = (byte)0x04;
    final byte RES_POLLING = (byte)0x05;
    final byte CMD_READ_WITHOUT_ENCRYPTION = (byte)0x06;
    final byte RES_READ_WITHOUT_ENCRYPTION = (byte)0x07;
    final byte CMD_WRITE_WITHOUT_ENCRYPTION = (byte)0x08;
    final byte RES_WRITE_WITHOUT_ENCRYPTION = (byte)0x09;

    //---
    final byte STATUS_FLAG1_SUCCESS = (byte)0x00;
    final byte STATUS_FLAG1_FAILED = (byte)0xFF;
    final byte STATUS_FLAG1_FELICA_LITE_ERROR = (byte)0x01;

    final byte STATUS_FLAG2_SUCCESS = (byte)0x00;
    final byte STATUS_FLAG2_READ_ERROR = (byte)0x70;
    final byte STATUS_FLAG2_READONLY = (byte)0xA8;
    final byte STATUS_FLAG2_NEED_AUTH = (byte)0xB1;
    final byte STATUS_FLAG2_SERVICE_NUM_ERROR = (byte)0xA1;
    final byte STATUS_FLAG2_BLOCK_NUM_ERROR = (byte)0xA2;
    final byte STATUS_FLAG2_SERVICE_CODE = (byte)0xA6;
    final byte STATUS_FLAG2_ACCESS_MODE = (byte)0xA7;

    final byte SERVICE_CODE_READ_ONLY = 0x000B;
    final byte SERVICE_CODE_READ_WRITE = 0x0009;


    @Override
    public void onCreate() {
        Log.d("HCEFService(NFCF)","onCreate");
        super.onCreate();
        Toast.makeText(this, "onCreate", Toast.LENGTH_LONG).show();
    }

    @Override
    public void onDestroy() {
        Log.d("HCEFService(NFCF)","onDestroy");
        super.onDestroy();
    }
    //onBind kann nicht erstellt werden

    @Override
    public byte[] processNfcFPacket(byte[] commandPacket, Bundle extras)
    {
        Log.d("HCEFService(NFCF)","processNfcFPacket: Received NFCF");
        Toast.makeText(this, "processNfcFPacket", Toast.LENGTH_LONG).show();

        //Fehler, wenn weniger als die erforderlichen Informationen vorliegen
        if (commandPacket.length < (PACKET_LENGTH_SIZE+COMMAND_TYPE_SIZE+IDM_SIZE)) {
            Log.e("HCEFService(NFCF)","processNfcFPacket: Packet size too short");
            return null;
        }

        byte commandType = commandPacket[COMMAND_TYPE_POS];
        switch(commandType)
        {
            case CMD_POLLING: return null;//stub
            case CMD_WRITE_WITHOUT_ENCRYPTION: return WriteWithoutEncryption(commandPacket);//stub
            case CMD_READ_WITHOUT_ENCRYPTION: return ReadWithoutEncryption(commandPacket);//stub
            default: return null; //Kein entsprechender Befehl
        }
    }

    @Override
    public void onDeactivated(int reason) { //Wenn RF getrennt ist
        if(reason == DEACTIVATION_LINK_LOSS)
        {
            Log.d("HCEFService(NFCF)","onDeactivated: DEACTIVATION_LINK_LOSS");
        }else{
            Log.d("HCEFService(NFCF)","onDeactivated: Unknown reason");
        }
    }

    private byte[] WriteWithoutEncryption(byte[] commandPacket)
    {
        Log.d("HCEFService(NFCF)","WriteWithoutEncryption");
        //response
        int len = PACKET_LENGTH_SIZE + RESPONSE_SIZE + IDM_SIZE + STATUS_FLAG1_SIZE + STATUS_FLAG2_SIZE;
        byte[] responsePacket = new byte[len];
        responsePacket[PACKET_LENGTH_POS] = (byte)len;
        responsePacket[COMMAND_TYPE_POS] = RES_WRITE_WITHOUT_ENCRYPTION;
        responsePacket[len-2] = STATUS_FLAG1_SUCCESS;
        responsePacket[len-1] = STATUS_FLAG2_SUCCESS;

        //IDm einstellen
        responsePacket = setIDmToPacket(responsePacket,getIDm(commandPacket));

        //analyze
        int serviceNum = commandPacket[10]&0xFF;
        if(serviceNum != 1)
        {
            responsePacket[len-2] = STATUS_FLAG1_FAILED;
            responsePacket[len-1] = STATUS_FLAG2_SERVICE_NUM_ERROR;
            Log.d("HCEFService(NFCF)","SERVICE_NUM_ERROR");
            return responsePacket; //ERROR RES
        }

        int serviceCode = (commandPacket[11]&0xFF) | ((commandPacket[12]&0xFF)<<8);
        Log.d("HCEFService(NFCF)",String.format("Service code : %04X,",serviceCode));

        if(serviceCode != SERVICE_CODE_READ_WRITE )
        {
            responsePacket[len-2] = STATUS_FLAG1_FELICA_LITE_ERROR;
            responsePacket[len-1] = STATUS_FLAG2_SERVICE_CODE;
            Log.d("HCEFService(NFCF)","STATUS_FLAG2_SERVICE_CODE");
            return responsePacket; //ERROR RES
        }

        int blockNum = commandPacket[13]&0xFF;
        if(blockNum != 1)
        {
            responsePacket[len-2] = STATUS_FLAG1_FAILED;
            responsePacket[len-1] = STATUS_FLAG2_BLOCK_NUM_ERROR;
            Log.d("HCEFService(NFCF)","BLOCK_NUM_ERROR");
            return responsePacket; //ERROR RES
        }

        int blockAddress = -1;
        int blockHeadPos = -1;
        int blocklist_1 = commandPacket[14]&0xFF;
        if(blocklist_1 == 0x80)
        {
            //1byte
            blockAddress = commandPacket[15]&0xFF;
            blockHeadPos = 16;
        }else if(blocklist_1 == 0x00)
        {
            //2byte
            blockAddress = (commandPacket[15]&0xFF) | ((commandPacket[16]&0xFF)<<8);
            blockHeadPos = 17;
        }else{
            responsePacket[len-2] = STATUS_FLAG1_FAILED;
            responsePacket[len-1] = STATUS_FLAG2_ACCESS_MODE;
            Log.d("HCEFService(NFCF)","SERVICE_NUM_ERROR");
            return responsePacket; //ERROR RES
        }

        Log.d("HCEFService(NFCF)",String.format("Block Address : %04X,",blockAddress));

        byte data[] = new byte[BLOCK_SIZE];
        System.arraycopy(commandPacket, blockHeadPos,data , 0, BLOCK_SIZE);

        String debug="";
        for(int i=0;i<data.length;i++)
        {
            debug += String.format("%02X,",data[i]);
        }
        Log.d("HCEFService(NFCF)",debug);
        Log.d("HCEFService(NFCF)","SUCCESS");
        return responsePacket; //SUCCESS
    }
    private byte[] ReadWithoutEncryption(byte[] commandPacket)
    {
        Log.d("HCEFService(NFCF)","ReadWithoutEncryption");
        //response
        int len = PACKET_LENGTH_SIZE + RESPONSE_SIZE + IDM_SIZE + STATUS_FLAG1_SIZE + STATUS_FLAG2_SIZE + BLOCK_NUM_SIZE + BLOCK_SIZE;
        int headLen = PACKET_LENGTH_SIZE + RESPONSE_SIZE + IDM_SIZE + STATUS_FLAG1_SIZE + STATUS_FLAG2_SIZE;
        byte[] responsePacket = new byte[len];
        responsePacket[PACKET_LENGTH_POS] = (byte)len;
        responsePacket[COMMAND_TYPE_POS] = RES_READ_WITHOUT_ENCRYPTION;
        responsePacket[headLen-2] = STATUS_FLAG1_SUCCESS;
        responsePacket[headLen-1] = STATUS_FLAG2_SUCCESS;
        responsePacket[headLen] = ONE_BLOCK;

        //IDm einstellen
        responsePacket = setIDmToPacket(responsePacket,getIDm(commandPacket));

        //analyze
        int serviceNum = commandPacket[10]&0xFF;
        if(serviceNum != 1)
        {
            responsePacket[len-2] = STATUS_FLAG1_FAILED;
            responsePacket[len-1] = STATUS_FLAG2_SERVICE_NUM_ERROR;
            Log.d("HCEFService(NFCF)","SERVICE_NUM_ERROR");
            return responsePacket; //ERROR RES
        }

        int serviceCode = (commandPacket[11]&0xFF) | ((commandPacket[12]&0xFF)<<8);
        Log.d("HCEFService(NFCF)",String.format("Service code : %04X,",serviceCode));

        if(serviceCode != SERVICE_CODE_READ_WRITE && serviceCode != SERVICE_CODE_READ_ONLY)
        {
            responsePacket[len-2] = STATUS_FLAG1_FELICA_LITE_ERROR;
            responsePacket[len-1] = STATUS_FLAG2_SERVICE_CODE;
            Log.d("HCEFService(NFCF)","STATUS_FLAG2_SERVICE_CODE");
            return responsePacket; //ERROR RES
        }

        int blockNum = commandPacket[13]&0xFF;
        if(blockNum != 1)
        {
            responsePacket[len-2] = STATUS_FLAG1_FAILED;
            responsePacket[len-1] = STATUS_FLAG2_BLOCK_NUM_ERROR;
            Log.d("HCEFService(NFCF)","BLOCK_NUM_ERROR");
            return responsePacket; //ERROR RES
        }

        int blockAddress = -1;
        int blocklist_1 = commandPacket[14]&0xFF;
        if(blocklist_1 == 0x80)
        {
            //1byte
            blockAddress = commandPacket[15]&0xFF;
        }else if(blocklist_1 == 0x00)
        {
            //2byte
            blockAddress = (commandPacket[15]&0xFF) | ((commandPacket[16]&0xFF)<<8);
        }else{
            responsePacket[len-2] = STATUS_FLAG1_FAILED;
            responsePacket[len-1] = STATUS_FLAG2_ACCESS_MODE;
            Log.d("HCEFService(NFCF)","SERVICE_NUM_ERROR");
            return responsePacket; //ERROR RES
        }

        Log.d("HCEFService(NFCF)",String.format("Block Address : %04X,",blockAddress));

        byte data[] = {(byte)0x00,(byte)0x01,(byte)0x02,(byte)0x03,(byte)0x04,(byte)0x05,(byte)0x06,(byte)0x07,(byte)0x08,(byte)0x09,(byte)0x0A,(byte)0x0B,(byte)0x0C,(byte)0x0D,(byte)0x0E,(byte)0x0F};
        System.arraycopy(data, 0,responsePacket , headLen + BLOCK_NUM_SIZE, BLOCK_SIZE);

        String debug="";
        for(int i=0;i<responsePacket.length;i++)
        {
            debug += String.format("%02X,",responsePacket[i]);
        }
        Log.d("HCEFService(NFCF)",debug);
        Log.d("HCEFService(NFCF)","SUCCESS");

        return responsePacket;
    }

    private byte[] getIDm(byte[] commandPacket)
    {
        byte[] IDm = new byte[8];
        System.arraycopy(commandPacket,2, IDm, 0, 8);

        return IDm;
    }

    private  byte[] setIDmToPacket(byte[] packet,byte[] IDm)
    {
        System.arraycopy(IDm, 0, packet, IDM_POS, IDM_SIZE);// NFCID2
        return packet;
    }
}


Separate Dienste und Verarbeitung mit LocalBroadCast

hcef_service.java


package jp.ne.sakura.sabowl.gpsnmeajp.intent_hce;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.cardemulation.HostNfcFService;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

public class hcef_service extends HostNfcFService {
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("HCEFService(NFCF)","onCreate");
        LocalBroadcastManager.getInstance(this).registerReceiver(mSendResponsePacketReceiver,
                new IntentFilter("sendResponsePacket"));
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("HCEFService(NFCF)","onDestroy");
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mSendResponsePacketReceiver);
    }

    @Override
    public byte[] processNfcFPacket(byte[] commandPacket, Bundle extras)
    {
        Log.d("HCEFService(NFCF)","processNfcFPacket: Received NFCF");

        //Forward
        Intent intent = new Intent("processNfcFPacket");
        intent.putExtra("packet", commandPacket);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
        return null;
    }

    @Override
    public void onDeactivated(int reason) { //Wenn RF getrennt ist
        Log.d("HCEFService(NFCF)","onDeactivated");

        //Forward
        Intent intent = new Intent("onDeactivated");
        intent.putExtra("reason", reason);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }

    private BroadcastReceiver mSendResponsePacketReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            byte responsePacket[] = intent.getByteArrayExtra("packet");
            sendResponsePacket(responsePacket);
            Log.d("HCEFService(NFCF)","sendResponsePacket");
        }
    };
}

MainActivity.java


package jp.ne.sakura.sabowl.gpsnmeajp.intent_hce;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.nfc.NfcAdapter;
import android.nfc.cardemulation.NfcFCardEmulation;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;

import android.util.Log;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity{
    private String debugMsgTitle = "NFCF-TEST";

    private NfcAdapter nfcAdapter;
    private NfcFCardEmulation nfcFCardEmulation;
    private ComponentName componentName;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(debugMsgTitle, "Create");
        setContentView(R.layout.activity_main);

        //------- HCE-F -------
        LocalBroadcastManager.getInstance(this).registerReceiver(mProcessNfcFPacketReceiver,
                new IntentFilter("processNfcFPacket"));
        LocalBroadcastManager.getInstance(this).registerReceiver(mOnDeactivatedReceiver,
                new IntentFilter("onDeactivated"));

        PackageManager pm = getPackageManager();
        if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF)) {
            Log.e(debugMsgTitle,"This device not supports HCE-F.");
            finish();
        }else {
            Log.d(debugMsgTitle, "This device supports HCE-F.");
        }

        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        nfcFCardEmulation = NfcFCardEmulation.getInstance(nfcAdapter);
        componentName = new ComponentName(
                "jp.ne.sakura.sabowl.gpsnmeajp.intent_hce", //Eigener Paketname
                "jp.ne.sakura.sabowl.gpsnmeajp.intent_hce.hcef_service"); //Eigener Servicename
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(debugMsgTitle,"Resume");

        Log.d(debugMsgTitle,"Enable service");
        nfcFCardEmulation.enableService(this, componentName);
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(debugMsgTitle,"Pause");

        Log.d(debugMsgTitle,"Disable service");
        nfcFCardEmulation.disableService(this);
    }

    //------------------------------------------------

    final int PACKET_LENGTH_POS = 0;
    final int PACKET_LENGTH_SIZE = 1;

    final int COMMAND_TYPE_POS = 1;
    final int COMMAND_TYPE_SIZE = 1;

    final int IDM_POS = 2;
    final int IDM_SIZE = 8;

    final int RESPONSE_SIZE = 1;
    final int STATUS_FLAG1_SIZE = 1;
    final int STATUS_FLAG2_SIZE = 1;

    final int BLOCK_NUM_SIZE = 1;
    final int BLOCK_SIZE = 16;

    final int ONE_BLOCK = 1;

    //---
    final byte CMD_POLLING = (byte)0x04;
    final byte RES_POLLING = (byte)0x05;
    final byte CMD_READ_WITHOUT_ENCRYPTION = (byte)0x06;
    final byte RES_READ_WITHOUT_ENCRYPTION = (byte)0x07;
    final byte CMD_WRITE_WITHOUT_ENCRYPTION = (byte)0x08;
    final byte RES_WRITE_WITHOUT_ENCRYPTION = (byte)0x09;

    //---
    final byte STATUS_FLAG1_SUCCESS = (byte)0x00;
    final byte STATUS_FLAG1_FAILED = (byte)0xFF;
    final byte STATUS_FLAG1_FELICA_LITE_ERROR = (byte)0x01;

    final byte STATUS_FLAG2_SUCCESS = (byte)0x00;
    final byte STATUS_FLAG2_READ_ERROR = (byte)0x70;
    final byte STATUS_FLAG2_READONLY = (byte)0xA8;
    final byte STATUS_FLAG2_NEED_AUTH = (byte)0xB1;
    final byte STATUS_FLAG2_SERVICE_NUM_ERROR = (byte)0xA1;
    final byte STATUS_FLAG2_BLOCK_NUM_ERROR = (byte)0xA2;
    final byte STATUS_FLAG2_SERVICE_CODE = (byte)0xA6;
    final byte STATUS_FLAG2_ACCESS_MODE = (byte)0xA7;

    final byte SERVICE_CODE_READ_ONLY = 0x000B;
    final byte SERVICE_CODE_READ_WRITE = 0x0009;

    private BroadcastReceiver mProcessNfcFPacketReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            byte commandPacket[] = intent.getByteArrayExtra("packet");
            Log.d(debugMsgTitle,"processNfcFPacket");

            byte responsePacket[] = processNfcFPacket(commandPacket);
            //Forward
            Intent responceIntent = new Intent("sendResponsePacket");
            responceIntent.putExtra("packet", responsePacket);
            LocalBroadcastManager.getInstance(context).sendBroadcast(responceIntent);
        }
    };

    private BroadcastReceiver mOnDeactivatedReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            int reason = intent.getIntExtra("reason",0);
            Log.d(debugMsgTitle,"onDeactivated");
        }
    };

    public byte[] processNfcFPacket(byte[] commandPacket)
    {
        Log.d(debugMsgTitle,"processNfcFPacket: Received NFCF");
        Toast.makeText(this, "processNfcFPacket", Toast.LENGTH_LONG).show();

        Intent intent = new Intent("custom-event-name");
        intent.putExtra("message", "This is my message!");
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);


        //Fehler, wenn weniger als die erforderlichen Informationen vorliegen
        if (commandPacket.length < (PACKET_LENGTH_SIZE+COMMAND_TYPE_SIZE+IDM_SIZE)) {
            Log.e(debugMsgTitle,"processNfcFPacket: Packet size too short");
            return null;
        }

        byte commandType = commandPacket[COMMAND_TYPE_POS];
        switch(commandType)
        {
            case CMD_POLLING: return null;//stub
            case CMD_WRITE_WITHOUT_ENCRYPTION: return WriteWithoutEncryption(commandPacket);//stub
            case CMD_READ_WITHOUT_ENCRYPTION: return ReadWithoutEncryption(commandPacket);//stub
            default: return null; //Kein entsprechender Befehl
        }
    }

    private byte[] WriteWithoutEncryption(byte[] commandPacket)
    {
        Log.d(debugMsgTitle,"WriteWithoutEncryption");
        //response
        int len = PACKET_LENGTH_SIZE + RESPONSE_SIZE + IDM_SIZE + STATUS_FLAG1_SIZE + STATUS_FLAG2_SIZE;
        byte[] responsePacket = new byte[len];
        responsePacket[PACKET_LENGTH_POS] = (byte)len;
        responsePacket[COMMAND_TYPE_POS] = RES_WRITE_WITHOUT_ENCRYPTION;
        responsePacket[len-2] = STATUS_FLAG1_SUCCESS;
        responsePacket[len-1] = STATUS_FLAG2_SUCCESS;

        //IDm einstellen
        responsePacket = setIDmToPacket(responsePacket,getIDm(commandPacket));

        //analyze
        int serviceNum = commandPacket[10]&0xFF;
        if(serviceNum != 1)
        {
            responsePacket[len-2] = STATUS_FLAG1_FAILED;
            responsePacket[len-1] = STATUS_FLAG2_SERVICE_NUM_ERROR;
            Log.d(debugMsgTitle,"SERVICE_NUM_ERROR");
            return responsePacket; //ERROR RES
        }

        int serviceCode = (commandPacket[11]&0xFF) | ((commandPacket[12]&0xFF)<<8);
        Log.d(debugMsgTitle,String.format("Service code : %04X,",serviceCode));

        if(serviceCode != SERVICE_CODE_READ_WRITE )
        {
            responsePacket[len-2] = STATUS_FLAG1_FELICA_LITE_ERROR;
            responsePacket[len-1] = STATUS_FLAG2_SERVICE_CODE;
            Log.d(debugMsgTitle,"STATUS_FLAG2_SERVICE_CODE");
            return responsePacket; //ERROR RES
        }

        int blockNum = commandPacket[13]&0xFF;
        if(blockNum != 1)
        {
            responsePacket[len-2] = STATUS_FLAG1_FAILED;
            responsePacket[len-1] = STATUS_FLAG2_BLOCK_NUM_ERROR;
            Log.d(debugMsgTitle,"BLOCK_NUM_ERROR");
            return responsePacket; //ERROR RES
        }

        int blockAddress = -1;
        int blockHeadPos = -1;
        int blocklist_1 = commandPacket[14]&0xFF;
        if(blocklist_1 == 0x80)
        {
            //1byte
            blockAddress = commandPacket[15]&0xFF;
            blockHeadPos = 16;
        }else if(blocklist_1 == 0x00)
        {
            //2byte
            blockAddress = (commandPacket[15]&0xFF) | ((commandPacket[16]&0xFF)<<8);
            blockHeadPos = 17;
        }else{
            responsePacket[len-2] = STATUS_FLAG1_FAILED;
            responsePacket[len-1] = STATUS_FLAG2_ACCESS_MODE;
            Log.d(debugMsgTitle,"SERVICE_NUM_ERROR");
            return responsePacket; //ERROR RES
        }

        Log.d(debugMsgTitle,String.format("Block Address : %04X,",blockAddress));

        byte data[] = new byte[BLOCK_SIZE];
        System.arraycopy(commandPacket, blockHeadPos,data , 0, BLOCK_SIZE);

        String debug="";
        for(int i=0;i<data.length;i++)
        {
            debug += String.format("%02X,",data[i]);
        }
        Log.d(debugMsgTitle,debug);
        Log.d(debugMsgTitle,"SUCCESS");
        return responsePacket; //SUCCESS
    }
    private byte[] ReadWithoutEncryption(byte[] commandPacket)
    {
        Log.d(debugMsgTitle,"ReadWithoutEncryption");
        //response
        int len = PACKET_LENGTH_SIZE + RESPONSE_SIZE + IDM_SIZE + STATUS_FLAG1_SIZE + STATUS_FLAG2_SIZE + BLOCK_NUM_SIZE + BLOCK_SIZE;
        int headLen = PACKET_LENGTH_SIZE + RESPONSE_SIZE + IDM_SIZE + STATUS_FLAG1_SIZE + STATUS_FLAG2_SIZE;
        byte[] responsePacket = new byte[len];
        responsePacket[PACKET_LENGTH_POS] = (byte)len;
        responsePacket[COMMAND_TYPE_POS] = RES_READ_WITHOUT_ENCRYPTION;
        responsePacket[headLen-2] = STATUS_FLAG1_SUCCESS;
        responsePacket[headLen-1] = STATUS_FLAG2_SUCCESS;
        responsePacket[headLen] = ONE_BLOCK;

        //IDm einstellen
        responsePacket = setIDmToPacket(responsePacket,getIDm(commandPacket));

        //analyze
        int serviceNum = commandPacket[10]&0xFF;
        if(serviceNum != 1)
        {
            responsePacket[len-2] = STATUS_FLAG1_FAILED;
            responsePacket[len-1] = STATUS_FLAG2_SERVICE_NUM_ERROR;
            Log.d(debugMsgTitle,"SERVICE_NUM_ERROR");
            return responsePacket; //ERROR RES
        }

        int serviceCode = (commandPacket[11]&0xFF) | ((commandPacket[12]&0xFF)<<8);
        Log.d(debugMsgTitle,String.format("Service code : %04X,",serviceCode));

        if(serviceCode != SERVICE_CODE_READ_WRITE && serviceCode != SERVICE_CODE_READ_ONLY)
        {
            responsePacket[len-2] = STATUS_FLAG1_FELICA_LITE_ERROR;
            responsePacket[len-1] = STATUS_FLAG2_SERVICE_CODE;
            Log.d(debugMsgTitle,"STATUS_FLAG2_SERVICE_CODE");
            return responsePacket; //ERROR RES
        }

        int blockNum = commandPacket[13]&0xFF;
        if(blockNum != 1)
        {
            responsePacket[len-2] = STATUS_FLAG1_FAILED;
            responsePacket[len-1] = STATUS_FLAG2_BLOCK_NUM_ERROR;
            Log.d(debugMsgTitle,"BLOCK_NUM_ERROR");
            return responsePacket; //ERROR RES
        }

        int blockAddress = -1;
        int blocklist_1 = commandPacket[14]&0xFF;
        if(blocklist_1 == 0x80)
        {
            //1byte
            blockAddress = commandPacket[15]&0xFF;
        }else if(blocklist_1 == 0x00)
        {
            //2byte
            blockAddress = (commandPacket[15]&0xFF) | ((commandPacket[16]&0xFF)<<8);
        }else{
            responsePacket[len-2] = STATUS_FLAG1_FAILED;
            responsePacket[len-1] = STATUS_FLAG2_ACCESS_MODE;
            Log.d(debugMsgTitle,"SERVICE_NUM_ERROR");
            return responsePacket; //ERROR RES
        }

        Log.d(debugMsgTitle,String.format("Block Address : %04X,",blockAddress));

        byte data[] = {(byte)0x00,(byte)0x01,(byte)0x02,(byte)0x03,(byte)0x04,(byte)0x05,(byte)0x06,(byte)0x07,(byte)0x08,(byte)0x09,(byte)0x0A,(byte)0x0B,(byte)0x0C,(byte)0x0D,(byte)0x0E,(byte)0x0F};
        System.arraycopy(data, 0,responsePacket , headLen + BLOCK_NUM_SIZE, BLOCK_SIZE);

        String debug="";
        for(int i=0;i<responsePacket.length;i++)
        {
            debug += String.format("%02X,",responsePacket[i]);
        }
        Log.d(debugMsgTitle,debug);
        Log.d(debugMsgTitle,"SUCCESS");

        return responsePacket;
    }

    private byte[] getIDm(byte[] commandPacket)
    {
        byte[] IDm = new byte[8];
        System.arraycopy(commandPacket,2, IDm, 0, 8);

        return IDm;
    }

    private  byte[] setIDmToPacket(byte[] packet,byte[] IDm)
    {
        System.arraycopy(IDm, 0, packet, IDM_POS, IDM_SIZE);// NFCID2
        return packet;
    }
}

Recommended Posts

Ich habe versucht, mit HCE-F von Android eine Funktion zu implementieren, die Felica Lite entspricht
Ich habe versucht, die Ajax-Verarbeitung der ähnlichen Funktion in Rails zu implementieren
Ich habe versucht, die Bildvorschau mit Rails / jQuery zu implementieren
Ich habe versucht, mit Rails eine Gruppenfunktion (Bulletin Board) zu erstellen
[Rails] Implementierung einer mehrschichtigen Kategoriefunktion unter Verwendung der Abstammung "Ich habe versucht, ein Fenster mit Bootstrap 3 zu erstellen"
[Android] Implementieren Sie schnell die Funktion zum Anzeigen des Passworts
Ich habe versucht, einen Server mit Netty zu implementieren
Ich habe versucht, den Block mit Java zu brechen (1)
[Android] Ich habe mit ListView + Bottom Sheet einen Materiallistenbildschirm erstellt
Ich habe versucht, eine Webanwendung voller Fehler mit Spring Boot zu klonen
Ich habe versucht, das Hochladen von Dateien mit Spring MVC zu implementieren
Ich habe versucht, TCP / IP + BIO mit JAVA zu implementieren
Ich habe versucht, eine Anmeldefunktion mit Java zu erstellen
Ich habe versucht, Sterling Sort mit Java Collector zu implementieren
Ich habe versucht, mit Java und Spring eine Funktion / einen Bildschirm für den Administrator einer Einkaufsseite zu erstellen
Ich habe versucht, eine Nachrichtenfunktion der Rails Tutorial-Erweiterung (Teil 1) zu erstellen: Erstellen Sie ein Modell
Implementieren wir eine Funktion, um die Anzahl der Zugriffe auf die API mit SpringBoot + Redis zu begrenzen
Ich habe versucht, mit Chocolatey eine Java8-Entwicklungsumgebung zu erstellen
Ich habe versucht, TabLayout unter Android eine Trennlinie hinzuzufügen
Ich habe versucht, eine Java EE-Anwendung mit OpenShift zu modernisieren.
[Rails] Ich habe versucht, eine Mini-App mit FullCalendar zu erstellen
Ich möchte eine Produktinformationsbearbeitungsfunktion ~ part1 ~ implementieren
Ich möchte eine Funktion mit Kotlin und Java erstellen!
[Rails] Ich habe versucht, die Stapelverarbeitung mit der Rake-Task zu implementieren
Ich habe versucht, eine Webanwendung voller Fehler mit Kotlin zu implementieren
Ich habe einen RESAS-API-Client in Java erstellt
Ich habe versucht, mit Docker eine Padrino-Entwicklungsumgebung zu erstellen
Ich habe versucht, eine Antwortfunktion für die Rails Tutorial-Erweiterung (Teil 3) zu erstellen: Ein Missverständnis der Spezifikationen wurde behoben
Ich habe versucht, eine Nachrichtenfunktion für die Erweiterung Rails Tutorial (Teil 2) zu erstellen: Erstellen Sie einen Bildschirm zum Anzeigen
Ich habe versucht, mit Java zu interagieren
Ich habe versucht, eine einfache Karten-App in Android Studio zu erstellen
Ich habe versucht, eine Kreditkartenhandelsanwendung mit Corda 1 auszuführen
Ich möchte eine Browsing-Funktion mit Ruby on Rails hinzufügen
Ich habe versucht, mit Docker eine Plant UML Server-Umgebung zu erstellen
Ich habe versucht, eine flexible ODER-Zuordnung mit MyBatis Dynamic SQL zu implementieren
Ich habe versucht, eine Android-Anwendung mit MVC zu erstellen (Java)
Ich habe versucht, den Betrieb des gRPC-Servers mit grpcurl zu überprüfen
Ich habe versucht, die Ergebnisse vor und nach der Date-Klasse mit einer geraden Zahl auszudrücken
Ich habe eine App für maschinelles Lernen mit Dash (+ Docker) Teil 2 ~ Grundlegende Schreibweise für Dash ~ erstellt
Ich habe versucht, ein übergeordnetes Wertklasseobjekt in Ruby zu erstellen
[Rails] Ich habe versucht, eine Transaktion zu implementieren, die mehrere DB-Prozesse kombiniert
Eine Geschichte, die ich mit der Stream-API von Java8 einem Prozess schreiben wollte, der einer while-Anweisung entspricht
Ich habe versucht, mit Web Assembly zu beginnen
[iOS] Ich habe versucht, mit Swift eine insta-ähnliche Verarbeitungsanwendung zu erstellen
Ich habe versucht, eine Web-API zu erstellen, die mit Quarkus eine Verbindung zur Datenbank herstellt
Versuchen Sie, eine Anmeldefunktion mit Spring-Boot zu implementieren
Ich wollte eine Diashow mit Slick modisch umsetzen.
Ich habe versucht, das Iterator-Muster zu implementieren
Ich habe versucht, ein wenig mit BottomNavigationView zu spielen ①
So implementieren Sie TextInputLayout mit Validierungsfunktion
Ich habe versucht, den Zugriff von Lambda → Athena mit AWS X-Ray zu visualisieren
Ich habe eine Janken App mit Android gemacht
"Lehrer, ich möchte im Frühjahr eine Anmeldefunktion implementieren" ① Hallo Welt
Ich habe versucht, die Geschwindigkeit von Graal VM mit JMH zu messen und zu vergleichen
Ich habe versucht, ein Portfolio mit AWS, Docker, CircleCI, Laravel [mit Referenzlink] zu erstellen.
Ich habe eine App für maschinelles Lernen mit Dash (+ Docker) Teil 3 ~ Übung ~ erstellt