Linux に接続した Bluetooth デバイスと通信が出来るようになるまでの流れ。
Linux に BT アダプタが接続される
もしも BT アダプタが存在していれば bt-adapter -l で表示される。また sysfs 経由でも確認出来る。
# bt-adapter -l
Available adapters:
qemux86-64 (00:1B:DC:08:A4:0B)
# ls /sys/class/bluetooth/
hci0 hci0:63 hci0:71
対象デバイスとペアリングが出来ている
ペアリングは GUI や bluetoothctl コマンドで行う。もしもペアリンス済なら bluetoothctl コマンドの paired-devices で表示される
# echo paired-devices | bluetoothctl
...
[M00213]# paired-devices
Device D4:0B:1A:F2:FE:DC M00213
...
対象デバイスと通信が出来る
一応 Ping してみる。
# l2ping D4:0B:1A:F2:FE:DC
Ping: D4:0B:1A:F2:FE:DC from 00:1B:DC:08:A4:0B (data size 44) ...
44 bytes from D4:0B:1A:F2:FE:DC id 0 time 8.62ms
44 bytes from D4:0B:1A:F2:FE:DC id 1 time 14.32ms
44 bytes from D4:0B:1A:F2:FE:DC id 2 time 1891.53ms
対象デバイス上で必要なサービスが動いている。
TCP/IP では IP アドレスとポート番号で接続先を指定するが、Bluetooth では Port 番号を Service Discovery Protocol (SDP) という仕組みで間接的に取得する。SDP 自体のポート番号は決め打ち。あるデバイスの SDP を見るには sdptool を使う
# sdptool browse D4:0B:1A:F2:FE:DC
Browsing D4:0B:1A:F2:FE:DC ...
...
Service Name: Handsfree Gateway
Service RecHandle: 0x10003
Service Class ID List:
"Handsfree Audio Gateway" (0x111f)
"Generic Audio" (0x1203)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 3
Profile Descriptor List:
"Handsfree" (0x111e)
Version: 0x0106
...
各項目の意味は以下の通り
- Service Name: このサービスの名前
- Service RecHandle: このレコードを特定するデバイス内で一意の ID
- Service Class ID List: この Service Record が理解する UUID のリスト
- 一つのサービスが複数の Service Class ID を持っても良い。
- サービスは必ず Service Class ID を持つ。
- Protocol Descriptor List: このサービスが使うプロトコルとポート番号のリスト
- L2CAP: UDP みたいな物。ポート番号は 1 - 32767 の奇数。
- L2CAP ではポート番号を Protocol Service Multiplexer (PSM) と呼ぶ。
- RFCOMM: TCP みたいな物。ポート番号は 1 - 30。
- RFCOMM ではポート番号を Channel と呼ぶ。
- L2CAP: UDP みたいな物。ポート番号は 1 - 32767 の奇数。
- Profile Descriptor List: このサービスが提供する Profile のリスト (オプション)
クライアントは、Service Class をキーにしてサービスを検索する。Profile も似たような目的らしいが良くわからなかった。
対象サービスに接続する
SDP の Protocol Descriptor List にポート番号が Channel または PSM として現れるので接続する。あとはインターネットソケットと同じ。