L2CAP(プロトコル)によるチャンネルの確保

L2CAPはLogical Link Control and Adaptation Protocolの略で、HCIプロトコルの上位プロトコルです。これには幾つかの働きがあるのですが、そのうち1つだけを説明します。それは、マスターとスレーブ間にデータを送る論理的なチャンネル(通信路)を確保することです。

L2CAP データ・パケットの構造

HCI ACL データ・パケットは、
      (Connection Handle+PB Flag+BC Flag)、ACLデータ長、ACLデータ列
の形式を持つことは、HCIプロトコルの章で書きました。 L2CAP データ・パケットは、HCI ACL データ・パケットなのですが、その中のACLデータ列がさらに構造化されており、

i)  最初に送信するパケット(PB Flag=10)の場合
        ACLデータ列=L2CAP全データ長、チャンネルID、L2CAPデータ列
ii)  分割された2番以降のパケット(PB Flag=01)の場合  *1
        ACLデータ列=L2CAPデータ列

なる構造を持っています。この章では、分割されていない場合しか例として出てきませんが、SDP(プロトコル)の章には、分割されている場合の例が出てきます。

*1)パケットが長い場合、パケットを分割します。

①  L2CAP全データ長(2バイト幅)
L2CAPデータ列の全長をバイト長で与えます。次のチャンネルIDの2バイトは含まれません(L2CAPデータではない)。パケットが分割されていない場合、そのパケットに含まれる(全)L2CAPデータの長さです。注意すべきなのは、パケットが分割されている場合です。この場合、それぞれの分割パケットに含まれているL2CAPデータをすべて統合して考えたときの全L2CAPデータ長であり、1パケットに含まれるL2CAPデータの長さではありません。

②  チャンネルID(CID:2バイト幅)
チャンネル番号です。Signaling channel(制御用チャンネル)の番号は0x0001と決まっており、データ・チャンネルの番号には0x0040以上の値を使います(データの送受信用チャンネル)。

③  L2CAPデータ列(バイト幅は変化する)
送受信するデータの長さによって変わります。

○  L2CAP データ・パケットの例
例えば、16進数列で
      2A 20 09 00 05 00 40 00 10 02 03 04 05
なるパケットを見てみます。

2A 20:(Connection Handle+PB Flag+BC Flag)接続ハンドルが0x02Aで、PB Flagが10、BC Flagが00
09 00:この数値以下に続くACLデータの長さを表すバイト数です。今の場合9バイトです。
05 00: L2CAPデータの長さを表すバイト数で、今の場合5バイトです。次のチャンネルIDの2バイトはデータ長には入りません。
40 00: チャンネルIDで、0x0040の値を持っていることから、以下のデータは普通のデータであることが分かります。
01 02 03 04 05:L2CAPデータ列で、01 02 03 04 05なる5バイトのデータ列を送信もしくは受信しています。


L2CAP データ・パケットによるチャンネル(通信路)の確保

bluetooth-HIDの応用として、wiiリモコン(スレーブ)とPIC基板(ホスト)を接続する例:bluetooth-HIDの応用例(wiiリモコン)をあげました。この時のログファイルwii2.txtを用いて、チャンネルの確保の仕方を説明します。1つのチャンネルを確保するために、マスター・スレーブ間で行うべき作業を以下の図にしてみました。6つのL2CAPデータ・パケット(①から⑥まで)がやり取りされます。

①から⑥まででやり取りされるL2CAPデータ・パケットの内容は、ログファイルを見ると分かるのですが、次の通りです。だたし、ここではHCIイベントはすべて無視します(だた、実際のファームウェアでは、これを読みとらないと、読みとったデータを貯めておくメモリすなわちバッファが満杯になりエラーとなりますので注意してください。単に読めば事足ります。)。

①  2A 20 0C 00 08 00 01 00 02 01 04 00 11 00 44 00
②  2A 20 10 00 0C 00 01 00 03 01 08 00 40 00 44 00 00 00 00 00
③  2A 20 10 00 0C 00 01 00 04 02 08 00 40 00 00 00 01 02 40 00
④  2A 20 12 00 0E 00 01 00 05 02 0A 00 44 00 00 00 00 00 01 02 40 00
⑤  2A 20 10 00 0C 00 01 00 04 02 08 00 44 00 00 00 01 02 B9 00
⑥  2A 20 12 00 0E 00 01 00 05 02 0A 00 40 00 00 00 00 00 01 02 B9 00

以下1つずつ説明して行きます。詳しくは、マニュアルCore v2.1 + EDR.pdf のVol3のPart A: Logical Link Control and Adaptation Protocol Specificationを参照下さい。

①  L2CAP接続要求(ホストPICがスレーブwiiへ要求)
        2A 20 0C 00 08 00 01 00 02 01 04 00 11 00 44 00
2A 20:(Connection Handle+PB Flag+BC Flag)
0C 00:ACLデータの長さを表すバイト数
08 00: L2CAPデータの長さを表すバイト数
01 00:チャンネルIDが0x0001であるので、以下のデータは単なるデータではなく制御用のデータであることを意味します。
02:コード02はCONNECTION REQUEST(接続要求)を意味します。マニュアルを参照願います。
01:Identifier:要求を出す方が決める数値です。いくつかの要求を送信する場合には、この値を1づつ増加させて行くことになります。応答する方は、必ず要求の場合と同じ数値を使います。つぎの②をみると、ここと同じ数値が使われているのが分かると思います。
04 00:以下のデータの長さを表すバイト数
11 00:PSM(Protocol/Service Multiplexer)で、Protocolに関しては、SDP 0x0001、RFCOMM 0x0003、HID_Control 0x0011、HID_Interrupt 0x0013等です。ここでは、HID_Controlに対するチャンネルを作ろうとしています。PSMに間しては、Protocol and Service Multiplexor (PSM)を参照ください。なお、 Multiplexerの方は理解していません。
44 00:Source CID  L2CAP接続要求を出す方をソース(要求元)と言い、また要求を受ける方をディスティネーション(要求の行き先)と言います。ソースのチャンネル番号(Source CID)、すなわちPICのチャンネル番号を適当に与えてください。ただし、0x0040以上の数値です。ここでは、0x0044番としています。

②  L2CAP接続応答(スレーブwiiがホストPICに応答する)
        2A 20 10 00 0C 00 01 00 03 01 08 00 40 00 44 00 00 00 00 00
2A 20:(Connection Handle+PB Flag+BC Flag)
10 00:ACLデータの長さを表すバイト数
0C 00: L2CAPデータの長さを表すバイト数
01 00:命令チャンネル
03:コード03はCONNECTION RESPONSE(接続応答)
01:Identifier:①への応答であることが分かる。
08 00:以下のデータの長さを表すバイト数
40 00:Destination CID  L2CAP接続要求を受ける方、すなわちwiiのチャンネル番号です。wiiがこの値をPIC側に返して来ます。
44 00:Source CID  ①で決めた値が返って来ます。Destination CIDとSource CIDと違っていますが、同じであってもかまいません。これで、ホスト側の0X044番チャンネルとスレーブ側の0X040番チャンネルが論理的に繋がりました。
00 00:結果  0x0000は接続成功を意味します。この値が返ってくるまで、スレーブ(wii)からの応答を受け続けます。
00 00:ステータス。ここは無視してかまいません。詳しくはマニュアルを参照してください。

これから設定に入りますが、相手方に自分がどれだけのバイト数を受け付けられるかを互いに知らせないといけません。まず、ホストからL2CAP設定要求を出して、スレーブがL2CAP設定応答をホストに返します。

③  L2CAP設定要求(ホストPICがスレーブwiiへ要求)
        2A 20 10 00 0C 00 01 00 04 02 08 00 40 00 00 00 01 02 40 00
2A 20:(Connection Handle+PB Flag+BC Flag)
10 00:ACLデータの長さを表すバイト数
0C 00: L2CAPデータの長さを表すバイト数
01 00:命令チャンネル
04:コード04はCONFIGURATION REQUEST(設定要求)
02:Identifier:①とは別の要求ですから00とは異なる数値を与えます。任意の数値でかまいません。ここでは02
08 00:以下のデータの長さを表すバイト数
40 00:Destination CIDですからwiiのチャンネル番号を与えます。
00 00:フラグで、Flags  最後の1ビットだけが意味を持ちます。以下の設定オプションがすべてこのパケットに収まる場合、0x0000とします。収まらない場合は、0x0001とします。
01 02 40 00:設定オプションで、最初の2バイトは、タイプが01で、バイト長が02バイト(40と00の2バイト)であるという意味です。この場合、1度にL2CAPデータを0x0040バイトまで、この要求をした方(PIC)が受信できることを、相手方(wii)に伝えています。

④  L2CAP設定応答(スレーブwiiがホストPICに応答する)
        2A 20 12 00 0E 00 01 00 05 02 0A 00 44 00 00 00 00 00 01 02 40 00
2A 20:(Connection Handle+PB Flag+BC Flag)
12 00:ACLデータの長さを表すバイト数
0E 00: L2CAPデータの長さを表すバイト数
01 00:命令チャンネル
05:コード05はCONFIGURATION RESPONSE(設定応答)
02:Identifier:③に対する応答02のままです。
0A 00:以下のデータの長さを表すバイト数
44 00:Source CIDですからPICのチャンネル番号。
00 00:フラグで、最後の1ビットだけが意味を持つ。これが、0x0000でなく0x0001に場合、L2CAP設定応答が1つのデータ・パケットに収まらなく、さらにデータ・パケットが続くという意味
00 00:結果で、0x0000は成功を、0x0001は失敗を意味する。
01 02 40 00:成功した場合、③で与えた設定オプションがそのまま返ってくる。失敗した場合は拒否パラメタ(失敗したことがないので、どんなものなのかは分かりません)が返ってくる。

次に、逆にスレーブ(wii)からL2CAP設定要求を出して、ホスト(PIC)がL2CAP設定応答をスレーブに返します。スレーブから④の応答がホストへ返って来た後、すぐに、スレーブから次の要求がホストへ届きます。

⑤  L2CAP設定要求(スレーブwiiがホストPICに要求)
        2A 20 10 00 0C 00 01 00 04 02 08 00 44 00 00 00 01 02 B9 00
2A 20:(Connection Handle+PB Flag+BC Flag)
10 00:ACLデータの長さを表すバイト数
0C 00: L2CAPデータの長さを表すバイト数
01 00:命令チャンネル
04:コード04はCONFIGURATION REQUEST(設定要求)
02:Identifier:Identifire: スレーブにより設定されます。
08 00:以下のデータの長さを表すバイト数
44 00:Destination CIDですから、要求の受け取り側、すなわちPICになります。③の場合と比較してください。同じDestination CIDといっても、どちらが要求を出すかに依ってDestination CIDは変わりますので注意が必要です。
00 00:フラグ  ③を参照のこと。
01 02 B9 00:設定オプションで、この要求をした方(wii)が1度にL2CAPデータを0x00B9バイト受信できることを相手方(PIC)に伝えます。③も参照のこと。

⑥  L2CAP設定応答(ホストPICがスレーブwiiに応答する)
        2A 20 12 00 0E 00 01 00 05 02 0A 00 40 00 00 00 00 00 01 02 B9 00
2A 20:(Connection Handle+PB Flag+BC Flag)
12 00:ACLデータの長さを表すバイト数
0E 00: L2CAPデータの長さを表すバイト数
01 00:命令チャンネル
05:コード05はCONFIGURATION RESPONSE(設定応答)
02:Identifier:⑤に対する応答と同じ数値0x02のままにする。
0A 00:以下のデータの長さを表すバイト数
40 00:Source CID  要求を出した方はwiiですから、この値になります。これも、③と比較すると分かるのですが、同じSource CIDといっても、どちらが要求を出すかに依ってSource CIDは変わりますので注意が必要です。
00 00:フラグで、最後の1ビットだけが意味を持つ。
00 00:結果で、0x0000は成功を意味する。
01 02 B9 00:成功した場合、⑤で与えた設定オプションと同じものを返すべきです。

HIDサービスの場合、コントロール用のチャンネルとインターラプト(データ送受信)用のチャンネルの2つが必要となります(普通のUSB通信と似てます;例えば、前者がエンドポイント0で後者がエンドポイント1と考えれば良いでしょう)。上の例ではコントロール用のチャンネル(HID_Control PSM=0x0011)を確保しましたが、さらにインターラプト用のチャンネル(HID_Interrupt PSM=0x0013)を確保する必要があります。実際のL2CAPデータ・パケットは以下の様になります。もう、容易に理解できると思います。

①  2A 20 0C 00 08 00 01 00 02 03 04 00 13 00 45 00
②  2A 20 10 00 0C 00 01 00 03 03 08 00 41 00 45 00 00 00 00 00
③  2A 20 10 00 0C 00 01 00 04 04 08 00 41 00 00 00 01 02 40 00
④  2A 20 12 00 0E 00 01 00 05 04 0A 00 45 00 00 00 00 00 01 02 40 00
⑤  2A 20 10 00 0C 00 01 00 04 03 08 00 45 00 00 00 01 02 B9 00
⑥  2A 20 12 00 0E 00 01 00 05 03 0A 00 41 00 00 00 00 00 01 02 B9 00

確保した2つのチャンネルを図示すると、以下の図のようになります。



さて、L2CAPの話というより、bluettoth HIDプロファイルの話に踏み込むことになりますが、ログファイルwii2.txtを用いて、チャンネルを確保した後の動作について見てみましょう。ログファイルの”HID_READ_FIRST_DATA”以下のL2CAPデータ・パケットだけを書き出すと

①  2A 20 08 00 04 00 45 00 A1 30 00 00
②  2A 20 07 00 03 00 41 00 A2 11 40
③  2A 20 08 00 04 00 45 00 A1 30 00 02
④  2A 20 08 00 04 00 45 00 A1 30 00 00

これらを読み解くためには、wiiリモコンのデータ (以後wiiマニュアルと呼びます)とHUMAN INTERFACE DEVICE (HID) PROFILE(以後b_HIDマニュアルと呼びます)の7.3節以降の説明が必要となります。

①  wiiリモコンからPICへ、wiiリモコンのボタンを離したという情報が送られてきます。これは、PICとwiiリモコンを接続するときに1というボタンと2というボタンを押して、接続が終わったときに、両ボタンとも離したことによります。そのまま、ボタン1とボタン2を押したままですと、別なデータ(データの最後が03)が送られてきます。まず、PICはこのデータバケットを読まなければいけません。
        2A 20 08 00 04 00 45 00 A1 30 00 00
2A 20:(Connection Handle+PB Flag+BC Flag)
08 00:ACLデータ長
04 00: L2CAPデーの長
45 00:送信先のデータチャンネル。PICのInterruptチャンネル(データ・チャンネル)へデータを送信したという意味。
A1:b_HIDマニュアルの7.4.9節 DATAに書いてありますが、入力データを意味します。
30:wiiマニュアルによれば、0x30はボタンの情報を送るHIDで言うところのreport ID番号です。
00 00:ボタンが離されたという意味です。現在はどのボタンも押されていない状態にいます。

②  PICからwiiリモコンへ、wiiリモコンの3番目のLED(発光ダイオード)点灯せよという命令を送っています。
        2A 20 07 00 03 00 41 00 A2 11 40
2A 20:(Connection Handle+PB Flag+BC Flag)
07 00:ACLデータ長
03 00: L2CAPデーの長
41 00:送信先のデータチャンネル。wiiリモコンのInterruptチャンネル(データ・チャンネル)へデータを送信するという意味。
A2:b_HIDマニュアルの7.4.9節 DATAに書いてありますが、出力データを意味します。
11:wiiマニュアルによれば、0x11はLEDの情報を受けるHIDで言うところのreport ID番号です。
40:0x40は、2進数で書くと0100で三番目(のLED)という意味です。2番目のLEDを点灯したければ0x20(0010)とすれば良いわけです。

③はボタン1が押されたという意味で、④はボタンが離されたという意味です。

戻る