先日、とある古いAndroid端末でRFCOMMを使った通信が可能かを確かめるのにLinuxで簡易Bluetooth評価環境を作りましたので紹介します。
評価環境といっても仮想PCにUbuntuをインストールして、apt-getで必要なパッケージをいれただけで大したことはしていません。しかし、Bluetoothデバイスの操作やパケットアナライザで通信内容がリアルタイムで見れるのでなかなかに重宝しました。
環境
ここでは下記環境でBluetooth RFCOMM通信を試みました。
- RFCOMMクライアント:
Android 1.6端末(SHARP IS01)
自作のテストプログラム(SPPクライアント) - RFCOMMサーバー:
Ubuntu 16.04(Windows10ホストのVirtualBoxを使用)
RFCOMMサーバ+ターミナルを使用
Wireshark(パケットキャプチャ)
IS01はBluetoothは搭載しているものの、公式にはSPPプロファイル非対応の端末です。このBluetoothモニタリング環境はIS01の非公開APIを使ってRFCOMM通信を行うテストプログラムを組む中で作成しました。
またLinux環境はお手軽に用意できるよう仮想PCソフトウェアを使って構築しました。
環境を構築する
概要
仮想PC上にモニタ環境を構築して、そこに必要なソフトウェアをインストールします。使用するソフトの関係からOSはLinux(Ubuntu)を選択しました。
- 仮想PC(VirtualBox)をインストール
- 仮想PC上にUbuntuをインストール
- 必要なツール類をapt-getでインストール
- BluetoothデバイスをゲストOS(Ubuntu)で認識させる
BluetoothパケットのキャプチャにはWiresharkを使用しました。このツールは元々がEthernetパケットキャプチャツールですが、Ver.2以降でBluetoothにも対応しました。この機能を利用するにはLinux環境が必要です(Windows版もありますが、こちらはBluetoothのキャプチャが出来ません)。
構成
以下のような構成になります(私の理解が間違っている場合はご指摘頂けると幸いです)。
以下は使用するツールです。
- bluetoothctl:Bluetoothデバイスとペアリング、情報取得等に使用
- sdptool:SDPテーブルにSPPを追加するために使用
- rfcomm:RFCOMMで待ち受けするために使用(デバイスファイル経由でminicomから接続)
- wireshark:パケットキャプチャ
仮想PC環境(VirtualBox)のインストール
今回はVirtualBoxという仮想PC環境を構築するツールを使ってWindows上にLinux環境を用意しました。実機があればそれを使っても構いません。
なお、VMWareを使った場合はゲストOS側からのBluetooth動作が上手くいきませんでした。ホストOSとゲストOSでBluetoothデバイスが共有されてしまい、ペアリングが上手くいきません。
VirtualBoxは以下のサイトからダウンロードできます。
- Oracle VM VirtualBox
https://www.virtualbox.org/
VirtualBox本体に加えて、Extension Packという機能拡張パック(USB2.0/USB3.0対応)もダウンロードします。ここでは以下のバージョンをダウンロードしました。
- VirtualBox 5.1.6 for Windows hosts
- VirtualBox 5.1.6 Oracle VM VirtualBox Extension Pack
まずVirtualBox本体をインストールして、機能拡張パックの導入を行ってください。本体インストール後に拡張パックをダブルクリックすれば自動的に導入されます。
LinuxOS(Ubuntu)のインストール
VirtualBoxを使って仮想マシンを作成して、そこにUbuntuをインストールします。仮想マシン設定ではUSBコントローラを有効にしておきます。
OSインストール後、念のためインストール済みのパッケージをアップデートしておきます。
$ sudo apt-get update
必要なソフトウェアのインストール
apt-getで必要なパッケージをインストールします。なお、Bluetoothパケットのキャプチャーで使用するwiresharkは2.x以上のバージョンが必要です(古いディストリビジョンだと1.x系のバージョンしか用意されていないかもしれません)。
$ sudo apt-get install bluez bluez-utils minicom wireshark
BluetoothデバイスをゲストOS(Ubuntu)に認識させる
お手持ちのBluetoothドングルを仮想PC上のLinuxで認識させます。以下の手順で操作します。
- PCにBluetoothドングルを接続する(ホスト側で正常に認識することを確認)
- 起動している仮想PCウィンドウのメニュー > デバイス > USB > 接続したBluetoothデバイスを選択
Ubuntuデスクトップの右上にBluetoothアイコンが表示されていれば認識されています。上手くいかない場合はドングルを抜き刺ししてみると改善することがあります。
sdptoolの動作確認
LinuxのSDPサーバを設定するのにsdptoolを使用します。試しにターミナルから以下のように入力してみてください。SDPに登録されているプロファイルの一覧が表示されます。おそらく初期状態では一覧の中にSPP(or SP)は無いと思います。これは後で追加します。
$ sdptool browse local
もしSDPサーバに接続出来ないといったエラーが発生するなら、bluetoothdの設定変更が必要です。以下のファイルを修正してください。
/etc/systemd/system/dbus-org.bluez.service
修正前
ExecStart=/usr/lib/bluetooth/bluetoothd
修正後
ExecStart=/usr/lib/bluetooth/bluetoothd --compat
修正が完了したらbluetoothdを再起動してもう一度確かめます。
$ sudo systemctl daemon-reload $ sudo systemctl restart bluetooth $ sdptool browse local
まだエラー(Permisson denied)が発生していているようであれば、以下のようにパーミッションを変更してから再度確かめます。
$ sudo chmod 777 /var/run/sdp $ sdptool browse local
RFCOMMサーバを準備する
必要なソフトウェアの準備が完了したので、いよいよRFCOMMサーバを起動します。
- Bluetoothデバイスとペアリングする
- SDPにSPPを追加する
- RFCOMMサーバで接続待ちする
- Wiresharkでパケットキャプチャする
bluetoothデバイスとペアリングする
まず、通信対象の端末とペアリングを行います。仮にホストOSでペアリングしている場合でも、ゲストOS側で別途ペアリングが必要です。
ここではbluetoothctlを使ってコンソールから行います。まず、周辺のBluetoothデバイスを検索します。
$ sudo bluetoothctl -a [bluetooth]# scan on Discovery started
ずらずらと見つかったデバイスが表示されるはずです。どれが目的のデバイスか分からない場合はinfo <ADDR>でデバイス名等が表示されます(ADDRの部分はTABキー補完が効きます)。
[bluetooth]# info A0:DD:E5:27:F9:95 Device A0:DD:E5:27:F9:95 Name: IS01 Alias: IS01 Class: 0x180204 Icon: phone Paired: no Trusted: no Blocked: no Connected: no LegacyPairing: yes UUID: OBEX Object Push (00001105-0000-1000-8000-00805f9b34fb) UUID: Audio Source (0000110a-0000-1000-8000-00805f9b34fb) UUID: A/V Remote Control Target (0000110c-0000-1000-8000-00805f9b34fb) UUID: Headset AG (00001112-0000-1000-8000-00805f9b34fb) UUID: Handsfree Audio Gateway (0000111f-0000-1000-8000-00805f9b34fb)
私の場合、IS01と通信したいのでpair <ADDR>としてIS01のアドレスを指定してペアリングを行います。
[bluetooth]# pair A0:DD:E5:27:F9:95 Attempting to pair with A0:DD:E5:27:F9:95 [CHG] Device A0:DD:E5:27:F9:95 Connected: yes Request PIN code [agent] Enter PIN code: 1234 [CHG] Device A0:DD:E5:27:F9:95 Paired: yes Pairing successful [CHG] Device A0:DD:E5:27:F9:95 Connected: no
これでペアリングは完了です。ペアリングの操作は以下のサイトが参考になります。
- archlinux ArchWiki - Bluetooth
https://wiki.archlinuxjp.org/index.php/Bluetooth
SDPにSPPを追加する
Bluetoothは接続時にSDPを使って目的のサービスが提供されているかの確認を行います。つまりRFCOMMで接続したい場合、サーバとなるPCのSDPにそれを追加してやる必要があります。
以下のようにコマンドを入力します。
$ sudo sdptool add --channel=22 SP Serial Port service registered
以下のようにコマンドを実行すると、SPが追加されているのが確認できます。
$ sdptool browse local
RFCOMMで待ち受けをする
最後にRFCOMMで受け待ち出来るようにします。
$ sudo rfcomm listen /dev/rfcomm1 22 Waiting for connection on channel 22
この状態で相手のデバイスからRFCOMMで接続することが出来ます。試しにIS01から接続してみると以下のように表示されます。
Connection from A0:DD:E5:27:F9:95 to /dev/rfcomm1 Press CTRL-C for hangup
メッセージの送受信はターミナルソフト(ここではminicom)を使用します。接続完了すると"/dev/rfcomm1"というデバイスファイルが生成されますので、これをminicomで開いてください。相手から何かメッセージを送信すれば画面に表示されると思います。
$ sudo minicom -D /dev/rfcomm1
Wiresharkでパケットキャプチャを行う
パケットキャプチャを行う場合はWiresharkを起動して、キャプチャするデバイスにbluetoothを指定します。
私の設定がまずいのかrootで立ち上げないとbluetoothがキャプチャ出来ませんでした。
$ sudo wireshark
デバイスをscanしているときの動作や、SDPサーバが応答しているやり取りなども表示されます。相手からの接続が上手くいかない場合にパケットのログを見ると(私はBluetoothをあまり理解していないので時間はかかりますが)何が起きているか追うことが出来ます。
所感
記事でも書きましたが、この環境はIS01でRFCOMM通信テストを行うために構築しました。IS01は公式にはRFCOMM未サポートでネットで検索しても具体的なものは発見できず(デバイスが古すぎか)、まさに手探り状態です。IS01からどんな通信が来ているのか、何処で通信がこけているのか、ということを調査するのにこの環境はとても役に立ってくれました。
欠点は第三者が通信している内容を取得出来ないことです。これが出来ればAndroid端末とマイコンを通信させてときにデバッグが捗るのですが、実現するには専用機器が必要になります。以下のようなものがあります(この手のものにしてはとても安価でいつか使ってみたいです)。
- Ubertooth One
http://ubertooth.sourceforge.net/hardware/one/
参考
この記事は以下のサイトを参考にさせていただきました。
- BlueCove
http://bluecove.org/ - VMwareゲストのUbuntuでBluetoothデバイスを接続する方法
http://web.sfc.keio.ac.jp/~yama/nos/?p=4531 - Linux PCにUSB Bluetoothを付けてNexus7と通信
http://loops.at.webry.info/201404/article_2.html - Linux PCにUSB Bluetoothを付けてRN-42と通信
http://loops.at.webry.info/201404/article_1.html - kakakikikekeのブログ - RaspberryPi の bluetoothctl で無線キーボードに接続
http://kakakikikeke.blogspot.jp/2015/10/raspberrypi-con-keyboard-bluetoothctl.html - RFCOMM with TS 07.10 - Bluetooth
http://hccc.ee.ccu.edu.tw/courses/bt/vg/rfcomm.pdf - RFCOMM Layer Tutorial
http://www.amd.e-technik.uni-rostock.de/ma/gol/lectures/wirlec/bluetooth_info/rfcomm.html - StackExchange - Failed to connect to SDP server on FF:FF:FF:00:00:00: No such file or directory
http://raspberrypi.stackexchange.com/questions/41776/failed-to-connect-to-sdp-server-on-ffffff000000-no-such-file-or-directory