2014年7月4日金曜日

PC/SCに潜む謎 その2

前回の(1年以上前ですが)「PC/SCに潜む謎」の続編です。実は何気にこのエントリーが一番アクセスが多いです。前回は PC/SC のコマンドがカードに対して投げるものであって、リーダに投げるものではないというお話でした。

しかしそう、あったんです。リーダに投げる方法がぁ!(騒いでるのは私だけです)

SCardConnect の際に ShareMode というのを指定するんですが、ここに SCARD_SHARE_DIRECT というのがありました。で、これで SCardConnect するとカードが無いのに待望のカードハンドルがもらえるのです!うはー!(激喜

そして、ここからは ACR122 だけの話かもしれませんが、SCardTransmit ではなくて SCardConrtol というコマンド(これもカードハンドルが必要)で投げることで DirectTransmit が可能になります。

というわけで前回の最後の方の「カードが置いてないときにAPDUコマンドは送信できない」という部分は間違いでございましたので訂正してお詫びいたします。

では早速やってみましょう。いつもの ACR122 ちゃんです。


SCardEstablishContext から SCardListReaders してリーダを取得するところまでは前回と同じです。

で、この状態で SCardConnect を SCARD_SHARE_DIRECT モードで実行すると、カードハンドルが取得できます。もちろんカードは置いていません。

そのカードハンドルを使って SCardConrtol コマンドを IOCTL_CCID_ESCAPE_SCARD_CTL_CODE というコントロールコードで実行します(追記:2014/09/19 Raspberry Pi ではこのコントロールコードは 0x42000DAC (0x42000000 | 3500) で動作します)。とりあえず Get Firmware Version というコマンド(FF 00 48 00 00)を投げてみます。

すると 41 43 52 31 32 32 55 32 31 30 (ASCIIで ACR122U210) が返ってきました。動作していますねー。

では DirectTransmit に挑戦です。
ACR122U には PN532 というチップが入っていますので、このチップに直接コマンドを送ることができます。
Direct Transmit についての詳細は「ACRリーダでNTAG固有のコマンドを使う」を参照ください。

今回は InAutoPoll というコマンドを実行してみます。これはポーリングを行うコマンドです。どのタイプのタグをポーリングするとか選んだりできますし、何よりタグが通信圏内に入るとすぐに通知してくれます。

最初にリーダの自動ポーリングをオフにします。これは ACRリーダの Set PICC コマンドを利用します。

で、InAutoPoll コマンドを投げます。ポーリング間隔を一番短い 150ms で実行します。するとプログラムは応答待ちになります。そこでカードを近づけると...おー!おぉー!ぐひひー!  って何やってるかわかんないですね。ACR122UToolで同じことやってみます。

まずはリーダの自動ポーリングをオフに。


そして InAutoPoll コマンドを投げます。すると応答待ちになります。


タグを近づけると...


きたー。NTAGを近づけてみたんですがちゃんとUIDが採れています。
って何か InAutoPoll の話になってきちゃってますが、今回はこれが PC/SC からできたよっていうお話なのでした。
うーん、謎は解決したということでいいんだろうか。関数名は SCardControl だしなぁ。まぁ、どうでもいいか。


0 件のコメント:

コメントを投稿