開発

#11 NFC処理実装 動作確認

NFC処理実装 動作確認

前回まででNFCカードにNDEFデータを読み書きする処理を実装しました。
今回は実際に動作させ、どのようなデータが返ってくるか見ていきます。

【注意事項】
本記事は、NFC技術の一般的な仕組みを解説するものです。
公共機関や第三者が管理・運用するNFCタグやICカードへの無断での書き込み・改変を推奨または容認するものではありません。

管理者の許可なくデータの書き込みや改変を行う行為は、不正アクセス禁止法や刑法等の法令に違反する可能性があります。
これらの行為により生じたいかなる損害・法的責任についても、当方は一切の責任を負いません。

・NFCを活用した新しいサービスや製品を企画・開発したい方
・スマートフォンやICカードとの連携機能を実装したいエンジニア
・IoT機器や非接触決済の技術に関心のある開発者

完成品画像NFC完成品紹介ページはこちら

開発環境

  • OS: macOS Sonoma 14.5
  • Xcode: Xcode 15.4 (15F31d)

 

事前準備

 ドライバアンインストール

以前の記事同様に、ドライバがインストール済の場合はアンインストールします。

 

 NFCカードの事前書き込み

別のツールを使って事前にカードにNDEFデータを書き込んでおきます。
今回は WakDev 社の「NFC Tools」を利用してNDEFデータを書き込みました。

NFCTools書き込み画面

今回の動作確認では、 test data という文字列レコード1つのみを書き込みました。

🔍補足
今回、カードアクセスのはじめに、NDEFアプリケーションを選択していますが、一度も書き込まれていないカードだとその時点でカードアクセスが失敗してしまいました。 そのような事情もあり、事前にNDEFデータを書き込まれたものを使用します。

一度も書き込まれていないカードでもアクセスできるようにする方法は今後も調査してまいります。

 

 モジュールとカードの設置

カードの捕捉は、プロトコル切り替えコマンドを実行する瞬間にのみ実施されます。
このため、今回の動作確認では、 RC-S660/S のアンテナ部にカードを置き、確実に反応するようにして動作確認します。

カード設置

 

動作確認

それではビルドして動作確認してみましょう。
デバイスが Mac に接続されている場合、アプリを実行する前にデバイスを抜いておきます。

以前の記事 と同様に、ドライバインストール後、コンソールをアプリを開いてからデバイスを接続します。
Start メソッドにカードアクセス処理も実装しているため、USBを接続した時点でカードアクセス処理も実行されます。

それぞれの処理で受信した応答データを詳しく見ていきましょう。
なお、コマンドパケットについては前回までの記事で確認済、レスポンスパケットはAPDUレスポンス部以外はほぼ同様なので、APDUレスポンス部のみに着目して確認していきます。

 

 カード操作のためのコマンドのレスポンス構造

カード操作のために使用する Manage Session , Switch Protocol , Transparent Exchange コマンドは、レスポンスデータが Data Field BER-TLV という構造になっています。
Data Field BER-TLV は、TLV構造データに加え、各コマンドで定義されるTLV構造のData objectが含まれる場合があります。

TLV 設定データ
Tag C0h : Generic error status
Length 03h
Value エラーステータス(取り得るデータの詳細はコマンドリファレンス参照)
Data object TLV構造のデータ(コマンドによって追加される)

なお、通常のレスポンス構造同様、 Data Field BER-TLV の後にステータスバイト SW1, SW2 もつきます。

 

 1. Transparent Session 開始

TS開始パケット解析

オフセット 名称   実データ
0 Data Field BER-TLV Tag c0 : Generic error status
1   Length 03
2   Value: エラーステータス 00 90 00
5 ステータスバイト   90 00

ステータスバイト SW1 = 90 , SW2 = 00 は正常終了であり、本コマンドが正しく実行できた事を表します。
Value: エラーステータス の 00 90 00 も正常終了を表すため、 Transparent Session が正常に開始されたことを示します。

 

 2. プロトコル切り替え

プロトコル切り替えパケット解析

オフセット 名称   実データ
0 Data Field BER-TLV Tag c0 : Generic error status
1   Length 03
2   Value: エラーステータス 00 90 00
5 Data object Tag 5f 51 : ATR
7   Length 06
8   Value: ATR 3b 81 80 01 80 80
14 ステータスバイト   90 00

ステータスバイト、エラーステータスが共に正常終了のため、プロトコル切り替えが正常に実行されたことを示します。
Data object の ATR データは、 Type A/B の Layer4 指定時に付加されます。

 

 3. フラグ設定

フラグ設定パケット解析

オフセット 名称   実データ
0 Data Field BER-TLV Tag c0 : Generic error status
1   Length 03
2   Value: エラーステータス 00 90 00
5 ステータスバイト   90 00

ステータスバイト、エラーステータスが共に正常終了のため、フラグ設定が正常に実行されたことを示します。

 

 4. RF 出力 ON

RFONパケット解析

オフセット 名称   実データ
0 Data Field BER-TLV Tag c0 : Generic error status
1   Length 03
2   Value: エラーステータス 00 90 00
5 ステータスバイト   90 00

ステータスバイト、エラーステータスが共に正常終了のため、 RF 出力が ON されたことを示します。

 

 5. カードコマンド送受信

(1) SELECT : NDEF アプリケーション

SELECT-NDEFアプリケーションパケット解析

オフセット 名称   実データ
0 Data Field BER-TLV Tag c0 : Generic error status
1   Length 03
2   Value: エラーステータス 00 90 00
5 Data object 1 Tag 92 : 受信データ最終バイト有効ビット数
6   Length 01
7   Value: 受信データ最終バイト有効ビット数 00
8 Data object 2 Tag 96 : 受信ステータス
9   Length 02
10   Value: 受信ステータス 00 00
12 Data object 3 Tag 97 : 受信データ
13   Length 02
14   Value: 受信データ 90 00
16 ステータスバイト   90 00

ステータスバイト、エラーステータスが共に正常終了のため、カードコマンドが正常に実行されたことを示します。

カードコマンド送受信で使用する Transceive (Tag= 95h ) 1つずつに対し、受信データ最終バイト有効ビット数 (Tag: 92h ), 受信ステータス (Tag: 96h ), 受信データ (Tag: 97h ) の3つがレスポンスとして返ります。

SELECT-NDEFアプリケーションパケット解析_フォーカス

受信データに着目すると 90 00 が返っています。
受信データは送信時の SELECT コマンドのレスポンスであり、 SELECT コマンドもAPDUのため、これは SELECT コマンドに対するステータスバイト SW1, SW2 となります。
そして、ステータスバイト SW1 = 90, SW2 = 00 は正常終了であるため、 NDEF アプリケーションが正常に選択できた事を表します。

 

(2)  SELECT : CC ファイル

SSELECT-CCファイルパケット解析

SELECT-CCファイルパケット解析_フォーカス

オフセット 名称   実データ
0 Data Field BER-TLV Tag c0 : Generic error status
1   Length 03
2   Value: エラーステータス 00 90 00
5 Data object 1 Tag 92 : 受信データ最終バイト有効ビット数
6   Length 01
7   Value: 受信データ最終バイト有効ビット数 00
8 Data object 2 Tag 96 : 受信ステータス
9   Length 02
10   Value: 受信ステータス 00 00
12 Data object 3 Tag 97 : 受信データ
13   Length 02
14   Value: 受信データ 90 00
16 ステータスバイト   90 00

ステータスバイト、エラーステータス、受信データ中のステータスバイト、全て正常終了のため、CCファイルが正常に選択できた事を表します。

 

(3)  READ BINARY : NDEF ファイル制御 TLV データの読み出し

READ-CCファイルパケット解析

オフセット 名称   実データ
0 Data Field BER-TLV Tag c0 : Generic error status
1   Length 03
2   Value: エラーステータス 00 90 00
5 Data object 1 Tag 92 : 受信データ最終バイト有効ビット数
6   Length 01
7   Value: 受信データ最終バイト有効ビット数 00
8 Data object 2 Tag 96 : 受信ステータス
9   Length 02
10   Value: 受信ステータス 00 00
12 Data object 3 Tag 97 : 受信データ
13   Length 11
14   Value: 受信データ 00 11 20 00 3b 00 34 04 06 e1 04 1e 00 00 00 90 00
31 ステータスバイト   90 00

ステータスバイト、エラーステータスが共に正常終了のため、カードコマンドが正常に実行されたことを示します。

READ-CCファイルパケット解析_フォーカス

これまで同様、受信データの末尾の2バイトはステータスバイトです。
READ BINARY コマンドでは現在選択しているファイルのデータを読み出します。ステータスバイトの前に、コマンドパケットの Le で指定したサイズ分のデータが返却されます。
ここでは CC ファイルの先頭15バイトを読み込んで NDEF ファイル制御 TLV データを取得し、NDEFファイルのファイルIDを特定します。
なお、CCファイルのデータ構成の詳細は前回記事を参照ください。

 

(4)  SELECT : NDEF ファイル

SELECT-NDEFファイルパケット解析

SELECT-NDEFファイルパケット解析_フォーカス

オフセット 名称   実データ
0 Data Field BER-TLV Tag c0 : Generic error status
1   Length 03
2   Value: エラーステータス 00 90 00
5 Data object 1 Tag 92 : 受信データ最終バイト有効ビット数
6   Length 01
7   Value: 受信データ最終バイト有効ビット数 00
8 Data object 2 Tag 96 : 受信ステータス
9   Length 02
10   Value: 受信ステータス 00 00
12 Data object 3 Tag 97 : 受信データ
13   Length 02
14   Value: 受信データ 90 00
16 ステータスバイト   90 00

ステータスバイト、エラーステータス、受信データ中のステータスバイト、全て正常終了のため、NDEFファイルが正常に選択できた事を表します。

 

(5)a. READ BINARY : データ読み出し

READ-NDEFファイルサイズパケット解析

オフセット 名称   実データ
0 Data Field BER-TLV Tag c0 : Generic error status
1   Length 03
2   Value: エラーステータス 00 90 00
5 Data object 1 Tag 92 : 受信データ最終バイト有効ビット数
6   Length 01
7   Value: 受信データ最終バイト有効ビット数 00
8 Data object 2 Tag 96 : 受信ステータス
9   Length 02
10   Value: 受信ステータス 00 00
12 Data object 3 Tag 97 : 受信データ
13   Length 04
14   Value: 受信データ 00 10 90 00
18 ステータスバイト   90 00

ステータスバイト、エラーステータスが共に正常終了のため、カードコマンドが正常に実行されたことを示します。

READ-NDEFファイルサイズパケット解析_フォーカス

受信データには、 NDEF ファイルの先頭2バイトとステータスバイト2バイトが返却されます。
ステータスバイト 90 00 は正常完了を示すため、読み出しが正常完了したことを表します。
NDEF ファイルの先頭2バイトは、続くNDEFメッセージのサイズを示しており、次のデータ読み込みのコマンドパケットに利用します。

READ-NDEFファイルデータパケット解析

オフセット 名称   実データ
0 Data Field BER-TLV Tag c0 : Generic error status
1   Length 03
2   Value: エラーステータス 00 90 00
5 Data object 1 Tag 92 : 受信データ最終バイト有効ビット数
6   Length 01
7   Value: 受信データ最終バイト有効ビット数 00
8 Data object 2 Tag 96 : 受信ステータス
9   Length 02
10   Value: 受信ステータス 00 00
12 Data object 3 Tag 97 : 受信データ
13   Length 12
14   Value: 受信データ d1 01 0c 54 02 65 6e 74
65 73 74 20 64 61 74 61
90 00
32 ステータスバイト   90 00

ステータスバイト、エラーステータスが共に正常終了のため、カードコマンドが正常に実行されたことを示します。

READ-NDEFファイルデータパケット解析_フォーカス

受信データには、NDEFメッセージとステータスコード2バイトが返却されます。
ステータスバイト 90 00 は正常完了を示すため、読み出しが正常完了したことを表します。
NDEFメッセージはNDEFレコードの集合体ですので、前回の記事で紹介したNDEFレコードの形式に則って確認します。

オフセット 名称   実データ
0 MB, ME, CF, SR, IL, TNF   d1 = 11010001b
1 TYPE_LENGTH   01
2 PAYLOAD_LENGTH   0c
3 TYPE   54 : 文字列レコード
4 PAYLOAD エンコード、言語コード長 02 = 00000010b
5   言語コード 65 6e
7   文字列データ 74 65 73 74 20 64 61 74 61

MB , ME に共に 1  がセットされているため、単一のレコードで構成されたNDEFメッセージであることを示しています。
また、 SR に 1 がセットされているため PAYLOAD_LENGTH は1バイト、 IL0 なので ID 及び ID_LENGTH が存在しないことを示しています。

TNF の値は 1 なので、 TYPE には NFC Forum で規定されているレコードタイプ定義(RTD)が指定されていることを示します。
TYPE の値 54h は、 NFC RTDにおいて文字列レコードを示します。

続いて PAYLOAD を見ていきましょう。
1バイト目の1ビット目はエンコードを表し、 0 の場合は UTF-8 であることを示します。
末尾6ビットは言語コードのサイズを表し、この後2バイトが言語コードであることを示します。

言語コード 65 6e は、 UTF-8 では en となります。
このため、この後に続く文字列データの言語が英語であることを示します。

文字列データ 74 65 73 74 20 64 61 74 61 は、 UTF-8 では test data となります。

以上、実際に読み込んだデータが、事前準備として書き込んだNDEFデータと一致していることが確認できました。

 

(5)b. UPDATE BINARY : データ書き込み

UPDATE-NDEFファイルパケット解析

UPDATE-NDEFファイルパケット解析_フォーカス

オフセット 名称   実データ
0 Data Field BER-TLV Tag c0 : Generic error status
1   Length 03
2   Value: エラーステータス 00 90 00
5 Data object 1 Tag 92 : 受信データ最終バイト有効ビット数
6   Length 01
7   Value: 受信データ最終バイト有効ビット数 00
8 Data object 2 Tag 96 : 受信ステータス
9   Length 02
10   Value: 受信ステータス 00 00
12 Data object 3 Tag 97 : 受信データ
13   Length 02
14   Value: 受信データ 90 00
16 ステータスバイト   90 00

ステータスバイト、エラーステータス、受信データ中のステータスバイト、全て正常終了のため、データが正常に書き込めた事を表します。

書き込み確認

実際に別のツールでカードのデータを読み込むと、コマンドパケットで指定した文字列 write test が設定されていることがわかります。

レコード確認

また、該当レコードの詳細を見ると、コマンドパケットで指定した各データ通りのレコードとなっていることがわかります。

 

 6. RF 出力 OFF

RFOFFパケット解析

オフセット 名称   実データ
0 Data Field BER-TLV Tag c0 : Generic error status
1   Length 03
2   Value: エラーステータス 00 90 00
5 ステータスバイト   90 00

ステータスバイト、エラーステータスが共に正常終了のため、 RF 出力が OFF されたことを示します。

 

 7. Transparent Session 終了

TS終了パケット解析

オフセット 名称   実データ
0 Data Field BER-TLV Tag c0 : Generic error status
1   Length 03
2   Value: エラーステータス 00 90 00
5 ステータスバイト   90 00

ステータスバイト、エラーステータスが共に正常終了のため、 Transparent Session が終了されたことを示します。

 

おわりに

以上で本シリーズにおける Mac 向け NFC 通信ドライバ開発は完了となります。

今回はNFC通信のための基本的な内容となりましたが、ユーザー操作画面との連携やさまざまなカードへの対応など、実製品としてはまだまだ考慮すべき点が多々あります。
今後も調査研究・開発を重ねていきます。

 


 

TOP