Bluetooth Low Energy リンクレイヤの解説
ここまでで、クラシックBTと比較したBLEの違いと特徴、そしてBLEの物理層を述べました。 ここでは、規格書をなぞる解説ではなく、iOSのアプリ開発とiOSと連携するBLEデバイス開発に役立てるための知識を提供する視点で、BLEのリンクレイヤを解説します。
リンクレイヤは、あるデバイスとあるデバイス間で、どうやって無線通信をするかを決めます。 リンクレイヤが定義するのは、パケット、アドバタイジングそしてデータチャネルです。 これらを使って、リンクレイヤは:
- 他のデバイスの発見、
- データのブロードキャスト、
- 接続の確立と維持、
- 接続を通したデータ通信、
を提供します。
BLEのトポロジー
BLEのネットワークは、1つのマスターに複数のスレーブが接続する、スター型のネットワークです。 1つのリンクレイヤが、同時にマスターかつスレーブになることはできません。
BLEのネットワークは、クラシックBluetoothのピコネットとは、違います。 クラシックBluetoothのピコネットは、 同期したクロック同じ周波数ホッピングの順番で、 同じ物理チャネルで通信するデバイス群です。1つのピコネットの複数あるスレーブは、1つだけあるマスターにクロックを同期して通信をします。 あるデバイスは複数のピコネットに同時に参加出来ます。 (Blluetooth specification Version 4.0 [Vol 1] 4.1.2 LE Topology)
LEのトポロジーを示します。デバイスAは、 デバイスBおよびCと接続しています。このときデバイスAは、master role(以下、マスター)、デバイスBとCがslave role(以下、スレーブ)を果たしています。 デバイスBとCは、全く何も同期しておらず、ただデバイスAとそれぞれが接続して通信をします。
BLEには、接続していなくても、アドバタイジングを使って情報をやり取りする仕組みがあります。 アドバタイジング・チャネルにアドバタイジング・パケットを創出するものをadvertiser、 アドバタイジング・チャネルをモニタして、アドバタイジング・パケットを受信するものをscannerといいます。 上図のデバイスDおよびEのように、すでに接続しているデバイスAおよびCは、マスター/スレーブどちらになっているかにかかわらず、 advertiserにもscannerにもなれます。またデバイスH, I, Jのように、アドバタイズメント・パケットだけで構築するネットワークもあります。
接続時、マスターが、スレーブとの接続と通信タイミングを制御します。 より多くのメモリと電池を必要とする機能をマスターに寄せて、スレーブに求めるメモリと電池の要求量を小さくする、非対称に役割をふることで、 スレーブの消費電力と製造コストがより小さくなります。
BLEのトポロジーでは、リンクレイヤが同時にマスターかつスレーブにはなれません。 クラシックBluetoothでは、同時にマスターかつスレーブとなりピコネット間をつなぐものをscatterと呼びます。BLEにscatterをサポートしません。
しかし、マスターからスレーブに役割を切り替えることができます。 Bluetooth Low Energyの半導体で、内蔵マイコンがリンクレイヤを制御しているものは、ファームウェアでスレーブかつマスターどちれにもなれるものがあります。
リンクレイヤのステート・マシーン
BLEのトポロジーを、振る舞いだけでみていると複雑なので、その振る舞いのもとになっているリンクレイヤのステート・マシーンという基本概念を説明します。 ステート・マシーンは、状態とその遷移でふるまいを表すモデルです。

リンクレイヤは5つの状態があります。
- Standby
- 初期状態です。電波の送受信をしません。
- Advertising
- アドバタイズメント・チャネルでの、アドバタイズメント・パケットの送受信をします。
- Scanning
- スキャニングは、アドバタイジング・チャネルの電波を受信します。
- スキャンには、パッシブスキャンとアクティブスキャンの2つがあります。
- パッシブスキャンは、アドバタイジング・パケットを受信するだけです。
- アクティブスキャンは、デバイスにSCAN_REQを送信して、アドバタイジング・パケットに収まりきらなかった情報をさらに取得します。
- Initiating
- 特定のデバイスからのアドバタイズメント・パケットの受信と、そのパケットへの応答をします。
- Connection
- 接続した状態です。
コネクション状態では、
- Master role
- Slave role
の2つの役割があります。Initiating stateからConnecting stateに遷移したものがMaster role、 Advertising stateからConnection stateに遷移したものがSlave roleです。
接続するまでのステート間の遷移は、 マスターは standby -> Initiating -> Connection、 スレーブは Standby -> Advertising -> Connection、 となります。
ここまでの説明だけなら、1つのリンクレイヤをステートマシーンで制御するだけだと理解しやすいのですが、BLEは複数のステートマシーンが持てます。 それぞれのステートマシーンがそれぞれ動作することで、例えば、あるステートマシーンがConnectionしているときに、別のステートマシンでAdvertisingをすることができます。
ですが、いくつかのステートマシーンの状態の組み合わせは禁止されています。 これは、同時にマスターかつスレーブにならないための、ルールです。接続状態にならなければよいので、すでにスレーブとして接続状態にあっても、接続状態にならないアドバタイズメント・パケットは送信できます。
その組み合わせずとその説明は以下のものです:

- Connectionステートにあるとき、同時にMaster roleとSlave roleにすべきではない。
- Slave roleでConnectionステートにあるリンクレイヤは、1つのコネクションだけをもつべきである。
- Master roleでConnectionステートにあるリンクレイヤは、複数のコネクションを持ってもよい。
- すでにリンクレイヤがSlave roleでConnectionステートにあるなら、リンクレイヤはInitiatingステートで動作すべきではない。
- リンクレイヤがConnectionステートもしくはInitiatingステートで動作しているなら、リンクレイヤはSlave roleで接続状態に入ることになるアドバタイズメントをするAdvertisingステートで動作すべきではない。
パケット
リンクレイヤのパケットフォーマットを示します:

最も短いパケットで80ビット(送信時間 80マイクロ秒)、最も長いもので376ビット(送信時間 367マイクロ秒)です。
ビットオーダー
BLEのリンクレイヤのパケットおよびパケットのフィールドProtocol Data Unit(PDU)のフィールドは、リトルエンディアンです。
- 表記b0は、最下位ビット(Least Significant Bit,LSB)を表します。
- 最下位ビットから送信されます。
0x3(011b)を送信するときは、110bと送信されます(1が最初、0が最後)。
また8ビットを1オクテットとします。CRCとMICを除き、それぞれのフィールドは最下位オクテットから送信されます。 0x1234(2進数0001_0010_0011_0100)を送信するときは、0010_1100_0100_1000b、と送信されます。
プリアンブル
プリアンブルは、0x55(01010101b)もしくは0xAA(10101010b)の0/1が繰り返すパターンで、信号のゲイン調整やデータを復調するための同期に使われます。 0x55と0xAAのどちらを使うかは、続くデバイス・アドレスと並べた時に'1’や'0’が連続しないほうを、選びます。
デバイス・アドレス
32ビットのパケットアドレス:
- アドバタイジング・アクセス・アドレス
- データ・アクセス・アドレス
アクセスアドレスは、個々のデバイスが通信時に使うランダムなアドレス値です。アドバタイズメント・パケットでは、固定値0x8E89BED6が使われます。
10001110100010011011111011010110b (0x8E89BED6)
アドバタイズメント。先頭アドレス固定。4んービットの一致検出。 3チャネル。20ミリ秒から1.んー秒。時間は長く。重なると悲惨、0~10ミリ秒ランダムにずらす。
アドバタイジング・チャネル PDUヘッダー

PDUタイプは、アドバタイズメント・チャネルPDUのタイプを指定します。 TxAddとRxAddは、PDUタイプごとに定義されるフィールドです。PDUタイプがこれを定義していないときは、将来使うための予約済フィールドとします。 Lengthはペイロードの長さをオクテットで表し、6から37までの値を取ります。
接続に係るPDUタプは次の4つです:
- ADV_IND
- 接続可能、ダイレクトではない
- ADV_NONCONN_IND
- 接続しない、ダイレクトではない
- ADV_SCAN_IND
- スキャン可能、直接ではない
- ADV_DIRECT_IND
- 接続可能、直接
このうち、ADV_DIRECT_IND は、AppleのBluetoothアクセサリ設計指針で使うべきではないと、書かれています。
アドバタイジング・データがパケットのペイロードに収まらないとき(31バイトより大きい時)、マスターはスレーブにスキャンを要求して、さらに情報を取得出来ます。そのためのPDUタイプがSCAN_REQ(スキャン・リクエスト)とSCAN_REP(スキャン・リクエストへのリプライ)です。また接続要求がCONNECT_REQです。
- SCAN_REQ
- SCAN_RSP
- CONNECT_REQ
アドバタイジング・データ
ADV_IND、ADV_SCAN_IND、ADV_NONCONN_INDのペイロードの構成は:
AdvAはアドバタイザーのアドレスを、AdvDataはアドバタイジング・データを表します。 TxAddの値は、アドレス値AdvAが、パブリック(TxAdd = 0)か、ランダム(TxAdd = 1)かを示します。
([Vol 6] 2.3.1)
アドバタイジング・データとスキャン・データのフォーマット
アドバタイジングとスキャン・データは、31オクテットを、いくつかのLength、Dataフィールドと、31バイトになるように0で埋めたものです。 このDataフィールドはAD TypeとAD dataで構成されます。AD Typeの実際の値は、https://www.bluetooth.org/Technical/AssignedNumbers/generic_access_profile.htm にあります。
31バイトのアドバタイジング・データでではアドバタイジングしたい情報が収まらない場合があります。その時に使うのがスキャンです。 アドバタイザは、受信したSCAN_REQに対して付加情報をSCAN_REPで返信します。このスキャンデータは、スタティック、であるべきです。 アドバタイジング・パケットは常に受信するものなので、そのデータが変化しても、マスターはそれをいちいち解釈するでしょう。しかしスキャンデータは、マスターが常に読み取ろうとするとは限りません。変化する情報を入れていた場合に、振る舞いが予測できなくなります。
iPhoneアクセサリでは、Bluetoothアクセサリに送信されたアドバタイジング・データは、 Bluetooth 4.0 仕様, Volume 3, Part C, Section 11 に記述されているように、 次の情報の少なくとも1つを含むべきです:
- Flags
- TX Power Level
- Local Name
- Services
アドバタイジング・データには次のタイプがあります:
- Local Name
- デバイス名です。完全もしくは短縮名です(section 3.2.2)。完全/短縮は、AD Typeで判別出来ます。
- もしも短縮名ならば、device name characteristicを読み出せば、完全なデバイス名が取れます。
- Flags
- フラグビットをbooleanで含みます。LE physical channelで使われるフラグは:
- Limited Discoverable mode
- General Discoverable mode
- VR/EDR Not Supported
- Simultaneous LE and BR/EDR to Same Device Capable (Controller)
- Simultaneous LE and BR/EDR to Same Device Capable (Host)
- TX Power Level
- 送信電力です。
- Service UUIDs
- サービスのUUID(16-bit, 128-bit)です。
- Manufacturer Specific Data
- Security Manager Out of Band
- Security Manager TK Value
- Slave Connection Interval Range
- Service Solicitation
- Service Data
LLコネクションパラメータ
ウィンドウサイズ、スレーブレイテンシ、スキャンインターバル、タイムアウト、をマスターからスレーブに設定する。 スキャンインターバルが決められているが、スレーブは、意図的に、データを送信しないでいい。タイムアウトするまでに、返答すれば接続は保たれる。
これは低レイテンシと低消費電力を両立するための工夫。例えばキーボードを考えれば、通信の遅延時間を20ミリ秒にしたいとする。 しかしキーボードが押されるイベントは、20ミリ秒よりもはるかに低い頻度でしか起こらない。 もしもスレーブが、20ミリ秒ごとに"データはない"という送信をすれば、その電波を出すために電力を消費する。
そこでインターバルがきても、データがないならば電波を出さないことで、低消費電力が得られる。 しかし20ミリ秒ごとにインターバルがあるので、送信すべきデータが来たならば直ちに次のインターバルでデータを送信できる。
データPDU
データPDUのフォーマット。暗号化するときはMICがはいる。 暗号化だけではなくて、CRCよりも強力なエラー検出が必要なときにも使える。

データの長さは、0~27。MICがあってもなくても、データ長はMICがある場合の最大値の27にしてある。 iOSでwrite~でデータを書き込むときに、最大27バイトで頭打ちになるのは、おそらくLL2CAPを通さずこのレイアを直接叩いているからかも。