NFC#08 RC-S660/S パケット仕様確認
今回は RC-S660/S との通信で使用されるパケット構造の理解を深めていきます。
・スマートフォンやICカードとの連携機能を実装したいエンジニア
・IoT機器や非接触決済の技術に関心のある開発者
パケット構造の概要
RC-S660/S との通信で使用されるパケットは、コマンドフレームとACKフレームの2種類が定義されています。
コマンドフレーム
ホスト(今回は Mac)から RC-S660/S へのコマンド送信、及び、 RC-S660/S からのレスポンスとして利用されます。
コマンドフレームの概略図を以下に示します。

コマンドフレームは、 CCID コマンドを内包します。
CCID はICカードインターフェースデバイスを示し、USB関連仕様として定義されています。
CCID コマンドは、USBホストがICカードインターフェースデバイス(CCID)を介して、ICカードとやり取りするためのコマンドとなります。
RC-S660/S でサポートしている CCID コマンドでは、CCIDコマンド中に RC-S660/S を制御するためのAPDUコマンドを内包するものがあります。
APDU(Application Protocol Data Unit)はスマートカード向けの通信プロトコルで、 ISO/IEC 7816-4 で定義されています。
さらにそのAPDUコマンドの中には、ICカードを操作するためのカードコマンドを内包するものがあります。
ACKフレーム
特定の目的でのみ利用されます。
例えば、ホスト(今回は Mac)からのコマンドを受信した際、データリンクレベルのエラーを検出しなかった場合に、 RC-S660/S からホストへ送信されます。
ACKフレームは特定のデータ列となります。
各データのパケット構成
それでは各データのパケット構成を詳しく見ていきましょう。
コマンドフレーム/ACKフレーム構成

コマンドフレーム/ACKフレームは以下の要素で構成されます。
| № | 名称 | バイト サイズ |
データ |
| 1 | プリアンブル | 1 | 00h |
| 2 | スタートコード | 2 | 00FFh |
| 3 | パケットデータ長 | 2 | パケットデータのバイトサイズ(LEN) ※ビッグエンディアン |
| 4 | パケットデータ長チェックサム | 1 | コマンドフレーム: パケットデータ長データ列のチェックサム ACKフレーム: FFh |
| 5 | パケットデータ | LEN | (コマンドフレームのみ)CCIDコマンドデータ列 |
| 6 | パケットデータチェックサム | 1 | (コマンドフレームのみ)パケットデータ列のチェックサム |
| 7 | ポストアンブル | 1 | 00h |
プリアンブル・スタートコードは、パケットデータの開始を識別するための固定のデータ列です。
また、ポストアンブルは、パケットデータの終了を示す固定のデータです。
コマンドフレームにおけるパケットデータはCCIDコマンドデータ列です。
CCIDコマンドデータ列のバイトサイズがパケットデータ長に格納されます。
なお、ACKフレームではパケットデータは存在せず、パケットデータ長には 0000h が格納されます。
チェックサムは誤り検出のためのデータで、 データ列の各バイトの総和 + チェックサムバイト の下位1バイトが 00h となるようなチェックサムを設定します。
ただし、ACKフレームにおいては、パケットデータ長チェックサムには FFh を設定します。
CCID コマンド/レスポンス構成

CCIDコマンドは以下の要素で構成されます。
| № | 名称 | バイト サイズ |
データ |
| 1 | メッセージタイプ | 1 | CCIDコマンドの種類を示す特定の値 |
| 2 | データ長 | 4 | 固有データのバイトサイズ(dwLength) ※リトルエンディアン |
| 3 | スロット番号 | 1 | RC-S660/S では 00h 固定 |
| 4 | シーケンス番号 | 1 | 送信ごとに単調増加するカウンタ |
| 5 | ステータスコード | 1 | (レスポンスのみ)RC-S660/S ではコマンドステータス 02h :エラーなし 42h :失敗(エラーで詳細を示す) |
| 6 | エラーコード | 1 | (レスポンスのみ)コマンドステータスが失敗の場合、エラー詳細を示す特定の値 |
| 7 | 固有ヘッダー | 1 or 3 | CCIDコマンドによる |
| 8 | 固有データ | dwLength | CCIDコマンドによる |
メッセージタイプはCCIDコマンドの種類を示し、各コマンドに対して特定の値が割り振られています。
スロット番号は、CCIDが複数のスロット(ICカード接続)をサポートしている場合に、どのスロットへのコマンドかを識別します。
RC-S660/S ではカード1枚での利用に限られているため、スロット番号は 00h 固定となります。
シーケンス番号は、CCIDコマンド送信ごとに単調増加で設定するカウンタです。
コマンドに設定したシーケンス番号がレスポンスにそのまま設定され、ホスト側でコマンド送信データとレスポンスデータの突合に利用します。
シーケンス番号の値そのものは RC-S660/S の挙動への影響はありません。
ステータスコード、エラーコードはレスポンスのみで使用され、スロットのステータス・エラーを示します。RC-S660/S においてはそれぞれ、コマンド処理のエラー有無と、エラー内容を示すデータが設定されます。
固有ヘッダー、固有データはCCIDコマンドによって設定データが異なります。
固有ヘッダーとして割り当てられている領域は3バイトですが、レスポンスではそのうちの2バイトがステータスコード、エラーコードとして利用されるため、残りの1バイトのみが固有ヘッダーとして利用できる領域となります。
◇RC-S660/S でサポートしている CCID コマンド
RC-S660/S では、以下の2つのCCIDコマンドのみがサポートされています。
- PC_to_RDR_Escape コマンド(メッセージタイプ 6Bh )
- RC-S660/S を制御するためのAPDUコマンドを送信する
- 固有ヘッダー:全て 00h
- 固有データ:
- コマンド時:APDUコマンドデータ
- レスポンス時:APDUレスポンスデータ
- PC_to_RDR_Abort コマンド(メッセージタイプ 72h )
- 実行中のCCIDコマンドを中断する
- 固有ヘッダー:全て 00h
- 固有データ:無し
今回の開発では単純なパターンのみとするため、 PC_to_RDR_Escape コマンドのみ取り扱います。
APDU コマンド構成
| 筆者注: APDU が定義されている ISO/IEC 7816-4 では “Command APDU”(コマンド APDU)と表記されます。 厳密には異なりますが、今回は RC-S660/S のリファレンスの表現に合わせて「APDU コマンド」という表記としております。 |

RC-S660/S における APDU コマンドは以下の要素で構成されます。
| № | 名称 | RC-S660/S 略称 | バイトサイズ | データ |
| 1 | クラスバイト | CLA | 1 | コマンドのクラスを示す特定の値 |
| 2 | 命令バイト | INS | 1 | 処理対象コマンドを示す特定の値 |
| 3 | パラメータバイト | P1, P2 | 2 | コマンド処理に関する制御とオプションを示す特定の値 |
| 4 | コマンドデータ長 | Lc | 1 | (コマンドデータが存在する場合のみ)コマンドデータのバイトサイズ |
| 5 | コマンドデータ | Data In | Lc | (コマンドデータが存在する場合のみ)コマンドデータそのもの |
| 6 | レスポンスデータ長 | Le | 1 | 期待するレスポンスデータのバイトサイズ |
クラスバイト、命令バイト、パラメータバイトはコマンドヘッダーとも呼ばれ、 APDU コマンドに応じた値を設定します。
ISO/IEC 7816-4 で定められているものの他、ベンダー独自で定義しているものもあります。
APDU コマンドがデータを持つ場合、コマンドヘッダーに続いてコマンドデータ長とコマンドデータを設定します。
コマンドデータ長は、 ISO/IEC 7816-4 の定義上は1バイトで表現できるサイズ(255バイト)を超えて設定できますが、 RC-S660/S においては1バイトで表現できるサイズ(255バイト)までとなっています。
コマンドヘッダー・コマンドデータに続いて、期待するレスポンスデータ長を設定できます。
この値はデータチェックに利用され、実際のレスポンスデータ長と異なる場合に RC-S660/S からエラーや警告が返却されます。
今回の開発では単純化のためデータチェックしないものとし、期待するレスポンスデータ長は設定しないものとします。
APDU レスポンス構成
| 筆者注: APDU が定義されている ISO/IEC 7816-4 では “Response APDU”(レスポンス APDU)と表記されます。 コマンドと同様に厳密には異なりますが、「APDU コマンド」の表記に対応して「APDU レスポンス」という表記としております。 |

APDU レスポンスは以下の要素で構成されます。
| № | 名称 | RC-S660/S 略称 | バイトサイズ | データ |
| 1 | レスポンスデータ | Data Out | 任意 | (レスポンスデータが存在する場合のみ)レスポンスデータそのもの |
| 2 | ステータスバイト | SW1, SW2 | 2 | 処理結果を示す特定の値 |
APDU コマンドを受信すると、デバイスはコマンドに応じた処理をし、ステータスバイトに処理結果を設定して返却します。
また、レスポンスにデータが含まれる場合、ステータスコードより先行してレスポンスデータが返却されます。
TLV 形式データ
APDU コマンド/レスポンスのデータでは、 TLV 形式でデータが取り扱われることがよくあります。
TLV 形式は、データの 種類/タグ(Type / Tag)、長さ(Length)、値(Value) をセットで表現するフォーマットです。
ISO/IEC 7816-4 では、 TLV は以下の用途で利用されます。
- タグ(Tag)
- タグ番号やレコード識別子として使用される
- 長さ(Length)
- 値のデータサイズ
- 値(Value)
- 実データ
パケット解析
解析に使用する通信パケット
前回、RC-S660/S と通信し、ファームウェアバージョンを取得しました。
その際の通信パケットを利用し、パケットの構成と照合していきましょう。

パケット全体
送受信パケット全体を見てみましょう。

送信パケットは1つのコマンドフレームとなっています。
また、受信パケットは、1つのACKフレームと1つのコマンドフレームとなっています。
受信のACKフレームとコマンドフレームは連続しているように見えますが、 RC-S660/S の挙動としては、
- ホストからコマンドフレームを受信すると、フレームに問題がなければ、10ミリ秒以内にACKフレームをホストへ返送する
- その後、コマンド処理が完了したら、レスポンスのコマンドフレームをホストへ返送する
というように段階的に送信されます。
| 【補足】 今回のドライバで連続しているように見えるのは、 FT232H のレイテンシタイマによるものとなります。 レイテンシタイマのタイムアウト値が経過するまではPC側へデータ転送されないため、その時間内にACKフレームと受信コマンドフレームの両方が RC-S660/S から FT232H へ送信されることで、 Mac 側の受信では連続したデータのように見えます。 レイテンシタイマについては前回の記事も参照してください。 |
送信コマンドフレーム
まずは送信パケットのコマンドフレームから見ていきます。

プリアンブル、スタートコード、ポストアンブルは仕様通りの固定のデータとなっています。
パケットデータ長はビッグエンディアンのため、 000Eh = 14 バイトとなります。
パケットデータの領域も 14 バイト分であり、実際のデータと一致します。
パケットデータは CCID コマンドそのものとなります。
データの内容については後ほど詳しく見ていきます。
チェックサムは、各バイトの総和との和の下位1バイトが 00h となるように設定します。
パケットデータ長の各バイトの総和は
| 00h + 0Eh = 0E |
のため、下位1バイトが 00h となるには F2h であり、実際のデータと一致します。
また、パケットデータのチェックサムは、総和が
| 6Bh + 04h + FFh + 56h = 01C4h ※ 00h は総和に影響しないため省略 |
のため、下位1バイトが 00h となるには 3Ch であり、こちらも実際のデータと一致します。
このように正しいコマンドフレームを送信することで、 RC-S660/S からACKフレームとレスポンスのコマンドフレームが返送されます。
◇CCID コマンド
送信コマンドフレーム中のCCIDコマンドについて詳しく見てみましょう。

RC-S660/S を制御するため、CCIDコマンドは PC_to_RDR_Escape コマンドを使用します。
PC_to_RDR_Escape コマンドのメッセージタイプ 6Bh であるため、仕様通りとなっています。
PC_to_RDR_Escape コマンドでは、固有ヘッダーは全て 00h であるため、こちらも仕様通りです。
固有データは APDU コマンドそのものとなり、データの内容については後ほど詳しく見ていきます。
データ長は、CCIDコマンドではリトルエンディアンで表現されるため、 00000004h = 4 バイトとなります。固有データの領域も 4 バイト分であり、実際のデータと一致します。
スロット番号は、RC-S660/S では 00h 固定であり、仕様通りとなっています。
また、今回は1度きりの送信のため、シーケンス番号は 00h としています。
◇APDU コマンド
CCIDコマンド中のAPDUコマンドについて詳しく見てみましょう。

RC-S660/S ファームウェアバージョン取得のAPDUコマンドは、 RC-S660/S 公式リファレンスより以下の通りです。
- コマンドヘッダー:
- CLA(クラスバイト): FFh
- INS(命令バイト): 56h
- パラメータバイト:
- SW1: 00h
- SW2: 00h
- Lc(コマンドデータ長):- ※コマンドデータを持たない
- Data In(コマンドデータ):- ※コマンドデータを持たない
- Le(レスポンスデータ長): XXh
コマンドヘッダーは全て仕様通りとなっています。
また、ファームウェアバージョン取得のAPDUコマンドではコマンドデータを持たないため、 Lc 及び Data In は存在しません。
ファームウェアバージョン取得ではレスポンスデータが存在するため、レスポンスデータ長を設定することができます。
しかし、今回の開発ではレスポンスデータ長によるデータチェックをしないものとしているため、パケットデータに含めておりません。
ACKフレーム
次に受信パケットのACKフレームを見てみましょう。

プリアンブル、スタートコード、ポストアンブルは仕様通りの固定のデータとなっています。
パケットデータ長はACKフレームの仕様通り、 0000h となっています。
またパケットデータ長チェックサムも、ACKフレームにおいては FFh 固定であるため、仕様通りとなっています。
受信コマンドフレーム
最後に受信パケットのコマンドフレームを見てみましょう。

プリアンブル、スタートコード、ポストアンブルは仕様通りの固定のデータとなっています。
パケットデータ長はビッグエンディアンのため、 001Eh = 30 バイトとなります。
パケットデータの領域も 30 バイト分であり、実際のデータと一致します。
パケットデータは、送信コマンドフレームの CCID コマンドに対する CCID レスポンスデータとなります。
データの内容については後ほど詳しく見ていきます。
送信コマンドフレームと同様にチェックサムを算出してみましょう。
パケットデータ長の各バイトの総和は
| 00h + 1Eh = 1Eh |
のため、下位1バイトが 00h となるには E2h であり、実際のデータと一致します。
また、パケットデータのチェックサムは、総和が
| 83h + 14h + 02h + 01h + 01h + 01h + 01h + FFh + FFh + 04h + 01h + FFh + FFh + 01h + FFh + FFh + 90h = 072Dh ※ 00h は総和に影響しないため省略 |
のため、下位1バイトが 00h となるには D3h であり、こちらも実際のデータと一致します。
◇CCID レスポンス
受信コマンドフレーム中のCCIDレスポンスについて詳しく見てみましょう。

送信時の PC_to_RDR_Escape コマンドに対するレスポンスは RDR_to_PC_Escape レスポンスとなります。 RDR_to_PC_Escape レスポンスのメッセージタイプ 83h であるため、仕様通りとなっています。
RDR_to_PC_Escape レスポンスでは、固有ヘッダーは 00h であるため、こちらも仕様通りです。
固有データは APDU レスポンスそのものとなり、データの内容については後ほど詳しく見ていきます。
データ長は、CCIDレスポンスでもリトルエンディアンで表現されるため、 00000014h = 20 バイトとなります。固有データの領域も 20 バイト分であり、実際のデータと一致します。
スロット番号、シーケンス番号は送信時のCCIDコマンドと同一の値が設定されます。
今回はどちらも 00h で送信しているため、 CCID レスポンスでも 00h が設定されています。
RC-S660/S において、ステータスコードはコマンド処理のエラー有無を示します。 02h はエラーがない時の値となります。
エラーコードはエラーの内容を示しますが、ステータスコードで「エラーなし」となっているため、今回のパケットでは意味を持ちません。
◇APDU レスポンス
CCIDレスポンス中のAPDUレスポンスについて詳しく見てみましょう。

APDUレスポンスは、末尾2バイトがステータスバイト、それより前は全てレスポンスデータとなります。
ステータスバイト SW1 = 90 , SW2 = 00 は正常終了であり、ファームウェアバージョン取得が正しく実行できた事を表します。
このため、レスポンスデータは取得されたファームウェアバージョン情報となります。
なお、 RC-S660/S 公式リファレンスより、取得されるファームウェアバージョン情報は以下の通りです。
| オフセット | 名称 | サイズ | 今回のパケットにおけるデータ |
| 0 | 全体ファームウェアバージョン | 4 | 00 00 01 01 |
| 4 | MCU ファームウェアバージョン | 2 | 01 01 |
| 6 | SAM ファームウェアバージョン | 2 | ff ff |
| 8 | RFFE ファームウェアバージョン | 2 | 04 01 |
| 10 | RFFE EEPROM バージョン | 2 | ff ff |
| 12 | ブートローダバージョン | 2 | 01 00 |
| 14 | ファームウェア更新状態 | 2 | ff ff |
| 16 | 起動状態 | 2 | 00 00 |
パケット要点まとめ
ここまで、送受信パケットの各データの詳細を見てきました。
最小で 20 バイト程度と比較的短いパケットですが、複数形式のコマンドが内包されているため、慣れていないと少し読みづらいかもしれません。
おわりに
今回は RC-S660/S で規定されている通信パケット構造と照合しながら、実際の通信パケットを解析しました。最小で 20 バイト程度と比較的短いパケットですが、複数形式のコマンドが内包されており、慣れていないと少し読みづらいかもしれません。
本シリーズではNFC体験ということで、以降の記事では、核となるAPDUコマンド・レスポンスに重点を置いて解説していくものとします。
より詳細にデータを読み解きたい場合は、本記事を振り返って参照ください。
次回はNFCカード読み書きについて実装していきます。

