「作ろう」って書くと、「レジ袋とペットボトルでペンギンを作ろう」という歌(オフロスキー)を思い出してしまう。
それはどうでもいいとして、前回FeliCa Liteの読み込みをやろうとしたが、MifareUltralightみたいなクラスがないのでめんどくさかった。
誰か作っていそうな気がするけど、勉強がてらFeliCa Lite用のライブラリを作ろう。
(途中省略)
ひとまず、1ブロックのReadとWriteを作った。
ReadはPAD0の読み込みだけ確認。Writeは動作確認すらしていない。
https://github.com/hirokuma/NfcTest4/blob/master/src/com/blogpost/hiro99ma/nfc/FelicaLite.java
NfcFクラスを継承して、置き換えて使ってもらえるようなものにしようかと思っていた。
が、NfcFクラスはfinal classで継承できず・・・。
では、その親のBasicTagTechnologyクラスを継承しようとしたが、これはpublicじゃないので見えず・・・。
じゃあ、packageをandroid.nfc.techにすればいいか?とも思ったが、それはだめなような気がするので、is-aは諦めてhas-aの形にした(なんて呼ぶかわからん)。
こういうの、C/C++だといろいろと「強引な」やりかたがあるんだけど、Javaはさすがにできませんな。
まあ、それはその方がいいと思う。
Read
public static byte[] readBlock(int blockNo) throws IOException {
byte[] buf = new byte[16];
buf[0] = 16; //length
buf[1] = (byte)0x06; //Read Without Encryption
System.arraycopy(mTag.getId(), 0, buf, 2, 8);
buf[10] = (byte)0x01; //service num
buf[11] = (byte)0x0b; //service code(lower)
buf[12] = (byte)0x00; //service code(upper)
buf[13] = (byte)0x01; //blocklist num
buf[14] = (byte)0x80; //2byte-blocklist(upper)
buf[15] = (byte)blockNo; //2byte-blocklist(lower)
byte[] ret = mNfcF.transceive(buf);
//length check
if(ret.length != 29) {
ret = null;
return null;
}
//IDm check
for(int i=2+0; i<2+8; i++) {
if(ret[i] != buf[i]) {
ret = null;
return null;
}
}
//status flag check
if((ret[10] != 0x00) || (ret[11] != 0x00)) {
ret = null;
return null;
}
//read data copy
System.arraycopy(ret, 13, buf, 0, 16);
ret = null;
return buf;
}
シンプルに「コマンドデータ作成」「送信」「受信データチェック」「受信データコピー」の順に処理。
まあ、それ以外無いけど。
あ、受信データチェックに応答コマンド値(0x07)を見てないな・・・。
ブロック数をチェックしてないのは、データ長でほぼそれがわかるし、それ以外の値だったとしてもまあいいか、ということで。
サービスコードが0x000b固定なのは、ReadOnlyにしておけばRWでもROでも読めるようだから。
製品仕様なのかな? ドキュメントを読みきれてないけど、動いてるというレベル。
Write
public static boolean writeBlock(int blockNo, byte[] data) throws IOException {
byte[] buf = new byte[32];
buf[0] = 32; //length
buf[1] = (byte)0x08; //Write Without Encryption
System.arraycopy(mTag.getId(), 0, buf, 2, 8);
buf[10] = (byte)0x01; //service num
buf[11] = (byte)0x09; //service code(lower)
buf[12] = (byte)0x00; //service code(upper)
buf[13] = (byte)0x01; //blocklist num
buf[14] = (byte)0x80; //2byte-blocklist(upper)
buf[15] = (byte)blockNo; //2byte-blocklist(lower)
System.arraycopy(data, 0, buf, 16, 16);
byte[] ret = mNfcF.transceive(buf);
//length check
if(ret.length != 12) {
ret = null;
return false;
}
//IDm check
for(int i=2+0; i<2+8; i++) {
if(ret[i] != buf[i]) {
ret = null;
return false;
}
}
//status flag check
if((ret[10] != 0x00) || (ret[11] != 0x00)) {
ret = null;
return false;
}
ret = null;
return true;
}
こちらも、基本はReadと同じ。
返すデータが書き込みの成功か失敗になる、というところか。
途中でreturnするのが嫌いな人も多いだろうが、私は関数の最初(パラメータチェック)と最後(結果のチェック)ならreturnで抜けてもいいかな、と思っているので、こうなってる。
NfcF#transceive()の戻り値をreturn前にnull代入しているが、そこまでする必要はあるのかな?
いらんと思うけど、知識がない。。
無駄なコードを作り込んでいるような気がしてならん。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。