2013年5月31日金曜日

PC/SCに潜む謎

WindowsでNFCなどのICカードを利用するのに便利なPC/SCというインターフェース仕様があります。

通常はリーダライタはそれぞれドライバがあってSDKが提供されたりしてそのリーダ用のプログラムを作成するわけなんですが、PC/SCに対応したリーダライタでPC/SCを利用してプログラミングしてしまえば、他のPC/SC対応リーダに変更してもそのまま使えちゃうわけですね。(まぁ、そんなにうまくはいかないんですが)

こういう共通インターフェース仕様っていうのはぶっ飛び系(なんで?こんだけのことするのに何でこんなにコードがいるわけ?など)が多いわけですが、このPC/SCも結構不思議ちゃんな部分があります。

実際に見てみましょう。ACSさんのACR122リーダを使用します。

PC/SCの実体というかAPIの呼び出し先はwinscard.dllというシステムファイルです。Windowsに含まれてますので、特に何かインストールしなくても普通に使えます。

で、だいたい次のようなAPIの呼び出しをして使います。

 SCardEstablishContext - まあ、これから使うよー的な。
     ↓
 SCardListReaders - これでWindowsが認識しているPC/SCに対応したリーダの一覧を取得します。
     ↓
 SCardGetStatusChange - リーダの状態の変化を察知します。カードが置かれたとかがわかります。
     ↓
 SCardConnect - カードが置かれてるようなら、これでカードと接続(おおげさな)します。
     ↓
 SCardTransmit - カードに対してコマンドを送信します。
     ↓
 SCardDisconnect - カードとの接続を切断(またおおげさな)します。
     ↓
 SCardReleaseContext - 終わったよー的な。

至って普通に見えますね。重要なのは SCardTransmit で、これでAPDU(Application Protocol Data Unit)という形式のバイナリデータを送ることでカードを操作します。たとえば「お前だれー」というときは

 FF CA 00 00 00 (16進数)

といったバイナリ列を送ればカードのIDを返してきます。APDUは定義されたものもあればメーカ独自のものもあります。
先ほどのIDの取得やタグの読み書きなどは定義されていますが、ACR122リーダではブザーを鳴らしたりLEDを点灯したりみたいなこともAPDUを送ることで可能です。

 FF 00 40 50 04 05 05 03 01

なんて送ると、赤のLEDが3回点滅してそれに合わせてピーピーピーと鳴ります。便利ですねー。これを使えばカードをかざしてお前のカード認証されてねーよみたいなときに警告としてピーピー言うこともできそうです。

ところが不都合が1つあります。先ほどのAPDUを送信するAPIなんですが、SCardTransmitなんです。そうです。S「Card」Transmitです。カードなんです。カードに送るんです。
まあ、カードに送るって言っても一旦はリーダに送るんだからいいんじゃね?とも思いますが、実際SCardTransmitの引数はこうなっています。

 SCardTransmit(カードハンドル, 送信パラメータ, 送信データ, 送信データの長さ, 受信パラメータ, 受信用バッファ, 受信用バッファの長さ)

いきなりカードハンドルというのがあります。これは SCardConnect の時に取得できるカードの識別子みたいなもんです。これがないと送信してくれません。0とかにしてもダメです。もちろん送信するときにはカードとリーダが通信できている状態にある必要があります。

要するに、カードが置いてないときにAPDUコマンドは送信できないのです。例えそのAPDUがリーダのブザーを鳴らすとかカードに全く関係のないコマンドであったとしてもです。えー!なんでー?謎。
(注:ACR122リーダではこれを回避?するため DirectTransmit というものがPC/SCとは別に用意されているようです)

※2014/07/04 追記 カードが無くてもコマンド送信は可能でした。お詫びいたします。詳細は新しいエントリー「PC/SCに潜む謎 その2」を参照ください。

2013年5月24日金曜日

WindowsとAndroidのおしゃべり


WindowsでNFCを使うときにはよくこのリーダを使います。


ACSさんのACR122リーダです。
4千円くらいで手頃ですし、PC/SCにも対応していて開発もやりやすいです。

使い方としては社員証のFeliCaなんかをユーザの識別用に使ったりとかします。
あとは大量のNFCタグをDBに登録しなきゃいけないようなときにMANICA EXCEL TOOLと繋いで
タグのIDを片っ端からエクセルに入れて登録したりします。
MANICA EXCEL TOOLではNDEFの書込みもできるようにしてますので、スマートポスターの作成とかもできます。

これだけだとつまんないので、ふとAndoridにBeam飛ばせないのかと思って調べたらありました。
https://code.google.com/p/ismb-snep-java/wiki/SNEP_From_ACR122_To_Phone

こちらはJavaで実装されてますが、まぁ何で実装しようがリーダの制御でBeamが飛ばせるという
ことはわかりました。

Android Beamといっても単にNDEFメッセージをSNEPというプロトコルで送信しているだけのようです。SNEPについてはこちらに資料がありました。
http://www.jortec.neec-fct.org/wp-content/uploads/2013/02/Simple_NDEF_Exchange_Protocol.pdf

 Version(1byte) | Request(1byte) | Length(4byte) | NDEF Data

これでいけそうです。しかしこれだけではなくて、SNEPデータをさらにLLCPというプロトコルに載せないとダメのようです。この部分がまたややこしくてInitiatorになったりTargetに接続したり(いわゆるビームが走るっていう部分ですね)とまぁいろいろあるんですが、先ほどのJavaのソースを参考に同じようにやればできそうなのでとりあえず実装してみました(多謝~)。
MANICA EXCEL TOOLを改造して、NDEF書込みの部分を書き込まずにSNEPで送信するように変更しました。

MANICA EXCEL TOOL(改造版)を起動してACRリーダの設定をします。


B列に送信したいURLを書きます。


で、Galaxy Nexusをリーダに置くと...


おー!URLが表示されました。
ってこれ何かに使えますかね?(笑)

2013年5月23日木曜日

EPCの謎に迫る2


Gen2のUHFパッシブタグのEPCの値は通常は96bit(12byte)なんですが変更も可能です。
EPCメモリバンクの構造は次のようになってます。

 CRC(チェックサム)2byte | PC(Protocol Control) 2byte | EPCの値 12byte(通常は)

EPCの値の前にPCという値があって、じつはこのPCの先頭5bitが後に続くEPCの値の長さになっています。正確にはワード単位の長さです。5bitなので、2進数で(00000)~(11111)までで10進数でいうと0~31までです。1ワードは2byte(16bit)ですから、0byte(0bit)~62byte(496bit)まで指定できることになります。

実際PCの部分をリーダで読むと、大概 30 00(16進数)になっています。リーダのアプリケーションによってはタグ読取時に表示するEPCの値がPCの部分からの表示になっているものもあり、「はじめの3000って何ね~」と言う人もかなりいます。3000は2進数にすると(0011 0000 0000 0000)で先頭5bitは(00110)で10進数で6になり、6ワード=12byteということで96bitになっているわけです。

496bitというと結構な量ですが本当にそんなに長くできるんでしょうか。AlienのHiggs3の仕様をみてみると、「96-EPC Bits, extensible to 480 Bits」って書いてありますので、480bitまでは拡張できるようです。

ということで実験です。
Morphicリーダに付属のアプリケーションではPCの書き換えまではできないので今回はNECのマルチリーダライタを使います。ソフトウェアは当社のMANICA EXCEL TOOL(改造版)です。この改造版はNECマルチリーダライタを使って「セルへ入力」をすると、セルへ現在のEPCの値を入力した後、右隣にあるセルの値をPC含めてEPCバンクに書込みをします。


NECマルチリーダライタです。950MHzの古いタイプです。


MANICA EXCEL TOOLを起動して、NECマルチリーダライタに設定します。

書き込みたい値をセルに入れておきます。480bit(60byte)なので、レングスは30ワードになり、PCの部分は(1111 0000 0000 0000)で、EPCの値は適当に16進数で 11 22 33 44 55 66 77 88 99 00 (これを6回繰り返し。計60byte)にします。ということでセルには


といれておきます。このセルの左のセルにフォーカスがある状態で


Higgs3のタグをリーダに乗せると(ピコッ)


セルに現在のEPCの値が入りました。

で、書き換えできたんでしょうか。Morphicで読んでみると


はみ出してて見えません(笑

実はMorphicもMANICA EXCEL TOOLに接続できます(便利ですね!)。


設定を追加して


Morphic側のMANICA EXCEL TOOLを起動し、読み込んでみると(ピッ)


確かに書込みできています!
こんなに長い値が書込みできるなんて、なんて開発者泣かせの迷惑便利なんでしょうか!
ちなみに496bitも試してみると何と書けました(笑)。仕様は480bitまでとなってるのであんまりやらない方がいいかもしれません。

拡張できることはわかりました。では縮小はどうでしょうか?


1ワード(2byte, 16bit)にしてみます。


できました。
ここで疑問が。いっそのこと0ワードってできるんでしょうか?

やってみます。


できました(笑)。ステルスタグとでも呼びますか。どうやって戻すんだろう(笑)

2013年5月21日火曜日

EPCの謎に迫る1


現在入手できるUHFのパッシブタグはEPC Class1 Generation2(「じぇんつー」とかいいます)という規格になっています。この規格ではタグのメモリが「EPCバンク」「TIDバンク」「Userバンク」「Reservedバンク」の4つのバンクから構成されています。

EPCバンクは書き換え可能で通常は96bitを使います。
TIDバンクはチップ製造時にタグ固有の値が書き込まれ、書き換えができないようになっています。
Userバンクはユーザが自由に読み書きできるように用意されている領域で、チップによって容量などが違います。
Reservedバンクは、タグのアクセス時などに使用するアクセスパスワードを保存する領域です。

この4つのバンクの中で非常によく使うのがEPCバンクです。
リーダでタグの読取をするとまずはこのEPCバンクの値が飛んできます。
その後、EPCの値を指定して、UserバンクやTIDバンクにアクセスします。

例として、EPCの値がそれぞれA、B、Cの3つのタグがあるところでリーダで読取を行うと、A、B、Cが一度に取得できます。その後、じゃあ、AさんのTIDは何かな?などと使用します。
つまり、EPCの値はタグを識別するために利用するものなのです。

しかしながら、EPCの値は書き換え可能です。ということは同じEPCの値を持つタグもすぐに作れます。というかチップメーカによって出荷時のEPCの値の扱いが違っていて、Alienのタグは出荷時に固有のEPCの値がエンコードされていますが、昔のImpinjのタグは同じEPCの値がエンコードされています。

じゃあ同じEPCの値のタグがいっぱいあったとき、読み書きはどのように動作するのでしょうか?
ということで実験してみました。

実験で使用するのはAlienのタグ3種類とNordicID製のMorphicです。カッコイイですね。

まずは普通に読んでみます。ちゃんと3枚読めました。E20~というのがEPCの値です。16進数で12桁(96bit)になってますね。Alienは出荷時に固有の値が書き込まれていますから、3枚とも違う値になっています。

これからこのタグのEPCの値を変更します。わかりやすいように1にしました。リストから書き換えたいタグを選択して、EPCライトボタンを押すとEPCの値が変更されます。これを3回繰り返して、3枚とも同じEPCの値にしてしまいます。

この状態で普通に読取をしてみると、なんとタグが1個になってしまいました。同じEPCの値なので同じタグということになっちゃったんですね。

ここからさらに、1から2へとライトをやってみます。3枚に向けてやった場合、3枚とも書き変わってしまうのか?

3枚に均等に電波があたるように(見えないのでわかりませんから感覚です)してEPCライトボタンを押します。

タグが2個になりました!1枚ずつ調べると、1枚だけ書き変わっていました。すべて書き変わることはないようです。

ではどういう基準で1枚が選択されるのでしょうか。距離で決まるのか?ということでいろいろ試しました。

何回か試したところ、3種類のタグの中でGタグと呼ばれている感度がよいとされているタグが書き変わることが多かったです。距離についてもより近い方が書き変わりやすかった気がします。(このあたりは主観です)