SDK for NFC Starter KitでFeliCa IDmを取得してみる

2011-12-28   treby   技術メモ  , このエントリーをはてなブックマークに追加

ごあいさつ

ども、アトリエのどかのまどろみはじめです。C81でFeliCa本を出させていただきます。といっても、FeliCa本自体はC80で出させていただいた分の増刷ですし、内容なんかは一年前のものです。

このままでは「最近いろいろ露出してるけど、ぶっちゃけあいつって何もできないよね。馬鹿なの?犬なの?死ぬの?」イメージがついてしまうと危惧し(あるいは既についてる?)、急遽記事を書かせていただく運びとなりました。

C81の出展物にFeliCaを期待されていた皆さんには、遅めのクリスマスプレゼント、もしくは早めのお年玉と思ってさっくり読んでみちゃってくださいな!てか、冬コミでは何も新しいの出せなくてホントごめんなさい。

目次

  1. 自己紹介
  2. FeliCaのリーダって入手できるの?
  3. SDK for NFC Starter Kit + C#
  4. FeliCa IDmを取得してみる

1. 自己紹介

自己紹介やどんなことをやっているかにつきましては、NTMF2ライトニングトーク資料(PDF/0.99MB)が詳しいですのでご参照ください。

2. FeliCaのリーダって入手できるの?

今年度に入ってから、私は様々な場所で「FeliCaでスタンプラリー」を売り込んできました。幸いにも拙い私のシステムでもそれなりには評価していただけたようで、中には興味を持ってくださる方もそこそこいらっしゃいました。

そのような方々とお話しして、頻出した質問が、「FeliCaのリーダって入手できるのか」ということでした。結論から言うと、もちろん入手は可能です。お店にもよるでしょうが、大体3000円程度で買うことができます。参考までにAmazonへのリンクを貼っておきます。

Amazon.co.jp : SONY 非接触 ICカードリーダ/ライタ USB 対応 パソリ RC-S370

このリーダ/ライタ「PaSoRi」はソニー製ですが、FeliCaのみならず、いわゆるTypeA(Mifare)やTypeBにも対応している優れものです。NFCを使って何か作りたいと考えているなら最低でも一台、手元に欲しいところです。

3. SDK for NFC Starter Kit + C#

で、次はソフトウェアライブラリもろもろです。

「FeliCaでスタンプラリー」では、有志が作成されたfelicalibなるライブラリを使っておりました。システム開発当時、ソニーのSDKが高いかつそもそも企業向けにしか開放していなかったため入手が困難だったんですね。

しかし、最近になってついに本家ソニーさんから無料版のSDK、「SDK for NFC Starter Kit(ICS-D010/10J)」がリリースされたのです!みたところfelicalibの開発は2008年から進んでいないようですし、新しく何か作るならこの「SDK for NFC Starter Kit」を使うのが間違いないと思います。

そこでまずはFeliCa IDmの読み取りだよね、と誰もが思いつくわけですが、(いろんな意味で)ぬるぬるの.NETプログラマな私としては、できればC#で書きたいところです。というかC++からは距離を置きたいところです(苦笑)。

そのことを念頭に先ほど落としてきたブツを漁ってみますと、一つだけC#のサンプルが見つかります(私が確認したものでは、(ルート)→ sample → NFC_and_PCSC → ReadingMifareCard → src → Csharp → nfc_sample_01フォルダ内にありました)。ただ、サンプルを実行する際に問題点が一つあります。既にお察しの方もいらっしゃるでしょうが、このサンプルコード、Mifare(TypeA)カード用なのです。困った!

が、ここで慌ててたら、FeliCa使いの名が廃ります。「MifareもFeliCaも、NFCの一種だ。SDK for NFCを冠する以上、FeliCa IDmも読めるはずだ」、と言いきれてこそ一人前です(実際にはこれで数日悩んだことは内緒w)。

次の章では、このMifare用のコードをFeliCa用に書き換える手順を説明します。

4. FeliCa IDmを取得してみる

これからC#のMifareカード読み取り用のコードをFeliCaカード読み取り用に改造していくわけですが、まずはフォルダ内がどのような構成になっているのか確認してみましょう。

  • felica_nfc_dll_wrapper_basic.cs
  • nfc_sample_01.cs
  • nfc_sample_01.csproj

以上、三つのファイルがありますね。このうち、「nfc_sample_01.csproj」はVisual Studioなんかで開くためのプロジェクトファイルですので置いといて、他二つのソースファイルはそれぞれ次の意味を持ちます。

  • felica_nfc_dll_wrapper_basic.cs …… DLL のラッパ(変更の必要なし)
  • nfc_sample_01.cs …… Mifareカード読み取りのためのコード(こちらを変更

つまり、コードをいじるのは「nfc_sample_01.cs」のみということになります。……なんか簡単そうに見えてきたでしょ。私はこの事実に気づくために長い時間を要しましたよorz

あ、ちなみにVisual Studioで「nfc_sample_01.csproj」を開かれた方は「nfc_sample_01.cs」がWindowsフォームアプリケーションのように見えているはずです。このままダブルクリックしても上手く開けませんので、「右クリック→コードの表示」で開きましょう。

いよいよコードに手を加えていきます。といってもメインの流れは変える必要がなくて、Mifare 特有の記述をFeliCa 用に変更していく作業が主なミッションとなります。

実際にはこのソースコードを完全に理解するには、それこそWindowsメッセージだとかいうところまで掘り下げなければいけないのですが、今回は説明を割愛します。別の機会があれば解説したいと思います。それこそ来年の夏コミの新刊あたりとか。てか、ググれば出てきますw

92, 93行目付近

const Int32 DEVICE_TYPE_NFC_14443A_18092_106K = 0x00000001; とあります。これはマニュアルの2.1.5(p5)にある以下の情報が参考になります。

  1. DEVICE_TYPE_NFC_14443A_18092_106K : 0x00000001
    …… ISO/IEC 14443 TypeA 106Kbps, ISO/IEC 18092 106Kbps
  2. DEVICE_TYPE_NFC_18092_212K : 0x00000002
    …… ISO/IEC 18092 212Kbps
  3. DEVICE_TYPE_NFC_18092_424K : 0x00000004
    …… ISO/IEC 18092 424Kbps
  4. DEVICE_TYPE_NFC_14443B_106K : 0x00000008
    …… ISO/IEC 14443-4 TypeB 106Kbps

ここでFeliCaを指すのは2番目と3番目のISO/IEC 18092 212Kbps/424Kbpsで、捕捉対象デバイスは複数指定できます(論理和で指定)とあるので0x00000006を与えれば良いことが分かります。

ですので、92行目はconst Int32 DEVICE_TYPE_NFC_18092_212_424K = 0x00000006; とでもしておきましょう。同時に93行目の修正もお忘れなく。

110, 111行目付近

byte[] command_packet_data = new byte[2] { 0x30, 0x00 };

felica_lib_nfc_thru 関数でカードに対して投げるコマンドパケットを指定する部分です。

マニュアルの2.1.12(p9)によれば、FeliCaにおいてはカードコマンドのペイロードデータ(LEN+Command)を指定すればよいことになっています。……とはいえ、そんなもの分かりっこないよという方、諦めないで!その情報もソニーのHPで公開されています(FeliCaカード ユーザーズマニュアル)。

今回はカードに対してPollingコマンドをリクエストして、そのレスポンスに含まれるIDmを取得できればよいのですから、Pollingコマンドの節を読んでみます(カードマニュアル 4.4.2. Pollingコマンド(p44))。すると、次の情報が得られます。

  • コマンドコード(1バイト):00h
  • システムコード(2バイト):(ff ff)h(ここではFeliCa全てを対象とするため)
  • リクエストコード(1バイト):00h(とりあえず)
  • タイムスロット(1バイト):00h(これもとりあえず)

これらバイト列の長さ(LEN)06h(1+2+1+1=5 +1(LENの分))を先頭につけてやれば、コマンドパケットの完成です。111行目も一緒に修正してやりましょう。

byte[] command_packet_data = new byte[] { 0x06, 0x00, 0xff, 0xff, 0x00, 0x00 };

UInt16 command_packet_data_length = 6;

289~292行目付近

DEVICE_DATA_NFC_14443A_18092_106K DeviceData_A =
   (DEVICE_DATA_NFC_14443A_18092_106K)
   Marshal.PtrToStructure(pDeviceData_A,
   typeof(DEVICE_DATA_NFC_14443A_18092_106K));

Windowsメッセージからデバイスの構造体を生成する、ある意味肝の部分です。これはマニュアルの2.2(p14)が参考になりますね。すなわち、変換する構造体をDEVICE_DATA_NFC_14443A_18092_106K からDEVICE_DATA_NFC_18092_212_424K に変更してやれば良いのです。コードを示すと次のような感じです。

DEVICE_DATA_NFC_18092_212_424K DeviceData_A =
   (DEVICE_DATA_NFC_18092_212_424K)
   Marshal.PtrToStructure(pDeviceData_A,
   typeof(DEVICE_DATA_NFC_18092_212_424K));

お好みで、pDeviceData_A をpDeviceData_FeliCa にDeviceData_A をDeviceData_FeliCaなんてリネームしてやってもよいかもです。

いざ実行!

そんなこんなで修正は以上です。PaSoRiをつないだのち、Ctrl + F5などで実行してみましょう。response_packet_data[2]~[9]がFeliCa カードのIDmとなります。

上手く行った方、お疲れ様でした。上手く行かなかった方、頑張ってください。あと、お疲れオレ(現在時刻3:12)。

おまけ

felicalibを使ってPaSoRiにアクセスするためには「felicalib.dll」なるDLLが必要でしたが、今回試す方法ではプログラムを実行するために特別なDLLを用意する必要はありません。

というのも、最近はPaSoRiのドライバ(FeliCaポートソフトウェア)を入れる際にDLLも一緒にインストールしてくれているからです。ファイルそのものは、Program FilesCommon FilesSony SharedFeliCaNFCLibrary あたりにあります。

このDLLにどんな関数が入っているかは、「SDK for NFC Starter Kit」のマニュアルに書いてあります。そして、これをラップしたものがnfc_sample_01フォルダ内のfelica_nfc_dll_wrapper_basic.cs なのです。