poky(yocto)などのRaspbian以外のOSでRPi3のオンボードのbluetoothを使用したいと思うケースは多いと思う。 しかし、現時点(20160329)でこれらのOSではおそらくbluetoothはそのままでは機能しない。
(少なくともmeta-raspberrypiの)カーネルからデバイスが見えないためだ。
今回はRaspbianの中身を覗き、何が必要かを解析したのでメモ。
ライセンスが不明瞭なので、商用利用や作成したイメージの二次配布などの際には気をつけること。
bleutoothが動作するまでに必要なこと
- cmdline.txtからttyAMA0を削除
- serial-getty@ttyAMA0.serviceのマスク
- pi-bluetoothに同梱されているhciuart.serviceのインストール
- bluez-firmwareに同梱されているファームウェア(BCM43430A1.hcd)のインストール
- bluez5へのパッチ適用
cmdline.txtの編集
RPiでUARTを使用するためにはttyAMA0をconsole指定からはずさなければならない。 しかし、systemd環境では少し注意する必要がある。
SDのBootパーティションにある、cmdline.txtを下記の様に編集する。
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 fsck.repair=yes rootwait
もしdebugの定義があるなら外したほうが無難かもしれない。
serial-getty@ttyAMA0.serviceのマスク
これをしないと、hciattachが見かけ上成功しても、実際にはデバイスにアクセスできない。
$ systemctl mask serial-getty@ttyAMA0.service
pi-bluetoothに同梱されているhciuart.serviceのインストール
pi-bluetoothで必要なファイルは「/lib/systemd/system/hciuart.service」
「/usr/share/doc/pi-bluetooth/copyright」によると、このライセンスはBSD-3-Clauseなので、二次使用は特に問題なさそう。
[Unit] Description=Configure Bluetooth Modems connected by UART ConditionPathIsDirectory=/proc/device-tree/soc/gpio@7e200000/bt_pins Before=bluetooth.service After=dev-ttyAMA0.device [Service] Type=forking ExecStart=/usr/bin/hciattach /dev/ttyAMA0 bcm43xx 921600 noflow - [Install] WantedBy=multi-user.target
主な処理としては、hciattachを実行する。 これと同等の処理があれば、このファイルそのものはなくても良い。
bluez-firmwareに同梱されているファームウェア(BCM43430A1.hcd)のインストール
bluez-firmwareの中で必要なファイルは「/lib/firmware/BCM43430A1.hcd」 このライセンスはプロプライエタリなもののようだが、取り扱いについてはここで議論されている。
BCM43430A1.hcdはバイナリの為、自分でコンパイルすることができないので、基本的にはRaspbianのイメージからコピーしてくるしか無さそう。
こちらはハッシュも一致している。 おそらくRaspbianから抜き出したものだろう。 ライセンスについて明示したファイルは見当たらないが。。。
これを利用するには下記のようにする。
$ wget https://github.com/OpenELEC/misc-firmware/raw/master/firmware/brcm/BCM43430A1.hcd
先述の通り、これはファイルそのものが必要となる。
bluez5へのパッチの適用
raspbianのbluez5のパッケージは下記の4つのパッチが適用されている。 upstreamからソースを取得する場合や他のディストリビューションのパッケージを使用する場合は、 これらの修正を適用する必要がある。
- 0050-bcm43xx-Add-bcm43xx-3wire-variant.patch
- 0051-bcm43xx-The-UART-speed-must-be-reset-after-the-firmw.patch
- 0052-Increase-firmware-load-timeout-to-30s.patch
- 0053-Move-43xx-firmware-to-lib-firmware.patch
このパッチがそのまま当たらない場合は、upstreamの5.37に適用できる形してくれているものがここにあるので参考にすると良い。
bluetooth起動手順
上記をすべて適用した環境で次の手順を実行すると、bleutoothが使用できるようになる。
$ systemctl start hciuart $ systemctl start bluetooth
この時点でrfkill listを実行してhci0が見えれば成功。
$ rfkill list rfkill list 0: phy0: wlan Soft blocked: yes Hard blocked: no 1: hci0: bluetooth Soft blocked: yes Hard blocked: no
blockされている場合は下記のようにしてunblockする。
$ rfkill unblock 1
トラブルシューティング
いくつかハマった点についてメモしておく。
controllerのBDアドレスがすべてAAになる
BCM43430A1.hcdが/lib/firmwareにない場合は、下記のように表示される。
$ bluetoothctl [NEW] Controller AA:AA:AA:AA:AA:AA raspberrypi3 [default]
BDアドレスが全てAAになった場合は、BCM43430A1.hcdの置き場所を確認すると良い。
bluetoothctlが無反応
bluetoothctl起動後に何を入力しても反応しない場合は下記の2点が考えられる。
- bluetoothdが起動していない。
- 権限が足りない。
前者の場合はsystemctl start bluetoothでbluetoothdを起動すれば良い。
後者の場合はsuやsudoでスーパーユーザー権限で実行すれば良い。