chakokuのブログ(rev4)

テック・コミック・ごくまれにチャリ

BLE MIDI実装でエラーになる原因を調査

ESP32用のデバッガが動くようになったので、俺BLE MIDIのエラー原因を調査。
そもそもデバッグ環境を構築した目的は、アドバタイズにBLE MIDIのサービスUUID(UUID128)を入れようとするとエラーになるのを調べるためであった。アドバタイズにUUID128を含める実装(使っているBLEライブラリはnimBLE)

    fields.uuids128 = BLE_UUID128(BLE_UUID128_DECLARE(0x00,0xC7,0xC4,
						      0x4E,0xE3,0x6C,0x51,0xA7,
						      0x33,0x4B,0xE8,0xED,0x5A,
						      0x0E,0xB8,0x03));
    fields.num_uuids128 = 1;
    fields.uuids128_is_complete = 0;

    fields.name = (uint8_t *)device_name;
    fields.name_len = strlen(device_name);
    fields.name_is_complete = 1;

    rc = ble_gap_adv_set_fields(&fields);
    if (rc != 0) {
        MODLOG_DFLT(ERROR, "error setting advertisement data; rc=%d\n", rc);
        return;
    }

上記コードを実行すると、ble_gap_adv_set_fieldsの戻り値が4になってエラーとなる。

error setting advertisement data; rc=4

UUID128を含めるとエラーになって、UUID128を含めないとエラーにならない。なぜUUID128を含めるとエラーになるのかが分からなった。gdbで実行を追いかけると、どうやら、いろいろ詰め込みすぎてAdvertiseの最大パケット長(31octet)を超えてまうからでは?と判断(確度低し)
判断した理由:
関数:adv_set_fieldsでAdvertise用フィールドに指定した情報をコピーするようなのだが、UUID128のコピーまでは成功し、次のnameをコピーする関数ble_hs_adv_set_flat_mbufで0x04を返している。文字列コピー段階でエラーが発生している。
(file: esp-idf/components/bt/host/nimble/nimble/nimble/host/src/ble_hs_adv.c)

311         if (adv_fields->name != NULL && adv_fields->name_len > 0) {
312             if (adv_fields->name_is_complete) {
318             rc = ble_hs_adv_set_flat_mbuf(type, adv_fields->name_len,
313                 type = BLE_HS_ADV_TYPE_COMP_NAME;
314             } else {
315                 type = BLE_HS_ADV_TYPE_INCOMP_NAME;
316             }
318             rc = ble_hs_adv_set_flat_mbuf(type, adv_fields->name_len,
319                  adv_fields->name, dst, dst_len, max_len,om);  <<<<<<<<エラー発生!!
321             if (rc != 0) {
322                 return rc;

実行時の変数値を確認

adv_fields->name ....            $12 = (uint8_t *) 0x3f403f30 "BLE MIDI 0.00"
adv_fields->name_len ....        $13 = 13 '\r'
adv_fields->name_is_complete ... $14 = 1

dst  .... $15 = (uint8_t *) 0x3ffc6d80 "\002\001\006\021\006"
*dst  ... $19 = 2 '\002'
dst_len ... $16 = (uint8_t *) 0x3ffc6d9f "\025\021"
*dst_len ... $20 = 21 '\025'
max_len ... $17 = 31 '\037'
om ... $18 = (struct os_mbuf *) 0x0

KORGのBLEキーボードでどんな風にアドバタイズパケットを送受信しているのかキャプチャして少し調べると、上限まで詰め込まず、どうやって分けて送っているか?が分かるはずなのだが。。

advertising , UUID128等で検索すると、「UUID128等の長い情報は、応答パケットに入れるように」という記述があった。APIにもレスポンス用設定があるので、応答パケットに入るよう修正してみる