BLE の接続シーケンスを Wireshark で確認してみる

 前回 BLE Sniffer と Wireshark で BLE パケットをスニッフィングする方法を書きましたが、 Wireshark で確認できる内容から BLE の接続シーケンスを確認してみたいと思います。手元にあった BLE デバイスで簡単に確認してみた結果を書いてみます。

ADV_IND

 BLE デバイスがアドバタイジングを開始するとアドバタイジング・パケットを送出し始めます。 PDU(プロトコル・データ・ユニット)のタイプとしては4タイプありますが、今回使用したデバイスでは ADV_IND となっていました。

f:id:akanuma-hiroaki:20180414135756p:plain

 ADV_IND を含め、アドバタイジング・パケットのタイプは下記の4タイプになります。

  • ADV_IND:不特定多数のデバイスから接続可能
  • ADV_NONCONN_IND:デバイスからの接続は不可能
  • ADV_SCAN_IND:デバイスからのスキャン可能
  • ADV_DIRECT_IND:特定デバイスから接続可能

SCAN_REQ

 セントラルデバイスがペリフェラルデバイスからアドバタイジング・パケットを受け取った時に、アドバタイジング・パケットのペイロードのデータだけでは情報が不足している場合、 スキャン・リクエスト(SCAN_REQ)パケットを送信します。

f:id:akanuma-hiroaki:20180414135829p:plain

SCAN_RSP

 ペリフェラルデバイスが SCAN_REQ パケットを受け取ると、その応答として SCAN_RSP パケットを送信します。

f:id:akanuma-hiroaki:20180414135845p:plain

CONNECT_REQ

 アドバタイジング・パケットの送受信が完了し、セントラルデバイスからペリフェラルデバイスに対して接続要求が行われると、 CONNECT_REQ パケットが送信され、接続状態に切り替わります。セントラルとペリフェラルはそれぞれマスター(Master)とスレイブ(Slave)になり、 Wireshark での Source と Definition のデバイス表示も、 MAC アドレス表示から Master, Slave に切り替わります。

f:id:akanuma-hiroaki:20180414135907p:plain

LL_VERSION_IND

 リンク層の接続制御に使われるロジカル・リンク・コントロール PDU では、オペコード(Opcode)でその種別が表されています。 LL_VERSION_IND はコントローラのバージョン番号を示すためのものです。

f:id:akanuma-hiroaki:20180414135940p:plain

Exchange MTU Request/Response

 Exchange MTU Request/Reponse はアトリビュート・プロトコルの最大長(MTU: Maximum Transfer Unit)を決定するために使われます。まずはクライアント側から自身が扱える ATT_MTU をサーバ側に通知します。そのレスポンスとしてサーバからはサーバ側で扱える ATT_MTU を返します。

f:id:akanuma-hiroaki:20180414140002p:plain

f:id:akanuma-hiroaki:20180414140113p:plain

Read Request/Response

 サーバのアトリビュートをクライアントから読み取るには Read Request/Response が使われます。 Read リクエストには下記の5種類があります。

  • Read
  • Read Multiple
  • Read Blob
  • Read By Type
  • Read By Group Type

 Read By Group Type ではアトリビュートのグループを読み出します。下記の例では GATT の Primary Service Declaration を読み取っています。

f:id:akanuma-hiroaki:20180414140933p:plain

f:id:akanuma-hiroaki:20180414141110p:plain

 Read By Type ではアトリビュート・タイプを指定した読み出しに使用します。下記は GATT の Characteristic Declaration の例です。

f:id:akanuma-hiroaki:20180414141256p:plain

f:id:akanuma-hiroaki:20180414141334p:plain

 アトリビュートが存在しない場合は下記のように Error Response が返ってくるようです。

f:id:akanuma-hiroaki:20180414142229p:plain

 Read ではアトリビュート・ハンドルを指定して値を読み出します。

f:id:akanuma-hiroaki:20180414143245p:plain

f:id:akanuma-hiroaki:20180414143330p:plain

 長さが ATT_MTU を超えるアトリビュート・バリューを持つアトリビュートはロング・アトリビュートと呼ばれ、その値を読み出す場合には Read Blob が使われます。

f:id:akanuma-hiroaki:20180414143734p:plain

f:id:akanuma-hiroaki:20180414220339p:plain

Find Information Request/Response

 アトリビュート・ハンドルの範囲を指定してアトリビュート・ハンドルとアトリビュート・タイプを読み出すには Find Information が使われます。アトリビュートのタイプとバリューが指定できる Find By Type Value リクエストもありますが、今回は使われていなかったようです。下記は Find Information の例です。

f:id:akanuma-hiroaki:20180414141457p:plain

f:id:akanuma-hiroaki:20180414141531p:plain

Write Request/Response

 アトリビュート・ハンドルを指定して書き込みを行うには Write が使用されます。

f:id:akanuma-hiroaki:20180414141757p:plain

f:id:akanuma-hiroaki:20180414141902p:plain

 Write には他にも下記の4種類がありますが、今回は使われていなかったようです。

  • Prepare Write
  • Execute Write
  • Write Command
  • Signed Write Command

Handle Value Notification

 サーバからクライアントへの通知には Handle Value Notification が使われます。

f:id:akanuma-hiroaki:20180414143716p:plain

Connection Parameter Update Request

 コネクションのパラメータを変更する場合には Connection Parameter Update Request が送信されます。

f:id:akanuma-hiroaki:20180414144317p:plain

 オペコードとしては LL_CONNECTION_UPDATE_REQ が使われます。

f:id:akanuma-hiroaki:20180414144438p:plain

 パラメータが変更されると Connection Parameter Update Response が返されます。

f:id:akanuma-hiroaki:20180414144544p:plain

LL_CHANNEL_MAP_REQ

 コネクションのチャンネル・マッピングを変更する際には LL_CHANNEL_MAP_REQ というオペコードが使われます。

f:id:akanuma-hiroaki:20180414144818p:plain

LL_TERMINATE_IND

 コネクションを切断するには LL_TERMINATE_IND オペコードが使われます。

f:id:akanuma-hiroaki:20180414145133p:plain

まとめ

 ざっとですが手持ちの一デバイスで確認できた内容を書いてみました。 BLE デバイスを使ったサービスを開発する場合に、BLEデバイスとの接続に問題がありそうな場合には、今回のように接続シーケンスを確認することで何か解決への手がかりが見つかるかもしれません。使用方法もとても簡単なので、勉強のためにも今後色々と使ってみたいと思います。

 今回は下記のサイトを参考にさせていただきました。

blog.reinforce-lab.com

dsas.blog.klab.org