ble: gattlib (4)
2025/04/06
はじめに
前回の続きで gattlib で BLE の central 操作するのを検討している。
BLEのスキャンはできているが、接続がときどき失敗する。
前回、リトライすることで対処したのだが、それはそれとして理由を調べよう。
ble_scan の概略
main():
ble_task()
をgattlib_mainloop()
で立ち上げるだけgattlib_mainloop()
に関数コメントはないのだが、gattlib で BLE 関係のイベントを Bluez などから受け取ったりするためのメインループのスレッドを立ち上げるのと同時にアプリのスレッドを立ち上げているのだろう
ble_task():
gattlib_adapter_open()
pthread_mutex_lock(&g_mutex)
※1-agattlib_adapter_scan_enable()
で BLE機器のスキャンを最大 10秒間続ける。検出したらble_discovered_device()
を呼び出す- 関数コメントとしてはタイムアウトか
gattlib_adapter_scan_disable()
が呼ばれるまで処理をブロックするそうだ ble_discovered_device():
- ユーザデータ
struct connection_t
のメモリを確保してデータを詰める pthread_create()
でユーザデータを付けてble_connect_device()
を呼ぶble_connect_device():
pthread_mutex_lock(&g_mutex)
※2-agattlib_connect()
で接続を行い、on_device_connect()
を呼び出すon_device_connect():
gattlib_discover_primary()
- 見つけたサービスを for 文でぐりぐり取得して出力
gattlib_discover_char()
- 見つけたキャラクタリスティックを for 文でぐりぐり取得して出力
gattlib_disconnect()
pthread_mutex_unlock(&g_mutex)
※2-b
- ユーザデータを LIST に追加
- ユーザデータ
- 関数コメントとしてはタイムアウトか
gattlib_adapter_scan_disable()
でスキャンの停止。タイムアウトしても呼んだ方がよいということか?pthread_mutex_unlock(&g_mutex)
※1-b
- LIST に追加したユーザデータ
- ユーザデータに thread_id があるので、それを
pthread_join()
で終了待ちする - LIST からそのユーザデータを取り除きメモリを解放
- ユーザデータに thread_id があるので、それを
ble_task()
で mutex している範囲は gattlib_adapter_scan_enable()
が終わるまで(※1-a ~ ※1-b。以下 ※1)だ。
もう1つの接続要求は gattlib_connect()
の始めから終わりまで(※2-a ~ ※2-b。以下 ※2)。
なので、※1 のスキャンが終わるまでは ※2 の接続要求がブロックされるはずだ。
そして ※2 はスレッドなので複数の BLE機器 の分が立ち上がっているかもしれないが、それぞれの ※2 がブロックし合うのでこれも衝突しないはずだ。
コードから見える部分に関しては問題ないようだ。
それでも HCI レベルでは処理が混ざっているということは、 gattlib 以下でブロックし切れていないところがあるのだろう。 ブロックし切れていないというより、処理が終わるはずのところが下側でちょっとだけ続いていたとかだろうか。
なんとなくだけど、ble_scan
や gattlib、Bluez ではなくデバイスドライバとかそういうところに原因があるんじゃないかなあ、という気がしている。
単に、他でも発生するなら v0.7.2 になるまで修正されないとは思えない、というだけの理由だ。