HCIプロトコルによる接続

  2つのbluetooth機器をHCIレーヤで接続する場合、すべきことを説明します。例として、PICーPIC間の接続を取り上げますHCIレイヤー(PIC-PIC間接続)。マスターとスレーブという言葉がでてきます。マスターもスレーブも、ここで取り上げる例では、ハードウェア的には、どちらもPIC24FJ64GB002とbluetooth USBドングルで構成されたものですが、マスターはスレーブに接続要求をだす(Pagingする)と言えば、区別は明らかになるでしょう。 以下、HCI命令パケットとそれに対する応答であるイベント・パケットに関する詳しい説明は、bluetoothのマニュアル Core v2.1 + EDR.pdf (以下、単にマニュアルと言う)のVolume2のPartE(HOST CONTROLLER INTERFACE FUNCTIONAL SPECIFICATION)を参照願います。HCI命令パケットに関しては、オペコード・グループが例えば0x01だとすると、7.1節に記述されています(0x02だとすると、7.2節にという具合です)。またイベント・パケットに関しては7.7節に記述されています。


ドングルの初期化

マスターもスレーブもそれぞれの持つドングルを初期化しなければなりません。マスターにおける初期化もスレーブにおけるものと同じですので、一括して説明します。ドングル・ホストはドングルにHCI命令パケットをだして、その応答であるHCIイベント・パケットを受け取るという動作を繰り返します。 ドングルの初期化には以下の5つのHCI命令パケットを使用します。なお、命令の出し方はファームウェアを、応答は得られるログファイルを、それぞれ参照ください。以下、断らないときは16進数表記とします。なお、ここでは、ドングルからドングル・ホストへは、あまり重要でないHCIイベント・パケットも返ってきますが、それについてはファームウェア上で無視する(読み飛ばす)ようにしていますので、ここでも説明はしません。

①  ドングルのリセット
命令  03  0c  00
03  0c:オペコード命令が03でオペコード・グループが03(0cを4で割る)で、Reset Command
00:以下に続くデータの数が0バイト

応答  0E 04 01 03 0C 00
0E:Command Complete Event
04:以下に続くデータの数が4バイト
01:これ以降にドングル・ホストからドングルへ送って良いHCI命令の数
03 0C:HCI命令03 0Cに対する応答であることを示している。
00:Reset CommandのReturn Parametersを見るとStatusを表していることが分かる。00は成功とい意味

②  ドングルのアドレス(BD_ADDR)取得
命令  09  10  0
09  10:オペコード命令が09でオペコード・グループが04で、Read BD_ADDR Command
00:以下に続くデータの数が0バイト

応答  0E 0A 01 09 10 00 22 0B 04 DC 1B 00
0E:Command Complete Event
0A:以下に続くデータの数が0x0Aバイト
01:これ以降にドングル・ホストからドングルへ送って良いHCI命令の数
09 10:HCI命令09 10に対する応答であることを示している。
00:Read BD_ADDR CommandのReturn Parametersを見るとStatusを表していることが分かる。00は成功とい意味
22 0B 04 DC 1B 00:Read BD_ADDR CommandのReturn Parametersを見るとBD_ADDR(Bluetooth Device Address)を表していることが分かる。BD_ADDRとはドングルに一意的に付けられた6バイト長の番号である。

③  機器の名前をつける
命令  13  0c  04  'y'  't'  's'  00
13  0c:オペコード命令が13でオペコード・グループが03で、Write Local Name Command
04:以下に続くデータの数が4バイト
'y'  't'  's'  00:ここではytsという名前にしているが適当な名前でよい。248文字以下であるが、248文字に満たない場合は、この例のように、最後に0x00をつける。PCと接続したとき、アイコンの名前として現れる。

応答  0E 04 01 13 0C 00
0E:Command Complete Event
04:以下に続くデータの数が4バイト
01:これ以降にドングル・ホストからドングルへ送って良いHCI命令の数
13 0C:HCI命令13 0Cに対する応答であることを示している。
00:Write Local Name CommandのReturn Parametersを見るとStatusを表していることが分かる。00は成功とい意味

④  機器が属するデバイス・クラスを指定する
命令  24  0c  03  04  05  00;
24  0c:オペコード命令が24でオペコード・グループが03で、Write Class of Device Command
03:以下に続くデータの数が3バイト
04  05  00:デバイス・クラス(Class_of_Device)。PCと接続したとき、このクラスに対応するアイコンが現れる。ここでは、Major Device Class(主デバイス・クラス)をPeripheral Class(マウス、ジョイスティック、キーボード等)とし、Minor Device Class(副デバイス・クラス)をジョイスティックとしています。詳しくは、The General- and Device-Specific Inquiry Access Codes (DIACs)Assigned Numbers - Bluetooth Basebandを参照して、どのデバイス・クラスにするか適当に決めて下さい。「間違って設定しても、アイコンに期待しないものが現れるだけですから気軽に決めてください。」と書いていましたが、場合に依ってはパスキーが強制的に求められたりする場合がありますので、適切に選ぶ必要があることが分かりました。デバイス・クラスの1部を書き出したのがCoD.txtです。

応答  0E 04 01 24 0C 00
0E:Command Complete Event
04:以下に続くデータの数が4バイト
01:これ以降にドングル・ホストからドングルへ送って良いHCI命令の数
24 0C:HCI命令24 0Cに対する応答であることを示している。
00:Write Class of Device CommandのReturn Parametersを見るとStatusを表していることが分かる。00は成功とい意味

⑤  スキャンを始める
命令  1a  0c  01  03
1a  0c:オペコード命令が1aでオペコード・グループが03で、Write Scan Enable Command
01:以下に続くデータの数が1バイト
03:Inquiry ScanもPage Scanも可能にする(0x03)。Inquiry Scanを不可能として、他のbluetooth機器から見えないようにすることもできますし、Page Scanを不可能として接続できないようにすることもできます。詳しくはマニュアルを参照ください。

応答  0E 04 01 1A 0C 00
0E:Command Complete Event
04:以下に続くデータの数が4バイト
01:これ以降にドングル・ホストからドングルへ送って良いHCI命令の数
1A 0C:HCI命令1A 0Cに対する応答であることを示している。
00:Write Scan Enable CommandのReturn Parametersを見るとStatusを表していることが分かる。00は成功とい意味

⑤における注釈:
Inquiryとは、マスターが自分の周りにどのようなスレーブがあるかを、照会(Inquirey)すなわち調査することです。照会するだけで接続はしませんが、スレーブ(のドングル)のBD_ADDRなどの情報を吸い上げます。

Pagingとは、マスターがInquiryでその存在を認識したスレーブのうち、特定のスレーブと接続することです。スレーブを特定するためにInquiry時に得たスレーブのBD_ADDRや以下に記述するスレーブのClock_Offsetなどの情報が利用されます。ここで、接続というのは、マスターとスレーブで、同じパターンで周波数ポッピング(通常1秒間に6000回の割合で、1MHZだけ互いに離れた周波数を飛び飛びに変えて行く)を行っている状態にすることで、結果としてHCI ACLデータ・パケットを送受信できるような状態にすることです。ところで、スレーブと接続する過程をページングというのは、スレーブのBD_ADDRをページ数になぞらえ、そのページを開けることに例えたのだと想像しています。

Scan(スキャン)を可能(enable)にするとは、スレーブ側の問題で、マスターからの照会(Inquirey)やページング(paging)に応答できるようにすることです。もう少し詳しく説明すると、スレーブは、自分の周波数を、ある決まった時間間隔(普通1.28から2.56秒)でポッピングします。これを周波数スキャンといい、スキャン中に、たまたまマスターの周波数に一致したときだけ通信が可能となります。通信可能(Inquirの時:一瞬通信可能となる)と接続可能(Pageの時:常時通信可能となる;マスターもスレーブも同じパターンで周波数ポッピングする)とは意味が違いますので、混同しないように願います。


接続過程

以下の図のような①から⑧までの過程となります。なお、⑦の過程の結果として、⑤と⑧の過程が実行されることなります。つまり、接続許可を出すと、接続完了が両方のドングル・ホストへ届きます。

ホストから見た接続過程

①  照会  (Inquiry)
        01  04  05  33  8b  9e  05  01
01  04:オペコード命令が01でオペコード・グループが01で、Inquiry Command
05:以下に続くデータの数が5バイト
33  8b  9e:LAP(Lower Address Part);Inquiryに対して応答するスレーブを制限するかどうかを指定します。制限しない場合、0x9E8B33 General/Unlimited Inquiry Access Code (GIAC)を使用します。制限する場合は、0x9E8B00 Limited Dedicated Inquiry Access Code (LIAC)を使用します。ここでは、前者を使用しています。LAPについては、Assigned Numbers - Bluetooth Basebandを参照ください。
05:Inquiryを05、すなわち(5 * 1.28 秒)の間だけ行う
01:探すスレーブの数

②照会結果
        02 0F 01 40 E4 03 DC 1B 00 01 02 00 04 05 00 C0 6D
02:Inquiry Result Event
0F:以下に続くデータの数が0x0Fバイト
01:探したスレーブの数
40 E4 03 DC 1B 00:スレーブ(のドングル)のBD_ADDR(Bluetooth Device Address
01:Page_Scan_Repetition_Mode;スレーブ側で決めているモードで、R0, R1, R2の3つのモードが設定されています。R0の場合は0x00、R1の場合は0x01、 R2の場合は0x02なる値になっています。前に書きましたが、スレーブは、自分の周波数を、ある決まった繰り返し時間(普通1.28から2.56秒)でポッピングします。その繰り返し時間の間、いつでもスレーブはマスターの電波を受信することができる訳ではなく、繰り返し時間の始まりからある時間間隔(通常11.25ミリ秒)だけしか受信できません。これらの”繰り返し時間”と”電波を受信できる時間間隔”をある程度指定できます。具体的には、R0(繰り返し時間は1.28 秒以下、実際に受信できる時間は繰り返し時間に等しく、1.28 秒以下),R1(繰り返し時間は1.28秒以下、実際に受信できる時間は通常11.25ミリ秒),R2(繰り返し時間は2.56秒以下、実際に受信できる時間は通常11.25ミリ秒)で指定します。結果として、接続が完了するまでの時間は、 R0で約 200 ミリ秒、R1で約 2.2秒、R2で約 3.5秒となります。R0が速く接続可能となるので良さそうに思えますが、スレーブが受信状態である間電力を消費しますので、消費電力は他のモードに比べて著しく増加しますので、あまり使用されません。
02 00:使用していないので意味はない
04 05 00:スレーブのClass_of_Device
C0 6D:スレーブのClock_Offset。マスターとスレーブは、それぞれ自分のクロック・カウンター(28ビットのカウンターで312.5 マイクロ秒ごとに1つずつ増加して行き、約1日でもとの値に戻ります)を持っています。ただ、これらカウンターの値は、互いに異なりますので、マスターとスレーブ間で、ホッピングのタイミングなどをあわせるためには、それらの値の違い(Clock_Offset)をスレーブは知っておく必要があります。スレーブは自分のクロック・カウンターの値に、Clock_Offsetを加算することにより、マスターのクロック・カウンターの値を得ます。これにより、マスターのクロック・カウンターを基準時計として、例えば、マスターもスレーブも同じタイミングでホッピング周波数を変えることができるようになります。

③照会完了
        01 01 00
01:Inquiry Complete Event
01:以下に続くデータの数が1バイト
00:Statusで、00はInquiryが成功したという意味

④  接続要求  (Paging)
        05  04  0D  40 E4 03 DC 1B 00  10  00  01  00  C0 6D  00
05  04:オペコード命令が05でオペコード・グループが01で、Create Connection Command
0D:以下に続くデータの数が0x0Dバイト
40 E4 03 DC 1B 00:Inquiry時に得たスレーブ(のドングル)のBD_ADDRを設定する。
10  00:Packet_Type、ここではDH1タイプを使う。DH1タイプを使うと最大データ転送速度が172.8kbpsとなります。他のタイプを使用する時にはマニュアルを参照ください。
01:Inquiry時に得たスレーブのPage_Scan_Repetition_Modeを設定する。
00:00で固定されている。
C0 6D:Inquiry時に得たスレーブのClock_Offsetを設定する。
00:Allow_Role_Switch。ここではマスターはマスターのままで、以後変えないことにしている。詳しくは、マニュアルを参照ください。

⑤  接続完了
        03 0B 00 2A 00 40 E4 03 DC 1B 00 01 00
03:Connection Complete Eventを表します。
0B:この数値以下に続くパラメタのバイト数です。
00: ステータスで、00は正常に接続ができたことを示しています。
2A 00: Connection Handle(接続ハンドル)が0x02Aという意味
40 E4 03 DC 1B 00:スレーブ(のドングル)のBD_ADDR
01:リンクの型で、01はACL
00:リンクレベルでの暗号化に関する情報だと思いますが、理解していません。00は、暗号化していないという意味です。


スレーブから見た接続過程

Inquireに対する応答はドングル自身が自動的に行うので、PICは何もしなくて良いのです。ただ、次に記述する接続要求を待つことになります。

⑥  接続要求の受信
        04 0A 22 0B 04 DC 1B 00 04 05 00 01
04:Connection Request Event
0A:以下に続くデータの数が10バイト
22 0B 04 DC 1B 00:マスター(のドングル)のBD_ADDR
04 05 00:マスターのデバイス・クラス
01:リンクの型で、01はACL

⑦  接続許可
        09  04  07  22 0B 04 DC 1B 00  01
09  04:オペコード命令が09でオペコード・グループが01で、Accept Connection Request Command
07:以下に続くデータの数が7バイト
22 0B 04 DC 1B 00:マスター(のドングル)のBD_ADDRを設定する。
01:スレーブのままでいる。マスターにするためには00とする。

⑧  接続完了
        03 0B 00 2A 00 22 0B 04 DC 1B 00 01 00
03:Connection Complete Event
0B:以下に続くデータの数が0x0Bバイト
00:ステータスで、00は正常に接続ができたことを示しています。
2A 00:Connection Handle(接続ハンドル)が0x02Aという意味
22 0B 04 DC 1B 00:マスター(のドングル)のBD_ADDR
01:リンクの型で、01はACL
00:リンクレベルでの暗号化に関する情報だと思いますが、理解していません。00は、暗号化していないという意味です。


以上でHCI  ACLデータパケットがマスター・スレーブ間で両方向送受信可能となります。


戻る