みつきんのメモ

組み込みエンジニアです。Interface誌で「Yocto Projectではじめる 組み込みLinux開発入門」連載中

raspberrypi3のオンボードのbluetoothをRaspbian以外のOSで使用する方法

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点が考えられる。

  1. bluetoothdが起動していない。
  2. 権限が足りない。

前者の場合はsystemctl start bluetoothでbluetoothdを起動すれば良い。

後者の場合はsuやsudoでスーパーユーザー権限で実行すれば良い。