2013年10月9日水曜日

Raspberry Pi で NFC

せっかく Raspberry Pi を入手したので、NFCリーダを取り付けてみましょう。リーダの制御PCの替わりになればいろんなところで使えそうです。リーダはいつもの ACR-122U を使います。


まずはネットで情報収集します。あー、やはり Raspberry Pi に ACR-122U を取り付けてる人いますねー。しかしみんな USB給電では足りないらしく、給電用のハブを利用しているようです。そうすると電源が2個になっちゃいますね。あぁ、早くも暗雲が...

何はともあれやってみましょう。Raspberry Pi を標準でセッティングして、とりあえず ACR-122U を USB に挿します。何も起きませんが、dmesg を見ると ACR122U PICC Interface として認識してます。通常ですとここでリーダの赤LEDが点くんですが点きません。
確か初期化コマンド投げないと点かなかったのでまぁよしとしましょう。

で、どうやって ACR-122U を制御するかが問題です。直接USBにアクセスしてもいいんですがあまりお行儀がよくないのでできれば PC/SC を使いたいところです。ということでパッケージを検索してみます。debian のパッケージサイトから pcsc 関連を見てみます。

おー、pcsc-lite ありますねー、しかも armhf 版の acsccid ドライバまであります。何て素敵な世の中なんでしょう!みんなありがとうぉー!
というわけで acsccid ドライバをインストール

pi@raspberrypi ~ $ sudo apt-get install libacsccid1

で、libpcsc-lite1をインストール

pi@raspberrypi ~ $ sudo apt-get install libpcsclite1

あ、これはすでに入ってるみたい。なんで?まぁいいや。
その後 pcscd を入れてみると、

pi@raspberrypi ~ $ sudo apt-get install pcscd

勝手にデーモンが起動し、


赤LED点きました。
給電は大丈夫なのか?タグを置くと一応反応しています。
うわー、こんな簡単でいいのか?後は PC/SC でコーディングすればよしと。PC/SCかぁ・・・。これが一番面倒だな(笑
開発用のパッケージをインストールします。

pi@raspberrypi ~ $ sudo apt-get install libpcsclite-dev

で、テストプログラムをコーディング

sample.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <winscard.h>

int main(int argc, char *argv[])
{
       SCARDCONTEXT hContext;
       SCARDHANDLE hCard;

       LPSTR lpszReaderName = NULL;
       LONG lResult;
       DWORD dwActiveProtocol;
       DWORD dwAutoAllocate = SCARD_AUTOALLOCATE;
       int i;

       char UID[24];
       memset(UID, 0, sizeof(UID));

       lResult = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &hContext);
       if (lResult != SCARD_S_SUCCESS) {
               printf("not service\r\n");
               return 1;
       }
       lResult = SCardListReaders(hContext, NULL, (LPTSTR)&lpszReaderName, &dwAutoAllocate);
       if (lResult != SCARD_S_SUCCESS) {
               printf("no reader\r\n");
               return 1;
       }
       printf("%s\r\n", lpszReaderName);

       lResult = SCardConnect(hContext, lpszReaderName, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
       if (lResult == SCARD_S_SUCCESS) {
               SCARD_IO_REQUEST request;
               request.dwProtocol = dwActiveProtocol;
               request.cbPciLength = 8;
               DWORD dwResponseSize;
               BYTE response[128];
               BYTE getUID[] = { 0xff, 0xca, 0x00, 0x00, 0x00 };

               dwResponseSize = sizeof(response);
               lResult = SCardTransmit(hCard, &request, getUID, sizeof(getUID), NULL, response, &dwResponseSize);
               if (lResult == SCARD_S_SUCCESS && response[dwResponseSize - 2] == 0x90 && response[dwResponseSize - 1] == 0x00) {
                       for (i = 0; i < dwResponseSize - 2; i++)
                               sprintf(UID, "%s%02X", UID, response[i]);
                       printf("%s\r\n", UID);
               }
               SCardDisconnect(hCard, SCARD_LEAVE_CARD);
       }
       SCardReleaseContext(hContext);

       return 0;
}

コンパイルして

pi@raspberrypi ~ $ gcc -I/usr/include/PCSC -lpcsclite -o sample sample.c

実行すると

pi@raspberrypi ~ $ ./sample
ACS ACR122U 00 00
04A57EE2613380

おー、読めてるー。ここまでくればあとは大丈夫そうですねー。

6 件のコメント:

  1. 参考にさせて頂いております。
    必要なドライバ、デーモンをインストールしました。
    デーモンの実行を /etc/init.d/pcscd status で確認して動作中であることを確認したのですが、赤LEDが点灯しません。
    また、テストプログラムを実行したところ、IDmが読めず、63 00 が戻ってきます。
    何かご存知でしたら、ご教示願います。

    返信削除
    返信
    1. コメントありがとうございます。
      製品のバージョンかもしれませんね。記事中の給電についても気になってはいたところです。こちらにあるリーダのファームのバージョンはACR122U210です。

      削除
    2. ご回答ありがとうございます。
      #返信が遅れまして、すみません。
      おっしゃる通り、リーダーの違いのようです。
      こちらで使用しているのは、ACR122U-A1です。
      0xff, 0xca, 0x00, 0x00, 0x00
      を送信するまえに、APDUを送信したらうまくいきました。
      ありがとうございました。

      削除
  2. Hi,

    when i run the program, i got this message :
    "no reader".
    The problem is i don't undersand C language...

    This is all my command befor running program
    sudo apt-get install libacsccid1
    sudo apt-get install libpcsclite1
    sudo apt-get install pcscd
    sudo apt-get install libpcsclite-dev

    Can you help me ?
    Thank you in advance

    返信削除
    返信
    1. Hi,

      If you use Raspberry Pi Model B+,
      the following article I'd be on your help.

      http://enjoy-rfid.blogspot.jp/2015/03/raspberry-pi-nfc.html

      thanks

      削除
  3. Great !!! It works !!!
    Thank you a lot !!
    Now i must learn c language in order to send data on remote server...

    返信削除