Bluetooth遊び

先日Bluetoothマウスを買ってきたついでにUSB接続のBluetoothドングルも買ってきていたので、そいつでちょっと遊ぶ。
Bluetoothドングルも一時よりもかなり安価になってきており、今回買ったのもBluetooth 2.0対応で2000円強。1.2でいいならば1000円ぐらいから買える。
対向はThinkPad T43に内蔵されていたBluetooth 1.2のデバイス。OSは最初から入っていたWindows XP、スタックはWIDCOMM 5.0.1.3200。スタックは購入後メジャーバージョンアップ1回を含めて数回更新されているので、一応最新版。
ドングルの方はDebian GNU/LinuxのPCに差した。Linuxはkernel 2.6.18、BluetoothのスタックはBluez 3.7。
一口にBluetoothといっても多彩なプロファイルが有ってかなり上位レイヤまで規定している。今回試したのは簡単そうなPAN、いわゆるEthernetのエミュレーションみたいなことをするプロファイル。実用上はWiFiに比べて格段に遅いので、積極的にこれを使うことは無さそうだけど簡単に設定できそうだったのでとりあえず。

Linux側のカーネルのドライバを有効にする

generic kernelを使っているなら不要。差した時点でドライバが適切にロードされているはず。
自前でコンパイルしていたので、Networkingの下にあるBluetooth subsystem以下で使いそうなのを全部有効にしておいた。今回使ったデバイスはhci_usbという汎用ドライバが対応していた。
ちなみに以下がUSB的に見たときのデバイスの見え方。

Bus 005 Device 003: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)

関連パッケージを入れる

Debianならbluez-utils

近隣のデバイスを探索

$ hcitool scan

付けている場合は、同時に名前も返す。

疎通の確認

とりあえずの疎通はl2pingというコマンドで確認できる。遅延が案外大きくて、30msぐらいかかる。floodモードでも15msぐらい。

バイスの詳細を問い合わせ

どのデバイスがどのプロファイルをサポートしているかなどは、SDP(Service Discovery Protocol)というのを使って調べる。あるプロファイルを持っているデバイスを探すには

$ sdptool search GN

みたいな感じ。GNというのはGroup ad-hoc Network (GN) controllerを行うノードのこと。逆にこのデバイスが何のプロファイルをサポートしているかは

$ sdptool browse  00:xx:xx:xx:xx:xx

で見ることができる。引数はbdaddrというEthernetにおけるMACアドレスのような固有のアドレス。

PANにおける3種類のノード

HOWTOにもある通りPANには3種類のノードがある。

  • エンドノードとなるPANU
  • Ad-hocネットワークのハブとなるGN
  • 外部へのゲートウェイとなるNAP

今回は隣り合ったPCで通信できればいいので、一方をGN、もう一方をPANUにしてみる。幸いThinkPad T43に標準搭載されているWIDCOMMのスタックでもGNにはなれるので、Windows側をGNにして、Linux側をPANUにしてみる。

通信の暗号化に使うPIN

WiFiにおけるWEPキーの役目がPIN。passkeyやセキュリティコードと記述されていたり、かなり表記に揺れがあるが全部同じ意味のようだ。

bluezにおけるPIN

Windows側は必要になればタスクトレイからポップアップが出て入力を要求されるのですぐにわかったのだけど、Linuxのbluezはどう管理しているのかよくわからなかった。以前のバージョンでは単純にファイルで管理していたようだが、最近のbluezではdbus経由で情報をやりとりするようだ。gnomeを使っているのならば専用のクライアントがある(Debianのパッケージでは、bluez-passkey-gnome)。CLIでのクライアントは何故かバイナリが配布されておらず、bluez-utilsの中にソースだけ収録されていた。
/usr/share/doc/bluez-utils/examples以下にMakefileとソースがあるので、必要なライブラリ(libdbus-1-devとか)を入れmake。manも用意されていないのだけど、

$ ./passkey-agent  00:xx:xx:xx:xx:xx

ってな感じで行けた。第2引数にbdaddrを指定したが、"--default"を指定しデフォルト値とするときはもちろん不要。

接続

今回はLinux側をクライアントにしたので、こちらのCLIから以下のようなコマンドを実行

$ sudo pand --connect 00:xx:xx:xx:xx:xx  -d PANU 

するとWindows側でPINの入力を求められるので、さきほどLinuxCLIで指定したのと同じPINを入力。
Linux側ではbnep0というデバイスが生えてくる。あとは適当にアドレスを付けるなり、DHCPを動かすなりすれば通信できる。

パフォーマンス

一方がBluetooth1.2ということで遅いことは承知の上で一応測ってみた。表記上700kbpsでリンクしているらしいが、ファイルなんかを転送すればその帯域の最大80%前後(560kbpsぐらい)は出るようだ。シリアルの代替としてはこんなもんかな。

雑感

セキュリティ関係の設定項目が少ないためかWiFi初期に比べればセットアップはまだ楽。デバイスの認識とかの段階はあっさり完了したが、その先のbluezのコマンド群が慣れていないため多少手間取った。コマンドの作り自体はわりと素直。唯一躓きそうなのはPIN関連かな、ただGNOMEのクライアントならば分り易いUIだろうからもう少しましかも。
LinuxBluetoothを使うときに参考になる日本語の文章はLinux/Zaurus関連ぐらいだった。まぁ、それでもなんとかなる程度には簡単だった。