ブログ/こばさんの wakwak 山歩き Twitter

2017-09-23 ESP32 SDK v3.0 で HCI コマンドの結果が来なくなった

ESP32 SDK v3.0 で HCI コマンドの結果が来なくなった

| ESP32 SDK v3.0 で HCI コマンドの結果が来なくなったを含むブックマーク

 運動会も終わって、お山・・・と言いたいところですが、一泊二日じゃ足りない体になってしまったので、大人しく ESP32 弄りを復活させようと思います。

 昔はこの時期に、三俣山荘まで忘れ物を取りに日帰りしたり早月尾根で劔を日帰りしたり してたんだなぁ〜と思うと実に感慨深い・・・(今の体力では厳しいのではないか)


 arduino-esp32 から Bluetooth Classic(SPPやHID)を扱おうとしているのですが、まずは 4月に部分的に動いたソース を何も弄らずに動かしてみようと思って試してみますと、全く動きません。

 いろいろと探すと外人フォーラム SimpleBLE.h example problem #373 と全く同じ現象であると確認。

 5/22 に me-no-dev という中の人と思しきが fixed したと言ってますが、github で当時のソースを見ると SimbleBLE.cpp の中身がほぼ入れ替えに近い変更が生じてました。

 HCI コマンドを叩いていた箇所が SimbleBLE.cpp の中から削除され、esp_gap_ble_api.h や esp_gatts_api.h に移ってしまってます。

 ちなみに、これらはヘッダーファイルのみで実体は libbt.a の中。


 コンパイル済みライブラリでして、これではソースが見れません!

 いったい何をどう fixed したと言うんだい!?

#include "bt.h"
#include "Arduino.h"

static bool btSetup()
{
    if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE){
        esp_bt_controller_config_t cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
        esp_bt_controller_init(&cfg);
        while(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE);
    }
    if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_INITED){
        if (esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) {
            Serial.println("BT Enable failed");
            return false;
        }
    }
    if(esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_ENABLED){
        return true;
    }
    Serial.println("BT Start failed");
}

static void _on_tx_ready(void)
{
    Serial.println("_on_tx_ready");
}

static int _on_rx_data(uint8_t *data, uint16_t len)
{
    Serial.println("_on_rx_data");
}

static esp_vhci_host_callback_t vhci_host_cb = {
    _on_tx_ready,
    _on_rx_data
};
  
void setup()
{
    Serial.begin(115200);
    Serial.print("ESP32 SDK: ");
    Serial.println(ESP.getSdkVersion());

    if(btSetup())
    {
        esp_vhci_host_register_callback(&vhci_host_cb);
        while (!esp_vhci_host_check_send_available());
        Serial.println("bluetooth started");
        delay(1000);

        uint8_t buf[4];

        // HCI RESET
        buf[0] = 0x01;
        buf[1] = 0x03;
        buf[2] = 0x0c;
        buf[3] = 0x00;
        esp_vhci_host_send_packet(buf, 4);
        Serial.println("esp_vhci_host_send_packet");
    }
    else
        Serial.println("bluetooth failured");
}

void loop()
{

}

 HCI RESET を示すパケット 01 03 0c 00 を投げつけると、04 0e 04 05 03 0c 00 が戻ってくるべきところなのですが、esp_vhci_host_send_packet() までは成功するものの、esp_vhci_host_register_callback() で設定した受信関数にコールバックが来ない有様。

 上記で言えば _on_rx_data() が呼ばれません。( _on_tx_ready() は呼ばれます)


 誰か手がかり情報もっておられる方おられますか〜?

 esp_bt_gap_set_scan_mode() がいつの間にか増えて、こいつが esp_vhci_host_register_callback() よりも優先してコールバックを横取りしてる気がしてならないのですが・・・


 ちなみに ESP32 SDK の表示は v3.0-dev-745-gc4e65d6a と出ます。


(追記)2017/09/26

 Github でつたない英語で質問したものの中の人に他所に行けって言われてしまいましたが、何とか自力解決できました。


 ESP32 はデュアルコアなのですが、Bluetooth 関係は Core0 を明示して動かさないと駄目ぽいです。

 arduino-esp32 でコンパイルされたプログラムはデフォルトで Core1 で動いてしまいます。

 Core0 を使って動かしたら、うまく HCI RESET に対する Response が届きました。


 4月の頃はコアを意識しないでも動いたので、きっとその時の arduino-esp32 は Core0 を使って動いていたのでしょう。

 そんで、SimpleBLE.h example problem #373 の時分にデフォルトで Core1 利用に変わって、そんで動かねぇ〜って外人が騒いだのではなかろうかと。。。

 んで、中の人が Core0 を使って動くようライブラリ関係を大きく作り替えて fixed した、と。


 そんな重要なこと、どっかに書いとけ!