2012/01/08

[nfc]SDK for NFC Starter KitでFeliCa Liteに読み書きする

SDK for NFC Starter Kitをちょっと使ってみたい、という人に向けて、FeliCa Lite用のサンプルを作りました。
https://github.com/hirokuma/NfcStarterKitWrap

PaSoRi(RC-S370)とFeliCa Liteがあれば、試せます。

ソース解説

主なソースファイルは、以下になります。
  • FelicaLiteReadWrite.cs
  • FelicaLite.cs
  • NfcStarterKit.cs
  • felica_nfc_dll_wrapper_basic.cs
ライブラリにあたるものは、青文字の3ファイル。
一番下にあるfelica_nfc_dll_wrapper_basic.csは、SDK for NFC Starter Kitに付属していたサンプルに手を加えた程度のものです。

NFCStarterKit.cs

Windowメッセージ処理と、SDK for NFC Starter Kitを使うときの基本処理を置いています。
これもまた、SDK for NFC Starter Kitのサンプルからけっこうな部分を持ってきています。
追加しているのは、NfcF_Read()とNfcF_Write()。
ここでFeliCa Liteに読み書きをしています。
bool NfcF_Read(ref byte[] buf, UInt16[] block, byte block_num, byte[] svc)

変更すればFeliCa Standardも読めるはずです。
サービス数を1固定にしているところが「NfcF」としている理由です。
サービス数が1固定なので、ブロックリストを返す関数CreateBlockList2()の第2引数が0になってます。
(先頭のサービスコードを使用する、という意味。)
svc[]はリトルエンディアンなので、ご注意を。
bool NfcF_Write(byte[] buf, UInt16[] block, byte block_num, byte[] svc)

Writeも同様。
サービス数は1固定です。

FelicaLite.cs

NfcStarterKit.csを、もう少しFeliCa Liteにカスタマイズしたクラス。
NfcF_Read()やNfcF_Write()のサービスコードは固定だし、書き込めるブロック数は1つだけなので、そこら辺を省略できるようにしてます。
bool Read(ref byte[] buf, UInt16 block)
bool Write(byte[] buf, UInt16 block)

そうそう、読み込みはNfcF_Read()内でバッファを確保して返すので、第1引数はnullが突っ込まれた変数とかでよいです。
それ以外は、1次発行向けの処理ばかりです。



コマンド解説

詳細はFeliCa Liteユーザーズマニュアルをダウンロードして参照してください。
・・・だけだと味気ないので、少し書いておきます。
まず注意点からですが、FeliCaLibNfcThru()でNFC-Fコマンドを使う場合にはバッファの先頭がバッファ長になります。
Mifareコマンドの場合はコマンドから始まるので、ちょっとはまりました。
なんで違うのか調べていたのですが「そういうものだから」という結論になりました。
NFC Forumの「Digital Protocol」ドキュメントに、NFC-A, B, Fの「Data and Payload Format」があるのですが、NFC-AとBはペイロードから始まっていて、NFC-Fはデータ長から始まっています。
せっかくライブラリになってるんだから吸収してくれてもいいんじゃないの、と思わなくもないですが、将来的な何かを気にしたのかもしれません。

Read without Encryption

「without」ということで、認証無しの読み込みができます。
もちろん、withoutなしのReadコマンドもあるのですが、使い方はよく知りません。
without有無の違いですが、認証されたところを読めるかどうかです。
携帯電話に搭載されているFeliCaチップは大部分が認証されたデータになっていますが、ところどころwithoutで読めるところもあります(確か)。
このコマンド、NFC Forumでは「CHECK」という名前になっています。
注意点は、サービスコードリストはリトルエンディアンで、ブロックリストはビッグエンディアンというところ。
サービスコードは、とりあえずRead Onlyのにしておけばいいでしょう。
Read/Writeでもいいけど、その場合はWriteできないブロックへのアクセスに失敗します。
FeliCa Liteの場合は最大で4ブロックまで同時に読めます。

Write without Encryption

Read w/o Encryptionとほぼ同じです。
書き込めるのは1ブロックのみ。
サービスコードは、当然Read/Writeです。

ステータスフラグ

結果にはステータスフラグが載ってくるので、それをチェックします。
ステータスフラグ1が0x00かどうかだけ見れば事足りるでしょう。
FeliCaのデータはEEPROMに保存されていると思うので、10万回か100万回くらい書き込みをすると「もうだめ」ということになると思います。
ステータス2の「致命的」なのは、そんな現象じゃないでしょうかね。
これはもう、ハードウェアの限界なので、交換しかなくなります。

ポーリング

読み書きする前に、カードを「捕捉する」という動作が必要になります。
それがポーリングです。
ポーリングについてはライブラリでサポートされているので、自前でコマンドを打たなくても大丈夫。