From c8e79a926620e48830778714cfe4b2ea2453fcaf Mon Sep 17 00:00:00 2001 From: jacqueline Date: Fri, 25 Jul 2025 13:33:07 +1000 Subject: Update forked idf components --- lib/bt/CMakeLists.txt | 326 ++- lib/bt/Kconfig | 2 - lib/bt/common/Kconfig.in | 134 ++ lib/bt/common/ble_log/ble_log_spi_out.c | 1247 +++++++++++ .../ble_log/include/ble_log/ble_log_spi_out.h | 64 + lib/bt/common/btc/core/btc_manage.c | 20 +- lib/bt/common/btc/core/btc_task.c | 89 +- lib/bt/common/btc/include/btc/btc_task.h | 18 +- .../profile/esp/blufi/bluedroid_host/esp_blufi.c | 37 +- lib/bt/common/btc/profile/esp/blufi/blufi_prf.c | 24 +- .../btc/profile/esp/blufi/include/blufi_int.h | 2 + .../btc/profile/esp/blufi/include/esp_blufi.h | 1 + .../btc/profile/esp/blufi/nimble_host/esp_blufi.c | 75 +- lib/bt/common/hci_log/bt_hci_log.c | 15 +- lib/bt/common/hci_log/include/hci_log/bt_hci_log.h | 1 + lib/bt/common/include/bt_common.h | 30 +- lib/bt/common/include/bt_user_config.h | 31 +- lib/bt/common/osi/allocator.c | 48 +- lib/bt/common/osi/include/osi/allocator.h | 49 +- lib/bt/common/osi/include/osi/fixed_pkt_queue.h | 4 + lib/bt/common/osi/include/osi/hash_map.h | 1 + lib/bt/common/osi/pkt_queue.c | 1 + lib/bt/common/osi/thread.c | 4 +- lib/bt/common/tinycrypt/AUTHORS | 15 + lib/bt/common/tinycrypt/LICENSE | 61 + lib/bt/common/tinycrypt/README | 70 + lib/bt/common/tinycrypt/VERSION | 1 + .../common/tinycrypt/documentation/tinycrypt.rst | 352 +++ lib/bt/common/tinycrypt/include/tinycrypt/aes.h | 134 ++ .../common/tinycrypt/include/tinycrypt/cbc_mode.h | 155 ++ .../common/tinycrypt/include/tinycrypt/ccm_mode.h | 215 ++ .../common/tinycrypt/include/tinycrypt/cmac_mode.h | 198 ++ .../common/tinycrypt/include/tinycrypt/constants.h | 65 + .../common/tinycrypt/include/tinycrypt/ctr_mode.h | 112 + .../common/tinycrypt/include/tinycrypt/ctr_prng.h | 172 ++ lib/bt/common/tinycrypt/include/tinycrypt/ecc.h | 551 +++++ lib/bt/common/tinycrypt/include/tinycrypt/ecc_dh.h | 135 ++ .../common/tinycrypt/include/tinycrypt/ecc_dsa.h | 145 ++ .../include/tinycrypt/ecc_platform_specific.h | 85 + lib/bt/common/tinycrypt/include/tinycrypt/hmac.h | 143 ++ .../common/tinycrypt/include/tinycrypt/hmac_prng.h | 168 ++ lib/bt/common/tinycrypt/include/tinycrypt/sha256.h | 135 ++ lib/bt/common/tinycrypt/include/tinycrypt/utils.h | 101 + lib/bt/common/tinycrypt/port/esp_tinycrypt_port.c | 87 + lib/bt/common/tinycrypt/port/esp_tinycrypt_port.h | 15 + lib/bt/common/tinycrypt/src/aes_decrypt.c | 170 ++ lib/bt/common/tinycrypt/src/aes_encrypt.c | 197 ++ lib/bt/common/tinycrypt/src/cbc_mode.c | 118 + lib/bt/common/tinycrypt/src/ccm_mode.c | 272 +++ lib/bt/common/tinycrypt/src/cmac_mode.c | 258 +++ lib/bt/common/tinycrypt/src/ctr_mode.c | 91 + lib/bt/common/tinycrypt/src/ctr_prng.c | 283 +++ lib/bt/common/tinycrypt/src/ecc.c | 972 +++++++++ lib/bt/common/tinycrypt/src/ecc_dh.c | 204 ++ lib/bt/common/tinycrypt/src/ecc_dsa.c | 298 +++ .../common/tinycrypt/src/ecc_platform_specific.c | 110 + lib/bt/common/tinycrypt/src/hmac.c | 152 ++ lib/bt/common/tinycrypt/src/hmac_prng.c | 218 ++ lib/bt/common/tinycrypt/src/sha256.c | 221 ++ lib/bt/common/tinycrypt/src/utils.c | 80 + lib/bt/controller/esp32/Kconfig.in | 114 +- lib/bt/controller/esp32/bt.c | 313 ++- lib/bt/controller/esp32c2/Kconfig.in | 372 +++- lib/bt/controller/esp32c2/ble.c | 71 + lib/bt/controller/esp32c2/ble_priv.h | 13 + lib/bt/controller/esp32c2/bt.c | 715 ++++--- lib/bt/controller/esp32c2/dummy.c | 320 +++ lib/bt/controller/esp32c2/esp_bt_cfg.h | 112 +- lib/bt/controller/esp32c3/Kconfig.in | 165 +- lib/bt/controller/esp32c3/bt.c | 655 +++++- lib/bt/controller/esp32c5/Kconfig.in | 339 ++- lib/bt/controller/esp32c5/ble.c | 165 ++ lib/bt/controller/esp32c5/ble_priv.h | 12 + lib/bt/controller/esp32c5/bt.c | 820 ++++--- lib/bt/controller/esp32c5/esp_bt_cfg.h | 86 +- lib/bt/controller/esp32c6/Kconfig.in | 363 +++- lib/bt/controller/esp32c6/ble.c | 171 ++ lib/bt/controller/esp32c6/ble_priv.h | 12 + lib/bt/controller/esp32c6/bt.c | 821 ++++--- lib/bt/controller/esp32c6/esp_bt_cfg.h | 89 +- lib/bt/controller/esp32c61/Kconfig.in | 1 + lib/bt/controller/esp32h2/Kconfig.in | 377 +++- lib/bt/controller/esp32h2/ble.c | 165 ++ lib/bt/controller/esp32h2/ble_priv.h | 12 + lib/bt/controller/esp32h2/bt.c | 762 ++++--- lib/bt/controller/esp32h2/esp_bt_cfg.h | 87 +- lib/bt/controller/esp32h21/Kconfig.in | 0 lib/bt/controller/esp32h4/Kconfig.in | 0 lib/bt/controller/lib_esp32/esp32/libbtdm_app.a | Bin 763748 -> 826428 bytes .../lib_esp32c2/esp32c2-bt-lib/libble_app.a | Bin 2295648 -> 2371782 bytes .../lib_esp32c2/esp32c2-bt-lib/libble_app_flash.a | Bin 0 -> 2429970 bytes .../lib_esp32c3_family/esp32c3/libbtdm_app.a | Bin 504018 -> 1360462 bytes .../lib_esp32c3_family/esp32c3/libbtdm_app_flash.a | Bin 0 -> 1362720 bytes .../lib_esp32c3_family/esp32s3/libbtdm_app.a | Bin 585198 -> 1516258 bytes .../lib_esp32c3_family/esp32s3/libbtdm_app_flash.a | Bin 0 -> 1743312 bytes .../controller/lib_esp32c5/esp32c5-bt-lib/NOTICE | 9 + .../lib_esp32c5/esp32c5-bt-lib/README.md | 1 + .../lib_esp32c5/esp32c5-bt-lib/libble_app.a | Bin 0 -> 3631294 bytes .../controller/lib_esp32c6/esp32c6-bt-lib/NOTICE | 2 +- .../esp32c6-bt-lib/esp32c6/libble_app.a | Bin 0 -> 3914274 bytes .../esp32c6-bt-lib/esp32c61/libble_app.a | Bin 0 -> 3632698 bytes .../lib_esp32c6/esp32c6-bt-lib/libble_app.a | Bin 3150354 -> 0 bytes .../lib_esp32h2/esp32h2-bt-lib/libble_app.a | Bin 3129370 -> 3655360 bytes lib/bt/esp_ble_mesh/Kconfig.in | 520 +++-- .../esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c | 26 +- .../api/core/esp_ble_mesh_common_api.c | 2 +- .../api/core/include/esp_ble_mesh_ble_api.h | 88 +- lib/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h | 25 +- lib/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c | 49 +- lib/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c | 10 +- lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h | 39 +- .../esp_ble_mesh/btc/include/btc_ble_mesh_prov.h | 2 +- lib/bt/esp_ble_mesh/common/atomic.c | 16 +- lib/bt/esp_ble_mesh/common/include/mesh/atomic.h | 27 + lib/bt/esp_ble_mesh/common/include/mesh/mutex.h | 7 +- lib/bt/esp_ble_mesh/common/include/mesh/queue.h | 33 + lib/bt/esp_ble_mesh/common/include/mesh/utils.h | 2 +- lib/bt/esp_ble_mesh/common/mutex.c | 53 +- lib/bt/esp_ble_mesh/common/queue.c | 48 + lib/bt/esp_ble_mesh/core/access.c | 148 +- lib/bt/esp_ble_mesh/core/adv.c | 775 +------ lib/bt/esp_ble_mesh/core/adv.h | 82 +- lib/bt/esp_ble_mesh/core/adv_common.c | 683 ++++++ lib/bt/esp_ble_mesh/core/adv_common.h | 293 +++ lib/bt/esp_ble_mesh/core/beacon.c | 13 +- lib/bt/esp_ble_mesh/core/ble_adv.c | 323 +++ lib/bt/esp_ble_mesh/core/ble_adv.h | 54 + lib/bt/esp_ble_mesh/core/bluedroid_host/adapter.c | 597 +++++- lib/bt/esp_ble_mesh/core/cfg_srv.c | 165 +- lib/bt/esp_ble_mesh/core/crypto.c | 2 + lib/bt/esp_ble_mesh/core/ext_adv.c | 427 ++++ lib/bt/esp_ble_mesh/core/ext_adv.h | 39 + lib/bt/esp_ble_mesh/core/friend.c | 34 +- lib/bt/esp_ble_mesh/core/include/mesh/access.h | 4 +- lib/bt/esp_ble_mesh/core/include/mesh/adapter.h | 161 +- lib/bt/esp_ble_mesh/core/lpn.c | 3 + lib/bt/esp_ble_mesh/core/main.c | 20 +- lib/bt/esp_ble_mesh/core/mesh.h | 1 + lib/bt/esp_ble_mesh/core/net.c | 289 ++- lib/bt/esp_ble_mesh/core/net.h | 14 +- lib/bt/esp_ble_mesh/core/nimble_host/adapter.c | 812 ++++++- lib/bt/esp_ble_mesh/core/prov_common.c | 33 +- lib/bt/esp_ble_mesh/core/prov_common.h | 2 + lib/bt/esp_ble_mesh/core/prov_node.c | 37 +- lib/bt/esp_ble_mesh/core/prov_pvnr.c | 55 +- lib/bt/esp_ble_mesh/core/prov_pvnr.h | 2 + lib/bt/esp_ble_mesh/core/proxy_client.c | 91 +- lib/bt/esp_ble_mesh/core/proxy_client.h | 4 + lib/bt/esp_ble_mesh/core/proxy_server.c | 121 +- lib/bt/esp_ble_mesh/core/proxy_server.h | 4 +- lib/bt/esp_ble_mesh/core/pvnr_mgmt.c | 2 + lib/bt/esp_ble_mesh/core/scan.c | 218 +- lib/bt/esp_ble_mesh/core/scan.h | 8 +- lib/bt/esp_ble_mesh/core/storage/settings.c | 5 +- lib/bt/esp_ble_mesh/core/tag.h | 53 + lib/bt/esp_ble_mesh/core/transport.c | 67 +- lib/bt/esp_ble_mesh/core/transport.enh.c | 6 +- lib/bt/esp_ble_mesh/lib/ext.c | 88 +- lib/bt/esp_ble_mesh/lib/include/mesh_v1.1/utils.h | 2 +- lib/bt/esp_ble_mesh/lib/lib/esp32/libble_mesh.a | Bin 943462 -> 1487706 bytes lib/bt/esp_ble_mesh/lib/lib/esp32c3/libble_mesh.a | Bin 2057546 -> 2605230 bytes lib/bt/esp_ble_mesh/lib/lib/esp32c5/libble_mesh.a | Bin 0 -> 2605230 bytes lib/bt/esp_ble_mesh/lib/lib/esp32c6/libble_mesh.a | Bin 2057546 -> 2605230 bytes lib/bt/esp_ble_mesh/lib/lib/esp32c61/libble_mesh.a | Bin 0 -> 2605230 bytes lib/bt/esp_ble_mesh/lib/lib/esp32h2/libble_mesh.a | Bin 2057546 -> 2605230 bytes lib/bt/esp_ble_mesh/lib/lib/esp32s3/libble_mesh.a | Bin 943462 -> 1487414 bytes lib/bt/esp_ble_mesh/models/client/client_common.c | 2 + .../esp_ble_mesh/models/server/time_scene_server.c | 6 +- .../v1.1/api/core/esp_ble_mesh_rpr_model_api.c | 33 +- .../api/core/include/esp_ble_mesh_rpr_model_api.h | 22 +- .../esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c | 84 +- .../v1.1/btc/include/btc_ble_mesh_rpr_model.h | 20 +- lib/bt/host/bluedroid/Kconfig.in | 409 +++- lib/bt/host/bluedroid/api/esp_a2dp_api.c | 150 +- lib/bt/host/bluedroid/api/esp_avrc_api.c | 185 +- lib/bt/host/bluedroid/api/esp_ble_cte_api.c | 224 ++ lib/bt/host/bluedroid/api/esp_ble_iso_api.c | 425 ++++ lib/bt/host/bluedroid/api/esp_bluedroid_hci.c | 9 +- lib/bt/host/bluedroid/api/esp_bt_device.c | 7 +- lib/bt/host/bluedroid/api/esp_bt_main.c | 32 +- lib/bt/host/bluedroid/api/esp_gap_ble_api.c | 417 +++- lib/bt/host/bluedroid/api/esp_gap_bt_api.c | 25 +- lib/bt/host/bluedroid/api/esp_gattc_api.c | 186 +- lib/bt/host/bluedroid/api/esp_gatts_api.c | 7 +- lib/bt/host/bluedroid/api/esp_hf_ag_api.c | 87 +- lib/bt/host/bluedroid/api/esp_hf_client_api.c | 82 +- lib/bt/host/bluedroid/api/esp_hidd_api.c | 15 +- lib/bt/host/bluedroid/api/esp_hidh_api.c | 15 +- lib/bt/host/bluedroid/api/esp_l2cap_bt_api.c | 29 +- lib/bt/host/bluedroid/api/esp_pbac_api.c | 251 +++ lib/bt/host/bluedroid/api/esp_sdp_api.c | 74 +- lib/bt/host/bluedroid/api/esp_spp_api.c | 15 +- .../host/bluedroid/api/include/api/esp_a2dp_api.h | 272 ++- .../api/include/api/esp_a2dp_legacy_api.h | 77 + .../host/bluedroid/api/include/api/esp_avrc_api.h | 210 +- .../bluedroid/api/include/api/esp_ble_cte_api.h | 379 ++++ .../bluedroid/api/include/api/esp_ble_iso_api.h | 660 ++++++ .../host/bluedroid/api/include/api/esp_bt_defs.h | 118 +- .../host/bluedroid/api/include/api/esp_bt_device.h | 13 +- .../host/bluedroid/api/include/api/esp_bt_main.h | 14 +- .../bluedroid/api/include/api/esp_gap_ble_api.h | 634 +++++- .../bluedroid/api/include/api/esp_gap_bt_api.h | 53 +- .../host/bluedroid/api/include/api/esp_gatt_defs.h | 15 +- .../host/bluedroid/api/include/api/esp_gattc_api.h | 1073 ++++++---- .../host/bluedroid/api/include/api/esp_gatts_api.h | 621 +++--- .../host/bluedroid/api/include/api/esp_hf_ag_api.h | 129 +- .../api/include/api/esp_hf_ag_legacy_api.h | 77 + .../bluedroid/api/include/api/esp_hf_client_api.h | 132 +- .../api/include/api/esp_hf_client_legacy_api.h | 78 + .../host/bluedroid/api/include/api/esp_hf_defs.h | 37 +- .../host/bluedroid/api/include/api/esp_hidd_api.h | 28 +- .../host/bluedroid/api/include/api/esp_hidh_api.h | 32 +- .../bluedroid/api/include/api/esp_l2cap_bt_api.h | 41 +- .../host/bluedroid/api/include/api/esp_pba_defs.h | 27 + .../host/bluedroid/api/include/api/esp_pbac_api.h | 340 +++ .../host/bluedroid/api/include/api/esp_sdp_api.h | 210 +- .../host/bluedroid/api/include/api/esp_spp_api.h | 20 +- lib/bt/host/bluedroid/bta/av/bta_av_aact.c | 47 +- lib/bt/host/bluedroid/bta/av/bta_av_act.c | 91 +- lib/bt/host/bluedroid/bta/av/bta_av_api.c | 90 + lib/bt/host/bluedroid/bta/av/bta_av_ca_act.c | 496 +++++ lib/bt/host/bluedroid/bta/av/bta_av_ca_sm.c | 170 ++ lib/bt/host/bluedroid/bta/av/bta_av_main.c | 113 +- lib/bt/host/bluedroid/bta/av/bta_av_sbc.c | 58 + lib/bt/host/bluedroid/bta/av/include/bta_av_int.h | 118 +- lib/bt/host/bluedroid/bta/dm/bta_dm_act.c | 413 +++- lib/bt/host/bluedroid/bta/dm/bta_dm_api.c | 902 +++++++- lib/bt/host/bluedroid/bta/dm/bta_dm_cfg.c | 16 +- lib/bt/host/bluedroid/bta/dm/bta_dm_co.c | 12 + lib/bt/host/bluedroid/bta/dm/bta_dm_main.c | 122 +- lib/bt/host/bluedroid/bta/dm/bta_dm_pm.c | 9 +- lib/bt/host/bluedroid/bta/dm/include/bta_dm_int.h | 665 +++++- lib/bt/host/bluedroid/bta/gatt/bta_gattc_act.c | 143 +- lib/bt/host/bluedroid/bta/gatt/bta_gattc_api.c | 98 +- lib/bt/host/bluedroid/bta/gatt/bta_gattc_main.c | 18 +- lib/bt/host/bluedroid/bta/gatt/bta_gattc_utils.c | 14 +- lib/bt/host/bluedroid/bta/gatt/bta_gatts_act.c | 41 +- lib/bt/host/bluedroid/bta/gatt/bta_gatts_api.c | 37 - lib/bt/host/bluedroid/bta/gatt/bta_gatts_main.c | 3 - .../bluedroid/bta/gatt/include/bta_gattc_int.h | 45 +- .../bluedroid/bta/gatt/include/bta_gatts_int.h | 13 +- lib/bt/host/bluedroid/bta/hf_ag/bta_ag_api.c | 67 + lib/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c | 2 +- lib/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c | 31 +- lib/bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c | 344 ++- .../host/bluedroid/bta/hf_ag/include/bta_ag_int.h | 18 + .../bluedroid/bta/hf_client/bta_hf_client_act.c | 2 + .../bluedroid/bta/hf_client/bta_hf_client_api.c | 87 +- .../bluedroid/bta/hf_client/bta_hf_client_main.c | 27 +- .../bluedroid/bta/hf_client/bta_hf_client_sco.c | 334 ++- .../bta/hf_client/include/bta_hf_client_int.h | 19 +- lib/bt/host/bluedroid/bta/hh/bta_hh_le.c | 40 +- lib/bt/host/bluedroid/bta/include/bta/bta_ag_api.h | 49 +- lib/bt/host/bluedroid/bta/include/bta/bta_api.h | 357 +++- lib/bt/host/bluedroid/bta/include/bta/bta_ar_api.h | 6 +- lib/bt/host/bluedroid/bta/include/bta/bta_av_api.h | 96 +- lib/bt/host/bluedroid/bta/include/bta/bta_av_sbc.h | 12 + .../host/bluedroid/bta/include/bta/bta_gatt_api.h | 90 +- .../bluedroid/bta/include/bta/bta_hf_client_api.h | 66 + lib/bt/host/bluedroid/bta/include/bta/bta_jv_api.h | 9 +- .../bluedroid/bta/include/bta/bta_pba_client_api.h | 92 + .../host/bluedroid/bta/include/bta/bta_pba_defs.h | 93 + .../host/bluedroid/bta/include/bta/bta_sdp_api.h | 33 +- lib/bt/host/bluedroid/bta/include/bta/bta_sys.h | 5 +- lib/bt/host/bluedroid/bta/include/bta/utl.h | 7 +- lib/bt/host/bluedroid/bta/jv/bta_jv_act.c | 22 +- lib/bt/host/bluedroid/bta/pba/bta_pba_client_act.c | 702 ++++++ lib/bt/host/bluedroid/bta/pba/bta_pba_client_api.c | 162 ++ .../host/bluedroid/bta/pba/bta_pba_client_main.c | 293 +++ lib/bt/host/bluedroid/bta/pba/bta_pba_client_sdp.c | 279 +++ .../bluedroid/bta/pba/include/bta_pba_client_int.h | 177 ++ lib/bt/host/bluedroid/bta/sdp/bta_sdp.c | 9 +- lib/bt/host/bluedroid/bta/sdp/bta_sdp_act.c | 144 +- lib/bt/host/bluedroid/bta/sdp/bta_sdp_api.c | 29 +- lib/bt/host/bluedroid/bta/sdp/bta_sdp_cfg.c | 8 + .../host/bluedroid/bta/sdp/include/bta_sdp_int.h | 2 + lib/bt/host/bluedroid/bta/sys/utl.c | 17 +- lib/bt/host/bluedroid/btc/core/btc_ble_storage.c | 13 +- lib/bt/host/bluedroid/btc/core/btc_config.c | 13 +- lib/bt/host/bluedroid/btc/core/btc_dm.c | 29 +- lib/bt/host/bluedroid/btc/core/btc_main.c | 51 +- lib/bt/host/bluedroid/btc/core/btc_util.c | 47 +- lib/bt/host/bluedroid/btc/include/btc/btc_config.h | 2 + lib/bt/host/bluedroid/btc/include/btc/btc_main.h | 4 +- lib/bt/host/bluedroid/btc/include/btc/btc_util.h | 9 +- .../bluedroid/btc/profile/std/a2dp/bta_av_co.c | 67 +- .../host/bluedroid/btc/profile/std/a2dp/btc_a2dp.c | 9 +- .../btc/profile/std/a2dp/btc_a2dp_control.c | 2 + .../bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c | 61 +- .../btc/profile/std/a2dp/btc_a2dp_sink_ext_coedc.c | 286 +++ .../btc/profile/std/a2dp/btc_a2dp_source.c | 50 +- .../profile/std/a2dp/btc_a2dp_source_ext_codec.c | 235 ++ .../host/bluedroid/btc/profile/std/a2dp/btc_av.c | 292 ++- .../btc/profile/std/a2dp/include/btc_av_co.h | 8 +- .../host/bluedroid/btc/profile/std/avrc/btc_avrc.c | 457 +++- .../bluedroid/btc/profile/std/cte/btc_ble_cte.c | 395 ++++ .../bluedroid/btc/profile/std/gap/btc_gap_ble.c | 589 +++-- .../bluedroid/btc/profile/std/gap/btc_gap_bt.c | 106 +- .../bluedroid/btc/profile/std/gatt/btc_gatt_util.c | 36 +- .../bluedroid/btc/profile/std/gatt/btc_gattc.c | 9 +- .../bluedroid/btc/profile/std/gatt/btc_gatts.c | 7 +- .../bluedroid/btc/profile/std/hf_ag/bta_ag_co.c | 136 +- .../bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c | 129 +- .../btc/profile/std/hf_client/bta_hf_client_co.c | 134 +- .../btc/profile/std/hf_client/btc_hf_client.c | 83 +- lib/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c | 33 +- lib/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c | 23 +- .../bluedroid/btc/profile/std/include/bt_sdp.h | 80 +- .../btc/profile/std/include/btc_a2dp_source.h | 100 +- .../bluedroid/btc/profile/std/include/btc_av.h | 124 +- .../bluedroid/btc/profile/std/include/btc_av_api.h | 3 + .../bluedroid/btc/profile/std/include/btc_avrc.h | 50 +- .../btc/profile/std/include/btc_ble_cte.h | 98 + .../btc/profile/std/include/btc_gap_ble.h | 125 +- .../bluedroid/btc/profile/std/include/btc_gap_bt.h | 5 + .../btc/profile/std/include/btc_gatt_util.h | 3 +- .../bluedroid/btc/profile/std/include/btc_gattc.h | 5 + .../bluedroid/btc/profile/std/include/btc_hd.h | 7 +- .../bluedroid/btc/profile/std/include/btc_hf_ag.h | 15 +- .../btc/profile/std/include/btc_hf_client.h | 16 +- .../bluedroid/btc/profile/std/include/btc_hh.h | 2 + .../btc/profile/std/include/btc_iso_ble.h | 222 ++ .../bluedroid/btc/profile/std/include/btc_l2cap.h | 6 +- .../btc/profile/std/include/btc_pba_client.h | 90 + .../bluedroid/btc/profile/std/include/btc_sdp.h | 13 +- .../bluedroid/btc/profile/std/include/btc_spp.h | 1 + .../bluedroid/btc/profile/std/iso/btc_iso_ble.c | 384 ++++ .../bluedroid/btc/profile/std/l2cap/btc_l2cap.c | 129 +- .../bluedroid/btc/profile/std/pba/btc_pba_client.c | 968 +++++++++ .../host/bluedroid/btc/profile/std/sdp/btc_sdp.c | 717 ++++--- .../host/bluedroid/btc/profile/std/spp/btc_spp.c | 40 +- .../common/include/common/bluedroid_user_config.h | 263 ++- .../bluedroid/common/include/common/bt_target.h | 473 +++- .../bluedroid/common/include/common/bt_trace.h | 192 ++ .../bluedroid/config/include/config/stack_config.h | 7 +- lib/bt/host/bluedroid/config/stack_config.c | 14 +- lib/bt/host/bluedroid/device/controller.c | 75 +- .../bluedroid/device/include/device/controller.h | 5 + .../external/sbc/decoder/include/oi_codec_sbc.h | 2 +- .../external/sbc/encoder/srce/sbc_encoder.c | 12 +- lib/bt/host/bluedroid/hci/ble_hci_iso.c | 346 +++ lib/bt/host/bluedroid/hci/hci_hal_h4.c | 158 +- lib/bt/host/bluedroid/hci/hci_layer.c | 2 + lib/bt/host/bluedroid/hci/hci_packet_factory.c | 28 +- lib/bt/host/bluedroid/hci/hci_packet_parser.c | 62 +- .../host/bluedroid/hci/include/hci/ble_hci_iso.h | 85 + lib/bt/host/bluedroid/hci/include/hci/hci_hal.h | 3 +- lib/bt/host/bluedroid/hci/include/hci/hci_layer.h | 3 +- .../bluedroid/hci/include/hci/hci_packet_factory.h | 10 + .../bluedroid/hci/include/hci/hci_packet_parser.h | 20 +- lib/bt/host/bluedroid/hci/packet_fragmenter.c | 6 + lib/bt/host/bluedroid/main/bte_init.c | 49 +- lib/bt/host/bluedroid/main/bte_main.c | 10 +- lib/bt/host/bluedroid/stack/avct/avct_lcb.c | 6 +- lib/bt/host/bluedroid/stack/avdt/avdt_api.c | 31 + lib/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c | 24 +- lib/bt/host/bluedroid/stack/avrc/avrc_pars_ct.c | 13 + lib/bt/host/bluedroid/stack/avrc/avrc_pars_tg.c | 2 +- lib/bt/host/bluedroid/stack/avrc/avrc_sdp.c | 23 +- lib/bt/host/bluedroid/stack/btm/btm_acl.c | 186 +- lib/bt/host/bluedroid/stack/btm/btm_ble.c | 80 +- lib/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c | 351 ++- lib/bt/host/bluedroid/stack/btm/btm_ble_addr.c | 12 + .../host/bluedroid/stack/btm/btm_ble_adv_filter.c | 30 +- .../host/bluedroid/stack/btm/btm_ble_batchscan.c | 36 +- lib/bt/host/bluedroid/stack/btm/btm_ble_bgconn.c | 46 +- .../host/bluedroid/stack/btm/btm_ble_cont_energy.c | 2 + lib/bt/host/bluedroid/stack/btm/btm_ble_cte.c | 237 ++ lib/bt/host/bluedroid/stack/btm/btm_ble_gap.c | 363 ++-- lib/bt/host/bluedroid/stack/btm/btm_ble_iso.c | 525 +++++ .../host/bluedroid/stack/btm/btm_ble_multi_adv.c | 23 +- lib/bt/host/bluedroid/stack/btm/btm_ble_privacy.c | 21 +- lib/bt/host/bluedroid/stack/btm/btm_dev.c | 29 +- lib/bt/host/bluedroid/stack/btm/btm_devctl.c | 44 +- lib/bt/host/bluedroid/stack/btm/btm_inq.c | 13 +- lib/bt/host/bluedroid/stack/btm/btm_main.c | 26 +- lib/bt/host/bluedroid/stack/btm/btm_pm.c | 10 +- lib/bt/host/bluedroid/stack/btm/btm_sco.c | 59 +- lib/bt/host/bluedroid/stack/btm/btm_sec.c | 18 +- .../host/bluedroid/stack/btm/include/btm_ble_int.h | 71 +- lib/bt/host/bluedroid/stack/btm/include/btm_int.h | 38 +- lib/bt/host/bluedroid/stack/btu/btu_hcif.c | 766 ++++++- lib/bt/host/bluedroid/stack/btu/btu_init.c | 11 - lib/bt/host/bluedroid/stack/btu/btu_task.c | 4 +- lib/bt/host/bluedroid/stack/gatt/gatt_api.c | 28 +- lib/bt/host/bluedroid/stack/gatt/gatt_db.c | 44 +- lib/bt/host/bluedroid/stack/gatt/gatt_main.c | 12 +- lib/bt/host/bluedroid/stack/gatt/gatt_sr.c | 25 +- lib/bt/host/bluedroid/stack/gatt/gatt_sr_hash.c | 1 - lib/bt/host/bluedroid/stack/gatt/gatt_utils.c | 42 +- .../host/bluedroid/stack/gatt/include/gatt_int.h | 9 +- lib/bt/host/bluedroid/stack/goep/goepc_api.c | 376 ++++ lib/bt/host/bluedroid/stack/goep/goepc_main.c | 528 +++++ .../host/bluedroid/stack/goep/include/goep_int.h | 103 + lib/bt/host/bluedroid/stack/hcic/hciblecmds.c | 942 +++++++- .../host/bluedroid/stack/include/stack/a2d_sbc.h | 7 +- .../stack/include/stack/acl_hci_link_interface.h | 2 +- .../host/bluedroid/stack/include/stack/avdt_api.h | 12 + .../host/bluedroid/stack/include/stack/avrc_api.h | 8 +- .../host/bluedroid/stack/include/stack/avrc_defs.h | 5 +- .../host/bluedroid/stack/include/stack/bt_types.h | 1 + .../host/bluedroid/stack/include/stack/btm_api.h | 60 +- .../bluedroid/stack/include/stack/btm_ble_api.h | 659 +++++- .../host/bluedroid/stack/include/stack/dyn_mem.h | 16 + .../host/bluedroid/stack/include/stack/gatt_api.h | 2 +- .../bluedroid/stack/include/stack/goep_common.h | 19 + .../host/bluedroid/stack/include/stack/goepc_api.h | 82 + .../host/bluedroid/stack/include/stack/hcidefs.h | 140 +- .../host/bluedroid/stack/include/stack/hcimsgs.h | 182 +- .../host/bluedroid/stack/include/stack/obex_api.h | 271 +++ .../host/bluedroid/stack/include/stack/sdp_api.h | 16 +- .../host/bluedroid/stack/l2cap/include/l2c_int.h | 14 +- lib/bt/host/bluedroid/stack/l2cap/l2c_ble.c | 42 +- lib/bt/host/bluedroid/stack/l2cap/l2c_link.c | 22 +- lib/bt/host/bluedroid/stack/l2cap/l2c_utils.c | 14 +- .../host/bluedroid/stack/obex/include/obex_int.h | 76 + lib/bt/host/bluedroid/stack/obex/include/obex_tl.h | 97 + .../bluedroid/stack/obex/include/obex_tl_l2cap.h | 18 + .../bluedroid/stack/obex/include/obex_tl_rfcomm.h | 18 + lib/bt/host/bluedroid/stack/obex/obex_api.c | 776 +++++++ lib/bt/host/bluedroid/stack/obex/obex_main.c | 216 ++ lib/bt/host/bluedroid/stack/obex/obex_tl_l2cap.c | 811 +++++++ lib/bt/host/bluedroid/stack/obex/obex_tl_rfcomm.c | 439 ++++ lib/bt/host/bluedroid/stack/sdp/sdp_api.c | 26 +- lib/bt/host/bluedroid/stack/sdp/sdp_db.c | 40 +- lib/bt/host/bluedroid/stack/sdp/sdp_discovery.c | 3 +- lib/bt/host/bluedroid/stack/smp/smp_act.c | 12 +- lib/bt/host/bluedroid/stack/smp/smp_utils.c | 5 +- lib/bt/host/nimble/Kconfig.in | 659 ++++-- lib/bt/host/nimble/esp-hci/src/esp_nimble_hci.c | 72 +- lib/bt/host/nimble/nimble/.travis.yml | 156 -- lib/bt/host/nimble/nimble/apps/blecent/src/main.c | 2 +- .../host/nimble/nimble/apps/bttester/src/atomic.h | 405 ---- .../nimble/nimble/apps/bttester/src/bttester.h | 1321 ------------ lib/bt/host/nimble/nimble/apps/bttester/src/gap.c | 1775 --------------- .../host/nimble/nimble/apps/bttester/src/gatt_cl.c | 1483 ------------- lib/bt/host/nimble/nimble/apps/bttester/src/glue.c | 129 -- lib/bt/host/nimble/nimble/apps/bttester/src/glue.h | 63 - .../host/nimble/nimble/apps/bttester/src/l2cap.c | 765 ------- lib/bt/host/nimble/nimble/apps/bttester/src/mesh.c | 993 --------- .../controller/include/controller/ble_ll_plna.h | 45 - .../controller/include/controller/ble_ll_test.h | 35 - .../nimble/nimble/controller/src/ble_ll_supp_cmd.c | 649 ------ .../nimble/controller/test/src/ble_ll_csa2_test.h | 27 - .../nimble/nimble/drivers/nrf52/include/ble/xcvr.h | 52 - .../nimble/nimble/drivers/nrf52/src/ble_hw.c | 511 ----- .../nimble/nimble/drivers/nrf52/src/ble_phy.c | 2257 -------------------- .../nimble/drivers/nrf52/src/ble_phy_trace.c | 44 - .../nimble/nimble/nimble/drivers/nrf52/syscfg.yml | 72 - .../nimble/drivers/nrf5340/include/ble/xcvr.h | 50 - .../nimble/nimble/drivers/nrf5340/src/ble_hw.c | 471 ---- .../nimble/nimble/drivers/nrf5340/src/ble_phy.c | 2038 ------------------ .../nimble/drivers/nrf5340/src/ble_phy_trace.c | 45 - .../nimble/nimble/drivers/nrf5340/syscfg.yml | 62 - .../nimble/nimble/drivers/plna/sky66112/pkg.yml | 31 - .../nimble/drivers/plna/sky66112/src/sky66112.c | 117 - .../nimble/nimble/drivers/plna/sky66112/syscfg.yml | 66 - .../nimble/nimble/host/include/host/ble_att.h | 9 +- .../nimble/nimble/host/include/host/ble_ead.h | 2 - .../nimble/nimble/host/include/host/ble_esp_gap.h | 38 + .../nimble/host/include/host/ble_esp_gattc_cache.h | 255 +++ .../nimble/nimble/host/include/host/ble_gap.h | 732 ++++++- .../nimble/nimble/host/include/host/ble_gatt.h | 87 +- .../nimble/nimble/host/include/host/ble_hs.h | 31 + .../nimble/nimble/host/include/host/ble_hs_adv.h | 28 +- .../nimble/nimble/host/include/host/ble_hs_pvcy.h | 2 +- .../nimble/nimble/host/include/host/ble_store.h | 34 + .../host/nimble/nimble/nimble/host/mesh/src/adv.c | 2 +- .../nimble/nimble/nimble/host/mesh/src/pb_adv.c | 13 +- .../nimble/nimble/host/mesh/src/prov_device.c | 4 +- lib/bt/host/nimble/nimble/nimble/host/pkg.yml | 3 + .../ans/include/services/ans/ble_svc_ans.h | 7 + .../nimble/host/services/ans/src/ble_svc_ans.c | 10 + .../bas/include/services/bas/ble_svc_bas.h | 8 + .../nimble/host/services/bas/src/ble_svc_bas.c | 2 + .../nimble/host/services/bleuart/src/bleuart.c | 2 + .../cte/include/services/cte/ble_svc_cte.h | 44 + .../nimble/nimble/nimble/host/services/cte/pkg.yml | 34 + .../nimble/host/services/cte/src/ble_svc_cte.c | 573 +++++ .../nimble/nimble/host/services/cte/syscfg.yml | 23 + .../cts/include/services/cts/ble_svc_cts.h | 8 + .../nimble/host/services/cts/src/ble_svc_cts.c | 3 +- .../dis/include/services/dis/ble_svc_dis.h | 34 + .../nimble/host/services/dis/src/ble_svc_dis.c | 53 + .../gap/include/services/gap/ble_svc_gap.h | 3 + .../nimble/host/services/gap/src/ble_svc_gap.c | 69 + .../gatt/include/services/gatt/ble_svc_gatt.h | 10 +- .../nimble/host/services/gatt/src/ble_svc_gatt.c | 24 + .../hid/include/services/hid/ble_svc_hid.h | 10 + .../nimble/host/services/hid/src/ble_svc_hid.c | 43 +- .../services/hr/include/services/hr/ble_svc_hr.h | 8 + .../nimble/host/services/hr/src/ble_svc_hr.c | 2 + .../htp/include/services/htp/ble_svc_htp.h | 8 + .../nimble/host/services/htp/src/ble_svc_htp.c | 2 + .../ias/include/services/ias/ble_svc_ias.h | 7 + .../nimble/host/services/ias/src/ble_svc_ias.c | 2 + .../nimble/host/services/ipss/src/ble_svc_ipss.c | 2 + .../nimble/host/services/lls/src/ble_svc_lls.c | 4 + .../prox/include/services/prox/ble_svc_prox.h | 8 + .../nimble/host/services/prox/src/ble_svc_prox.c | 2 + .../sps/include/services/sps/ble_svc_sps.h | 13 +- .../nimble/host/services/sps/src/ble_svc_sps.c | 15 +- .../tps/include/services/tps/ble_svc_tps.h | 7 + .../nimble/host/services/tps/src/ble_svc_tps.c | 2 + .../nimble/nimble/nimble/host/src/ble_aes_ccm.c | 23 +- .../host/nimble/nimble/nimble/host/src/ble_att.c | 238 ++- .../nimble/nimble/nimble/host/src/ble_att_clt.c | 184 +- .../nimble/nimble/nimble/host/src/ble_att_cmd.c | 55 +- .../nimble/nimble/host/src/ble_att_cmd_priv.h | 25 +- .../nimble/nimble/nimble/host/src/ble_att_priv.h | 115 +- .../nimble/nimble/nimble/host/src/ble_att_svr.c | 339 ++- .../host/nimble/nimble/nimble/host/src/ble_ead.c | 27 +- .../host/nimble/nimble/nimble/host/src/ble_eatt.c | 605 ++++++ .../nimble/nimble/nimble/host/src/ble_eatt_priv.h | 58 + .../host/nimble/nimble/nimble/host/src/ble_gap.c | 1815 ++++++++++++++-- .../nimble/nimble/nimble/host/src/ble_gap_priv.h | 17 + .../nimble/nimble/nimble/host/src/ble_gatt_priv.h | 46 +- .../host/nimble/nimble/nimble/host/src/ble_gattc.c | 1024 ++++++++- .../nimble/nimble/host/src/ble_gattc_cache.c | 77 +- .../nimble/nimble/host/src/ble_gattc_cache_conn.c | 886 +++++++- .../nimble/nimble/host/src/ble_gattc_cache_priv.h | 146 +- .../host/nimble/nimble/nimble/host/src/ble_gatts.c | 124 +- lib/bt/host/nimble/nimble/nimble/host/src/ble_hs.c | 57 +- .../nimble/nimble/nimble/host/src/ble_hs_adv.c | 37 + .../nimble/nimble/host/src/ble_hs_adv_priv.h | 2 - .../nimble/nimble/nimble/host/src/ble_hs_cfg.c | 4 + .../nimble/nimble/nimble/host/src/ble_hs_conn.c | 20 +- .../nimble/nimble/host/src/ble_hs_conn_priv.h | 7 + .../nimble/nimble/nimble/host/src/ble_hs_hci.c | 257 ++- .../nimble/nimble/nimble/host/src/ble_hs_hci_cmd.c | 2 +- .../nimble/nimble/nimble/host/src/ble_hs_hci_evt.c | 333 ++- .../nimble/nimble/host/src/ble_hs_hci_priv.h | 6 + .../host/nimble/nimble/nimble/host/src/ble_hs_id.c | 2 + .../nimble/nimble/nimble/host/src/ble_hs_priv.h | 1 + .../nimble/nimble/nimble/host/src/ble_hs_pvcy.c | 4 +- .../nimble/nimble/nimble/host/src/ble_hs_resolv.c | 14 +- .../nimble/nimble/nimble/host/src/ble_hs_startup.c | 80 +- .../host/nimble/nimble/nimble/host/src/ble_l2cap.c | 28 +- .../nimble/nimble/nimble/host/src/ble_l2cap_coc.c | 6 +- .../nimble/nimble/nimble/host/src/ble_l2cap_priv.h | 15 + .../nimble/nimble/nimble/host/src/ble_l2cap_sig.c | 38 +- .../nimble/nimble/host/src/ble_l2cap_sig_priv.h | 4 +- lib/bt/host/nimble/nimble/nimble/host/src/ble_sm.c | 214 +- .../nimble/nimble/nimble/host/src/ble_sm_alg.c | 28 +- .../nimble/nimble/nimble/host/src/ble_sm_cmd.c | 6 +- .../host/nimble/nimble/nimble/host/src/ble_store.c | 62 +- .../nimble/nimble/nimble/host/src/ble_store_util.c | 9 + .../host/store/config/src/ble_store_config.c | 150 +- .../host/store/config/src/ble_store_config_conf.c | 39 + .../host/store/config/src/ble_store_config_priv.h | 6 + .../nimble/host/store/config/src/ble_store_nvs.c | 80 +- .../nimble/host/store/ram/src/ble_store_ram.c | 132 +- lib/bt/host/nimble/nimble/nimble/host/syscfg.yml | 37 + .../nimble/nimble/host/test/src/ble_att_clt_test.c | 53 +- .../nimble/nimble/host/test/src/ble_att_svr_test.c | 27 +- .../nimble/host/test/src/ble_gatt_conn_test.c | 36 + .../nimble/host/test/src/ble_gatt_disc_c_test.c | 32 +- .../nimble/host/test/src/ble_gatt_disc_d_test.c | 24 +- .../nimble/host/test/src/ble_gatt_disc_s_test.c | 52 +- .../nimble/host/test/src/ble_gatt_find_s_test.c | 37 +- .../nimble/host/test/src/ble_gatt_read_test.c | 44 +- .../nimble/host/test/src/ble_gatt_write_test.c | 73 +- .../nimble/nimble/host/test/src/ble_hs_pvcy_test.c | 6 +- .../nimble/nimble/host/test/src/ble_hs_test_util.c | 9 +- .../nimble/nimble/host/test/src/ble_hs_test_util.h | 6 +- .../nimble/host/test/src/ble_hs_test_util_hci.c | 13 + .../nimble/nimble/host/test/src/ble_os_test.c | 2 +- .../host/nimble/nimble/nimble/host/test/syscfg.yml | 1 + .../host/nimble/nimble/nimble/include/nimble/ble.h | 1 + .../nimble/nimble/include/nimble/hci_common.h | 288 ++- .../nimble/nimble/include/nimble/nimble_opt_auto.h | 4 + .../transport/dialog_cmac/cmac_driver/diag/pkg.yml | 28 - .../dialog_cmac/cmac_driver/diag/src/cmac_diag.c | 66 - .../cmac_driver/include/cmac_driver/cmac_diag.h | 34 - .../cmac_driver/include/cmac_driver/cmac_host.h | 35 - .../cmac_driver/include/cmac_driver/cmac_shared.h | 194 -- .../transport/dialog_cmac/cmac_driver/pkg.yml | 39 - .../cmac_driver/scripts/build_libcmac.sh | 45 - .../cmac_driver/scripts/create_cmac_bin.sh | 31 - .../dialog_cmac/cmac_driver/src/cmac_host.c | 375 ---- .../dialog_cmac/cmac_driver/src/cmac_mbox.c | 174 -- .../dialog_cmac/cmac_driver/src/cmac_rand.c | 145 -- .../dialog_cmac/cmac_driver/src/cmac_shared.c | 96 - .../transport/dialog_cmac/cmac_driver/syscfg.yml | 104 - .../nimble/transport/esp_ipc/src/hci_esp_ipc.c | 71 + .../esp_ipc_legacy/src/hci_esp_ipc_legacy.c | 39 + .../nimble/transport/include/nimble/transport.h | 158 +- .../transport/include/nimble/transport_impl.h | 2 + .../nimble/nimble/transport/nrf5340/syscfg.yml | 20 - .../nimble/nimble/transport/uart_ll/src/hci_uart.c | 10 + .../porting/examples/linux/include/logcfg/logcfg.h | 7 + .../porting/examples/linux/include/syscfg/syscfg.h | 24 + .../examples/linux_blemesh/include/logcfg/logcfg.h | 7 + .../examples/linux_blemesh/include/syscfg/syscfg.h | 24 + .../porting/examples/nuttx/include/syscfg/syscfg.h | 4 + .../nimble/porting/nimble/include/hal/hal_uart.h | 5 + .../nimble/porting/nimble/include/logcfg/logcfg.h | 7 + .../nimble/nimble/porting/nimble/include/os/os.h | 8 - .../nimble/porting/nimble/include/syscfg/syscfg.h | 24 + .../nimble/nimble/porting/nimble/src/hal_uart.c | 8 + .../nimble/nimble/porting/nimble/src/nimble_port.c | 13 +- .../nimble/nimble/porting/nimble/src/os_mbuf.c | 14 + .../nimble/nimble/porting/nimble/src/os_mempool.c | 1 + .../freertos/include/nimble/nimble_port_freertos.h | 1 + .../porting/npl/freertos/src/npl_os_freertos.c | 38 +- .../porting/npl/riot/include/logcfg/logcfg.h | 7 + .../npl/riot/include/npl_syscfg/npl_sycfg.h | 1991 ++++++++++++++++- .../porting/npl/riot/include/syscfg/syscfg.h | 24 + lib/bt/host/nimble/nimble/sbom.yml | 2 +- lib/bt/host/nimble/port/include/esp_nimble_cfg.h | 272 ++- lib/bt/include/esp32/include/esp_bt.h | 708 +++--- lib/bt/include/esp32/include/esp_bt_vs.h | 252 +++ lib/bt/include/esp32c2/include/esp_bt.h | 69 +- lib/bt/include/esp32c2/include/esp_bt_vs.h | 214 ++ lib/bt/include/esp32c3/include/esp_bt.h | 820 ++++--- lib/bt/include/esp32c3/include/esp_bt_vs.h | 175 ++ lib/bt/include/esp32c5/include/esp_bt.h | 61 +- lib/bt/include/esp32c5/include/esp_bt_vs.h | 360 ++++ lib/bt/include/esp32c6/include/esp_bt.h | 122 +- lib/bt/include/esp32c6/include/esp_bt_vs.h | 360 ++++ lib/bt/include/esp32h2/include/esp_bt.h | 82 +- lib/bt/include/esp32h2/include/esp_bt_vs.h | 360 ++++ lib/bt/include/esp32h4/include/esp_bt_cfg.h | 20 +- lib/bt/linker.lf | 57 - lib/bt/linker.lf.esp32c2 | 60 - lib/bt/linker_common.lf | 29 - lib/bt/linker_esp32c2.lf | 49 +- lib/bt/linker_esp_ble_controller.lf | 42 + lib/bt/linker_rw_bt_controller.lf | 30 + lib/bt/porting/ext/tinycrypt/AUTHORS | 15 - lib/bt/porting/ext/tinycrypt/LICENSE | 61 - lib/bt/porting/ext/tinycrypt/README | 70 - lib/bt/porting/ext/tinycrypt/VERSION | 1 - .../ext/tinycrypt/documentation/tinycrypt.rst | 352 --- .../porting/ext/tinycrypt/include/tinycrypt/aes.h | 130 -- .../ext/tinycrypt/include/tinycrypt/cbc_mode.h | 151 -- .../ext/tinycrypt/include/tinycrypt/ccm_mode.h | 211 -- .../ext/tinycrypt/include/tinycrypt/cmac_mode.h | 194 -- .../ext/tinycrypt/include/tinycrypt/constants.h | 61 - .../ext/tinycrypt/include/tinycrypt/ctr_mode.h | 108 - .../ext/tinycrypt/include/tinycrypt/ctr_prng.h | 166 -- .../porting/ext/tinycrypt/include/tinycrypt/ecc.h | 545 ----- .../ext/tinycrypt/include/tinycrypt/ecc_dh.h | 131 -- .../ext/tinycrypt/include/tinycrypt/ecc_dsa.h | 139 -- .../include/tinycrypt/ecc_platform_specific.h | 81 - .../porting/ext/tinycrypt/include/tinycrypt/hmac.h | 139 -- .../ext/tinycrypt/include/tinycrypt/hmac_prng.h | 164 -- .../ext/tinycrypt/include/tinycrypt/sha256.h | 129 -- .../ext/tinycrypt/include/tinycrypt/utils.h | 95 - lib/bt/porting/ext/tinycrypt/src/aes_decrypt.c | 164 -- lib/bt/porting/ext/tinycrypt/src/aes_encrypt.c | 191 -- lib/bt/porting/ext/tinycrypt/src/cbc_mode.c | 114 - lib/bt/porting/ext/tinycrypt/src/ccm_mode.c | 266 --- lib/bt/porting/ext/tinycrypt/src/cmac_mode.c | 254 --- lib/bt/porting/ext/tinycrypt/src/ctr_mode.c | 85 - lib/bt/porting/ext/tinycrypt/src/ctr_prng.c | 279 --- lib/bt/porting/ext/tinycrypt/src/ecc.c | 939 -------- lib/bt/porting/ext/tinycrypt/src/ecc_dh.c | 200 -- lib/bt/porting/ext/tinycrypt/src/ecc_dsa.c | 294 --- .../ext/tinycrypt/src/ecc_platform_specific.c | 104 - lib/bt/porting/ext/tinycrypt/src/hmac.c | 148 -- lib/bt/porting/ext/tinycrypt/src/hmac_prng.c | 212 -- lib/bt/porting/ext/tinycrypt/src/sha256.c | 217 -- lib/bt/porting/ext/tinycrypt/src/utils.c | 74 - lib/bt/porting/include/ble_hci_trans.h | 315 --- lib/bt/porting/mem/bt_osi_mem.c | 23 +- lib/bt/porting/mem/bt_osi_mem.h | 21 - lib/bt/porting/nimble/include/nimble/ble.h | 319 --- .../porting/nimble/include/nimble/ble_hci_trans.h | 328 --- lib/bt/porting/nimble/include/nimble/nimble_npl.h | 180 -- lib/bt/porting/nimble/include/nimble/nimble_opt.h | 34 - .../nimble/include/nimble/nimble_opt_auto.h | 128 -- lib/bt/porting/nimble/include/nimble/nimble_port.h | 78 - lib/bt/porting/nimble/include/os/endian.h | 296 --- lib/bt/porting/nimble/include/os/os.h | 66 - lib/bt/porting/nimble/include/os/os_error.h | 69 - lib/bt/porting/nimble/include/os/os_mbuf.h | 1145 ---------- lib/bt/porting/nimble/include/os/os_mempool.h | 407 ---- lib/bt/porting/nimble/include/os/queue.h | 218 -- lib/bt/porting/nimble/include/os/util.h | 45 - lib/bt/porting/nimble/src/os_msys_init.c | 240 --- lib/bt/porting/npl/freertos/src/npl_os_freertos.c | 63 +- .../transport/driver/common/hci_driver_h4.c | 421 ++++ .../transport/driver/common/hci_driver_mem.c | 62 + .../transport/driver/common/hci_driver_util.c | 232 ++ .../transport/driver/uart/hci_driver_uart.c | 239 +++ .../transport/driver/uart/hci_driver_uart.h | 87 + .../transport/driver/uart/hci_driver_uart_config.c | 68 + .../transport/driver/uart/hci_driver_uart_dma.c | 664 ++++++ .../transport/driver/vhci/hci_driver_nimble.c | 61 + .../transport/driver/vhci/hci_driver_standard.c | 161 ++ .../transport/driver/vhci/hci_driver_tamplete.c | 133 ++ .../transport/include/common/hci_driver_h4.h | 88 + .../transport/include/common/hci_driver_mem.h | 25 + .../transport/include/common/hci_driver_util.h | 23 + lib/bt/porting/transport/include/esp_hci_driver.h | 81 + .../porting/transport/include/esp_hci_internal.h | 121 ++ .../porting/transport/include/esp_hci_transport.h | 83 + lib/bt/porting/transport/include/hci_uart.h | 100 - lib/bt/porting/transport/src/hci_transport.c | 177 ++ lib/bt/porting/transport/uart/hci_uart.c | 207 -- lib/bt/sdkconfig.rename | 1 - lib/bt/test_apps/CMakeLists.txt | 9 - lib/bt/test_apps/README.md | 21 - .../basic_unit_test/pytest_basic_unit_test.py | 6 +- lib/bt/test_apps/main/CMakeLists.txt | 6 - lib/bt/test_apps/main/test_bt_common.c | 24 - lib/bt/test_apps/main/test_bt_main.c | 48 - lib/bt/test_apps/main/test_smp.c | 126 -- .../test_apps/memory_release/main/test_app_main.c | 5 +- .../memory_release/pytest_memory_release.py | 20 +- lib/bt/test_apps/memory_release/sdkconfig.defaults | 2 + lib/bt/test_apps/pytest_bt.py | 12 - lib/bt/test_apps/sdkconfig.defaults | 3 - lib/fatfs/.build-test-rules.yml | 7 - lib/fatfs/Kconfig | 111 +- lib/fatfs/diskio/diskio.c | 6 +- lib/fatfs/diskio/diskio_rawflash.c | 16 +- lib/fatfs/diskio/diskio_sdmmc.c | 18 +- lib/fatfs/diskio/diskio_sdmmc.h | 2 +- lib/fatfs/diskio/diskio_wl.c | 24 +- lib/fatfs/fatfs_utils/boot_sector.py | 22 +- lib/fatfs/fatfs_utils/fatfs_state.py | 3 +- lib/fatfs/fatfs_utils/utils.py | 34 +- lib/fatfs/fatfsgen.py | 67 +- lib/fatfs/fatfsparse.py | 11 +- lib/fatfs/host_test/.build-test-rules.yml | 7 + lib/fatfs/host_test/CMakeLists.txt | 4 +- lib/fatfs/host_test/main/CMakeLists.txt | 8 +- lib/fatfs/host_test/main/idf_component.yml | 2 + lib/fatfs/host_test/main/main.cpp | 7 - lib/fatfs/host_test/main/test_fatfs.cpp | 22 +- lib/fatfs/host_test/partition_table.csv | 4 +- lib/fatfs/host_test/pytest_fatfs_linux.py | 5 +- lib/fatfs/host_test/sdkconfig.defaults | 1 - lib/fatfs/port/freertos/ffsystem.c | 2 +- lib/fatfs/project_include.cmake | 57 +- lib/fatfs/src/ff.c | 59 +- lib/fatfs/src/ff.h | 12 +- lib/fatfs/src/ffconf.h | 43 +- lib/fatfs/test_apps/.build-test-rules.yml | 48 +- lib/fatfs/test_apps/README.md | 4 + lib/fatfs/test_apps/dyn_buffers/CMakeLists.txt | 7 + lib/fatfs/test_apps/dyn_buffers/README.md | 8 + .../test_apps/dyn_buffers/main/CMakeLists.txt | 3 + .../dyn_buffers/main/test_fatfs_dyn_buffers.c | 101 + lib/fatfs/test_apps/dyn_buffers/partitions.csv | 5 + .../dyn_buffers/pytest_fatfs_dyn_buffers.py | 22 + .../test_apps/dyn_buffers/sdkconfig.ci.dyn_buffers | 1 + .../dyn_buffers/sdkconfig.ci.no_dyn_buffers | 1 + lib/fatfs/test_apps/dyn_buffers/sdkconfig.defaults | 14 + lib/fatfs/test_apps/flash_ro/README.md | 4 +- .../test_apps/flash_ro/main/test_fatfs_flash_ro.c | 3 +- .../test_apps/flash_ro/pytest_fatfs_flash_ro.py | 12 +- lib/fatfs/test_apps/flash_wl/README.md | 4 +- lib/fatfs/test_apps/flash_wl/main/CMakeLists.txt | 2 +- .../test_apps/flash_wl/main/Kconfig.projbuild | 10 + .../test_apps/flash_wl/main/test_fatfs_flash_wl.c | 92 +- .../flash_wl/main/test_fatfs_small_partition.c | 76 + lib/fatfs/test_apps/flash_wl/partitions.csv | 1 + .../test_apps/flash_wl/pytest_fatfs_flash_wl.py | 27 +- .../test_apps/flash_wl/sdkconfig.ci.auto_fsync | 2 + .../test_apps/flash_wl/sdkconfig.ci.dyn_buffers | 1 + lib/fatfs/test_apps/flash_wl/sdkconfig.ci.psram | 3 - .../test_apps/flash_wl/sdkconfig.ci.psram.esp32 | 4 + lib/fatfs/test_apps/sdcard/README.md | 4 +- lib/fatfs/test_apps/sdcard/main/CMakeLists.txt | 2 +- lib/fatfs/test_apps/sdcard/main/test_fatfs_sdmmc.c | 275 ++- lib/fatfs/test_apps/sdcard/main/test_fatfs_sdspi.c | 61 +- lib/fatfs/test_apps/sdcard/pytest_fatfs_sdcard.py | 48 +- lib/fatfs/test_apps/sdcard/sdkconfig.ci.psram | 3 - .../test_apps/sdcard/sdkconfig.ci.psram.esp32 | 4 + .../test_apps/test_fatfs_common/CMakeLists.txt | 2 +- .../test_fatfs_common/test_fatfs_common.c | 245 ++- .../test_fatfs_common/test_fatfs_common.h | 10 +- lib/fatfs/test_fatfs_host/Makefile | 106 - lib/fatfs/test_fatfs_host/Makefile.files | 44 - lib/fatfs/test_fatfs_host/component.mk | 17 - lib/fatfs/test_fatfs_host/main.cpp | 2 - lib/fatfs/test_fatfs_host/partition_table.csv | 6 - lib/fatfs/test_fatfs_host/test_fatfs.cpp | 94 - lib/fatfs/test_fatfsgen/test_fatfsgen.py | 441 +++- lib/fatfs/test_fatfsgen/test_fatfsparse.py | 50 +- lib/fatfs/test_fatfsgen/test_wl_fatfsgen.py | 187 +- lib/fatfs/vfs/esp_vfs_fat.h | 118 +- lib/fatfs/vfs/vfs_fat.c | 625 ++++-- lib/fatfs/vfs/vfs_fat_internal.h | 47 +- lib/fatfs/vfs/vfs_fat_sdmmc.c | 85 +- lib/fatfs/vfs/vfs_fat_spiflash.c | 168 +- lib/fatfs/wl_fatfsgen.py | 33 +- 790 files changed, 70268 insertions(+), 36118 deletions(-) create mode 100644 lib/bt/common/ble_log/ble_log_spi_out.c create mode 100644 lib/bt/common/ble_log/include/ble_log/ble_log_spi_out.h create mode 100644 lib/bt/common/tinycrypt/AUTHORS create mode 100644 lib/bt/common/tinycrypt/LICENSE create mode 100644 lib/bt/common/tinycrypt/README create mode 100644 lib/bt/common/tinycrypt/VERSION create mode 100644 lib/bt/common/tinycrypt/documentation/tinycrypt.rst create mode 100644 lib/bt/common/tinycrypt/include/tinycrypt/aes.h create mode 100644 lib/bt/common/tinycrypt/include/tinycrypt/cbc_mode.h create mode 100644 lib/bt/common/tinycrypt/include/tinycrypt/ccm_mode.h create mode 100644 lib/bt/common/tinycrypt/include/tinycrypt/cmac_mode.h create mode 100644 lib/bt/common/tinycrypt/include/tinycrypt/constants.h create mode 100644 lib/bt/common/tinycrypt/include/tinycrypt/ctr_mode.h create mode 100644 lib/bt/common/tinycrypt/include/tinycrypt/ctr_prng.h create mode 100644 lib/bt/common/tinycrypt/include/tinycrypt/ecc.h create mode 100644 lib/bt/common/tinycrypt/include/tinycrypt/ecc_dh.h create mode 100644 lib/bt/common/tinycrypt/include/tinycrypt/ecc_dsa.h create mode 100644 lib/bt/common/tinycrypt/include/tinycrypt/ecc_platform_specific.h create mode 100644 lib/bt/common/tinycrypt/include/tinycrypt/hmac.h create mode 100644 lib/bt/common/tinycrypt/include/tinycrypt/hmac_prng.h create mode 100644 lib/bt/common/tinycrypt/include/tinycrypt/sha256.h create mode 100644 lib/bt/common/tinycrypt/include/tinycrypt/utils.h create mode 100644 lib/bt/common/tinycrypt/port/esp_tinycrypt_port.c create mode 100644 lib/bt/common/tinycrypt/port/esp_tinycrypt_port.h create mode 100644 lib/bt/common/tinycrypt/src/aes_decrypt.c create mode 100644 lib/bt/common/tinycrypt/src/aes_encrypt.c create mode 100644 lib/bt/common/tinycrypt/src/cbc_mode.c create mode 100644 lib/bt/common/tinycrypt/src/ccm_mode.c create mode 100644 lib/bt/common/tinycrypt/src/cmac_mode.c create mode 100644 lib/bt/common/tinycrypt/src/ctr_mode.c create mode 100644 lib/bt/common/tinycrypt/src/ctr_prng.c create mode 100644 lib/bt/common/tinycrypt/src/ecc.c create mode 100644 lib/bt/common/tinycrypt/src/ecc_dh.c create mode 100644 lib/bt/common/tinycrypt/src/ecc_dsa.c create mode 100644 lib/bt/common/tinycrypt/src/ecc_platform_specific.c create mode 100644 lib/bt/common/tinycrypt/src/hmac.c create mode 100644 lib/bt/common/tinycrypt/src/hmac_prng.c create mode 100644 lib/bt/common/tinycrypt/src/sha256.c create mode 100644 lib/bt/common/tinycrypt/src/utils.c create mode 100644 lib/bt/controller/esp32c2/ble.c create mode 100644 lib/bt/controller/esp32c2/ble_priv.h create mode 100644 lib/bt/controller/esp32c2/dummy.c create mode 100644 lib/bt/controller/esp32c5/ble.c create mode 100644 lib/bt/controller/esp32c5/ble_priv.h create mode 100644 lib/bt/controller/esp32c6/ble.c create mode 100644 lib/bt/controller/esp32c6/ble_priv.h create mode 100644 lib/bt/controller/esp32h2/ble.c create mode 100644 lib/bt/controller/esp32h2/ble_priv.h create mode 100644 lib/bt/controller/esp32h21/Kconfig.in create mode 100644 lib/bt/controller/esp32h4/Kconfig.in mode change 100644 => 100755 lib/bt/controller/lib_esp32c2/esp32c2-bt-lib/libble_app.a create mode 100755 lib/bt/controller/lib_esp32c2/esp32c2-bt-lib/libble_app_flash.a mode change 100644 => 100755 lib/bt/controller/lib_esp32c3_family/esp32c3/libbtdm_app.a create mode 100755 lib/bt/controller/lib_esp32c3_family/esp32c3/libbtdm_app_flash.a mode change 100644 => 100755 lib/bt/controller/lib_esp32c3_family/esp32s3/libbtdm_app.a create mode 100755 lib/bt/controller/lib_esp32c3_family/esp32s3/libbtdm_app_flash.a create mode 100644 lib/bt/controller/lib_esp32c5/esp32c5-bt-lib/NOTICE create mode 100644 lib/bt/controller/lib_esp32c5/esp32c5-bt-lib/README.md create mode 100755 lib/bt/controller/lib_esp32c5/esp32c5-bt-lib/libble_app.a create mode 100755 lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/esp32c6/libble_app.a create mode 100755 lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/esp32c61/libble_app.a delete mode 100644 lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/libble_app.a mode change 100644 => 100755 lib/bt/controller/lib_esp32h2/esp32h2-bt-lib/libble_app.a create mode 100644 lib/bt/esp_ble_mesh/common/include/mesh/queue.h create mode 100644 lib/bt/esp_ble_mesh/common/queue.c create mode 100644 lib/bt/esp_ble_mesh/core/adv_common.c create mode 100644 lib/bt/esp_ble_mesh/core/adv_common.h create mode 100644 lib/bt/esp_ble_mesh/core/ble_adv.c create mode 100644 lib/bt/esp_ble_mesh/core/ble_adv.h create mode 100644 lib/bt/esp_ble_mesh/core/ext_adv.c create mode 100644 lib/bt/esp_ble_mesh/core/ext_adv.h create mode 100644 lib/bt/esp_ble_mesh/core/tag.h create mode 100644 lib/bt/esp_ble_mesh/lib/lib/esp32c5/libble_mesh.a create mode 100644 lib/bt/esp_ble_mesh/lib/lib/esp32c61/libble_mesh.a create mode 100644 lib/bt/host/bluedroid/api/esp_ble_cte_api.c create mode 100644 lib/bt/host/bluedroid/api/esp_ble_iso_api.c create mode 100644 lib/bt/host/bluedroid/api/esp_pbac_api.c create mode 100644 lib/bt/host/bluedroid/api/include/api/esp_a2dp_legacy_api.h create mode 100644 lib/bt/host/bluedroid/api/include/api/esp_ble_cte_api.h create mode 100644 lib/bt/host/bluedroid/api/include/api/esp_ble_iso_api.h create mode 100644 lib/bt/host/bluedroid/api/include/api/esp_hf_ag_legacy_api.h create mode 100644 lib/bt/host/bluedroid/api/include/api/esp_hf_client_legacy_api.h create mode 100644 lib/bt/host/bluedroid/api/include/api/esp_pba_defs.h create mode 100644 lib/bt/host/bluedroid/api/include/api/esp_pbac_api.h create mode 100644 lib/bt/host/bluedroid/bta/av/bta_av_ca_act.c create mode 100644 lib/bt/host/bluedroid/bta/av/bta_av_ca_sm.c create mode 100644 lib/bt/host/bluedroid/bta/include/bta/bta_pba_client_api.h create mode 100644 lib/bt/host/bluedroid/bta/include/bta/bta_pba_defs.h create mode 100644 lib/bt/host/bluedroid/bta/pba/bta_pba_client_act.c create mode 100644 lib/bt/host/bluedroid/bta/pba/bta_pba_client_api.c create mode 100644 lib/bt/host/bluedroid/bta/pba/bta_pba_client_main.c create mode 100644 lib/bt/host/bluedroid/bta/pba/bta_pba_client_sdp.c create mode 100644 lib/bt/host/bluedroid/bta/pba/include/bta_pba_client_int.h create mode 100644 lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink_ext_coedc.c create mode 100644 lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source_ext_codec.c create mode 100644 lib/bt/host/bluedroid/btc/profile/std/cte/btc_ble_cte.c create mode 100644 lib/bt/host/bluedroid/btc/profile/std/include/btc_ble_cte.h create mode 100644 lib/bt/host/bluedroid/btc/profile/std/include/btc_iso_ble.h create mode 100644 lib/bt/host/bluedroid/btc/profile/std/include/btc_pba_client.h create mode 100644 lib/bt/host/bluedroid/btc/profile/std/iso/btc_iso_ble.c create mode 100644 lib/bt/host/bluedroid/btc/profile/std/pba/btc_pba_client.c create mode 100644 lib/bt/host/bluedroid/hci/ble_hci_iso.c create mode 100644 lib/bt/host/bluedroid/hci/include/hci/ble_hci_iso.h create mode 100644 lib/bt/host/bluedroid/stack/btm/btm_ble_cte.c create mode 100644 lib/bt/host/bluedroid/stack/btm/btm_ble_iso.c create mode 100644 lib/bt/host/bluedroid/stack/goep/goepc_api.c create mode 100644 lib/bt/host/bluedroid/stack/goep/goepc_main.c create mode 100644 lib/bt/host/bluedroid/stack/goep/include/goep_int.h create mode 100644 lib/bt/host/bluedroid/stack/include/stack/goep_common.h create mode 100644 lib/bt/host/bluedroid/stack/include/stack/goepc_api.h create mode 100644 lib/bt/host/bluedroid/stack/include/stack/obex_api.h create mode 100644 lib/bt/host/bluedroid/stack/obex/include/obex_int.h create mode 100644 lib/bt/host/bluedroid/stack/obex/include/obex_tl.h create mode 100644 lib/bt/host/bluedroid/stack/obex/include/obex_tl_l2cap.h create mode 100644 lib/bt/host/bluedroid/stack/obex/include/obex_tl_rfcomm.h create mode 100644 lib/bt/host/bluedroid/stack/obex/obex_api.c create mode 100644 lib/bt/host/bluedroid/stack/obex/obex_main.c create mode 100644 lib/bt/host/bluedroid/stack/obex/obex_tl_l2cap.c create mode 100644 lib/bt/host/bluedroid/stack/obex/obex_tl_rfcomm.c delete mode 100644 lib/bt/host/nimble/nimble/.travis.yml delete mode 100644 lib/bt/host/nimble/nimble/apps/bttester/src/atomic.h delete mode 100644 lib/bt/host/nimble/nimble/apps/bttester/src/bttester.h delete mode 100644 lib/bt/host/nimble/nimble/apps/bttester/src/gap.c delete mode 100644 lib/bt/host/nimble/nimble/apps/bttester/src/gatt_cl.c delete mode 100644 lib/bt/host/nimble/nimble/apps/bttester/src/glue.c delete mode 100644 lib/bt/host/nimble/nimble/apps/bttester/src/glue.h delete mode 100644 lib/bt/host/nimble/nimble/apps/bttester/src/l2cap.c delete mode 100644 lib/bt/host/nimble/nimble/apps/bttester/src/mesh.c delete mode 100644 lib/bt/host/nimble/nimble/nimble/controller/include/controller/ble_ll_plna.h delete mode 100644 lib/bt/host/nimble/nimble/nimble/controller/include/controller/ble_ll_test.h delete mode 100644 lib/bt/host/nimble/nimble/nimble/controller/src/ble_ll_supp_cmd.c delete mode 100644 lib/bt/host/nimble/nimble/nimble/controller/test/src/ble_ll_csa2_test.h delete mode 100644 lib/bt/host/nimble/nimble/nimble/drivers/nrf52/include/ble/xcvr.h delete mode 100644 lib/bt/host/nimble/nimble/nimble/drivers/nrf52/src/ble_hw.c delete mode 100644 lib/bt/host/nimble/nimble/nimble/drivers/nrf52/src/ble_phy.c delete mode 100644 lib/bt/host/nimble/nimble/nimble/drivers/nrf52/src/ble_phy_trace.c delete mode 100644 lib/bt/host/nimble/nimble/nimble/drivers/nrf52/syscfg.yml delete mode 100644 lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/include/ble/xcvr.h delete mode 100644 lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/src/ble_hw.c delete mode 100644 lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/src/ble_phy.c delete mode 100644 lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/src/ble_phy_trace.c delete mode 100644 lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/syscfg.yml delete mode 100644 lib/bt/host/nimble/nimble/nimble/drivers/plna/sky66112/pkg.yml delete mode 100644 lib/bt/host/nimble/nimble/nimble/drivers/plna/sky66112/src/sky66112.c delete mode 100644 lib/bt/host/nimble/nimble/nimble/drivers/plna/sky66112/syscfg.yml create mode 100644 lib/bt/host/nimble/nimble/nimble/host/include/host/ble_esp_gattc_cache.h create mode 100644 lib/bt/host/nimble/nimble/nimble/host/services/cte/include/services/cte/ble_svc_cte.h create mode 100644 lib/bt/host/nimble/nimble/nimble/host/services/cte/pkg.yml create mode 100644 lib/bt/host/nimble/nimble/nimble/host/services/cte/src/ble_svc_cte.c create mode 100644 lib/bt/host/nimble/nimble/nimble/host/services/cte/syscfg.yml create mode 100644 lib/bt/host/nimble/nimble/nimble/host/src/ble_eatt.c create mode 100644 lib/bt/host/nimble/nimble/nimble/host/src/ble_eatt_priv.h delete mode 100644 lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/diag/pkg.yml delete mode 100644 lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/diag/src/cmac_diag.c delete mode 100644 lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_diag.h delete mode 100644 lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_host.h delete mode 100644 lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_shared.h delete mode 100644 lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/pkg.yml delete mode 100755 lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/build_libcmac.sh delete mode 100755 lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/create_cmac_bin.sh delete mode 100644 lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_host.c delete mode 100644 lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_mbox.c delete mode 100644 lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_rand.c delete mode 100644 lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_shared.c delete mode 100644 lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/syscfg.yml create mode 100644 lib/bt/host/nimble/nimble/nimble/transport/esp_ipc/src/hci_esp_ipc.c create mode 100644 lib/bt/host/nimble/nimble/nimble/transport/esp_ipc_legacy/src/hci_esp_ipc_legacy.c delete mode 100644 lib/bt/host/nimble/nimble/nimble/transport/nrf5340/syscfg.yml mode change 120000 => 100644 lib/bt/host/nimble/nimble/porting/npl/riot/include/npl_syscfg/npl_sycfg.h create mode 100644 lib/bt/include/esp32/include/esp_bt_vs.h create mode 100644 lib/bt/include/esp32c2/include/esp_bt_vs.h create mode 100644 lib/bt/include/esp32c3/include/esp_bt_vs.h create mode 100644 lib/bt/include/esp32c5/include/esp_bt_vs.h create mode 100644 lib/bt/include/esp32c6/include/esp_bt_vs.h create mode 100644 lib/bt/include/esp32h2/include/esp_bt_vs.h delete mode 100644 lib/bt/linker.lf delete mode 100644 lib/bt/linker.lf.esp32c2 delete mode 100644 lib/bt/porting/ext/tinycrypt/AUTHORS delete mode 100644 lib/bt/porting/ext/tinycrypt/LICENSE delete mode 100644 lib/bt/porting/ext/tinycrypt/README delete mode 100644 lib/bt/porting/ext/tinycrypt/VERSION delete mode 100644 lib/bt/porting/ext/tinycrypt/documentation/tinycrypt.rst delete mode 100644 lib/bt/porting/ext/tinycrypt/include/tinycrypt/aes.h delete mode 100644 lib/bt/porting/ext/tinycrypt/include/tinycrypt/cbc_mode.h delete mode 100644 lib/bt/porting/ext/tinycrypt/include/tinycrypt/ccm_mode.h delete mode 100644 lib/bt/porting/ext/tinycrypt/include/tinycrypt/cmac_mode.h delete mode 100644 lib/bt/porting/ext/tinycrypt/include/tinycrypt/constants.h delete mode 100644 lib/bt/porting/ext/tinycrypt/include/tinycrypt/ctr_mode.h delete mode 100644 lib/bt/porting/ext/tinycrypt/include/tinycrypt/ctr_prng.h delete mode 100644 lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc.h delete mode 100644 lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_dh.h delete mode 100644 lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_dsa.h delete mode 100644 lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_platform_specific.h delete mode 100644 lib/bt/porting/ext/tinycrypt/include/tinycrypt/hmac.h delete mode 100644 lib/bt/porting/ext/tinycrypt/include/tinycrypt/hmac_prng.h delete mode 100644 lib/bt/porting/ext/tinycrypt/include/tinycrypt/sha256.h delete mode 100644 lib/bt/porting/ext/tinycrypt/include/tinycrypt/utils.h delete mode 100644 lib/bt/porting/ext/tinycrypt/src/aes_decrypt.c delete mode 100644 lib/bt/porting/ext/tinycrypt/src/aes_encrypt.c delete mode 100644 lib/bt/porting/ext/tinycrypt/src/cbc_mode.c delete mode 100644 lib/bt/porting/ext/tinycrypt/src/ccm_mode.c delete mode 100644 lib/bt/porting/ext/tinycrypt/src/cmac_mode.c delete mode 100644 lib/bt/porting/ext/tinycrypt/src/ctr_mode.c delete mode 100644 lib/bt/porting/ext/tinycrypt/src/ctr_prng.c delete mode 100644 lib/bt/porting/ext/tinycrypt/src/ecc.c delete mode 100644 lib/bt/porting/ext/tinycrypt/src/ecc_dh.c delete mode 100644 lib/bt/porting/ext/tinycrypt/src/ecc_dsa.c delete mode 100644 lib/bt/porting/ext/tinycrypt/src/ecc_platform_specific.c delete mode 100644 lib/bt/porting/ext/tinycrypt/src/hmac.c delete mode 100644 lib/bt/porting/ext/tinycrypt/src/hmac_prng.c delete mode 100644 lib/bt/porting/ext/tinycrypt/src/sha256.c delete mode 100644 lib/bt/porting/ext/tinycrypt/src/utils.c delete mode 100644 lib/bt/porting/include/ble_hci_trans.h delete mode 100644 lib/bt/porting/mem/bt_osi_mem.h delete mode 100644 lib/bt/porting/nimble/include/nimble/ble.h delete mode 100644 lib/bt/porting/nimble/include/nimble/ble_hci_trans.h delete mode 100644 lib/bt/porting/nimble/include/nimble/nimble_npl.h delete mode 100644 lib/bt/porting/nimble/include/nimble/nimble_opt.h delete mode 100644 lib/bt/porting/nimble/include/nimble/nimble_opt_auto.h delete mode 100644 lib/bt/porting/nimble/include/nimble/nimble_port.h delete mode 100644 lib/bt/porting/nimble/include/os/endian.h delete mode 100644 lib/bt/porting/nimble/include/os/os.h delete mode 100644 lib/bt/porting/nimble/include/os/os_error.h delete mode 100644 lib/bt/porting/nimble/include/os/os_mbuf.h delete mode 100644 lib/bt/porting/nimble/include/os/os_mempool.h delete mode 100644 lib/bt/porting/nimble/include/os/queue.h delete mode 100644 lib/bt/porting/nimble/include/os/util.h delete mode 100644 lib/bt/porting/nimble/src/os_msys_init.c create mode 100644 lib/bt/porting/transport/driver/common/hci_driver_h4.c create mode 100644 lib/bt/porting/transport/driver/common/hci_driver_mem.c create mode 100644 lib/bt/porting/transport/driver/common/hci_driver_util.c create mode 100644 lib/bt/porting/transport/driver/uart/hci_driver_uart.c create mode 100644 lib/bt/porting/transport/driver/uart/hci_driver_uart.h create mode 100644 lib/bt/porting/transport/driver/uart/hci_driver_uart_config.c create mode 100644 lib/bt/porting/transport/driver/uart/hci_driver_uart_dma.c create mode 100644 lib/bt/porting/transport/driver/vhci/hci_driver_nimble.c create mode 100644 lib/bt/porting/transport/driver/vhci/hci_driver_standard.c create mode 100644 lib/bt/porting/transport/driver/vhci/hci_driver_tamplete.c create mode 100644 lib/bt/porting/transport/include/common/hci_driver_h4.h create mode 100644 lib/bt/porting/transport/include/common/hci_driver_mem.h create mode 100644 lib/bt/porting/transport/include/common/hci_driver_util.h create mode 100644 lib/bt/porting/transport/include/esp_hci_driver.h create mode 100644 lib/bt/porting/transport/include/esp_hci_internal.h create mode 100644 lib/bt/porting/transport/include/esp_hci_transport.h delete mode 100644 lib/bt/porting/transport/include/hci_uart.h create mode 100644 lib/bt/porting/transport/src/hci_transport.c delete mode 100644 lib/bt/porting/transport/uart/hci_uart.c delete mode 100644 lib/bt/test_apps/CMakeLists.txt delete mode 100644 lib/bt/test_apps/README.md delete mode 100644 lib/bt/test_apps/main/CMakeLists.txt delete mode 100644 lib/bt/test_apps/main/test_bt_common.c delete mode 100644 lib/bt/test_apps/main/test_bt_main.c delete mode 100644 lib/bt/test_apps/main/test_smp.c delete mode 100644 lib/bt/test_apps/pytest_bt.py delete mode 100644 lib/bt/test_apps/sdkconfig.defaults delete mode 100644 lib/fatfs/.build-test-rules.yml create mode 100644 lib/fatfs/host_test/.build-test-rules.yml create mode 100644 lib/fatfs/host_test/main/idf_component.yml delete mode 100644 lib/fatfs/host_test/main/main.cpp create mode 100644 lib/fatfs/test_apps/dyn_buffers/CMakeLists.txt create mode 100644 lib/fatfs/test_apps/dyn_buffers/README.md create mode 100644 lib/fatfs/test_apps/dyn_buffers/main/CMakeLists.txt create mode 100644 lib/fatfs/test_apps/dyn_buffers/main/test_fatfs_dyn_buffers.c create mode 100644 lib/fatfs/test_apps/dyn_buffers/partitions.csv create mode 100644 lib/fatfs/test_apps/dyn_buffers/pytest_fatfs_dyn_buffers.py create mode 100644 lib/fatfs/test_apps/dyn_buffers/sdkconfig.ci.dyn_buffers create mode 100644 lib/fatfs/test_apps/dyn_buffers/sdkconfig.ci.no_dyn_buffers create mode 100644 lib/fatfs/test_apps/dyn_buffers/sdkconfig.defaults create mode 100644 lib/fatfs/test_apps/flash_wl/main/Kconfig.projbuild create mode 100644 lib/fatfs/test_apps/flash_wl/main/test_fatfs_small_partition.c create mode 100644 lib/fatfs/test_apps/flash_wl/sdkconfig.ci.dyn_buffers delete mode 100644 lib/fatfs/test_apps/flash_wl/sdkconfig.ci.psram create mode 100644 lib/fatfs/test_apps/flash_wl/sdkconfig.ci.psram.esp32 delete mode 100644 lib/fatfs/test_apps/sdcard/sdkconfig.ci.psram create mode 100644 lib/fatfs/test_apps/sdcard/sdkconfig.ci.psram.esp32 delete mode 100644 lib/fatfs/test_fatfs_host/Makefile delete mode 100644 lib/fatfs/test_fatfs_host/Makefile.files delete mode 100644 lib/fatfs/test_fatfs_host/component.mk delete mode 100644 lib/fatfs/test_fatfs_host/main.cpp delete mode 100644 lib/fatfs/test_fatfs_host/partition_table.csv delete mode 100644 lib/fatfs/test_fatfs_host/test_fatfs.cpp diff --git a/lib/bt/CMakeLists.txt b/lib/bt/CMakeLists.txt index 6dd5ef9b..a5a0742f 100644 --- a/lib/bt/CMakeLists.txt +++ b/lib/bt/CMakeLists.txt @@ -4,29 +4,19 @@ if(${target} STREQUAL "linux") return() # This component is not supported by the POSIX/Linux simulator endif() +if(CONFIG_IDF_TARGET_ESP32S3) + set(target_name "esp32c3") +elseif(CONFIG_IDF_TARGET_ESP32C61) + set(target_name "esp32c6") +else() + set(target_name "${idf_target}") +endif() + # API headers that are used in the docs are also compiled # even if CONFIG_BT_ENABLED=n as long as CONFIG_IDF_DOC_BUILD=y -if(CONFIG_IDF_TARGET_ESP32) - set(target_specific_include_dirs include/esp32/include) - -elseif(CONFIG_IDF_TARGET_ESP32C3) - set(target_specific_include_dirs include/esp32c3/include) - -elseif(CONFIG_IDF_TARGET_ESP32S3) - set(target_specific_include_dirs include/esp32c3/include) - -elseif(CONFIG_IDF_TARGET_ESP32C2) - set(target_specific_include_dirs include/esp32c2/include) - -elseif(CONFIG_IDF_TARGET_ESP32C6) - set(target_specific_include_dirs include/esp32c6/include) - -elseif(CONFIG_IDF_TARGET_ESP32H2) - set(target_specific_include_dirs include/esp32h2/include) - -elseif(CONFIG_IDF_TARGET_ESP32C5) - set(target_specific_include_dirs include/esp32c5/include) +if(CONFIG_SOC_BT_SUPPORTED) + set(target_specific_include_dirs include/${target_name}/include) endif() set(common_include_dirs @@ -34,6 +24,7 @@ set(common_include_dirs common/btc/profile/esp/blufi/include common/btc/profile/esp/include common/hci_log/include + common/ble_log/include ) set(ble_mesh_include_dirs @@ -49,12 +40,20 @@ set(ble_mesh_include_dirs "esp_ble_mesh/api/core/include" "esp_ble_mesh/api/models/include" "esp_ble_mesh/api" +) + +set(ble_mesh_v11_include_dirs "esp_ble_mesh/lib/include" "esp_ble_mesh/v1.1/api/core/include" "esp_ble_mesh/v1.1/api/models/include" "esp_ble_mesh/v1.1/btc/include" ) +if(CONFIG_IDF_DOC_BUILD) + list(APPEND ble_mesh_include_dirs + ${ble_mesh_v11_include_dirs}) +endif() + set(bluedroid_include_dirs host/bluedroid/api/include/api) if(CONFIG_BT_CONTROLLER_ENABLED OR CONFIG_IDF_DOC_BUILD) @@ -76,34 +75,24 @@ if(CONFIG_BT_ENABLED) set(include_dirs "") set(ldscripts "linker_common.lf") if(CONFIG_BT_CONTROLLER_ENABLED) + list(APPEND srcs "controller/${target_name}/bt.c") + if(CONFIG_IDF_TARGET_ESP32) - list(APPEND srcs "controller/esp32/bt.c" - "controller/esp32/hli_api.c" + list(APPEND srcs "controller/esp32/hli_api.c" "controller/esp32/hli_vectors.S") list(APPEND ldscripts "linker_rw_bt_controller.lf") - elseif(CONFIG_IDF_TARGET_ESP32C3) - list(APPEND srcs "controller/esp32c3/bt.c") list(APPEND ldscripts "linker_rw_bt_controller.lf") - elseif(CONFIG_IDF_TARGET_ESP32S3) - list(APPEND srcs "controller/esp32c3/bt.c") list(APPEND ldscripts "linker_rw_bt_controller.lf") - elseif(CONFIG_IDF_TARGET_ESP32C2) - list(APPEND srcs "controller/esp32c2/bt.c") + list(APPEND srcs "controller/${target_name}/ble.c") + if(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) + list(APPEND srcs "controller/esp32c2/dummy.c") + endif() set(ldscripts "linker_esp32c2.lf") - - elseif(CONFIG_IDF_TARGET_ESP32C6) - list(APPEND srcs "controller/esp32c6/bt.c") - list(APPEND ldscripts "linker_esp_ble_controller.lf") - - elseif(CONFIG_IDF_TARGET_ESP32H2) - list(APPEND srcs "controller/esp32h2/bt.c") - list(APPEND ldscripts "linker_esp_ble_controller.lf") - - elseif(CONFIG_IDF_TARGET_ESP32C5) - list(APPEND srcs "controller/esp32c5/bt.c") + else() + list(APPEND srcs "controller/${target_name}/ble.c") list(APPEND ldscripts "linker_esp_ble_controller.lf") endif() @@ -117,6 +106,7 @@ if(CONFIG_BT_ENABLED) common/btc/include common/include porting/mem/ + porting/include ) list(APPEND include_dirs ${common_include_dirs}) @@ -143,6 +133,7 @@ if(CONFIG_BT_ENABLED) "common/osi/osi.c" "common/osi/semaphore.c" "porting/mem/bt_osi_mem.c" + "common/ble_log/ble_log_spi_out.c" ) # Host Bluedroid @@ -159,6 +150,7 @@ if(CONFIG_BT_ENABLED) host/bluedroid/bta/hd/include host/bluedroid/bta/hh/include host/bluedroid/bta/jv/include + host/bluedroid/bta/pba/include host/bluedroid/bta/sdp/include host/bluedroid/bta/sys/include host/bluedroid/device/include @@ -182,6 +174,8 @@ if(CONFIG_BT_ENABLED) host/bluedroid/stack/avdt/include host/bluedroid/stack/a2dp/include host/bluedroid/stack/rfcomm/include + host/bluedroid/stack/obex/include + host/bluedroid/stack/goep/include host/bluedroid/stack/include host/bluedroid/common/include host/bluedroid/config/include) @@ -205,10 +199,13 @@ if(CONFIG_BT_ENABLED) "host/bluedroid/api/esp_spp_api.c" "host/bluedroid/api/esp_sdp_api.c" "host/bluedroid/api/esp_l2cap_bt_api.c" + "host/bluedroid/api/esp_pbac_api.c" "host/bluedroid/bta/ar/bta_ar.c" "host/bluedroid/bta/av/bta_av_aact.c" "host/bluedroid/bta/av/bta_av_act.c" "host/bluedroid/bta/av/bta_av_api.c" + "host/bluedroid/bta/av/bta_av_ca_act.c" + "host/bluedroid/bta/av/bta_av_ca_sm.c" "host/bluedroid/bta/av/bta_av_cfg.c" "host/bluedroid/bta/av/bta_av_ci.c" "host/bluedroid/bta/av/bta_av_main.c" @@ -266,6 +263,10 @@ if(CONFIG_BT_ENABLED) "host/bluedroid/bta/hf_client/bta_hf_client_rfc.c" "host/bluedroid/bta/hf_client/bta_hf_client_sco.c" "host/bluedroid/bta/hf_client/bta_hf_client_sdp.c" + "host/bluedroid/bta/pba/bta_pba_client_act.c" + "host/bluedroid/bta/pba/bta_pba_client_api.c" + "host/bluedroid/bta/pba/bta_pba_client_main.c" + "host/bluedroid/bta/pba/bta_pba_client_sdp.c" "host/bluedroid/bta/sdp/bta_sdp.c" "host/bluedroid/bta/sdp/bta_sdp_act.c" "host/bluedroid/bta/sdp/bta_sdp_api.c" @@ -287,7 +288,9 @@ if(CONFIG_BT_ENABLED) "host/bluedroid/btc/profile/std/a2dp/btc_a2dp.c" "host/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c" "host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c" + "host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink_ext_coedc.c" "host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c" + "host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source_ext_codec.c" "host/bluedroid/btc/profile/std/a2dp/btc_av.c" "host/bluedroid/btc/profile/std/avrc/btc_avrc.c" "host/bluedroid/btc/profile/std/avrc/bta_avrc_co.c" @@ -308,6 +311,7 @@ if(CONFIG_BT_ENABLED) "host/bluedroid/btc/profile/std/spp/btc_spp.c" "host/bluedroid/btc/profile/std/sdp/btc_sdp.c" "host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c" + "host/bluedroid/btc/profile/std/pba/btc_pba_client.c" "host/bluedroid/device/bdaddr.c" "host/bluedroid/device/controller.c" "host/bluedroid/device/interop.c" @@ -404,6 +408,8 @@ if(CONFIG_BT_ENABLED) "host/bluedroid/stack/gatt/gatt_sr.c" "host/bluedroid/stack/gatt/gatt_sr_hash.c" "host/bluedroid/stack/gatt/gatt_utils.c" + "host/bluedroid/stack/goep/goepc_api.c" + "host/bluedroid/stack/goep/goepc_main.c" "host/bluedroid/stack/hcic/hciblecmds.c" "host/bluedroid/stack/hcic/hcicmds.c" "host/bluedroid/stack/l2cap/l2c_api.c" @@ -415,6 +421,10 @@ if(CONFIG_BT_ENABLED) "host/bluedroid/stack/l2cap/l2c_ucd.c" "host/bluedroid/stack/l2cap/l2c_utils.c" "host/bluedroid/stack/l2cap/l2cap_client.c" + "host/bluedroid/stack/obex/obex_api.c" + "host/bluedroid/stack/obex/obex_main.c" + "host/bluedroid/stack/obex/obex_tl_l2cap.c" + "host/bluedroid/stack/obex/obex_tl_rfcomm.c" "host/bluedroid/stack/rfcomm/port_api.c" "host/bluedroid/stack/rfcomm/port_rfc.c" "host/bluedroid/stack/rfcomm/port_utils.c" @@ -451,6 +461,19 @@ if(CONFIG_BT_ENABLED) list(APPEND srcs "esp_ble_mesh/core/bluedroid_host/adapter.c") endif() + if(CONFIG_BT_BLE_FEAT_ISO_EN) + list(APPEND srcs "host/bluedroid/stack/btm/btm_ble_iso.c" + "host/bluedroid/btc/profile/std/iso/btc_iso_ble.c" + "host/bluedroid/api/esp_ble_iso_api.c" + "host/bluedroid/hci/ble_hci_iso.c") + endif() + + if(CONFIG_BT_BLE_FEAT_CTE_EN) + list(APPEND srcs "host/bluedroid/stack/btm/btm_ble_cte.c" + "host/bluedroid/btc/profile/std/cte/btc_ble_cte.c" + "host/bluedroid/api/esp_ble_cte_api.c") + endif() + endif() if(CONFIG_BLE_MESH) @@ -497,13 +520,15 @@ if(CONFIG_BT_ENABLED) "esp_ble_mesh/common/common.c" "esp_ble_mesh/common/kernel.c" "esp_ble_mesh/common/mutex.c" + "esp_ble_mesh/common/queue.c" "esp_ble_mesh/common/timer.c" "esp_ble_mesh/common/utils.c" "esp_ble_mesh/core/storage/settings_nvs.c" "esp_ble_mesh/core/storage/settings_uid.c" "esp_ble_mesh/core/storage/settings.c" "esp_ble_mesh/core/access.c" - "esp_ble_mesh/core/adv.c" + "esp_ble_mesh/core/adv_common.c" + "esp_ble_mesh/core/ble_adv.c" "esp_ble_mesh/core/beacon.c" "esp_ble_mesh/core/cfg_cli.c" "esp_ble_mesh/core/cfg_srv.c" @@ -539,89 +564,124 @@ if(CONFIG_BT_ENABLED) "esp_ble_mesh/models/server/server_common.c" "esp_ble_mesh/models/server/state_binding.c" "esp_ble_mesh/models/server/state_transition.c" - "esp_ble_mesh/models/server/time_scene_server.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_agg_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_brc_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_cm_data_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_df_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_lcd_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_odp_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_prb_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_sar_model_api.c" - "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_srpl_model_api.c" - "esp_ble_mesh/v1.1/api/models/esp_ble_mesh_mbt_model_api.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_agg_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_brc_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_df_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_lcd_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_mbt_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_odp_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_prb_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_sar_model.c" - "esp_ble_mesh/v1.1/btc/btc_ble_mesh_srpl_model.c" - "esp_ble_mesh/lib/ext.c") - - if(CONFIG_BLE_MESH_SAR_ENHANCEMENT) - list(APPEND srcs "esp_ble_mesh/core/transport.enh.c") + "esp_ble_mesh/models/server/time_scene_server.c") + if(CONFIG_BLE_MESH_V11_SUPPORT) + list(APPEND include_dirs ${ble_mesh_v11_include_dirs}) + + list(APPEND srcs + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_agg_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_brc_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_cm_data_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_df_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_lcd_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_odp_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_prb_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_sar_model_api.c" + "esp_ble_mesh/v1.1/api/core/esp_ble_mesh_srpl_model_api.c" + "esp_ble_mesh/v1.1/api/models/esp_ble_mesh_mbt_model_api.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_agg_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_brc_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_df_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_lcd_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_mbt_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_odp_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_prb_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_sar_model.c" + "esp_ble_mesh/v1.1/btc/btc_ble_mesh_srpl_model.c" + "esp_ble_mesh/lib/ext.c") + if(CONFIG_BLE_MESH_SAR_ENHANCEMENT) + list(APPEND srcs "esp_ble_mesh/core/transport.enh.c") + else() + list(APPEND srcs "esp_ble_mesh/core/transport.c") + endif() else() - list(APPEND srcs "esp_ble_mesh/core/transport.c") + list(APPEND srcs + "esp_ble_mesh/core/transport.c") + endif() + if(CONFIG_BLE_MESH_SUPPORT_MULTI_ADV) + list(APPEND srcs "esp_ble_mesh/core/ext_adv.c") + else() + list(APPEND srcs "esp_ble_mesh/core/adv.c") endif() endif() if(CONFIG_BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT) + list(APPEND srcs + "porting/npl/freertos/src/npl_os_freertos.c" + "porting/mem/os_msys_init.c" + "porting/transport/src/hci_transport.c" + ) + + if(CONFIG_BT_CONTROLLER_DISABLED) list(APPEND srcs - "porting/npl/freertos/src/npl_os_freertos.c" - "porting/mem/os_msys_init.c" + "host/nimble/nimble/porting/nimble/src/hal_uart.c" ) - - if(CONFIG_BT_CONTROLLER_DISABLED) + elseif(CONFIG_BT_LE_HCI_INTERFACE_USE_RAM) + if(CONFIG_BT_NIMBLE_ENABLED) list(APPEND srcs - "host/nimble/nimble/porting/nimble/src/hal_uart.c" - ) + "porting/transport/driver/vhci/hci_driver_nimble.c" + "host/nimble/nimble/nimble/transport/esp_ipc/src/hci_esp_ipc.c" + ) + else() + list(APPEND srcs + "porting/transport/driver/vhci/hci_driver_standard.c" + ) endif() - list(APPEND include_dirs - porting/include - porting/npl/freertos/include - porting/transport/include - ) - - if(CONFIG_BT_LE_HCI_INTERFACE_USE_UART) + elseif(CONFIG_BT_LE_HCI_INTERFACE_USE_UART) list(APPEND srcs - "porting/transport/uart/hci_uart.c" - ) + "porting/transport/driver/common/hci_driver_util.c" + "porting/transport/driver/common/hci_driver_h4.c" + "porting/transport/driver/common/hci_driver_mem.c" + "porting/transport/driver/uart/hci_driver_uart_config.c" + ) + if(CONFIG_BT_LE_UART_HCI_DMA_MODE) + list(APPEND srcs + "porting/transport/driver/uart/hci_driver_uart_dma.c" + ) + else() + list(APPEND srcs + "porting/transport/driver/uart/hci_driver_uart.c" + ) endif() - endif() + endif() + list(APPEND include_dirs + porting/include + porting/npl/freertos/include + porting/transport/include + ) + endif() if(NOT (CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS OR CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS)) list(APPEND include_dirs - porting/ext/tinycrypt/include + common/tinycrypt/include + common/tinycrypt/port ) - list(APPEND srcs "porting/ext/tinycrypt/src/utils.c" - "porting/ext/tinycrypt/src/sha256.c" - "porting/ext/tinycrypt/src/ecc.c" - "porting/ext/tinycrypt/src/ctr_prng.c" - "porting/ext/tinycrypt/src/ctr_mode.c" - "porting/ext/tinycrypt/src/aes_decrypt.c" - "porting/ext/tinycrypt/src/aes_encrypt.c" - "porting/ext/tinycrypt/src/ccm_mode.c" - "porting/ext/tinycrypt/src/ecc_dsa.c" - "porting/ext/tinycrypt/src/cmac_mode.c" - "porting/ext/tinycrypt/src/ecc_dh.c" - "porting/ext/tinycrypt/src/hmac_prng.c" - "porting/ext/tinycrypt/src/ecc_platform_specific.c" - "porting/ext/tinycrypt/src/hmac.c" - "porting/ext/tinycrypt/src/cbc_mode.c") + list(APPEND srcs "common/tinycrypt/src/utils.c" + "common/tinycrypt/src/sha256.c" + "common/tinycrypt/src/ecc.c" + "common/tinycrypt/src/ctr_prng.c" + "common/tinycrypt/src/ctr_mode.c" + "common/tinycrypt/src/aes_decrypt.c" + "common/tinycrypt/src/aes_encrypt.c" + "common/tinycrypt/src/ccm_mode.c" + "common/tinycrypt/src/ecc_dsa.c" + "common/tinycrypt/src/cmac_mode.c" + "common/tinycrypt/src/ecc_dh.c" + "common/tinycrypt/src/hmac_prng.c" + "common/tinycrypt/src/ecc_platform_specific.c" + "common/tinycrypt/src/hmac.c" + "common/tinycrypt/src/cbc_mode.c" + "common/tinycrypt/port/esp_tinycrypt_port.c") endif() if(CONFIG_BT_NIMBLE_ENABLED) list(APPEND include_dirs - host/nimble/nimble/nimble/host/include host/nimble/nimble/nimble/include host/nimble/nimble/nimble/host/services/ans/include @@ -639,6 +699,7 @@ if(CONFIG_BT_ENABLED) host/nimble/nimble/nimble/host/services/tps/include host/nimble/nimble/nimble/host/services/hid/include host/nimble/nimble/nimble/host/services/sps/include + host/nimble/nimble/nimble/host/services/cte/include host/nimble/nimble/nimble/host/util/include host/nimble/nimble/nimble/host/store/ram/include host/nimble/nimble/nimble/host/store/config/include @@ -661,6 +722,7 @@ if(CONFIG_BT_ENABLED) "host/nimble/nimble/nimble/host/services/cts/src/ble_svc_cts.c" "host/nimble/nimble/nimble/host/services/hid/src/ble_svc_hid.c" "host/nimble/nimble/nimble/host/services/sps/src/ble_svc_sps.c" + "host/nimble/nimble/nimble/host/services/cte/src/ble_svc_cte.c" "host/nimble/nimble/nimble/host/src/ble_hs_conn.c" "host/nimble/nimble/nimble/host/src/ble_store_util.c" "host/nimble/nimble/nimble/host/src/ble_sm.c" @@ -711,6 +773,7 @@ if(CONFIG_BT_ENABLED) "host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c" "host/nimble/nimble/nimble/host/src/ble_gattc_cache.c" "host/nimble/nimble/nimble/host/src/ble_gattc_cache_conn.c" + "host/nimble/nimble/nimble/host/src/ble_eatt.c" ) if(CONFIG_BT_CONTROLLER_DISABLED AND CONFIG_BT_NIMBLE_TRANSPORT_UART) @@ -725,10 +788,12 @@ if(CONFIG_BT_ENABLED) "host/nimble/nimble/porting/npl/freertos/src/nimble_port_freertos.c" "host/nimble/port/src/nvs_port.c" ) + list(APPEND include_dirs host/nimble/nimble/porting/nimble/include host/nimble/port/include host/nimble/nimble/nimble/transport/include + host/nimble/nimble/nimble/include ) if(CONFIG_BT_CONTROLLER_DISABLED) @@ -762,6 +827,7 @@ if(CONFIG_BT_ENABLED) if(CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE AND CONFIG_BT_CONTROLLER_ENABLED) list(APPEND srcs "host/nimble/esp-hci/src/esp_nimble_hci.c" + "host/nimble/nimble/nimble/transport/esp_ipc_legacy/src/hci_esp_ipc_legacy.c" ) list(APPEND include_dirs ${nimble_hci_include_dirs}) endif() @@ -822,11 +888,27 @@ if(CONFIG_BT_ENABLED) endif() + +set(bt_priv_requires + nvs_flash + soc + esp_pm + esp_phy + esp_coex + mbedtls + esp_driver_uart + vfs + esp_ringbuf + esp_driver_spi + esp_driver_gpio + esp_gdbstub +) + idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "${include_dirs}" PRIV_INCLUDE_DIRS "${priv_include_dirs}" REQUIRES esp_timer esp_wifi - PRIV_REQUIRES nvs_flash soc esp_pm esp_phy esp_coex mbedtls esp_driver_uart vfs esp_ringbuf + PRIV_REQUIRES "${bt_priv_requires}" LDFRAGMENTS "${ldscripts}") if(CONFIG_BT_ENABLED) @@ -839,13 +921,42 @@ if(CONFIG_BT_ENABLED) elseif(CONFIG_IDF_TARGET_ESP32C3) target_link_directories(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c3_family/esp32c3") - target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app) + if(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) + target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app_flash) + else() + target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app) + endif() elseif(CONFIG_IDF_TARGET_ESP32S3) target_link_directories(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c3_family/esp32s3") - target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app) + if(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) + target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app_flash) + else() + target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app) + endif() elseif(CONFIG_BT_CONTROLLER_ENABLED) - add_prebuilt_library(libble_app "controller/lib_${target}/${target}-bt-lib/libble_app.a") + if(CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=esp_panic_handler") + endif() + if(CONFIG_IDF_TARGET_ESP32C6) + add_prebuilt_library(libble_app + "${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c6/esp32c6-bt-lib/esp32c6/libble_app.a" + REQUIRES esp_phy) + elseif(CONFIG_IDF_TARGET_ESP32C61) + add_prebuilt_library(libble_app + "${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c6/esp32c6-bt-lib/esp32c61/libble_app.a" + REQUIRES esp_phy) + else() + if(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY AND CONFIG_IDF_TARGET_ESP32C2) + add_prebuilt_library(libble_app + "controller/lib_${target_name}/${target_name}-bt-lib/libble_app_flash.a" + REQUIRES esp_phy) + else() + add_prebuilt_library(libble_app + "controller/lib_${target_name}/${target_name}-bt-lib/libble_app.a" + REQUIRES esp_phy) + endif() + endif() target_link_libraries(${COMPONENT_LIB} PRIVATE libble_app) endif() @@ -859,7 +970,7 @@ if(CONFIG_BT_ENABLED) target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") endif() -if(CONFIG_BLE_MESH) +if(CONFIG_BLE_MESH_V11_SUPPORT) if(CONFIG_IDF_TARGET_ESP32) add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32/libble_mesh.a") target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh) @@ -872,11 +983,14 @@ if(CONFIG_BLE_MESH) elseif(CONFIG_IDF_TARGET_ESP32C6) add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32c6/libble_mesh.a") target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh) + elseif(CONFIG_IDF_TARGET_ESP32C61) + add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32c61/libble_mesh.a") + target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh) elseif(CONFIG_IDF_TARGET_ESP32H2) add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32h2/libble_mesh.a") target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh) elseif(CONFIG_IDF_TARGET_ESP32C5) - add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32C5/libble_mesh.a") + add_prebuilt_library(ble_mesh "esp_ble_mesh/lib/lib/esp32c5/libble_mesh.a") target_link_libraries(${COMPONENT_LIB} PRIVATE ble_mesh) endif() endif() diff --git a/lib/bt/Kconfig b/lib/bt/Kconfig index 65c757a2..417a8c18 100644 --- a/lib/bt/Kconfig +++ b/lib/bt/Kconfig @@ -81,8 +81,6 @@ menu "Bluetooth" So this option will disable the PMP (ESP_SYSTEM_PMP_IDRAM_SPLIT) menu "Common Options" - visible if (BT_BLUEDROID_ENABLED || BT_NIMBLE_ENABLED) - source "$IDF_PATH/components/bt/common/Kconfig.in" endmenu diff --git a/lib/bt/common/Kconfig.in b/lib/bt/common/Kconfig.in index 6b19dd8e..ff1947a3 100644 --- a/lib/bt/common/Kconfig.in +++ b/lib/bt/common/Kconfig.in @@ -1,6 +1,140 @@ config BT_ALARM_MAX_NUM int "Maximum number of Bluetooth alarms" default 50 + depends on (BT_BLUEDROID_ENABLED || BT_NIMBLE_ENABLED) help This option decides the maximum number of alarms which could be used by Bluetooth host. + +config BT_BLE_LOG_SPI_OUT_ENABLED + bool "Output ble logs to SPI bus (Experimental)" + default n + help + Output ble logs to SPI bus + +config BT_BLE_LOG_SPI_OUT_UL_TASK_BUF_SIZE + int "SPI transaction buffer size for upper layer task logs" + depends on BT_BLE_LOG_SPI_OUT_ENABLED + default 512 + help + SPI transaction buffer size for upper layer task logs. + There will be 2 SPI DMA buffers with the same size. + +config BT_BLE_LOG_SPI_OUT_HCI_ENABLED + bool "Enable HCI log output to SPI" + depends on BT_BLE_LOG_SPI_OUT_ENABLED + default n + help + Enable logging of HCI packets to the SPI bus when BLE SPI log output is enabled. + +config BT_BLE_LOG_SPI_OUT_HOST_ENABLED + bool "Enable Host log output to SPI" + depends on BT_BLE_LOG_SPI_OUT_ENABLED + default n + help + This configuration applies to the logs of both Bluedroid Host and NimBLE Host. + When BLE SPI log output is enabled, this option allows host logs to be transmitted via SPI. + +config BT_BLE_LOG_SPI_OUT_LL_ENABLED + bool "Enable Controller log output to SPI" + depends on BT_BLE_LOG_SPI_OUT_ENABLED + depends on BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + default n + help + Enable controller log output to SPI bus. + +config BT_BLE_LOG_SPI_OUT_LL_TASK_BUF_SIZE + int "SPI transaction buffer size for lower layer task logs" + depends on BT_BLE_LOG_SPI_OUT_LL_ENABLED + default 1024 + help + SPI transaction buffer size for lower layer task logs. + There will be 2 SPI DMA buffers with the same size. + +config BT_BLE_LOG_SPI_OUT_LL_ISR_BUF_SIZE + int "SPI transaction buffer size for lower layer ISR logs" + depends on BT_BLE_LOG_SPI_OUT_LL_ENABLED + default 512 + help + SPI transaction buffer size for lower layer ISR logs. + There will be 2 SPI DMA buffers with the same size. + +config BT_BLE_LOG_SPI_OUT_LL_HCI_BUF_SIZE + int "SPI transaction buffer size for lower layer HCI logs" + depends on BT_BLE_LOG_SPI_OUT_LL_ENABLED + default 512 + help + SPI transaction buffer size for upper layer HCI logs. + There will be 2 SPI DMA buffers with the same size + +config BT_BLE_LOG_SPI_OUT_MOSI_IO_NUM + int "GPIO number of SPI MOSI" + depends on BT_BLE_LOG_SPI_OUT_ENABLED + default 0 + help + GPIO number of SPI MOSI + +config BT_BLE_LOG_SPI_OUT_SCLK_IO_NUM + int "GPIO number of SPI SCLK" + depends on BT_BLE_LOG_SPI_OUT_ENABLED + default 1 + help + GPIO number of SPI SCLK + +config BT_BLE_LOG_SPI_OUT_CS_IO_NUM + int "GPIO number of SPI CS" + depends on BT_BLE_LOG_SPI_OUT_ENABLED + default 2 + help + GPIO number of SPI CS + +config BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED + bool "Enable ble log & logic analyzer log time sync" + depends on BT_BLE_LOG_SPI_OUT_ENABLED + default y + help + Enable ble log & logic analyzer log time sync + +config BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM + int "GPIO number of SYNC IO" + depends on BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED + default 3 + help + GPIO number of SYNC IO + +config BT_BLE_LOG_SPI_OUT_TS_SYNC_SLEEP_SUPPORT + bool "Enable ble log & logic analyzer log time sync sleep support" + depends on BT_BLE_LOG_SPI_OUT_LL_ENABLED + default n + help + Enable ble log & logic analyzer log time sync sleep support + +config BT_BLE_LOG_SPI_OUT_FLUSH_TIMER_ENABLED + bool "Enable periodic buffer flush out" + depends on BT_BLE_LOG_SPI_OUT_ENABLED + default n + help + Enable periodic buffer flush out + Not recommended when SPI receiver is unavailable + +config BT_BLE_LOG_SPI_OUT_FLUSH_TIMEOUT + int "Buffer flush out period in unit of ms" + depends on BT_BLE_LOG_SPI_OUT_FLUSH_TIMER_ENABLED + default 1000 + help + Buffer flush out period in unit of ms + +config BT_BLE_LOG_SPI_OUT_LE_AUDIO_ENABLED + bool "Enable LE Audio log output to SPI" + depends on BT_BLE_LOG_SPI_OUT_ENABLED + default n + help + Enable LE Audio log output to SPI + +config BT_BLE_LOG_SPI_OUT_LE_AUDIO_BUF_SIZE + int "SPI transaction buffer size for LE Audio logs" + depends on BT_BLE_LOG_SPI_OUT_LE_AUDIO_ENABLED + default 1024 + help + SPI transaction buffer size for LE Audio logs. + There will be 2 SPI DMA buffers with the same size. diff --git a/lib/bt/common/ble_log/ble_log_spi_out.c b/lib/bt/common/ble_log/ble_log_spi_out.c new file mode 100644 index 00000000..3ee7f511 --- /dev/null +++ b/lib/bt/common/ble_log/ble_log_spi_out.c @@ -0,0 +1,1247 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "ble_log/ble_log_spi_out.h" + +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +// Private includes +#include "esp_bt.h" + +// sdkconfig defines +#define SPI_OUT_UL_TASK_BUF_SIZE CONFIG_BT_BLE_LOG_SPI_OUT_UL_TASK_BUF_SIZE +#define SPI_OUT_LL_ENABLED CONFIG_BT_BLE_LOG_SPI_OUT_LL_ENABLED +#define SPI_OUT_LL_TASK_BUF_SIZE CONFIG_BT_BLE_LOG_SPI_OUT_LL_TASK_BUF_SIZE +#define SPI_OUT_LL_ISR_BUF_SIZE CONFIG_BT_BLE_LOG_SPI_OUT_LL_ISR_BUF_SIZE +#define SPI_OUT_LL_HCI_BUF_SIZE CONFIG_BT_BLE_LOG_SPI_OUT_LL_HCI_BUF_SIZE +#define SPI_OUT_MOSI_IO_NUM CONFIG_BT_BLE_LOG_SPI_OUT_MOSI_IO_NUM +#define SPI_OUT_SCLK_IO_NUM CONFIG_BT_BLE_LOG_SPI_OUT_SCLK_IO_NUM +#define SPI_OUT_CS_IO_NUM CONFIG_BT_BLE_LOG_SPI_OUT_CS_IO_NUM +#define SPI_OUT_TS_SYNC_ENABLED CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED +#define SPI_OUT_SYNC_IO_NUM CONFIG_BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM +#define SPI_OUT_TS_SYNC_SLEEP_SUPPORT CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_SLEEP_SUPPORT +#define SPI_OUT_FLUSH_TIMER_ENABLED CONFIG_BT_BLE_LOG_SPI_OUT_FLUSH_TIMER_ENABLED +#define SPI_OUT_FLUSH_TIMEOUT_US (CONFIG_BT_BLE_LOG_SPI_OUT_FLUSH_TIMEOUT * 1000) +#define SPI_OUT_LE_AUDIO_ENABLED CONFIG_BT_BLE_LOG_SPI_OUT_LE_AUDIO_ENABLED +#define SPI_OUT_LE_AUDIO_BUF_SIZE CONFIG_BT_BLE_LOG_SPI_OUT_LE_AUDIO_BUF_SIZE + +// Private defines +#define BLE_LOG_TAG "BLE_LOG" +#define SPI_OUT_BUS SPI2_HOST +#define SPI_OUT_MAX_TRANSFER_SIZE (10240) +#define SPI_OUT_FRAME_HEAD_LEN (4) +#define SPI_OUT_FRAME_TAIL_LEN (4) +#define SPI_OUT_FRAME_OVERHEAD (8) +#define SPI_OUT_PACKET_LOSS_FRAME_SIZE (6) +#define SPI_OUT_TRANS_ITVL_MIN_US (30) +#define SPI_OUT_UL_LOG_STR_BUF_SIZE (100) +#define SPI_OUT_MALLOC(size) heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) + +#if SPI_OUT_TS_SYNC_ENABLED +#define SPI_OUT_TS_SYNC_TIMEOUT (1000 * 1000) +#endif // SPI_OUT_TS_SYNC_ENABLED + +// Queue size defines +#define SPI_OUT_PING_PONG_BUF_CNT (2) +#define SPI_OUT_UL_QUEUE_SIZE (SPI_OUT_PING_PONG_BUF_CNT) + +#if SPI_OUT_LL_ENABLED +#define SPI_OUT_LL_QUEUE_SIZE (3 * SPI_OUT_PING_PONG_BUF_CNT) +#else +#define SPI_OUT_LL_QUEUE_SIZE (0) +#endif // SPI_OUT_LL_ENABLED + +#define SPI_OUT_SPI_MASTER_QUEUE_SIZE (SPI_OUT_UL_QUEUE_SIZE +\ + SPI_OUT_LL_QUEUE_SIZE) + +// Private typedefs +typedef struct { + // CRITICAL: 0 for available, 1 for need queue (ISR), 2 for in queue + // This flag is for multithreading, must be a word, do not modify + volatile uint32_t flag; + uint16_t buf_size; + uint16_t length; + spi_transaction_t trans; +} spi_out_trans_cb_t; + +typedef struct { + spi_out_trans_cb_t *trans_cb[2]; + uint8_t trans_cb_idx; + uint8_t frame_sn; + uint16_t lost_frame_cnt; + uint32_t lost_bytes_cnt; + uint8_t type; +} spi_out_log_cb_t; + +typedef struct { + uint16_t length; + uint8_t source; + uint8_t frame_sn; +} __attribute__((packed)) frame_head_t; + +typedef struct { + uint8_t type; + uint16_t lost_frame_cnt; + uint32_t lost_bytes_cnt; +} __attribute__((packed)) loss_payload_t; + +typedef struct { + uint8_t io_level; + uint32_t lc_ts; + uint32_t esp_ts; +} __attribute__((packed)) ts_sync_data_t; + +// Private enums +enum { + TRANS_CB_FLAG_AVAILABLE = 0, + TRANS_CB_FLAG_NEED_QUEUE, + TRANS_CB_FLAG_IN_QUEUE, +}; + +enum { + LOG_CB_TYPE_UL = 0, + LOG_CB_TYPE_LL_TASK, + LOG_CB_TYPE_LL_ISR, + LOG_CB_TYPE_LL_HCI, + LOG_CB_TYPE_LE_AUDIO, +}; + +enum { + LL_LOG_FLAG_CONTINUE = 0, + LL_LOG_FLAG_END, + LL_LOG_FLAG_TASK, + LL_LOG_FLAG_ISR, + LL_LOG_FLAG_HCI, + LL_LOG_FLAG_RAW, +}; + +enum { + LL_EV_FLAG_ISR_APPEND = 0, + LL_EV_FLAG_FLUSH_LOG, +}; + +// Private variables +static bool spi_out_inited = false; +static bool spi_out_enabled = false; +static spi_device_handle_t spi_handle = NULL; +static uint32_t last_tx_done_ts = 0; + +static bool ul_log_inited = false; +static SemaphoreHandle_t ul_log_mutex = NULL; +static spi_out_log_cb_t *ul_log_cb = NULL; +static uint8_t *ul_log_str_buf = NULL; + +#if SPI_OUT_LL_ENABLED +static bool ll_log_inited = false; +static spi_out_log_cb_t *ll_task_log_cb = NULL; +static spi_out_log_cb_t *ll_isr_log_cb = NULL; +static spi_out_log_cb_t *ll_hci_log_cb = NULL; +static uint32_t ll_ev_flags = 0; +#endif // SPI_OUT_LL_ENABLED + +#if SPI_OUT_TS_SYNC_ENABLED +static bool ts_sync_inited = false; +static bool ts_sync_enabled = false; +static ts_sync_data_t ts_sync_data = {0}; + +#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT +static esp_timer_handle_t ts_sync_timer = NULL; +#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT +#endif // SPI_OUT_TS_SYNC_ENABLED + +#if SPI_OUT_FLUSH_TIMER_ENABLED +static esp_timer_handle_t flush_timer = NULL; +#endif // SPI_OUT_FLUSH_TIMER_ENABLED + +#if SPI_OUT_LE_AUDIO_ENABLED +static bool le_audio_log_inited = false; +static spi_out_log_cb_t *le_audio_log_cb = NULL; +#endif // SPI_OUT_LE_AUDIO_ENABLED + +// Extern function declarations +extern void esp_panic_handler_feed_wdts(void); + +// Private function declarations +static int spi_out_init_trans(spi_out_trans_cb_t **trans_cb, uint16_t buf_size); +static void spi_out_deinit_trans(spi_out_trans_cb_t **trans_cb); +static void spi_out_tx_done_cb(spi_transaction_t *ret_trans); +static inline void spi_out_append_trans(spi_out_trans_cb_t *trans_cb); + +static int spi_out_log_cb_init(spi_out_log_cb_t **log_cb, uint16_t buf_size, uint8_t type); +static void spi_out_log_cb_deinit(spi_out_log_cb_t **log_cb); +static inline bool spi_out_log_cb_check_trans(spi_out_log_cb_t *log_cb, uint16_t len, bool *need_append); +static inline void spi_out_log_cb_append_trans(spi_out_log_cb_t *log_cb); +static inline void spi_out_log_cb_flush_trans(spi_out_log_cb_t *log_cb); +static bool spi_out_log_cb_write(spi_out_log_cb_t *log_cb, const uint8_t *addr, uint16_t len, + const uint8_t *addr_append, uint16_t len_append, uint8_t source, + bool with_checksum); +static void spi_out_log_cb_write_loss(spi_out_log_cb_t *log_cb); +static void spi_out_log_cb_dump(spi_out_log_cb_t *log_cb); +static void spi_out_log_flush(void); + +static int spi_out_ul_log_init(void); +static void spi_out_ul_log_deinit(void); +static void spi_out_ul_log_write(uint8_t source, const uint8_t *addr, uint16_t len, bool with_ts); +static bool spi_out_ul_log_printf(uint8_t source, const char *format, va_list args, int offset); + +#if SPI_OUT_LL_ENABLED +static int spi_out_ll_log_init(void); +static void spi_out_ll_log_deinit(void); +static void spi_out_ll_log_flush(void); + +#if defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) ||\ + defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32H21) +extern void r_ble_log_simple_put_ev(void); +#define SPI_OUT_LL_PUT_EV r_ble_log_simple_put_ev() +#elif defined(CONFIG_IDF_TARGET_ESP32C2) +extern void ble_log_simple_put_ev(void); +#define SPI_OUT_LL_PUT_EV ble_log_simple_put_ev() +#else +#define SPI_OUT_LL_PUT_EV +#endif +#endif // SPI_OUT_LL_ENABLED + +#if SPI_OUT_TS_SYNC_ENABLED +static int spi_out_ts_sync_init(void); +static void spi_out_ts_sync_deinit(void); +static void spi_out_ts_sync_enable(bool enable); +static void spi_out_ts_sync_toggle(void); + +#if defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C5) ||\ + defined(CONFIG_IDF_TARGET_ESP32C61) || defined(CONFIG_IDF_TARGET_ESP32H21) +extern uint32_t r_ble_lll_timer_current_tick_get(void); +#define SPI_OUT_GET_LC_TIME r_ble_lll_timer_current_tick_get() +#elif defined(CONFIG_IDF_TARGET_ESP32C2) +extern uint32_t r_os_cputime_get32(void); +#define SPI_OUT_GET_LC_TIME r_os_cputime_get32() +#else +#define SPI_OUT_GET_LC_TIME 0 +#endif + +#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT +static void esp_timer_cb_ts_sync(void); +#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT +#endif // SPI_OUT_TS_SYNC_ENABLED + +#if SPI_OUT_LE_AUDIO_ENABLED +static int spi_out_le_audio_log_init(void); +static void spi_out_le_audio_log_deinit(void); +#endif // SPI_OUT_LE_AUDIO_ENABLED + +// Private functions +static int spi_out_init_trans(spi_out_trans_cb_t **trans_cb, uint16_t buf_size) +{ + // Memory allocations + *trans_cb = (spi_out_trans_cb_t *)SPI_OUT_MALLOC(sizeof(spi_out_trans_cb_t)); + if (!(*trans_cb)) { + return -1; + } + memset(*trans_cb, 0, sizeof(spi_out_trans_cb_t)); + + uint8_t *buf = (uint8_t *)SPI_OUT_MALLOC((size_t)buf_size); + if (!buf) { + free(*trans_cb); + *trans_cb = NULL; + return -1; + } + + // Initialization + (*trans_cb)->buf_size = buf_size; + (*trans_cb)->trans.tx_buffer = buf; + (*trans_cb)->trans.user = (void *)(*trans_cb); + return 0; +} + +static void spi_out_deinit_trans(spi_out_trans_cb_t **trans_cb) +{ + if (!(*trans_cb)) { + return; + } + if ((*trans_cb)->trans.tx_buffer) { + free((uint8_t *)(*trans_cb)->trans.tx_buffer); + (*trans_cb)->trans.tx_buffer = NULL; + } + + free(*trans_cb); + *trans_cb = NULL; + return; +} + +IRAM_ATTR static void spi_out_tx_done_cb(spi_transaction_t *ret_trans) +{ + last_tx_done_ts = esp_timer_get_time(); + spi_out_trans_cb_t *trans_cb = (spi_out_trans_cb_t *)ret_trans->user; + trans_cb->length = 0; + trans_cb->flag = TRANS_CB_FLAG_AVAILABLE; +} + +IRAM_ATTR static void spi_out_pre_tx_cb(spi_transaction_t *ret_trans) +{ + // SPI slave continuous transaction workaround + while (esp_timer_get_time() - last_tx_done_ts < SPI_OUT_TRANS_ITVL_MIN_US) {} +} + +IRAM_ATTR static inline void spi_out_append_trans(spi_out_trans_cb_t *trans_cb) +{ + if (trans_cb->flag != TRANS_CB_FLAG_NEED_QUEUE || !trans_cb->length) { + return; + } + + // Note: To support dump log when disabled + if (!spi_out_enabled) { + goto recycle; + } + + // CRITICAL: Length unit conversion from bytes to bits + trans_cb->trans.length = trans_cb->length * 8; + trans_cb->trans.rxlength = 0; + trans_cb->flag = TRANS_CB_FLAG_IN_QUEUE; + if (spi_device_queue_trans(spi_handle, &(trans_cb->trans), 0) != ESP_OK) { + goto recycle; + } + return; + +recycle: + trans_cb->length = 0; + trans_cb->flag = TRANS_CB_FLAG_AVAILABLE; + return; +} + +static int spi_out_log_cb_init(spi_out_log_cb_t **log_cb, uint16_t buf_size, uint8_t type) +{ + // Initialize log control block + *log_cb = (spi_out_log_cb_t *)SPI_OUT_MALLOC(sizeof(spi_out_log_cb_t)); + if (!(*log_cb)) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control block!"); + return -1; + } + memset(*log_cb, 0, sizeof(spi_out_log_cb_t)); + + // Initialize transactions + int ret = 0; + for (uint8_t i = 0; i < 2; i++) { + ret |= spi_out_init_trans(&((*log_cb)->trans_cb[i]), buf_size); + } + if (ret != 0) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize SPI transactions!"); + spi_out_log_cb_deinit(log_cb); + return -1; + } + + (*log_cb)->type = type; + return 0; +} + +static void spi_out_log_cb_deinit(spi_out_log_cb_t **log_cb) +{ + if (!(*log_cb)) { + return; + } + + for (uint8_t i = 0; i < 2; i++) { + if ((*log_cb)->trans_cb[i]) { + spi_out_deinit_trans(&((*log_cb)->trans_cb[i])); + } + } + free(*log_cb); + *log_cb = NULL; + return; +} + +IRAM_ATTR static inline bool spi_out_log_cb_check_trans(spi_out_log_cb_t *log_cb, uint16_t len, bool *need_append) +{ + spi_out_trans_cb_t *trans_cb; + uint16_t frame_len = len + SPI_OUT_FRAME_OVERHEAD; + *need_append = false; + for (uint8_t i = 0; i < 2; i++) { + trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx]; + if (frame_len > trans_cb->buf_size) { + goto failed; + } + if (trans_cb->flag == TRANS_CB_FLAG_AVAILABLE) { + if ((trans_cb->buf_size - trans_cb->length) >= frame_len) { + return true; + } else { + trans_cb->flag = TRANS_CB_FLAG_NEED_QUEUE; + *need_append = true; + } + } + log_cb->trans_cb_idx = !(log_cb->trans_cb_idx); + } +failed: + log_cb->lost_bytes_cnt += frame_len; + log_cb->lost_frame_cnt++; + log_cb->frame_sn++; + return false; +} + +// CRITICAL: Shall not be called from ISR! +IRAM_ATTR static inline void spi_out_log_cb_append_trans(spi_out_log_cb_t *log_cb) +{ + spi_out_trans_cb_t *trans_cb; + uint8_t idx = !log_cb->trans_cb_idx; + for (uint8_t i = 0; i < 2; i++) { + trans_cb = log_cb->trans_cb[idx]; + if (trans_cb->flag == TRANS_CB_FLAG_NEED_QUEUE) { + spi_out_append_trans(trans_cb); + } + idx = !idx; + } +} + +IRAM_ATTR static inline void spi_out_log_cb_flush_trans(spi_out_log_cb_t *log_cb) +{ + spi_out_trans_cb_t *trans_cb; + for (uint8_t i = 0; i < 2; i++) { + trans_cb = log_cb->trans_cb[i]; + if (trans_cb->length && (trans_cb->flag == TRANS_CB_FLAG_AVAILABLE)) { + trans_cb->flag = TRANS_CB_FLAG_NEED_QUEUE; + } + } +} + +// Return value: Need append +IRAM_ATTR static bool spi_out_log_cb_write(spi_out_log_cb_t *log_cb, const uint8_t *addr, uint16_t len, + const uint8_t *addr_append, uint16_t len_append, uint8_t source, + bool with_checksum) +{ + spi_out_trans_cb_t *trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx]; + + uint8_t *buf = (uint8_t *)trans_cb->trans.tx_buffer + trans_cb->length; + uint16_t total_length = len + len_append; + frame_head_t head = { + .length = total_length, + .source = source, + .frame_sn = log_cb->frame_sn, + }; + uint32_t checksum = 0; + if (with_checksum) { + for (int i = 0; i < len; i++) { + checksum += addr[i]; + } + for (int i = 0; i < len_append; i++) { + checksum += addr_append[i]; + } + } + + memcpy(buf, (const uint8_t *)&head, SPI_OUT_FRAME_HEAD_LEN); + memcpy(buf + SPI_OUT_FRAME_HEAD_LEN, addr, len); + if (len_append && addr_append) { + memcpy(buf + SPI_OUT_FRAME_HEAD_LEN + len, addr_append, len_append); + } + memcpy(buf + SPI_OUT_FRAME_HEAD_LEN + total_length, &checksum, SPI_OUT_FRAME_TAIL_LEN); + + trans_cb->length += total_length + SPI_OUT_FRAME_OVERHEAD; + log_cb->frame_sn++; + if ((trans_cb->buf_size - trans_cb->length) <= SPI_OUT_FRAME_OVERHEAD) { + trans_cb->flag = TRANS_CB_FLAG_NEED_QUEUE; + return true; + } + return false; +} + +IRAM_ATTR static void spi_out_log_cb_write_loss(spi_out_log_cb_t *log_cb) +{ + if (!log_cb->lost_bytes_cnt || !log_cb->lost_frame_cnt) { + return; + } + bool need_append; + if (spi_out_log_cb_check_trans(log_cb, sizeof(loss_payload_t), &need_append)) { + loss_payload_t payload = { + .type = log_cb->type, + .lost_frame_cnt = log_cb->lost_frame_cnt, + .lost_bytes_cnt = log_cb->lost_bytes_cnt, + }; + spi_out_log_cb_write(log_cb, (const uint8_t *)&payload, sizeof(loss_payload_t), + NULL, 0, BLE_LOG_SPI_OUT_SOURCE_LOSS, true); + + log_cb->lost_frame_cnt = 0; + log_cb->lost_bytes_cnt = 0; + } +} + +static void spi_out_log_cb_dump(spi_out_log_cb_t *log_cb) +{ + spi_out_trans_cb_t *trans_cb; + uint8_t *buf; + for (uint8_t i = 0; i < 2; i++) { + // Dump the last transaction before dumping the current transaction + log_cb->trans_cb_idx = !(log_cb->trans_cb_idx); + trans_cb = log_cb->trans_cb[log_cb->trans_cb_idx]; + buf = (uint8_t *)trans_cb->trans.tx_buffer; + for (uint16_t j = 0; j < trans_cb->buf_size; j++) { + esp_rom_printf("%02x ", buf[j]); + + // Feed watchdogs periodically to avoid wdts timeout + if ((j % 100) == 0) { + esp_panic_handler_feed_wdts(); + } + } + } +} + +static void spi_out_log_flush(void) +{ + // Flush ul log + xSemaphoreTake(ul_log_mutex, portMAX_DELAY); + spi_out_log_cb_flush_trans(ul_log_cb); + spi_out_log_cb_append_trans(ul_log_cb); + xSemaphoreGive(ul_log_mutex); + +#if SPI_OUT_LL_ENABLED + if (esp_bt_controller_get_status() >= ESP_BT_CONTROLLER_STATUS_INITED) { + ll_ev_flags |= BIT(LL_EV_FLAG_FLUSH_LOG); + SPI_OUT_LL_PUT_EV; + } +#endif // SPI_OUT_LL_ENABLED +} + +#if SPI_OUT_FLUSH_TIMER_ENABLED +// Context: ESP timer +static void esp_timer_cb_log_flush(void) +{ + spi_out_log_flush(); + esp_timer_start_once(flush_timer, SPI_OUT_FLUSH_TIMEOUT_US); +} +#endif // SPI_OUT_FLUSH_TIMER_ENABLED + +static int spi_out_ul_log_init(void) +{ + if (ul_log_inited) { + return 0; + } + + // Initialize mutex + ul_log_mutex = xSemaphoreCreateMutex(); + if (!ul_log_mutex) { + ESP_LOGE(BLE_LOG_TAG, "Failed to create mutex for upper layer task log!"); + goto mutex_init_failed; + } + + // Initialize string buffer + ul_log_str_buf = (uint8_t *)SPI_OUT_MALLOC(SPI_OUT_UL_LOG_STR_BUF_SIZE); + if (!ul_log_str_buf) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize string buffer for upper layer task log!"); + goto str_buf_init_failed; + } + + // Initialize log control block + if (spi_out_log_cb_init(&ul_log_cb, SPI_OUT_UL_TASK_BUF_SIZE, LOG_CB_TYPE_UL) != 0) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control blocks for upper layer task log!"); + goto log_cb_init_failed; + } + + // Initialization done + ESP_LOGI(BLE_LOG_TAG, "Succeeded to initialize upper layer task log!"); + ul_log_inited = true; + return 0; + +log_cb_init_failed: + if (ul_log_str_buf) { + free(ul_log_str_buf); + ul_log_str_buf = NULL; + } +str_buf_init_failed: + vSemaphoreDelete(ul_log_mutex); +mutex_init_failed: + return -1; +} + +static void spi_out_ul_log_deinit(void) +{ + if (!ul_log_inited) { + return; + } + ul_log_inited = false; + + xSemaphoreTake(ul_log_mutex, portMAX_DELAY); + if (ul_log_str_buf) { + free(ul_log_str_buf); + ul_log_str_buf = NULL; + } + spi_out_log_cb_deinit(&ul_log_cb); + xSemaphoreGive(ul_log_mutex); + + vSemaphoreDelete(ul_log_mutex); + ul_log_mutex = NULL; + + ESP_LOGI(BLE_LOG_TAG, "Succeeded to deinitialize upper layer log!"); + return; +} + +static void spi_out_ul_log_write(uint8_t source, const uint8_t *addr, uint16_t len, bool with_ts) +{ + uint16_t total_len = with_ts? (len + sizeof(uint32_t)): len; + bool need_append; + if (spi_out_log_cb_check_trans(ul_log_cb, total_len, &need_append)) { + if (with_ts) { + uint32_t esp_ts = esp_timer_get_time(); + need_append |= spi_out_log_cb_write(ul_log_cb, (const uint8_t *)&esp_ts, + sizeof(uint32_t), addr, len, source, true); + } else { + need_append |= spi_out_log_cb_write(ul_log_cb, addr, len, NULL, 0, source, true); + } + } + if (need_append) { + spi_out_log_cb_append_trans(ul_log_cb); + } + spi_out_log_cb_write_loss(ul_log_cb); +} + +static bool spi_out_ul_log_printf(uint8_t source, const char *format, va_list args, int offset) +{ + int len = vsnprintf((char *)(ul_log_str_buf + offset), + SPI_OUT_UL_LOG_STR_BUF_SIZE - offset, format, args); + if (len < 0) { + return false; + } + len += offset; + + // Truncate string if overflowed + if (len >= SPI_OUT_UL_LOG_STR_BUF_SIZE) { + len = SPI_OUT_UL_LOG_STR_BUF_SIZE - 1; + ul_log_str_buf[len] = '\0'; + } + + spi_out_ul_log_write(source, ul_log_str_buf, len, true); + return true; +} + +#if SPI_OUT_LL_ENABLED +static int spi_out_ll_log_init(void) +{ + if (ll_log_inited) { + return 0; + } + + // Initialize log control blocks for controller task & ISR logs + if (spi_out_log_cb_init(&ll_task_log_cb, SPI_OUT_LL_TASK_BUF_SIZE, LOG_CB_TYPE_LL_TASK) != 0) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control blocks for controller task!"); + goto task_log_cb_init_failed; + } + if (spi_out_log_cb_init(&ll_isr_log_cb, SPI_OUT_LL_ISR_BUF_SIZE, LOG_CB_TYPE_LL_ISR) != 0) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control blocks for controller ISR!"); + goto isr_log_cb_init_failed; + } + if (spi_out_log_cb_init(&ll_hci_log_cb, SPI_OUT_LL_HCI_BUF_SIZE, LOG_CB_TYPE_LL_HCI) != 0) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control blocks for controller ISR!"); + goto hci_log_cb_init_failed; + } + + // Initialization done + ESP_LOGI(BLE_LOG_TAG, "Succeeded to initialize log control blocks for controller task & ISR!"); + ll_log_inited = true; + return 0; + +hci_log_cb_init_failed: + spi_out_log_cb_deinit(&ll_isr_log_cb); +isr_log_cb_init_failed: + spi_out_log_cb_deinit(&ll_task_log_cb); +task_log_cb_init_failed: + return -1; +} + +static void spi_out_ll_log_deinit(void) +{ + if (!ll_log_inited) { + return; + } + + spi_out_log_cb_deinit(&ll_hci_log_cb); + spi_out_log_cb_deinit(&ll_isr_log_cb); + spi_out_log_cb_deinit(&ll_task_log_cb); + + // Deinitialization done + ESP_LOGI(BLE_LOG_TAG, "Succeeded to deinitialize controller log!"); + ll_log_inited = false; + return; +} + +// Context: LL task +static void spi_out_ll_log_flush(void) +{ + // Flush task log and hci log buffer + spi_out_log_cb_flush_trans(ll_task_log_cb); + spi_out_log_cb_flush_trans(ll_hci_log_cb); + + // Race condition for isr log buffer + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + spi_out_log_cb_flush_trans(ll_isr_log_cb); + portEXIT_CRITICAL_SAFE(&spinlock); + + // Note: Save SPI transfer start time + spi_out_log_cb_append_trans(ll_task_log_cb); + spi_out_log_cb_append_trans(ll_hci_log_cb); + spi_out_log_cb_append_trans(ll_isr_log_cb); +} +#endif // SPI_OUT_LL_ENABLED + +#if SPI_OUT_TS_SYNC_ENABLED +static int spi_out_ts_sync_init(void) +{ + if (ts_sync_inited) { + return 0; + } + +#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT + // Initialize sync timer + esp_timer_create_args_t timer_args = { + .callback = (esp_timer_cb_t)esp_timer_cb_ts_sync, + .dispatch_method = ESP_TIMER_TASK + }; + if (esp_timer_create(&timer_args, &ts_sync_timer) != ESP_OK) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize timestamp synchronizer timer!"); + goto timer_init_failed; + } +#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT + + // Initialize sync IO + gpio_config_t io_conf = { + .intr_type = GPIO_INTR_DISABLE, + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = BIT(SPI_OUT_SYNC_IO_NUM), + .pull_down_en = 0, + .pull_up_en = 0 + }; + if (gpio_config(&io_conf) != ESP_OK) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize timestamp synchronizer IO!"); + goto gpio_init_failed; + } + + // Initialization done + ESP_LOGI(BLE_LOG_TAG, "Succeeded to initialize timestamp synchronizer!"); + ts_sync_inited = true; + return 0; + +gpio_init_failed: +#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT + esp_timer_delete(ts_sync_timer); + ts_sync_timer = NULL; +timer_init_failed: +#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT + return -1; +} + +static void spi_out_ts_sync_deinit(void) +{ + if (!ts_sync_inited) { + return; + } + +#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT + // Deinitialize timestamp synchronizer + esp_timer_stop(ts_sync_timer); + esp_timer_delete(ts_sync_timer); + ts_sync_timer = NULL; +#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT + + // Deinitialize sync IO + spi_out_ts_sync_enable(false); + gpio_reset_pin(SPI_OUT_SYNC_IO_NUM); + + // Deinitialization done + ESP_LOGI(BLE_LOG_TAG, "Succeeded to deinitialize timestamp synchronizer!"); + ts_sync_inited = false; + return; +} + +static void spi_out_ts_sync_enable(bool enable) +{ + // Update ts sync status + ts_sync_enabled = enable; + if (enable) { +#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT + // Start timestamp sync timer + if (ts_sync_timer) { + if (!esp_timer_is_active(ts_sync_timer)) { + esp_timer_start_periodic(ts_sync_timer, SPI_OUT_TS_SYNC_TIMEOUT); + } + } +#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT + } else { +#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT + // Stop timestamp sync timer + if (ts_sync_timer) { + if (esp_timer_is_active(ts_sync_timer)) { + esp_timer_stop(ts_sync_timer); + } + } +#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT + if (!ts_sync_data.io_level) { + gpio_set_level(SPI_OUT_SYNC_IO_NUM, 1); + } + } + ts_sync_data.io_level = 0; + gpio_set_level(SPI_OUT_SYNC_IO_NUM, (uint32_t)ts_sync_data.io_level); +} + +static void spi_out_ts_sync_toggle(void) +{ + // Toggle sync IO + ts_sync_data.io_level = !ts_sync_data.io_level; + + // Enter critical + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL(&spinlock); + + // Get LC timestamp + ts_sync_data.lc_ts = SPI_OUT_GET_LC_TIME; + + // Set sync IO level + gpio_set_level(SPI_OUT_SYNC_IO_NUM, (uint32_t)ts_sync_data.io_level); + + // Get ESP timestamp + ts_sync_data.esp_ts = esp_timer_get_time(); + portEXIT_CRITICAL(&spinlock); + // Exit critical +} + +#if !SPI_OUT_TS_SYNC_SLEEP_SUPPORT +// CRITICAL: This function is called in ESP Timer task +static void esp_timer_cb_ts_sync(void) +{ + spi_out_ts_sync_toggle(); + ble_log_spi_out_write(BLE_LOG_SPI_OUT_SOURCE_SYNC, (const uint8_t *)&ts_sync_data, + sizeof(ts_sync_data_t)); +} +#else + +#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT +#endif // SPI_OUT_TS_SYNC_ENABLED + +#if SPI_OUT_LE_AUDIO_ENABLED +static int spi_out_le_audio_log_init(void) +{ + if (le_audio_log_inited) { + return 0; + } + + // Initialize log control blocks for controller task & ISR logs + if (spi_out_log_cb_init(&le_audio_log_cb, SPI_OUT_LE_AUDIO_BUF_SIZE, LOG_CB_TYPE_LE_AUDIO) != 0) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize log control blocks for LE audio!"); + return -1; + } + + // Initialization done + ESP_LOGI(BLE_LOG_TAG, "Succeeded to initialize log control blocks for LE Audio!"); + le_audio_log_inited = true; + return 0; +} + +static void spi_out_le_audio_log_deinit(void) +{ + if (!le_audio_log_inited) { + return; + } + + spi_out_log_cb_deinit(&le_audio_log_cb); + + // Deinitialization done + ESP_LOGI(BLE_LOG_TAG, "Succeeded to deinitialize LE audio log!"); + le_audio_log_inited = false; + return; +} +#endif // SPI_OUT_LE_AUDIO_ENABLED + +// Public functions +int ble_log_spi_out_init(void) +{ + // Avoid double init + if (spi_out_inited) { + return 0; + } + + // Initialize SPI + spi_bus_config_t bus_config = { + .miso_io_num = -1, + .mosi_io_num = SPI_OUT_MOSI_IO_NUM, + .sclk_io_num = SPI_OUT_SCLK_IO_NUM, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = SPI_OUT_MAX_TRANSFER_SIZE, +#if CONFIG_SPI_MASTER_ISR_IN_IRAM + .intr_flags = ESP_INTR_FLAG_IRAM +#endif // CONFIG_SPI_MASTER_ISR_IN_IRAM + }; + spi_device_interface_config_t dev_config = { + .clock_speed_hz = SPI_MASTER_FREQ_20M, + .mode = 0, + .spics_io_num = SPI_OUT_CS_IO_NUM, + .queue_size = SPI_OUT_SPI_MASTER_QUEUE_SIZE, + .post_cb = spi_out_tx_done_cb, + .pre_cb = spi_out_pre_tx_cb, + .flags = SPI_DEVICE_NO_RETURN_RESULT + }; + if (spi_bus_initialize(SPI_OUT_BUS, &bus_config, SPI_DMA_CH_AUTO) != ESP_OK) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize SPI bus!"); + goto spi_bus_init_failed; + } + if (spi_bus_add_device(SPI_OUT_BUS, &dev_config, &spi_handle) != ESP_OK) { + ESP_LOGE(BLE_LOG_TAG, "Failed to add device to SPI bus!"); + goto spi_device_add_failed; + } + + if (spi_out_ul_log_init() != 0) { + goto ul_log_init_failed; + } + +#if SPI_OUT_LL_ENABLED + if (spi_out_ll_log_init() != 0) { + goto ll_log_init_failed; + } +#endif // SPI_OUT_LL_ENABLED + +#if SPI_OUT_TS_SYNC_ENABLED + if (spi_out_ts_sync_init() != 0) { + goto ts_sync_init_failed; + } +#endif // SPI_OUT_TS_SYNC_ENABLED + +#if SPI_OUT_LE_AUDIO_ENABLED + if (spi_out_le_audio_log_init() != 0) { + goto le_audio_init_failed; + } +#endif // SPI_OUT_LE_AUDIO_ENABLED + +#if SPI_OUT_FLUSH_TIMER_ENABLED + esp_timer_create_args_t timer_args = { + .callback = (esp_timer_cb_t)esp_timer_cb_log_flush, + .dispatch_method = ESP_TIMER_TASK + }; + if (esp_timer_create(&timer_args, &flush_timer) != ESP_OK) { + ESP_LOGE(BLE_LOG_TAG, "Failed to initialize flush timer!"); + goto timer_init_failed; + } +#endif // SPI_OUT_FLUSH_TIMER_ENABLED + + // Initialization done + ESP_LOGI(BLE_LOG_TAG, "Succeeded to initialize BLE log SPI output interface!"); + spi_out_inited = true; + spi_out_enabled = true; + +#if SPI_OUT_FLUSH_TIMER_ENABLED + esp_timer_start_once(flush_timer, SPI_OUT_FLUSH_TIMEOUT_US); +#endif // SPI_OUT_FLUSH_TIMER_ENABLED + return 0; + +#if SPI_OUT_FLUSH_TIMER_ENABLED +timer_init_failed: +#endif // SPI_OUT_FLUSH_TIMER_ENABLED +#if SPI_OUT_LE_AUDIO_ENABLED + spi_out_le_audio_log_deinit(); +le_audio_init_failed: +#endif // SPI_OUT_LE_AUDIO_ENABLED +#if SPI_OUT_TS_SYNC_ENABLED + spi_out_ts_sync_deinit(); +ts_sync_init_failed: +#endif // SPI_OUT_TS_SYNC_ENABLED +#if SPI_OUT_LL_ENABLED + spi_out_ll_log_deinit(); +ll_log_init_failed: +#endif // SPI_OUT_LL_ENABLED + spi_out_ul_log_deinit(); +ul_log_init_failed: + spi_bus_remove_device(spi_handle); + spi_handle = NULL; +spi_device_add_failed: + spi_bus_free(SPI_OUT_BUS); +spi_bus_init_failed: + return -1; +} + +void ble_log_spi_out_deinit(void) +{ + // Avoid double deinit + if (!spi_out_inited) { + return; + } + +#if SPI_OUT_FLUSH_TIMER_ENABLED + esp_timer_stop(flush_timer); + esp_timer_delete(flush_timer); + flush_timer = NULL; +#endif // SPI_OUT_FLUSH_TIMER_ENABLED + + // Drain all queued transactions + assert(spi_device_acquire_bus(spi_handle, portMAX_DELAY) == ESP_OK); + spi_device_release_bus(spi_handle); + + // Remove SPI master + spi_bus_remove_device(spi_handle); + spi_handle = NULL; + spi_bus_free(SPI_OUT_BUS); + +#if SPI_OUT_TS_SYNC_ENABLED + spi_out_ts_sync_deinit(); +#endif // SPI_OUT_TS_SYNC_ENABLED + +#if SPI_OUT_LL_ENABLED + spi_out_ll_log_deinit(); +#endif // SPI_OUT_LL_ENABLED + + spi_out_ul_log_deinit(); + + // Reset init flag + spi_out_inited = false; + spi_out_enabled = false; +} + +#if SPI_OUT_TS_SYNC_ENABLED +void ble_log_spi_out_ts_sync_start(void) +{ + // Check if SPI out is initialized + if (!spi_out_inited) { + return; + } + spi_out_ts_sync_enable(true); +} + +void ble_log_spi_out_ts_sync_stop(void) +{ + // Check if SPI out is initialized + if (!spi_out_inited) { + return; + } + spi_out_ts_sync_enable(false); +} +#endif // SPI_OUT_TS_SYNC_ENABLED + +#if SPI_OUT_LL_ENABLED +// Only LL task has access to this API +IRAM_ATTR void ble_log_spi_out_ll_write(uint32_t len, const uint8_t *addr, uint32_t len_append, + const uint8_t *addr_append, uint32_t flag) +{ + // Raw logs will come in case of assert, shall be printed to console directly + if (flag & BIT(LL_LOG_FLAG_RAW)) { + if (len && addr) { + for (uint32_t i = 0; i < len; i++) { esp_rom_printf("%02x ", addr[i]); } + } + if (len_append && addr_append) { + for (uint32_t i = 0; i < len_append; i++) { esp_rom_printf("%02x ", addr_append[i]); } + } + if (flag & BIT(LL_LOG_FLAG_END)) { esp_rom_printf("\n"); } + } + + if (!ll_log_inited) { + return; + } + + bool in_isr = false; + uint8_t source; + spi_out_log_cb_t *log_cb; + if (flag & BIT(LL_LOG_FLAG_ISR)) { + log_cb = ll_isr_log_cb; + source = BLE_LOG_SPI_OUT_SOURCE_ESP_ISR; + in_isr = true; + } else if (flag & BIT(LL_LOG_FLAG_HCI)) { + log_cb = ll_hci_log_cb; + source = BLE_LOG_SPI_OUT_SOURCE_LL_HCI; + } else { + log_cb = ll_task_log_cb; + source = BLE_LOG_SPI_OUT_SOURCE_ESP; + } + + bool need_append; + if (spi_out_log_cb_check_trans(log_cb, (uint16_t)(len + len_append), &need_append)) { + need_append |= spi_out_log_cb_write(log_cb, addr, (uint16_t)len, addr_append, + (uint16_t)len_append, source, true); + } + if (need_append) { + if (in_isr) { + ll_ev_flags |= BIT(LL_EV_FLAG_ISR_APPEND); + SPI_OUT_LL_PUT_EV; + } else { + spi_out_log_cb_append_trans(log_cb); + +#if SPI_OUT_TS_SYNC_SLEEP_SUPPORT + if (ts_sync_inited && ts_sync_enabled) { + if (last_tx_done_ts >= (SPI_OUT_TS_SYNC_TIMEOUT + ts_sync_data.esp_ts)) { + if (spi_out_log_cb_check_trans(ll_task_log_cb, sizeof(ts_sync_data_t), &need_append)) { + spi_out_ts_sync_toggle(); + spi_out_log_cb_write(ll_task_log_cb, (const uint8_t *)&ts_sync_data, + sizeof(ts_sync_data_t), NULL, 0, BLE_LOG_SPI_OUT_SOURCE_SYNC, true); + } + } + } +#endif // !SPI_OUT_TS_SYNC_SLEEP_SUPPORT + } + } + spi_out_log_cb_write_loss(log_cb); +} + +IRAM_ATTR void ble_log_spi_out_ll_log_ev_proc(void) +{ + if (!ll_log_inited) { + return; + } + + if (ll_ev_flags & BIT(LL_EV_FLAG_ISR_APPEND)) { + spi_out_log_cb_append_trans(ll_isr_log_cb); + ll_ev_flags &= ~BIT(LL_EV_FLAG_ISR_APPEND); + } + + if (ll_ev_flags & BIT(LL_EV_FLAG_FLUSH_LOG)) { + spi_out_ll_log_flush(); + ll_ev_flags &= ~BIT(LL_EV_FLAG_FLUSH_LOG); + } + + ll_ev_flags = 0; +} +#endif // SPI_OUT_LL_ENABLED + +int ble_log_spi_out_write(uint8_t source, const uint8_t *addr, uint16_t len) +{ + if (!ul_log_inited) { + return -1; + } + + xSemaphoreTake(ul_log_mutex, portMAX_DELAY); + spi_out_ul_log_write(source, addr, len, false); + xSemaphoreGive(ul_log_mutex); + return 0; +} + +int ble_log_spi_out_printf(uint8_t source, const char *format, ...) +{ + if (!ul_log_inited) { + return -1; + } + + if (!format) { + return -1; + } + + // Get arguments + va_list args; + va_start(args, format); + + va_list args_copy; + va_copy(args_copy, args); + + xSemaphoreTake(ul_log_mutex, portMAX_DELAY); + bool ret = spi_out_ul_log_printf(source, format, args_copy, 0); + xSemaphoreGive(ul_log_mutex); + + va_end(args_copy); + va_end(args); + return ret? 0: -1; +} + +int ble_log_spi_out_printf_enh(uint8_t source, uint8_t level, const char *tag, const char *format, ...) +{ + if (!ul_log_inited) { + return -1; + } + + if (!tag || !format) { + return -1; + } + + va_list args; + va_start(args, format); + + va_list args_copy; + va_copy(args_copy, args); + + // Create log prefix in the format: "[level][tag] " + bool ret = false; + xSemaphoreTake(ul_log_mutex, portMAX_DELAY); + int prefix_len = snprintf((char *)ul_log_str_buf, SPI_OUT_UL_LOG_STR_BUF_SIZE, + "[%d][%s]", level, tag? tag: "NULL"); + if ((prefix_len < 0) || (prefix_len >= SPI_OUT_UL_LOG_STR_BUF_SIZE)) { + goto exit; + } + ret = spi_out_ul_log_printf(source, format, args_copy, prefix_len); +exit: + xSemaphoreGive(ul_log_mutex); + va_end(args_copy); + va_end(args); + return ret? 0: -1; +} + +int ble_log_spi_out_write_with_ts(uint8_t source, const uint8_t *addr, uint16_t len) +{ + if (!ul_log_inited) { + return -1; + } + + xSemaphoreTake(ul_log_mutex, portMAX_DELAY); + spi_out_ul_log_write(source, addr, len, true); + xSemaphoreGive(ul_log_mutex); + return 0; +} + +void ble_log_spi_out_dump_all(void) +{ + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + +#if SPI_OUT_LL_ENABLED + if (ll_log_inited) { + // Dump lower layer log buffer + esp_rom_printf("[LL_ISR_LOG_DUMP_START:\n"); + spi_out_log_cb_dump(ll_isr_log_cb); + esp_rom_printf("\n:LL_ISR_LOG_DUMP_END]\n\n"); + + esp_rom_printf("[LL_TASK_LOG_DUMP_START:\n"); + spi_out_log_cb_dump(ll_task_log_cb); + esp_rom_printf("\n:LL_TASK_LOG_DUMP_END]\n\n"); + + esp_rom_printf("[LL_HCI_LOG_DUMP_START:\n"); + spi_out_log_cb_dump(ll_hci_log_cb); + esp_rom_printf("\n:LL_HCI_LOG_DUMP_END]\n\n"); + } +#endif // SPI_OUT_LL_ENABLED + + if (ul_log_inited) { + // Dump upper layer log buffer + esp_rom_printf("[UL_LOG_DUMP_START:\n"); + spi_out_log_cb_dump(ul_log_cb); + esp_rom_printf("\n:UL_LOG_DUMP_END]\n\n"); + } + portEXIT_CRITICAL_SAFE(&spinlock); +} + +void ble_log_spi_out_enable(bool enable) +{ + spi_out_enabled = enable; + + if (!enable) { +#if CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED + ble_log_spi_out_ts_sync_stop(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED + } +} + +void ble_log_spi_out_flush(void) +{ + if (!spi_out_enabled) { + return; + } + + spi_out_log_flush(); +} + +#if CONFIG_BT_BLE_LOG_SPI_OUT_LE_AUDIO_ENABLED +IRAM_ATTR void ble_log_spi_out_le_audio_write(const uint8_t *addr, uint16_t len) +{ + if (!le_audio_log_inited) { + return; + } + + bool need_append; + if (spi_out_log_cb_check_trans(le_audio_log_cb, len, &need_append)) { + need_append |= spi_out_log_cb_write(le_audio_log_cb, addr, len, NULL, 0, + BLE_LOG_SPI_OUT_SOURCE_LE_AUDIO, false); + } + if (need_append) { + spi_out_log_cb_append_trans(le_audio_log_cb); + } + spi_out_log_cb_write_loss(le_audio_log_cb); + return; +} +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_LE_AUDIO_ENABLED +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED diff --git a/lib/bt/common/ble_log/include/ble_log/ble_log_spi_out.h b/lib/bt/common/ble_log/include/ble_log/ble_log_spi_out.h new file mode 100644 index 00000000..3a4f8d90 --- /dev/null +++ b/lib/bt/common/ble_log/include/ble_log/ble_log_spi_out.h @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef __BT_SPI_OUT_H__ +#define __BT_SPI_OUT_H__ + +#include +#include +#include "driver/spi_master.h" +#include "driver/gpio.h" +#include "esp_timer.h" +#include "esp_log.h" +#include "freertos/semphr.h" +#include "esp_heap_caps.h" + +// Public enums +enum { + BLE_LOG_SPI_OUT_SOURCE_ESP = 0, + BLE_LOG_SPI_OUT_SOURCE_ESP_LEGACY, + BLE_LOG_SPI_OUT_SOURCE_BLUEDROID, + BLE_LOG_SPI_OUT_SOURCE_NIMBLE, + BLE_LOG_SPI_OUT_SOURCE_HCI_UPSTREAM, + BLE_LOG_SPI_OUT_SOURCE_HCI_DOWNSTREAM, + BLE_LOG_SPI_OUT_SOURCE_ESP_ISR, + BLE_LOG_SPI_OUT_SOURCE_ESP_LEGACY_ISR, + BLE_LOG_SPI_OUT_SOURCE_LL_HCI, + BLE_LOG_SPI_OUT_SOURCE_LE_AUDIO, + BLE_LOG_SPI_OUT_SOURCE_USER = 0x10, + BLE_LOG_SPI_OUT_SOURCE_SSC = 0xFD, + BLE_LOG_SPI_OUT_SOURCE_SYNC, + BLE_LOG_SPI_OUT_SOURCE_LOSS, +}; + +enum { + BLE_LOG_SPI_OUT_LEVEL_NONE = 0, + BLE_LOG_SPI_OUT_LEVEL_ERROR, + BLE_LOG_SPI_OUT_LEVEL_WARN, + BLE_LOG_SPI_OUT_LEVEL_INFO, + BLE_LOG_SPI_OUT_LEVEL_DEBUG, + BLE_LOG_SPI_OUT_LEVEL_VERBOSE, + BLE_LOG_SPI_OUT_LEVEL_MAX, +}; + +// Public functions +int ble_log_spi_out_init(void); +void ble_log_spi_out_deinit(void); +void ble_log_spi_out_timer_control(bool enable); +int ble_log_spi_out_write(uint8_t source, const uint8_t *addr, uint16_t len); +void ble_log_spi_out_ll_write(uint32_t len, const uint8_t *addr, uint32_t len_append,\ + const uint8_t *addr_append, uint32_t flag); +void ble_log_spi_out_ll_log_ev_proc(void); +void ble_log_spi_out_ts_sync_start(void); +void ble_log_spi_out_ts_sync_stop(void); +int ble_log_spi_out_printf(uint8_t source, const char *format, ...); +int ble_log_spi_out_printf_enh(uint8_t source, uint8_t level, const char *tag, const char *format, ...); +int ble_log_spi_out_write_with_ts(uint8_t source, const uint8_t *addr, uint16_t len); +void ble_log_spi_out_dump_all(void); +void ble_log_spi_out_enable(bool enable); +void ble_log_spi_out_flush(void); +void ble_log_spi_out_le_audio_write(const uint8_t *addr, uint16_t len); + +#endif // __BT_SPI_OUT_H__ diff --git a/lib/bt/common/btc/core/btc_manage.c b/lib/bt/common/btc/core/btc_manage.c index 52aa837b..e65e1079 100644 --- a/lib/bt/common/btc/core/btc_manage.c +++ b/lib/bt/common/btc/core/btc_manage.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,6 +16,12 @@ void **btc_profile_cb_tab; void esp_profile_cb_reset(void) { + #if BTC_DYNAMIC_MEMORY == TRUE + if (btc_profile_cb_tab == NULL) { + return; + } + #endif + int i; for (i = 0; i < BTC_PID_NUM; i++) { @@ -25,6 +31,12 @@ void esp_profile_cb_reset(void) int btc_profile_cb_set(btc_pid_t profile_id, void *cb) { + #if BTC_DYNAMIC_MEMORY == TRUE + if (btc_profile_cb_tab == NULL) { + return -1; + } + #endif + if (profile_id < 0 || profile_id >= BTC_PID_NUM) { return -1; } @@ -36,6 +48,12 @@ int btc_profile_cb_set(btc_pid_t profile_id, void *cb) void *btc_profile_cb_get(btc_pid_t profile_id) { + #if BTC_DYNAMIC_MEMORY == TRUE + if (btc_profile_cb_tab == NULL) { + return NULL; + } + #endif + if (profile_id < 0 || profile_id >= BTC_PID_NUM) { return NULL; } diff --git a/lib/bt/common/btc/core/btc_task.c b/lib/bt/common/btc/core/btc_task.c index 0f2b6bc0..c240004a 100644 --- a/lib/bt/common/btc/core/btc_task.c +++ b/lib/bt/common/btc/core/btc_task.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -24,6 +24,8 @@ #include "btc_gattc.h" #include "btc_gatt_common.h" #include "btc_gap_ble.h" +#include "btc_iso_ble.h" +#include "btc_ble_cte.h" #include "btc/btc_dm.h" #include "bta/bta_gatt_api.h" #if CLASSIC_BT_INCLUDED @@ -42,9 +44,9 @@ #if (BTC_L2CAP_INCLUDED == TRUE) #include "btc_l2cap.h" #endif /* #if (BTC_L2CAP_INCLUDED == TRUE) */ -#if (BTC_SDP_INCLUDED == TRUE) +#if (BTC_SDP_COMMON_INCLUDED == TRUE) #include "btc_sdp.h" -#endif /* #if (BTC_SDP_INCLUDED == TRUE) */ +#endif /* #if (BTC_SDP_COMMON_INCLUDED == TRUE) */ #if BTC_HF_INCLUDED #include "btc_hf_ag.h" #endif/* #if BTC_HF_INCLUDED */ @@ -57,6 +59,9 @@ #if BTC_HH_INCLUDED == TRUE #include "btc_hh.h" #endif /* BTC_HH_INCLUDED */ +#if BTC_PBA_CLIENT_INCLUDED +#include "btc_pba_client.h" +#endif #endif /* #if CLASSIC_BT_INCLUDED */ #endif @@ -69,6 +74,12 @@ #include "btc_ble_mesh_prov.h" #include "btc_ble_mesh_health_model.h" #include "btc_ble_mesh_config_model.h" +#include "btc_ble_mesh_generic_model.h" +#include "btc_ble_mesh_lighting_model.h" +#include "btc_ble_mesh_sensor_model.h" +#include "btc_ble_mesh_time_scene_model.h" +#if CONFIG_BLE_MESH_V11_SUPPORT +#include "btc_ble_mesh_mbt_model.h" #include "btc_ble_mesh_agg_model.h" #include "btc_ble_mesh_brc_model.h" #include "btc_ble_mesh_df_model.h" @@ -78,11 +89,7 @@ #include "btc_ble_mesh_rpr_model.h" #include "btc_ble_mesh_sar_model.h" #include "btc_ble_mesh_srpl_model.h" -#include "btc_ble_mesh_generic_model.h" -#include "btc_ble_mesh_lighting_model.h" -#include "btc_ble_mesh_sensor_model.h" -#include "btc_ble_mesh_time_scene_model.h" -#include "btc_ble_mesh_mbt_model.h" +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ #endif /* #if CONFIG_BLE_MESH */ #define BTC_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE) @@ -138,9 +145,9 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = { #if (BTC_L2CAP_INCLUDED == TRUE) [BTC_PID_L2CAP] = {btc_l2cap_call_handler, btc_l2cap_cb_handler }, #endif /* #if (BTC_L2CAP_INCLUDED == TRUE) */ -#if (BTC_SDP_INCLUDED == TRUE) +#if (BTC_SDP_COMMON_INCLUDED == TRUE) [BTC_PID_SDP] = {btc_sdp_call_handler, btc_sdp_cb_handler }, -#endif /* #if (BTC_SDP_INCLUDED == TRUE) */ +#endif /* #if (BTC_SDP_COMMON_INCLUDED == TRUE) */ #if BTC_HF_INCLUDED [BTC_PID_HF] = {btc_hf_call_handler, btc_hf_cb_handler}, #endif /* #if BTC_HF_INCLUDED */ @@ -153,6 +160,9 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = { #if BTC_HH_INCLUDED [BTC_PID_HH] = {btc_hh_call_handler, btc_hh_cb_handler }, #endif +#if BTC_PBA_CLIENT_INCLUDED + [BTC_PID_PBA_CLIENT] = {btc_pba_client_call_handler, btc_pba_client_cb_handler}, +#endif #endif /* #if CLASSIC_BT_INCLUDED */ #endif #if CONFIG_BLE_MESH @@ -208,7 +218,7 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = { [BTC_PID_RPR_CLIENT] = {btc_ble_mesh_rpr_client_call_handler, btc_ble_mesh_rpr_client_cb_handler }, #endif /* CONFIG_BLE_MESH_RPR_CLI */ #if CONFIG_BLE_MESH_RPR_SRV - [BTC_PID_RPR_SERVER] = {NULL, btc_ble_mesh_rpr_server_cb_handler }, + [BTC_PID_RPR_SERVER] = {btc_ble_mesh_rpr_server_call_handler, btc_ble_mesh_rpr_server_cb_handler }, #endif /* CONFIG_BLE_MESH_RPR_SRV */ #if CONFIG_BLE_MESH_SAR_CLI [BTC_PID_SAR_CLIENT] = {btc_ble_mesh_sar_client_call_handler, btc_ble_mesh_sar_client_cb_handler }, @@ -252,10 +262,16 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = { #if CONFIG_BLE_MESH_MBT_SRV [BTC_PID_MBT_SERVER] = {btc_ble_mesh_mbt_server_call_handler, btc_ble_mesh_mbt_server_cb_handler }, #endif /* CONFIG_BLE_MESH_MBT_SRV */ -#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT +#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50 [BTC_PID_BLE_MESH_BLE_COEX] = {btc_ble_mesh_ble_call_handler, btc_ble_mesh_ble_cb_handler }, -#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT */ +#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50 */ #endif /* #if CONFIG_BLE_MESH */ +#if (BLE_FEAT_ISO_EN == TRUE) + [BTC_PID_ISO_BLE] = {btc_iso_ble_call_handler, btc_iso_ble_cb_handler }, +#endif // #if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_CTE_EN == TRUE) + [BTC_PID_BLE_CTE] = {btc_ble_cte_call_handler, btc_ble_cte_cb_handler }, +#endif // #if (BLE_FEAT_CTE_EN == TRUE) }; /***************************************************************************** @@ -295,8 +311,8 @@ static bt_status_t btc_task_post(btc_msg_t *msg, uint32_t timeout) /** * transfer an message to another module in the different task. * @param msg message - * @param arg paramter - * @param arg_len length of paramter + * @param arg parameter + * @param arg_len length of parameter * @param copy_func deep copy function * @param free_func deep free function * @return BT_STATUS_SUCCESS: success @@ -342,7 +358,7 @@ bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg } /** - * transfer an message to another module in tha same task. + * transfer an message to another module in the same task. * @param msg message * @return BT_STATUS_SUCCESS: success * others: fail @@ -380,7 +396,8 @@ static void btc_deinit_mem(void) { btc_profile_cb_tab = NULL; } -#if (BLE_INCLUDED == TRUE) +#if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_ADV_EN == TRUE) if (gl_bta_adv_data_ptr) { osi_free(gl_bta_adv_data_ptr); gl_bta_adv_data_ptr = NULL; @@ -390,7 +407,8 @@ static void btc_deinit_mem(void) { osi_free(gl_bta_scan_rsp_data_ptr); gl_bta_scan_rsp_data_ptr = NULL; } -#endif ///BLE_INCLUDED == TRUE +#endif // #if (BLE_42_ADV_EN == TRUE) +#endif // BLE_42_FEATURE_SUPPORT #if GATTS_INCLUDED == TRUE && GATT_DYNAMIC_MEMORY == TRUE if (btc_creat_tab_env_ptr) { @@ -442,7 +460,9 @@ static bt_status_t btc_init_mem(void) { } memset((void *)btc_profile_cb_tab, 0, sizeof(void *) * BTC_PID_NUM); -#if (BLE_INCLUDED == TRUE) +#if BTC_DYNAMIC_MEMORY == TRUE +#if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_ADV_EN == TRUE) if ((gl_bta_adv_data_ptr = (tBTA_BLE_ADV_DATA *)osi_malloc(sizeof(tBTA_BLE_ADV_DATA))) == NULL) { goto error_exit; } @@ -452,7 +472,9 @@ static bt_status_t btc_init_mem(void) { goto error_exit; } memset((void *)gl_bta_scan_rsp_data_ptr, 0, sizeof(tBTA_BLE_ADV_DATA)); -#endif ///BLE_INCLUDED == TRUE +#endif // #if (BLE_42_ADV_EN == TRUE) +#endif // (BLE_42_FEATURE_SUPPORT == TRUE) +#endif // BTC_DYNAMIC_MEMORY == TRUE #if GATTS_INCLUDED == TRUE && GATT_DYNAMIC_MEMORY == TRUE if ((btc_creat_tab_env_ptr = (esp_btc_creat_tab_t *)osi_malloc(sizeof(esp_btc_creat_tab_t))) == NULL) { @@ -514,21 +536,30 @@ bt_status_t btc_init(void) return BT_STATUS_NOMEM; } #endif +#if BTC_GAP_BT_INCLUDED + btc_gap_bt_init(); +#endif #if (BLE_INCLUDED == TRUE) btc_gap_callback_init(); +#if (BLE_FEAT_ISO_EN == TRUE) + btc_iso_callback_init(); +#endif // #if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_CTE_EN == TRUE) + btc_cte_callback_init(); +#endif // #if (BLE_FEAT_CTE_EN == TRUE) btc_gap_ble_init(); #endif ///BLE_INCLUDED == TRUE -#if SCAN_QUEUE_CONGEST_CHECK - btc_adv_list_init(); -#endif /* TODO: initial the profile_tab */ return BT_STATUS_SUCCESS; } void btc_deinit(void) { +#if BTC_GAP_BT_INCLUDED + btc_gap_bt_deinit(); +#endif #if BTC_DYNAMIC_MEMORY btc_deinit_mem(); #endif @@ -538,18 +569,6 @@ void btc_deinit(void) #if (BLE_INCLUDED == TRUE) btc_gap_ble_deinit(); #endif ///BLE_INCLUDED == TRUE -#if SCAN_QUEUE_CONGEST_CHECK - btc_adv_list_deinit(); -#endif -} - -bool btc_check_queue_is_congest(void) -{ - if (osi_thread_queue_wait_size(btc_thread, 0) >= BT_QUEUE_CONGEST_SIZE) { - return true; - } - - return false; } int get_btc_work_queue_size(void) diff --git a/lib/bt/common/btc/include/btc/btc_task.h b/lib/bt/common/btc/include/btc/btc_task.h index 232186b5..04365582 100644 --- a/lib/bt/common/btc/include/btc/btc_task.h +++ b/lib/bt/common/btc/include/btc/btc_task.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -67,6 +67,9 @@ typedef enum { #if (BTC_HF_CLIENT_INCLUDED == TRUE) BTC_PID_HF_CLIENT, #endif /* BTC_HF_CLIENT_INCLUDED */ +#if (BTC_PBA_CLIENT_INCLUDED == TRUE) + BTC_PID_PBA_CLIENT, +#endif /* BTC_PBA_CLIENT_INCLUDED */ #endif /* CLASSIC_BT_INCLUDED */ #if CONFIG_BLE_MESH BTC_PID_PROV, @@ -105,6 +108,12 @@ typedef enum { BTC_PID_MBT_SERVER, BTC_PID_BLE_MESH_BLE_COEX, #endif /* CONFIG_BLE_MESH */ +#if (BLE_FEAT_ISO_EN == TRUE) + BTC_PID_ISO_BLE, +#endif // #if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_CTE_EN == TRUE) + BTC_PID_BLE_CTE, +#endif // #if (BLE_FEAT_CTE_EN == TRUE) BTC_PID_NUM, } btc_pid_t; //btc profile id @@ -123,8 +132,8 @@ extern "C" { /** * transfer an message to another module in the different task. * @param msg message - * @param arg paramter - * @param arg_len length of paramter + * @param arg parameter + * @param arg_len length of parameter * @param copy_func deep copy function * @param free_func deep free function * @return BT_STATUS_SUCCESS: success @@ -134,7 +143,7 @@ bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg btc_arg_deep_free_t free_func); /** - * transfer an message to another module in tha same task. + * transfer an message to another module in the same task. * @param msg message * @return BT_STATUS_SUCCESS: success * others: fail @@ -143,7 +152,6 @@ bt_status_t btc_inter_profile_call(btc_msg_t *msg); bt_status_t btc_init(void); void btc_deinit(void); -bool btc_check_queue_is_congest(void); int get_btc_work_queue_size(void); /** diff --git a/lib/bt/common/btc/profile/esp/blufi/bluedroid_host/esp_blufi.c b/lib/bt/common/btc/profile/esp/blufi/bluedroid_host/esp_blufi.c index 47022992..f0c0aa4a 100644 --- a/lib/bt/common/btc/profile/esp/blufi/bluedroid_host/esp_blufi.c +++ b/lib/bt/common/btc/profile/esp/blufi/bluedroid_host/esp_blufi.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -160,20 +160,31 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) if (p_data->req_data.p_data->write_req.is_prep) { tBTA_GATT_STATUS status = GATT_SUCCESS; - if (blufi_env.prepare_buf == NULL) { - blufi_env.prepare_buf = osi_malloc(BLUFI_PREPAIR_BUF_MAX_SIZE); - blufi_env.prepare_len = 0; - if (blufi_env.prepare_buf == NULL) { - BLUFI_TRACE_ERROR("Blufi prep no mem\n"); - status = GATT_NO_RESOURCES; + do { + if (p_data->req_data.p_data->write_req.offset > BLUFI_PREPARE_BUF_MAX_SIZE) { + status = ESP_GATT_INVALID_OFFSET; + break; } - } else { - if (p_data->req_data.p_data->write_req.offset > BLUFI_PREPAIR_BUF_MAX_SIZE) { - status = GATT_INVALID_OFFSET; - } else if ((p_data->req_data.p_data->write_req.offset + p_data->req_data.p_data->write_req.len) > BLUFI_PREPAIR_BUF_MAX_SIZE) { - status = GATT_INVALID_ATTR_LEN; + + if ((p_data->req_data.p_data->write_req.offset + p_data->req_data.p_data->write_req.len) > BLUFI_PREPARE_BUF_MAX_SIZE) { + status = ESP_GATT_INVALID_ATTR_LEN; + break; } - } + + if (blufi_env.prepare_buf == NULL) { + if (p_data->req_data.p_data->write_req.offset != 0) { + status = GATT_INVALID_OFFSET; + break; + } + blufi_env.prepare_buf = osi_malloc(BLUFI_PREPARE_BUF_MAX_SIZE); + blufi_env.prepare_len = 0; + if (blufi_env.prepare_buf == NULL) { + BLUFI_TRACE_ERROR("Blufi prep no mem\n"); + status = GATT_NO_RESOURCES; + break; + } + } + } while (0); memset(&rsp, 0, sizeof(tGATTS_RSP)); rsp.attr_value.handle = p_data->req_data.p_data->write_req.handle; diff --git a/lib/bt/common/btc/profile/esp/blufi/blufi_prf.c b/lib/bt/common/btc/profile/esp/blufi/blufi_prf.c index 2c7be212..81bb0308 100644 --- a/lib/bt/common/btc/profile/esp/blufi/blufi_prf.c +++ b/lib/bt/common/btc/profile/esp/blufi/blufi_prf.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -95,7 +95,29 @@ void btc_blufi_report_error(esp_blufi_error_state_t state) void btc_blufi_recv_handler(uint8_t *data, int len) { + if (len < sizeof(struct blufi_hdr)) { + BTC_TRACE_ERROR("%s invalid data length: %d", __func__, len); + btc_blufi_report_error(ESP_BLUFI_DATA_FORMAT_ERROR); + return; + } + struct blufi_hdr *hdr = (struct blufi_hdr *)data; + + // Verify if the received data length matches the expected length based on the BLUFI protocol + int target_data_len; + + if (BLUFI_FC_IS_CHECK(hdr->fc)) { + target_data_len = hdr->data_len + 4 + 2; // Data + (Type + Frame Control + Sequence Number + Data Length) + Checksum + } else { + target_data_len = hdr->data_len + 4; // Data + (Type + Frame Control + Sequence Number + Data Length) + } + + if (len != target_data_len) { + BTC_TRACE_ERROR("%s: Invalid data length: %d, expected: %d", __func__, len, target_data_len); + btc_blufi_report_error(ESP_BLUFI_DATA_FORMAT_ERROR); + return; + } + uint16_t checksum, checksum_pkt; int ret; diff --git a/lib/bt/common/btc/profile/esp/blufi/include/blufi_int.h b/lib/bt/common/btc/profile/esp/blufi/include/blufi_int.h index e85ad73d..a7f4f292 100644 --- a/lib/bt/common/btc/profile/esp/blufi/include/blufi_int.h +++ b/lib/bt/common/btc/profile/esp/blufi/include/blufi_int.h @@ -36,7 +36,9 @@ typedef struct { UINT32 trans_id; UINT8 congest; UINT16 frag_size; +// Deprecated: This macro will be removed in the future #define BLUFI_PREPAIR_BUF_MAX_SIZE 1024 +#define BLUFI_PREPARE_BUF_MAX_SIZE 1024 uint8_t *prepare_buf; int prepare_len; /* Control reference */ diff --git a/lib/bt/common/btc/profile/esp/blufi/include/esp_blufi.h b/lib/bt/common/btc/profile/esp/blufi/include/esp_blufi.h index db2203b1..862f7bf0 100644 --- a/lib/bt/common/btc/profile/esp/blufi/include/esp_blufi.h +++ b/lib/bt/common/btc/profile/esp/blufi/include/esp_blufi.h @@ -44,6 +44,7 @@ void esp_blufi_gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *a /* Initialise gatt server */ int esp_blufi_gatt_svr_init(void); +int esp_blufi_gatt_svr_deinit(void); void esp_blufi_btc_init(void); void esp_blufi_btc_deinit(void); #endif diff --git a/lib/bt/common/btc/profile/esp/blufi/nimble_host/esp_blufi.c b/lib/bt/common/btc/profile/esp/blufi/nimble_host/esp_blufi.c index 67a83951..d40a4f4c 100644 --- a/lib/bt/common/btc/profile/esp/blufi/nimble_host/esp_blufi.c +++ b/lib/bt/common/btc/profile/esp/blufi/nimble_host/esp_blufi.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -124,7 +124,31 @@ static size_t write_value(uint16_t conn_handle, uint16_t attr_handle, } } - btc_blufi_recv_handler(&ctxt->om->om_data[0], ctxt->om->om_len); + /* Data may come in linked om. So retrieve all data */ + if (SLIST_NEXT(ctxt->om, om_next) != NULL) { + uint8_t *fw_buf = (uint8_t *)malloc(517 * sizeof(uint8_t)); + memset(fw_buf, 0x0, 517); + + memcpy(fw_buf, &ctxt->om->om_data[0], ctxt->om->om_len); + struct os_mbuf *last; + last = ctxt->om; + uint32_t offset = ctxt->om->om_len; + + while (SLIST_NEXT(last, om_next) != NULL) { + struct os_mbuf *temp = SLIST_NEXT(last, om_next); + memcpy(fw_buf + offset , &temp->om_data[0], temp->om_len); + offset += temp->om_len; + last = SLIST_NEXT(last, om_next); + temp = NULL; + } + btc_blufi_recv_handler(fw_buf, offset); + + free(fw_buf); + } + else { + btc_blufi_recv_handler(&ctxt->om->om_data[0], ctxt->om->om_len); + } + rc = ble_hs_mbuf_to_flat(ctxt->om, value->buf->om_data, value->buf->om_len, &len); if (rc != 0) { @@ -216,6 +240,32 @@ static void init_gatt_values(void) } +static void deinit_gatt_values(void) +{ + int i = 0; + const struct ble_gatt_svc_def *svc; + const struct ble_gatt_chr_def *chr; + const struct ble_gatt_dsc_def *dsc; + + for (svc = gatt_svr_svcs; svc && svc->uuid; svc++) { + for (chr = svc->characteristics; chr && chr->uuid; chr++) { + if (i < SERVER_MAX_VALUES && gatt_values[i].buf != NULL) { + os_mbuf_free(gatt_values[i].buf); /* Free the buffer */ + gatt_values[i].buf = NULL; /* Nullify the pointer to avoid dangling references */ + } + ++i; + + for (dsc = chr->descriptors; dsc && dsc->uuid; dsc++) { + if (i < SERVER_MAX_VALUES && gatt_values[i].buf != NULL) { + os_mbuf_free(gatt_values[i].buf); /* Free the buffer */ + gatt_values[i].buf = NULL; /* Nullify the pointer to avoid dangling references */ + } + ++i; + } + } + } +} + int esp_blufi_gatt_svr_init(void) { int rc; @@ -236,6 +286,18 @@ int esp_blufi_gatt_svr_init(void) return 0; } +int esp_blufi_gatt_svr_deinit(void) +{ + deinit_gatt_values(); + + ble_gatts_free_svcs(); + /* Deinitialize BLE GATT and GAP services */ + ble_svc_gatt_deinit(); + ble_svc_gap_deinit(); + + return 0; +} + static int esp_blufi_gap_event(struct ble_gap_event *event, void *arg) { @@ -418,8 +480,10 @@ uint8_t esp_blufi_init(void) void esp_blufi_deinit(void) { blufi_env.enabled = false; - btc_msg_t msg; esp_blufi_cb_param_t param; + btc_msg_t msg; + memset (&msg, 0x0, sizeof (msg)); + msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_BLUFI; msg.act = ESP_BLUFI_EVENT_DEINIT_FINISH; param.deinit_finish.state = ESP_BLUFI_DEINIT_OK; @@ -447,7 +511,10 @@ void esp_blufi_disconnect(void) ble_gap_terminate(blufi_env.conn_id, BLE_ERR_REM_USER_CONN_TERM); } -void esp_blufi_adv_stop(void) {} +void esp_blufi_adv_stop(void) +{ + ble_gap_adv_stop(); +} void esp_blufi_send_encap(void *arg) { diff --git a/lib/bt/common/hci_log/bt_hci_log.c b/lib/bt/common/hci_log/bt_hci_log.c index e35bf1a7..ef0d2294 100644 --- a/lib/bt/common/hci_log/bt_hci_log.c +++ b/lib/bt/common/hci_log/bt_hci_log.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -124,6 +124,11 @@ static char IRAM_ATTR *bt_data_type_to_str(uint8_t data_type) // self-defining data tag = "S"; break; + case HCI_LOG_DATA_TYPE_ISO_DATA: + // 5.2 iso data + tag = "I"; + break; + break; default: // unknown data type tag = "U"; @@ -305,19 +310,27 @@ void bt_hci_log_data_show(bt_hci_log_t *p_hci_log_ctl) osi_mutex_unlock(&mutex_lock); } +static bool enable_hci_log_flag = true; +void bt_hci_log_record_hci_enable(bool enable) +{ + enable_hci_log_flag = enable; +} esp_err_t IRAM_ATTR bt_hci_log_record_hci_data(uint8_t data_type, uint8_t *data, uint8_t data_len) { + if (!enable_hci_log_flag) return ESP_OK; return bt_hci_log_record_data(&g_bt_hci_log_data_ctl, NULL, data_type, data, data_len); } esp_err_t IRAM_ATTR bt_hci_log_record_custom_data(char *string, uint8_t *data, uint8_t data_len) { + if (!enable_hci_log_flag) return ESP_OK; return bt_hci_log_record_data(&g_bt_hci_log_data_ctl, string, HCI_LOG_DATA_TYPE_SELF_DEFINE, data, data_len); } esp_err_t IRAM_ATTR bt_hci_log_record_hci_adv(uint8_t data_type, uint8_t *data, uint8_t data_len) { + if (!enable_hci_log_flag) return ESP_OK; return bt_hci_log_record_data(&g_bt_hci_log_adv_ctl, NULL, data_type, data, data_len); } diff --git a/lib/bt/common/hci_log/include/hci_log/bt_hci_log.h b/lib/bt/common/hci_log/include/hci_log/bt_hci_log.h index 512a307e..2c11729f 100644 --- a/lib/bt/common/hci_log/include/hci_log/bt_hci_log.h +++ b/lib/bt/common/hci_log/include/hci_log/bt_hci_log.h @@ -21,6 +21,7 @@ extern "C" { #define HCI_LOG_DATA_TYPE_ADV (5) #define HCI_LOG_DATA_TYPE_SELF_DEFINE (6) #define HCI_LOG_DATA_TYPE_C2H_ACL (7) +#define HCI_LOG_DATA_TYPE_ISO_DATA (8) /** * diff --git a/lib/bt/common/include/bt_common.h b/lib/bt/common/include/bt_common.h index f3c5ba0e..300bbc6d 100644 --- a/lib/bt/common/include/bt_common.h +++ b/lib/bt/common/include/bt_common.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -46,6 +46,7 @@ #define OSI_INITIAL_TRACE_LEVEL UC_BT_LOG_OSI_TRACE_LEVEL #define BLUFI_INITIAL_TRACE_LEVEL UC_BT_LOG_BLUFI_TRACE_LEVEL +// MEMORY #if UC_BT_BLE_DYNAMIC_ENV_MEMORY #define BT_BLE_DYNAMIC_ENV_MEMORY TRUE #define BTC_DYNAMIC_MEMORY TRUE @@ -64,12 +65,39 @@ #define BT_BLE_DYNAMIC_ENV_MEMORY FALSE #endif +#if UC_HEAP_ALLOCATION_FROM_SPIRAM_FIRST +#define HEAP_ALLOCATION_FROM_SPIRAM_FIRST TRUE +#else +#define HEAP_ALLOCATION_FROM_SPIRAM_FIRST FALSE +#endif + +#if UC_BT_ABORT_WHEN_ALLOCATION_FAILS +#define HEAP_ALLOCATION_FAILS_ABORT TRUE +#else +#define HEAP_ALLOCATION_FAILS_ABORT FALSE +#endif + +// HCI LOG #if UC_BT_HCI_LOG_DEBUG_EN #define BT_HCI_LOG_INCLUDED UC_BT_HCI_LOG_DEBUG_EN #else #define BT_HCI_LOG_INCLUDED FALSE #endif +// HCI LOG TO SPI +#if UC_BT_BLE_LOG_SPI_OUT_HCI_ENABLED +#define BT_BLE_LOG_SPI_OUT_HCI_ENABLED UC_BT_BLE_LOG_SPI_OUT_HCI_ENABLED +#else +#define BT_BLE_LOG_SPI_OUT_HCI_ENABLED FALSE +#endif + +// BLURDROID LOG TO SPI +#if UC_BT_BLE_LOG_SPI_OUT_HOST_ENABLED +#define BT_BLE_LOG_SPI_OUT_HOST_ENABLED UC_BT_BLE_LOG_SPI_OUT_HOST_ENABLED +#else +#define BT_BLE_LOG_SPI_OUT_HOST_ENABLED FALSE +#endif + #if UC_BT_HCI_LOG_DATA_BUFFER_SIZE #define HCI_LOG_DATA_BUFFER_SIZE UC_BT_HCI_LOG_DATA_BUFFER_SIZE #else diff --git a/lib/bt/common/include/bt_user_config.h b/lib/bt/common/include/bt_user_config.h index 029766b7..5632b5fe 100644 --- a/lib/bt/common/include/bt_user_config.h +++ b/lib/bt/common/include/bt_user_config.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -100,19 +100,46 @@ #define UC_BT_BLUFI_ENABLE FALSE #endif -//MEMORY DEBUG +//MEMORY #ifdef CONFIG_BT_BLUEDROID_MEM_DEBUG #define UC_BT_BLUEDROID_MEM_DEBUG TRUE #else #define UC_BT_BLUEDROID_MEM_DEBUG FALSE #endif +#ifdef CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST +#define UC_HEAP_ALLOCATION_FROM_SPIRAM_FIRST CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST +#else +#define UC_HEAP_ALLOCATION_FROM_SPIRAM_FIRST FALSE +#endif + +#ifdef CONFIG_BT_ABORT_WHEN_ALLOCATION_FAILS +#define UC_BT_ABORT_WHEN_ALLOCATION_FAILS CONFIG_BT_ABORT_WHEN_ALLOCATION_FAILS +#else +#define UC_BT_ABORT_WHEN_ALLOCATION_FAILS FALSE +#endif + +//HCI LOG #ifdef CONFIG_BT_HCI_LOG_DEBUG_EN #define UC_BT_HCI_LOG_DEBUG_EN TRUE #else #define UC_BT_HCI_LOG_DEBUG_EN FALSE #endif +//HCI LOG TO SPI +#ifdef CONFIG_BT_BLE_LOG_SPI_OUT_HCI_ENABLED +#define UC_BT_BLE_LOG_SPI_OUT_HCI_ENABLED TRUE +#else +#define UC_BT_BLE_LOG_SPI_OUT_HCI_ENABLED FALSE +#endif + +//BLUEDROID LOG TO SPI +#ifdef CONFIG_BT_BLE_LOG_SPI_OUT_HOST_ENABLED +#define UC_BT_BLE_LOG_SPI_OUT_HOST_ENABLED TRUE +#else +#define UC_BT_BLE_LOG_SPI_OUT_HOST_ENABLED FALSE +#endif + #ifdef CONFIG_BT_HCI_LOG_DATA_BUFFER_SIZE #define UC_BT_HCI_LOG_DATA_BUFFER_SIZE CONFIG_BT_HCI_LOG_DATA_BUFFER_SIZE #else diff --git a/lib/bt/common/osi/allocator.c b/lib/bt/common/osi/allocator.c index 4d10e10f..86fb705b 100644 --- a/lib/bt/common/osi/allocator.c +++ b/lib/bt/common/osi/allocator.c @@ -213,42 +213,30 @@ char *osi_strdup(const char *str) void *osi_malloc_func(size_t size) { -#if HEAP_MEMORY_DEBUG - void *p; -#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST - p = heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); -#else - p = malloc(size); -#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */ - osi_mem_dbg_record(p, size, __func__, __LINE__); + void *p = osi_malloc_base(size); + + if (size != 0 && p == NULL) { + OSI_TRACE_ERROR("malloc failed (caller=%p size=%u)\n", __builtin_return_address(0), size); +#if HEAP_ALLOCATION_FAILS_ABORT + assert(0); +#endif + } + return p; -#else -#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST - return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); -#else - return malloc(size); -#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */ -#endif /* #if HEAP_MEMORY_DEBUG */ } void *osi_calloc_func(size_t size) { -#if HEAP_MEMORY_DEBUG - void *p; -#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST - p = heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); -#else - p = calloc(1, size); -#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */ - osi_mem_dbg_record(p, size, __func__, __LINE__); + void *p = osi_calloc_base(size); + + if (size != 0 && p == NULL) { + OSI_TRACE_ERROR("calloc failed (caller=%p size=%u)\n", __builtin_return_address(0), size); +#if HEAP_ALLOCATION_FAILS_ABORT + assert(0); +#endif + } + return p; -#else -#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST - return heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); -#else - return calloc(1, size); -#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */ -#endif /* #if HEAP_MEMORY_DEBUG */ } void osi_free_func(void *ptr) diff --git a/lib/bt/common/osi/include/osi/allocator.h b/lib/bt/common/osi/include/osi/allocator.h index 579f2b2b..d9504053 100644 --- a/lib/bt/common/osi/include/osi/allocator.h +++ b/lib/bt/common/osi/include/osi/allocator.h @@ -29,6 +29,15 @@ void *osi_malloc_func(size_t size); void *osi_calloc_func(size_t size); void osi_free_func(void *ptr); +// Memory alloc function without print and assertion +#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST +#define osi_malloc_base(size) heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL) +#define osi_calloc_base(size) heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL) +#else +#define osi_malloc_base(size) malloc((size)) +#define osi_calloc_base(size) calloc(1, (size)) +#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */ + #if HEAP_MEMORY_DEBUG void osi_mem_dbg_init(void); @@ -41,13 +50,10 @@ void osi_men_dbg_set_section_start(uint8_t index); void osi_men_dbg_set_section_end(uint8_t index); uint32_t osi_mem_dbg_get_max_size_section(uint8_t index); -#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST #define osi_malloc(size) \ ({ \ void *p; \ - p = heap_caps_malloc_prefer(size, 2, \ - MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, \ - MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); \ + p = osi_malloc_base(size); \ osi_mem_dbg_record(p, size, __func__, __LINE__); \ (void *)p; \ }) @@ -55,34 +61,11 @@ uint32_t osi_mem_dbg_get_max_size_section(uint8_t index); #define osi_calloc(size) \ ({ \ void *p; \ - p = heap_caps_calloc_prefer(1, size, 2, \ - MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, \ - MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); \ - osi_mem_dbg_record(p, size, __func__, __LINE__); \ - (void *)p; \ -}) - -#else - -#define osi_malloc(size) \ -({ \ - void *p; \ - p = malloc((size)); \ + p = osi_calloc_base(size); \ osi_mem_dbg_record(p, size, __func__, __LINE__); \ (void *)p; \ }) -#define osi_calloc(size) \ -({ \ - void *p; \ - p = calloc(1, (size)); \ - osi_mem_dbg_record(p, size, __func__, __LINE__); \ - (void *)p; \ -}) - -#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */ - - #if 0 #define osi_malloc(size) \ do { \ @@ -122,13 +105,9 @@ do { \ #else -#if HEAP_ALLOCATION_FROM_SPIRAM_FIRST -#define osi_malloc(size) heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL) -#define osi_calloc(size) heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL) -#else -#define osi_malloc(size) malloc((size)) -#define osi_calloc(size) calloc(1, (size)) -#endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */ +// Memory alloc function with print and assertion when fails +#define osi_malloc(size) osi_malloc_func((size)) +#define osi_calloc(size) osi_calloc_func((size)) #define osi_free(p) free((p)) #endif /* HEAP_MEMORY_DEBUG */ diff --git a/lib/bt/common/osi/include/osi/fixed_pkt_queue.h b/lib/bt/common/osi/include/osi/fixed_pkt_queue.h index f4235ca5..e121235e 100644 --- a/lib/bt/common/osi/include/osi/fixed_pkt_queue.h +++ b/lib/bt/common/osi/include/osi/fixed_pkt_queue.h @@ -76,4 +76,8 @@ void fixed_pkt_queue_unregister_dequeue(fixed_pkt_queue_t *queue); void fixed_pkt_queue_process(fixed_pkt_queue_t *queue); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lib/bt/common/osi/include/osi/hash_map.h b/lib/bt/common/osi/include/osi/hash_map.h index fea1e021..a26eda61 100644 --- a/lib/bt/common/osi/include/osi/hash_map.h +++ b/lib/bt/common/osi/include/osi/hash_map.h @@ -20,6 +20,7 @@ #define _HASH_MAP_H_ #include +#include #include struct hash_map_t; diff --git a/lib/bt/common/osi/pkt_queue.c b/lib/bt/common/osi/pkt_queue.c index 81abd1f0..4c149be2 100644 --- a/lib/bt/common/osi/pkt_queue.c +++ b/lib/bt/common/osi/pkt_queue.c @@ -25,6 +25,7 @@ struct pkt_queue *pkt_queue_create(void) } if (osi_mutex_new(&queue->lock) != 0) { osi_free(queue); + return NULL; } struct pkt_queue_header *p = &queue->header; STAILQ_INIT(p); diff --git a/lib/bt/common/osi/thread.c b/lib/bt/common/osi/thread.c index f53eadb6..91bc7906 100644 --- a/lib/bt/common/osi/thread.c +++ b/lib/bt/common/osi/thread.c @@ -271,10 +271,10 @@ _err: } for (int i = 0; i < thread->work_queue_num; i++) { - if (thread->work_queues[i]) { + if (thread->work_queues && thread->work_queues[i]) { osi_work_queue_delete(thread->work_queues[i]); + thread->work_queues[i] = NULL; } - thread->work_queues[i] = NULL; } if (thread->work_queues) { diff --git a/lib/bt/common/tinycrypt/AUTHORS b/lib/bt/common/tinycrypt/AUTHORS new file mode 100644 index 00000000..bd1c1a1f --- /dev/null +++ b/lib/bt/common/tinycrypt/AUTHORS @@ -0,0 +1,15 @@ +Architect: +Rafael Misoczki + +Open Source Maintainer: +Constanza Heath +Rafael Misoczki + +Contributors: +Constanza Heath +Rafael Misoczki +Flavio Santes +Jarkko Sakkinen +Chris Morrison +Marti Bolivar +Colin Ian King diff --git a/lib/bt/common/tinycrypt/LICENSE b/lib/bt/common/tinycrypt/LICENSE new file mode 100644 index 00000000..b3c55243 --- /dev/null +++ b/lib/bt/common/tinycrypt/LICENSE @@ -0,0 +1,61 @@ + +================================================================================ + + TinyCrypt Cryptographic Library + +================================================================================ + + Copyright (c) 2017, Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + - Neither the name of the Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +================================================================================ +Copyright (c) 2014, Kenneth MacKay +All rights reserved. + +https://github.com/kmackay/micro-ecc + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +================================================================================ diff --git a/lib/bt/common/tinycrypt/README b/lib/bt/common/tinycrypt/README new file mode 100644 index 00000000..48bdf9ba --- /dev/null +++ b/lib/bt/common/tinycrypt/README @@ -0,0 +1,70 @@ + +================================================================================ + + TinyCrypt Cryptographic Library + +================================================================================ + + Copyright (c) 2017, Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + - Neither the name of the Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +================================================================================ + +Overview: + +The TinyCrypt Library provides an implementation for constrained devices of a +minimal set of standard cryptography primitives. + +Please, ***SEE THE DOCUMENTATION*** folder for more information on the supported +cryptographic primitives and the limitations of TinyCrypt library. For usage, +security and technicalities, please see the corresponding header file of each +cryptographic primitive. + +================================================================================ + +Organization: + +/lib: C source code of the cryptographic primitives. +/lib/include/tinycrypt: C header files of the cryptographic primitives. +/tests: Test vectors of the cryptographic primitives. +/doc: Documentation of TinyCrypt. + +================================================================================ + +Building: + +1) In Makefile.conf set: + - CFLAGS for compiler flags. + - CC for compiler. + - ENABLE_TESTS for enabling (true) or disabling (false) tests compilation. +2) In lib/Makefile select the primitives required by your project. +3) In tests/Makefile select the corresponding tests of the selected primitives. +4) make +5) run tests in tests/ + +================================================================================ diff --git a/lib/bt/common/tinycrypt/VERSION b/lib/bt/common/tinycrypt/VERSION new file mode 100644 index 00000000..a45be462 --- /dev/null +++ b/lib/bt/common/tinycrypt/VERSION @@ -0,0 +1 @@ +0.2.8 diff --git a/lib/bt/common/tinycrypt/documentation/tinycrypt.rst b/lib/bt/common/tinycrypt/documentation/tinycrypt.rst new file mode 100644 index 00000000..356c099a --- /dev/null +++ b/lib/bt/common/tinycrypt/documentation/tinycrypt.rst @@ -0,0 +1,352 @@ + +TinyCrypt Cryptographic Library +############################### +Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + +Overview +******** +The TinyCrypt Library provides an implementation for targeting constrained devices +with a minimal set of standard cryptography primitives, as listed below. To better +serve applications targeting constrained devices, TinyCrypt implementations differ +from the standard specifications (see the Important Remarks section for some +important differences). Certain cryptographic primitives depend on other +primitives, as mentioned in the list below. + +Aside from the Important Remarks section below, valuable information on the usage, +security and technicalities of each cryptographic primitive are found in the +corresponding header file. + +* SHA-256: + + * Type of primitive: Hash function. + * Standard Specification: NIST FIPS PUB 180-4. + * Requires: -- + +* HMAC-SHA256: + + * Type of primitive: Message authentication code. + * Standard Specification: RFC 2104. + * Requires: SHA-256 + +* HMAC-PRNG: + + * Type of primitive: Pseudo-random number generator (256-bit strength). + * Standard Specification: NIST SP 800-90A. + * Requires: SHA-256 and HMAC-SHA256. + +* AES-128: + + * Type of primitive: Block cipher. + * Standard Specification: NIST FIPS PUB 197. + * Requires: -- + +* AES-CBC mode: + + * Type of primitive: Encryption mode of operation. + * Standard Specification: NIST SP 800-38A. + * Requires: AES-128. + +* AES-CTR mode: + + * Type of primitive: Encryption mode of operation. + * Standard Specification: NIST SP 800-38A. + * Requires: AES-128. + +* AES-CMAC mode: + + * Type of primitive: Message authentication code. + * Standard Specification: NIST SP 800-38B. + * Requires: AES-128. + +* AES-CCM mode: + + * Type of primitive: Authenticated encryption. + * Standard Specification: NIST SP 800-38C. + * Requires: AES-128. + +* CTR-PRNG: + + * Type of primitive: Pseudo-random number generator (128-bit strength). + * Standard Specification: NIST SP 800-90A. + * Requires: AES-128. + +* ECC-DH: + + * Type of primitive: Key exchange based on curve NIST p-256. + * Standard Specification: RFC 6090. + * Requires: ECC auxiliary functions (ecc.h/c). + +* ECC-DSA: + + * Type of primitive: Digital signature based on curve NIST p-256. + * Standard Specification: RFC 6090. + * Requires: ECC auxiliary functions (ecc.h/c). + +Design Goals +************ + +* Minimize the code size of each cryptographic primitive. This means minimize + the size of a platform-independent implementation, as presented in TinyCrypt. + Note that various applications may require further features, optimizations with + respect to other metrics and countermeasures for particular threats. These + peculiarities would increase the code size and thus are not considered here. + +* Minimize the dependencies among the cryptographic primitives. This means + that it is unnecessary to build and allocate object code for more primitives + than the ones strictly required by the intended application. In other words, + one can select and compile only the primitives required by the application. + + +Important Remarks +***************** + +The cryptographic implementations in TinyCrypt library have some limitations. +Some of these limitations are inherent to the cryptographic primitives +themselves, while others are specific to TinyCrypt. These limitations were accepted +in order to meet its design goals (in special, minimal code size) and to better +serve applications targeting constrained devices in general. Some of these +limitations are discussed in-depth below. + +General Remarks +*************** + +* TinyCrypt does **not** intend to be fully side-channel resistant. Due to the + variety of side-channel attacks, many of them only relevant to certain + platforms. In this sense, instead of penalizing all library users with + side-channel countermeasures such as increasing the overall code size, + TinyCrypt only implements certain generic timing-attack countermeasures. + +Specific Remarks +**************** + +* SHA-256: + + * The number of bits_hashed in the state is not checked for overflow. Note + however that this will only be a problem if you intend to hash more than + 2^64 bits, which is an extremely large window. + +* HMAC: + + * The HMAC verification process is assumed to be performed by the application. + This compares the computed tag with some given tag. + Note that conventional memory-comparison methods (such as memcmp function) + might be vulnerable to timing attacks; thus be sure to use a constant-time + memory comparison function (such as compare_constant_time + function provided in lib/utils.c). + + * The tc_hmac_final function, responsible for computing the message tag, + cleans the state context before exiting. Thus, applications do not need to + clean the TCHmacState_t ctx after calling tc_hmac_final. This should not + be changed in future versions of the library as there are applications + currently relying on this good-practice/feature of TinyCrypt. + +* HMAC-PRNG: + + * Before using HMAC-PRNG, you *must* find an entropy source to produce a seed. + PRNGs only stretch the seed into a seemingly random output of arbitrary + length. The security of the output is exactly equal to the + unpredictability of the seed. + + * NIST SP 800-90A requires three items as seed material in the initialization + step: entropy seed, personalization and a nonce (which is not implemented). + TinyCrypt requires the personalization byte array and automatically creates + the entropy seed using a mandatory call to the re-seed function. + +* AES-128: + + * The current implementation does not support other key-lengths (such as 256 + bits). Note that if you need AES-256, it doesn't sound as though your + application is running in a constrained environment. AES-256 requires keys + twice the size as for AES-128, and the key schedule is 40% larger. + +* CTR mode: + + * The AES-CTR mode limits the size of a data message they encrypt to 2^32 + blocks. If you need to encrypt larger data sets, your application would + need to replace the key after 2^32 block encryptions. + +* CTR-PRNG: + + * Before using CTR-PRNG, you *must* find an entropy source to produce a seed. + PRNGs only stretch the seed into a seemingly random output of arbitrary + length. The security of the output is exactly equal to the + unpredictability of the seed. + +* CBC mode: + + * TinyCrypt CBC decryption assumes that the iv and the ciphertext are + contiguous (as produced by TinyCrypt CBC encryption). This allows for a + very efficient decryption algorithm that would not otherwise be possible. + +* CMAC mode: + + * AES128-CMAC mode of operation offers 64 bits of security against collision + attacks. Note however that an external attacker cannot generate the tags + him/herself without knowing the MAC key. In this sense, to attack the + collision property of AES128-CMAC, an external attacker would need the + cooperation of the legal user to produce an exponentially high number of + tags (e.g. 2^64) to finally be able to look for collisions and benefit + from them. As an extra precaution, the current implementation allows to at + most 2^48 calls to tc_cmac_update function before re-calling tc_cmac_setup + (allowing a new key to be set), as suggested in Appendix B of SP 800-38B. + +* CCM mode: + + * There are a few tradeoffs for the selection of the parameters of CCM mode. + In special, there is a tradeoff between the maximum number of invocations + of CCM under a given key and the maximum payload length for those + invocations. Both things are related to the parameter 'q' of CCM mode. The + maximum number of invocations of CCM under a given key is determined by + the nonce size, which is: 15-q bytes. The maximum payload length for those + invocations is defined as 2^(8q) bytes. + + To achieve minimal code size, TinyCrypt CCM implementation fixes q = 2, + which is a quite reasonable choice for constrained applications. The + implications of this choice are: + + The nonce size is: 13 bytes. + + The maximum payload length is: 2^16 bytes = 65 KB. + + The mac size parameter is an important parameter to estimate the security + against collision attacks (that aim at finding different messages that + produce the same authentication tag). TinyCrypt CCM implementation + accepts any even integer between 4 and 16, as suggested in SP 800-38C. + + * TinyCrypt CCM implementation accepts associated data of any length between + 0 and (2^16 - 2^8) = 65280 bytes. + + * TinyCrypt CCM implementation accepts: + + * Both non-empty payload and associated data (it encrypts and + authenticates the payload and only authenticates the associated data); + + * Non-empty payload and empty associated data (it encrypts and + authenticates the payload); + + * Non-empty associated data and empty payload (it degenerates to an + authentication-only mode on the associated data). + + * RFC-3610, which also specifies CCM, presents a few relevant security + suggestions, such as: it is recommended for most applications to use a + mac size greater than 8. Besides, it is emphasized that the usage of the + same nonce for two different messages which are encrypted with the same + key obviously destroys the security properties of CCM mode. + +* ECC-DH and ECC-DSA: + + * TinyCrypt ECC implementation is based on micro-ecc (see + https://github.com/kmackay/micro-ecc). In the original micro-ecc + documentation, there is an important remark about the way integers are + represented: + + "Integer representation: To reduce code size, all large integers are + represented using little-endian words - so the least significant word is + first. You can use the 'ecc_bytes2native()' and 'ecc_native2bytes()' + functions to convert between the native integer representation and the + standardized octet representation." + + Note that the assumed bit layout is: {31, 30, ..., 0}, {63, 62, ..., 32}, + {95, 94, ..., 64}, {127, 126, ..., 96} for a very-long-integer (vli) + consisting of 4 unsigned integers (as an example). + + * A cryptographically-secure PRNG function must be set (using uECC_set_rng()) + before calling uECC_make_key() or uECC_sign(). + +Examples of Applications +************************ +It is possible to do useful cryptography with only the given small set of +primitives. With this list of primitives it becomes feasible to support a range +of cryptography usages: + + * Measurement of code, data structures, and other digital artifacts (SHA256); + + * Generate commitments (SHA256); + + * Construct keys (HMAC-SHA256); + + * Extract entropy from strings containing some randomness (HMAC-SHA256); + + * Construct random mappings (HMAC-SHA256); + + * Construct nonces and challenges (HMAC-PRNG, CTR-PRNG); + + * Authenticate using a shared secret (HMAC-SHA256); + + * Create an authenticated, replay-protected session (HMAC-SHA256 + HMAC-PRNG); + + * Authenticated encryption (AES-128 + AES-CCM); + + * Key-exchange (EC-DH); + + * Digital signature (EC-DSA); + +Test Vectors +************ + +The library provides a test program for each cryptographic primitive (see 'test' +folder). Besides illustrating how to use the primitives, these tests evaluate +the correctness of the implementations by checking the results against +well-known publicly validated test vectors. + +For the case of the HMAC-PRNG, due to the necessity of performing an extensive +battery test to produce meaningful conclusions, we suggest the user to evaluate +the unpredictability of the implementation by using the NIST Statistical Test +Suite (see References). + +For the case of the EC-DH and EC-DSA implementations, most of the test vectors +were obtained from the site of the NIST Cryptographic Algorithm Validation +Program (CAVP), see References. + +References +********** + +* `NIST FIPS PUB 180-4 (SHA-256)`_ + +.. _NIST FIPS PUB 180-4 (SHA-256): + http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf + +* `NIST FIPS PUB 197 (AES-128)`_ + +.. _NIST FIPS PUB 197 (AES-128): + http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + +* `NIST SP800-90A (HMAC-PRNG)`_ + +.. _NIST SP800-90A (HMAC-PRNG): + http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf + +* `NIST SP 800-38A (AES-CBC and AES-CTR)`_ + +.. _NIST SP 800-38A (AES-CBC and AES-CTR): + http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + +* `NIST SP 800-38B (AES-CMAC)`_ + +.. _NIST SP 800-38B (AES-CMAC): + http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf + +* `NIST SP 800-38C (AES-CCM)`_ + +.. _NIST SP 800-38C (AES-CCM): + http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + +* `NIST Statistical Test Suite (useful for testing HMAC-PRNG)`_ + +.. _NIST Statistical Test Suite (useful for testing HMAC-PRNG): + http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html + +* `NIST Cryptographic Algorithm Validation Program (CAVP) site`_ + +.. _NIST Cryptographic Algorithm Validation Program (CAVP) site: + http://csrc.nist.gov/groups/STM/cavp/ + +* `RFC 2104 (HMAC-SHA256)`_ + +.. _RFC 2104 (HMAC-SHA256): + https://www.ietf.org/rfc/rfc2104.txt + +* `RFC 6090 (ECC-DH and ECC-DSA)`_ + +.. _RFC 6090 (ECC-DH and ECC-DSA): + https://www.ietf.org/rfc/rfc6090.txt diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/aes.h b/lib/bt/common/tinycrypt/include/tinycrypt/aes.h new file mode 100644 index 00000000..04f6de50 --- /dev/null +++ b/lib/bt/common/tinycrypt/include/tinycrypt/aes.h @@ -0,0 +1,134 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief -- Interface to an AES-128 implementation. + * + * Overview: AES-128 is a NIST approved block cipher specified in + * FIPS 197. Block ciphers are deterministic algorithms that + * perform a transformation specified by a symmetric key in fixed- + * length data sets, also called blocks. + * + * Security: AES-128 provides approximately 128 bits of security. + * + * Usage: 1) call tc_aes128_set_encrypt/decrypt_key to set the key. + * + * 2) call tc_aes_encrypt/decrypt to process the data. + */ + +#ifndef __TC_AES_H__ +#define __TC_AES_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define Nb (4) /* number of columns (32-bit words) comprising the state */ +#define Nk (4) /* number of 32-bit words comprising the key */ +#define Nr (10) /* number of rounds */ +#define TC_AES_BLOCK_SIZE (Nb*Nk) +#define TC_AES_KEY_SIZE (Nb*Nk) + +typedef struct tc_aes_key_sched_struct { + unsigned int words[Nb*(Nr+1)]; +} *TCAesKeySched_t; + +/** + * @brief Set AES-128 encryption key + * Uses key k to initialize s + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL + * @note This implementation skips the additional steps required for keys + * larger than 128 bits, and must not be used for AES-192 or + * AES-256 key schedule -- see FIPS 197 for details + * @param s IN/OUT -- initialized struct tc_aes_key_sched_struct + * @param k IN -- points to the AES key + */ +int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k); + +/** + * @brief AES-128 Encryption procedure + * Encrypts contents of in buffer into out buffer under key; + * schedule s + * @note Assumes s was initialized by aes_set_encrypt_key; + * out and in point to 16 byte buffers + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: out == NULL or in == NULL or s == NULL + * @param out IN/OUT -- buffer to receive ciphertext block + * @param in IN -- a plaintext block to encrypt + * @param s IN -- initialized AES key schedule + */ +int tc_aes_encrypt(uint8_t *out, const uint8_t *in, + const TCAesKeySched_t s); + +/** + * @brief Set the AES-128 decryption key + * Uses key k to initialize s + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL + * @note This is the implementation of the straightforward inverse cipher + * using the cipher documented in FIPS-197 figure 12, not the + * equivalent inverse cipher presented in Figure 15 + * @warning This routine skips the additional steps required for keys larger + * than 128, and must not be used for AES-192 or AES-256 key + * schedule -- see FIPS 197 for details + * @param s IN/OUT -- initialized struct tc_aes_key_sched_struct + * @param k IN -- points to the AES key + */ +int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k); + +/** + * @brief AES-128 Encryption procedure + * Decrypts in buffer into out buffer under key schedule s + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: out is NULL or in is NULL or s is NULL + * @note Assumes s was initialized by aes_set_encrypt_key + * out and in point to 16 byte buffers + * @param out IN/OUT -- buffer to receive ciphertext block + * @param in IN -- a plaintext block to encrypt + * @param s IN -- initialized AES key schedule + */ +int tc_aes_decrypt(uint8_t *out, const uint8_t *in, + const TCAesKeySched_t s); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_AES_H__ */ diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/cbc_mode.h b/lib/bt/common/tinycrypt/include/tinycrypt/cbc_mode.h new file mode 100644 index 00000000..dadc59fc --- /dev/null +++ b/lib/bt/common/tinycrypt/include/tinycrypt/cbc_mode.h @@ -0,0 +1,155 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to a CBC mode implementation. + * + * Overview: CBC (for "cipher block chaining") mode is a NIST approved mode of + * operation defined in SP 800-38a. It can be used with any block + * cipher to provide confidentiality of strings whose lengths are + * multiples of the block_size of the underlying block cipher. + * TinyCrypt hard codes AES as the block cipher. + * + * Security: CBC mode provides data confidentiality given that the maximum + * number q of blocks encrypted under a single key satisfies + * q < 2^63, which is not a practical constraint (it is considered a + * good practice to replace the encryption when q == 2^56). CBC mode + * provides NO data integrity. + * + * CBC mode assumes that the IV value input into the + * tc_cbc_mode_encrypt is randomly generated. The TinyCrypt library + * provides HMAC-PRNG module, which generates suitable IVs. Other + * methods for generating IVs are acceptable, provided that the + * values of the IVs generated appear random to any adversary, + * including someone with complete knowledge of the system design. + * + * The randomness property on which CBC mode's security depends is + * the unpredictability of the IV. Since it is unpredictable, this + * means in practice that CBC mode requires that the IV is stored + * somehow with the ciphertext in order to recover the plaintext. + * + * TinyCrypt CBC encryption prepends the IV to the ciphertext, + * because this affords a more efficient (few buffers) decryption. + * Hence tc_cbc_mode_encrypt assumes the ciphertext buffer is always + * 16 bytes larger than the plaintext buffer. + * + * Requires: AES-128 + * + * Usage: 1) call tc_cbc_mode_encrypt to encrypt data. + * + * 2) call tc_cbc_mode_decrypt to decrypt data. + * + */ + +#ifndef __TC_CBC_MODE_H__ +#define __TC_CBC_MODE_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief CBC encryption procedure + * CBC encrypts inlen bytes of the in buffer into the out buffer + * using the encryption key schedule provided, prepends iv to out + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * out == NULL or + * in == NULL or + * ctr == NULL or + * sched == NULL or + * inlen == 0 or + * (inlen % TC_AES_BLOCK_SIZE) != 0 or + * (outlen % TC_AES_BLOCK_SIZE) != 0 or + * outlen != inlen + TC_AES_BLOCK_SIZE + * @note Assumes: - sched has been configured by aes_set_encrypt_key + * - iv contains a 16 byte random string + * - out buffer is large enough to hold the ciphertext + iv + * - out buffer is a contiguous buffer + * - in holds the plaintext and is a contiguous buffer + * - inlen gives the number of bytes in the in buffer + * @param out IN/OUT -- buffer to receive the ciphertext + * @param outlen IN -- length of ciphertext buffer in bytes + * @param in IN -- plaintext to encrypt + * @param inlen IN -- length of plaintext buffer in bytes + * @param iv IN -- the IV for the this encrypt/decrypt + * @param sched IN -- AES key schedule for this encrypt + */ +int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, + unsigned int inlen, const uint8_t *iv, + const TCAesKeySched_t sched); + +/** + * @brief CBC decryption procedure + * CBC decrypts inlen bytes of the in buffer into the out buffer + * using the provided encryption key schedule + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * out == NULL or + * in == NULL or + * sched == NULL or + * inlen == 0 or + * outlen == 0 or + * (inlen % TC_AES_BLOCK_SIZE) != 0 or + * (outlen % TC_AES_BLOCK_SIZE) != 0 or + * outlen != inlen + TC_AES_BLOCK_SIZE + * @note Assumes:- in == iv + ciphertext, i.e. the iv and the ciphertext are + * contiguous. This allows for a very efficient decryption + * algorithm that would not otherwise be possible + * - sched was configured by aes_set_decrypt_key + * - out buffer is large enough to hold the decrypted plaintext + * and is a contiguous buffer + * - inlen gives the number of bytes in the in buffer + * @param out IN/OUT -- buffer to receive decrypted data + * @param outlen IN -- length of plaintext buffer in bytes + * @param in IN -- ciphertext to decrypt, including IV + * @param inlen IN -- length of ciphertext buffer in bytes + * @param iv IN -- the IV for the this encrypt/decrypt + * @param sched IN -- AES key schedule for this decrypt + * + */ +int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, + unsigned int inlen, const uint8_t *iv, + const TCAesKeySched_t sched); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_CBC_MODE_H__ */ diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/ccm_mode.h b/lib/bt/common/tinycrypt/include/tinycrypt/ccm_mode.h new file mode 100644 index 00000000..af9d79ba --- /dev/null +++ b/lib/bt/common/tinycrypt/include/tinycrypt/ccm_mode.h @@ -0,0 +1,215 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to a CCM mode implementation. + * + * Overview: CCM (for "Counter with CBC-MAC") mode is a NIST approved mode of + * operation defined in SP 800-38C. + * + * TinyCrypt CCM implementation accepts: + * + * 1) Both non-empty payload and associated data (it encrypts and + * authenticates the payload and also authenticates the associated + * data); + * 2) Non-empty payload and empty associated data (it encrypts and + * authenticates the payload); + * 3) Non-empty associated data and empty payload (it degenerates to + * an authentication mode on the associated data). + * + * TinyCrypt CCM implementation accepts associated data of any length + * between 0 and (2^16 - 2^8) bytes. + * + * Security: The mac length parameter is an important parameter to estimate the + * security against collision attacks (that aim at finding different + * messages that produce the same authentication tag). TinyCrypt CCM + * implementation accepts any even integer between 4 and 16, as + * suggested in SP 800-38C. + * + * RFC-3610, which also specifies CCM, presents a few relevant + * security suggestions, such as: it is recommended for most + * applications to use a mac length greater than 8. Besides, the + * usage of the same nonce for two different messages which are + * encrypted with the same key destroys the security of CCM mode. + * + * Requires: AES-128 + * + * Usage: 1) call tc_ccm_config to configure. + * + * 2) call tc_ccm_mode_encrypt to encrypt data and generate tag. + * + * 3) call tc_ccm_mode_decrypt to decrypt data and verify tag. + */ + +#ifndef __TC_CCM_MODE_H__ +#define __TC_CCM_MODE_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* max additional authenticated size in bytes: 2^16 - 2^8 = 65280 */ +#define TC_CCM_AAD_MAX_BYTES 0xff00 + +/* max message size in bytes: 2^(8L) = 2^16 = 65536 */ +#define TC_CCM_PAYLOAD_MAX_BYTES 0x10000 + +/* struct tc_ccm_mode_struct represents the state of a CCM computation */ +typedef struct tc_ccm_mode_struct { + TCAesKeySched_t sched; /* AES key schedule */ + uint8_t *nonce; /* nonce required by CCM */ + unsigned int mlen; /* mac length in bytes (parameter t in SP-800 38C) */ +} *TCCcmMode_t; + +/** + * @brief CCM configuration procedure + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * c == NULL or + * sched == NULL or + * nonce == NULL or + * mlen != {4, 6, 8, 10, 12, 16} + * @param c -- CCM state + * @param sched IN -- AES key schedule + * @param nonce IN - nonce + * @param nlen -- nonce length in bytes + * @param mlen -- mac length in bytes (parameter t in SP-800 38C) + */ +int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce, + unsigned int nlen, unsigned int mlen); + +/** + * @brief CCM tag generation and encryption procedure + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * out == NULL or + * c == NULL or + * ((plen > 0) and (payload == NULL)) or + * ((alen > 0) and (associated_data == NULL)) or + * (alen >= TC_CCM_AAD_MAX_BYTES) or + * (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or + * (olen < plen + maclength) + * + * @param out OUT -- encrypted data + * @param olen IN -- output length in bytes + * @param associated_data IN -- associated data + * @param alen IN -- associated data length in bytes + * @param payload IN -- payload + * @param plen IN -- payload length in bytes + * @param c IN -- CCM state + * + * @note: out buffer should be at least (plen + c->mlen) bytes long. + * + * @note: The sequence b for encryption is formatted as follows: + * b = [FLAGS | nonce | counter ], where: + * FLAGS is 1 byte long + * nonce is 13 bytes long + * counter is 2 bytes long + * The byte FLAGS is composed by the following 8 bits: + * 0-2 bits: used to represent the value of q-1 + * 3-7 btis: always 0's + * + * @note: The sequence b for authentication is formatted as follows: + * b = [FLAGS | nonce | length(mac length)], where: + * FLAGS is 1 byte long + * nonce is 13 bytes long + * length(mac length) is 2 bytes long + * The byte FLAGS is composed by the following 8 bits: + * 0-2 bits: used to represent the value of q-1 + * 3-5 bits: mac length (encoded as: (mlen-2)/2) + * 6: Adata (0 if alen == 0, and 1 otherwise) + * 7: always 0 + */ +int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen, + const uint8_t *associated_data, + unsigned int alen, const uint8_t *payload, + unsigned int plen, TCCcmMode_t c); + +/** + * @brief CCM decryption and tag verification procedure + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * out == NULL or + * c == NULL or + * ((plen > 0) and (payload == NULL)) or + * ((alen > 0) and (associated_data == NULL)) or + * (alen >= TC_CCM_AAD_MAX_BYTES) or + * (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or + * (olen < plen - c->mlen) + * + * @param out OUT -- decrypted data + * @param associated_data IN -- associated data + * @param alen IN -- associated data length in bytes + * @param payload IN -- payload + * @param plen IN -- payload length in bytes + * @param c IN -- CCM state + * + * @note: out buffer should be at least (plen - c->mlen) bytes long. + * + * @note: The sequence b for encryption is formatted as follows: + * b = [FLAGS | nonce | counter ], where: + * FLAGS is 1 byte long + * nonce is 13 bytes long + * counter is 2 bytes long + * The byte FLAGS is composed by the following 8 bits: + * 0-2 bits: used to represent the value of q-1 + * 3-7 btis: always 0's + * + * @note: The sequence b for authentication is formatted as follows: + * b = [FLAGS | nonce | length(mac length)], where: + * FLAGS is 1 byte long + * nonce is 13 bytes long + * length(mac length) is 2 bytes long + * The byte FLAGS is composed by the following 8 bits: + * 0-2 bits: used to represent the value of q-1 + * 3-5 bits: mac length (encoded as: (mlen-2)/2) + * 6: Adata (0 if alen == 0, and 1 otherwise) + * 7: always 0 + */ +int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen, + const uint8_t *associated_data, + unsigned int alen, const uint8_t *payload, unsigned int plen, + TCCcmMode_t c); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_CCM_MODE_H__ */ diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/cmac_mode.h b/lib/bt/common/tinycrypt/include/tinycrypt/cmac_mode.h new file mode 100644 index 00000000..e1cf7d56 --- /dev/null +++ b/lib/bt/common/tinycrypt/include/tinycrypt/cmac_mode.h @@ -0,0 +1,198 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to a CMAC implementation. + * + * Overview: CMAC is defined NIST in SP 800-38B, and is the standard algorithm + * for computing a MAC using a block cipher. It can compute the MAC + * for a byte string of any length. It is distinguished from CBC-MAC + * in the processing of the final message block; CMAC uses a + * different technique to compute the final message block is full + * size or only partial, while CBC-MAC uses the same technique for + * both. This difference permits CMAC to be applied to variable + * length messages, while all messages authenticated by CBC-MAC must + * be the same length. + * + * Security: AES128-CMAC mode of operation offers 64 bits of security against + * collision attacks. Note however that an external attacker cannot + * generate the tags him/herself without knowing the MAC key. In this + * sense, to attack the collision property of AES128-CMAC, an + * external attacker would need the cooperation of the legal user to + * produce an exponentially high number of tags (e.g. 2^64) to + * finally be able to look for collisions and benefit from them. As + * an extra precaution, the current implementation allows to at most + * 2^48 calls to the tc_cmac_update function before re-calling + * tc_cmac_setup (allowing a new key to be set), as suggested in + * Appendix B of SP 800-38B. + * + * Requires: AES-128 + * + * Usage: This implementation provides a "scatter-gather" interface, so that + * the CMAC value can be computed incrementally over a message + * scattered in different segments throughout memory. Experience shows + * this style of interface tends to minimize the burden of programming + * correctly. Like all symmetric key operations, it is session + * oriented. + * + * To begin a CMAC session, use tc_cmac_setup to initialize a struct + * tc_cmac_struct with encryption key and buffer. Our implementation + * always assume that the AES key to be the same size as the block + * cipher block size. Once setup, this data structure can be used for + * many CMAC computations. + * + * Once the state has been setup with a key, computing the CMAC of + * some data requires three steps: + * + * (1) first use tc_cmac_init to initialize a new CMAC computation. + * (2) next mix all of the data into the CMAC computation state using + * tc_cmac_update. If all of the data resides in a single data + * segment then only one tc_cmac_update call is needed; if data + * is scattered throughout memory in n data segments, then n calls + * will be needed. CMAC IS ORDER SENSITIVE, to be able to detect + * attacks that swap bytes, so the order in which data is mixed + * into the state is critical! + * (3) Once all of the data for a message has been mixed, use + * tc_cmac_final to compute the CMAC tag value. + * + * Steps (1)-(3) can be repeated as many times as you want to CMAC + * multiple messages. A practical limit is 2^48 1K messages before you + * have to change the key. + * + * Once you are done computing CMAC with a key, it is a good idea to + * destroy the state so an attacker cannot recover the key; use + * tc_cmac_erase to accomplish this. + */ + +#ifndef __TC_CMAC_MODE_H__ +#define __TC_CMAC_MODE_H__ + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* padding for last message block */ +#define TC_CMAC_PADDING 0x80 + +/* struct tc_cmac_struct represents the state of a CMAC computation */ +typedef struct tc_cmac_struct { +/* initialization vector */ + uint8_t iv[TC_AES_BLOCK_SIZE]; +/* used if message length is a multiple of block_size bytes */ + uint8_t K1[TC_AES_BLOCK_SIZE]; +/* used if message length isn't a multiple block_size bytes */ + uint8_t K2[TC_AES_BLOCK_SIZE]; +/* where to put bytes that didn't fill a block */ + uint8_t leftover[TC_AES_BLOCK_SIZE]; +/* identifies the encryption key */ + unsigned int keyid; +/* next available leftover location */ + unsigned int leftover_offset; +/* AES key schedule */ + TCAesKeySched_t sched; +/* calls to tc_cmac_update left before re-key */ + uint64_t countdown; +} *TCCmacState_t; + +/** + * @brief Configures the CMAC state to use the given AES key + * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state + * returns TC_CRYPTO_FAIL (0) if: + * s == NULL or + * key == NULL + * + * @param s IN/OUT -- the state to set up + * @param key IN -- the key to use + * @param sched IN -- AES key schedule + */ +int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, + TCAesKeySched_t sched); + +/** + * @brief Erases the CMAC state + * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state + * returns TC_CRYPTO_FAIL (0) if: + * s == NULL + * + * @param s IN/OUT -- the state to erase + */ +int tc_cmac_erase(TCCmacState_t s); + +/** + * @brief Initializes a new CMAC computation + * @return returns TC_CRYPTO_SUCCESS (1) after having initialized the CMAC state + * returns TC_CRYPTO_FAIL (0) if: + * s == NULL + * + * @param s IN/OUT -- the state to initialize + */ +int tc_cmac_init(TCCmacState_t s); + +/** + * @brief Incrementally computes CMAC over the next data segment + * @return returns TC_CRYPTO_SUCCESS (1) after successfully updating the CMAC state + * returns TC_CRYPTO_FAIL (0) if: + * s == NULL or + * if data == NULL when dlen > 0 + * + * @param s IN/OUT -- the CMAC state + * @param data IN -- the next data segment to MAC + * @param dlen IN -- the length of data in bytes + */ +int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t dlen); + +/** + * @brief Generates the tag from the CMAC state + * @return returns TC_CRYPTO_SUCCESS (1) after successfully generating the tag + * returns TC_CRYPTO_FAIL (0) if: + * tag == NULL or + * s == NULL + * + * @param tag OUT -- the CMAC tag + * @param s IN -- CMAC state + */ +int tc_cmac_final(uint8_t *tag, TCCmacState_t s); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_CMAC_MODE_H__ */ diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/constants.h b/lib/bt/common/tinycrypt/include/tinycrypt/constants.h new file mode 100644 index 00000000..3abe98db --- /dev/null +++ b/lib/bt/common/tinycrypt/include/tinycrypt/constants.h @@ -0,0 +1,65 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief -- Interface to constants. + * + */ + +#ifndef __TC_CONSTANTS_H__ +#define __TC_CONSTANTS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#define TC_CRYPTO_SUCCESS 1 +#define TC_CRYPTO_FAIL 0 + +#define TC_ZERO_BYTE 0x00 + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_CONSTANTS_H__ */ diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/ctr_mode.h b/lib/bt/common/tinycrypt/include/tinycrypt/ctr_mode.h new file mode 100644 index 00000000..1b0bab43 --- /dev/null +++ b/lib/bt/common/tinycrypt/include/tinycrypt/ctr_mode.h @@ -0,0 +1,112 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to CTR mode. + * + * Overview: CTR (pronounced "counter") mode is a NIST approved mode of + * operation defined in SP 800-38a. It can be used with any + * block cipher to provide confidentiality of strings of any + * length. TinyCrypt hard codes AES128 as the block cipher. + * + * Security: CTR mode achieves confidentiality only if the counter value is + * never reused with a same encryption key. If the counter is + * repeated, than an adversary might be able to defeat the scheme. + * + * A usual method to ensure different counter values refers to + * initialize the counter in a given value (0, for example) and + * increases it every time a new block is enciphered. This naturally + * leaves to a limitation on the number q of blocks that can be + * enciphered using a same key: q < 2^(counter size). + * + * TinyCrypt uses a counter of 32 bits. This means that after 2^32 + * block encryptions, the counter will be reused (thus losing CBC + * security). 2^32 block encryptions should be enough for most of + * applications targeting constrained devices. Applications intended + * to encrypt a larger number of blocks must replace the key after + * 2^32 block encryptions. + * + * CTR mode provides NO data integrity. + * + * Requires: AES-128 + * + * Usage: 1) call tc_ctr_mode to process the data to encrypt/decrypt. + * + */ + +#ifndef __TC_CTR_MODE_H__ +#define __TC_CTR_MODE_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief CTR mode encryption/decryption procedure. + * CTR mode encrypts (or decrypts) inlen bytes from in buffer into out buffer + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * out == NULL or + * in == NULL or + * ctr == NULL or + * sched == NULL or + * inlen == 0 or + * outlen == 0 or + * inlen != outlen + * @note Assumes:- The current value in ctr has NOT been used with sched + * - out points to inlen bytes + * - in points to inlen bytes + * - ctr is an integer counter in littleEndian format + * - sched was initialized by aes_set_encrypt_key + * @param out OUT -- produced ciphertext (plaintext) + * @param outlen IN -- length of ciphertext buffer in bytes + * @param in IN -- data to encrypt (or decrypt) + * @param inlen IN -- length of input data in bytes + * @param ctr IN/OUT -- the current counter value + * @param sched IN -- an initialized AES key schedule + */ +int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, + unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_CTR_MODE_H__ */ diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/ctr_prng.h b/lib/bt/common/tinycrypt/include/tinycrypt/ctr_prng.h new file mode 100644 index 00000000..ecff008d --- /dev/null +++ b/lib/bt/common/tinycrypt/include/tinycrypt/ctr_prng.h @@ -0,0 +1,172 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* ctr_prng.h - TinyCrypt interface to a CTR-PRNG implementation */ + +/* + * Copyright (c) 2016, Chris Morrison + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to a CTR-PRNG implementation. + * + * Overview: A pseudo-random number generator (PRNG) generates a sequence + * of numbers that have a distribution close to the one expected + * for a sequence of truly random numbers. The NIST Special + * Publication 800-90A specifies several mechanisms to generate + * sequences of pseudo random numbers, including the CTR-PRNG one + * which is based on AES. TinyCrypt implements CTR-PRNG with + * AES-128. + * + * Security: A cryptographically secure PRNG depends on the existence of an + * entropy source to provide a truly random seed as well as the + * security of the primitives used as the building blocks (AES-128 + * in this instance). + * + * Requires: - AES-128 + * + * Usage: 1) call tc_ctr_prng_init to seed the prng context + * + * 2) call tc_ctr_prng_reseed to mix in additional entropy into + * the prng context + * + * 3) call tc_ctr_prng_generate to output the pseudo-random data + * + * 4) call tc_ctr_prng_uninstantiate to zero out the prng context + */ + +#ifndef __TC_CTR_PRNG_H__ +#define __TC_CTR_PRNG_H__ + +#include + +#define TC_CTR_PRNG_RESEED_REQ -1 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + /* updated each time another BLOCKLEN_BYTES bytes are produced */ + uint8_t V[TC_AES_BLOCK_SIZE]; + + /* updated whenever the PRNG is reseeded */ + struct tc_aes_key_sched_struct key; + + /* number of requests since initialization/reseeding */ + uint64_t reseedCount; +} TCCtrPrng_t; + + +/** + * @brief CTR-PRNG initialization procedure + * Initializes prng context with entropy and personalization string (if any) + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * ctx == NULL, + * entropy == NULL, + * entropyLen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) + * @note Only the first (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes of + * both the entropy and personalization inputs are used - + * supplying additional bytes has no effect. + * @param ctx IN/OUT -- the PRNG context to initialize + * @param entropy IN -- entropy used to seed the PRNG + * @param entropyLen IN -- entropy length in bytes + * @param personalization IN -- personalization string used to seed the PRNG + * (may be null) + * @param plen IN -- personalization length in bytes + * + */ +int tc_ctr_prng_init(TCCtrPrng_t * const ctx, + uint8_t const * const entropy, + unsigned int entropyLen, + uint8_t const * const personalization, + unsigned int pLen); + +/** + * @brief CTR-PRNG reseed procedure + * Mixes entropy and additional_input into the prng context + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * ctx == NULL, + * entropy == NULL, + * entropylen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) + * @note It is better to reseed an existing prng context rather than + * re-initialise, so that any existing entropy in the context is + * presereved. This offers some protection against undetected failures + * of the entropy source. + * @note Assumes tc_ctr_prng_init has been called for ctx + * @param ctx IN/OUT -- the PRNG state + * @param entropy IN -- entropy to mix into the prng + * @param entropylen IN -- length of entropy in bytes + * @param additional_input IN -- additional input to the prng (may be null) + * @param additionallen IN -- additional input length in bytes + */ +int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx, + uint8_t const * const entropy, + unsigned int entropyLen, + uint8_t const * const additional_input, + unsigned int additionallen); + +/** + * @brief CTR-PRNG generate procedure + * Generates outlen pseudo-random bytes into out buffer, updates prng + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CTR_PRNG_RESEED_REQ (-1) if a reseed is needed + * returns TC_CRYPTO_FAIL (0) if: + * ctx == NULL, + * out == NULL, + * outlen >= 2^16 + * @note Assumes tc_ctr_prng_init has been called for ctx + * @param ctx IN/OUT -- the PRNG context + * @param additional_input IN -- additional input to the prng (may be null) + * @param additionallen IN -- additional input length in bytes + * @param out IN/OUT -- buffer to receive output + * @param outlen IN -- size of out buffer in bytes + */ +int tc_ctr_prng_generate(TCCtrPrng_t * const ctx, + uint8_t const * const additional_input, + unsigned int additionallen, + uint8_t * const out, + unsigned int outlen); + +/** + * @brief CTR-PRNG uninstantiate procedure + * Zeroes the internal state of the supplied prng context + * @return none + * @param ctx IN/OUT -- the PRNG context + */ +void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_CTR_PRNG_H__ */ diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/ecc.h b/lib/bt/common/tinycrypt/include/tinycrypt/ecc.h new file mode 100644 index 00000000..d963ae3c --- /dev/null +++ b/lib/bt/common/tinycrypt/include/tinycrypt/ecc.h @@ -0,0 +1,551 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* ecc.h - TinyCrypt interface to common ECC functions */ + +/* Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief -- Interface to common ECC functions. + * + * Overview: This software is an implementation of common functions + * necessary to elliptic curve cryptography. This implementation uses + * curve NIST p-256. + * + * Security: The curve NIST p-256 provides approximately 128 bits of security. + * + */ + +#ifndef __TC_UECC_H__ +#define __TC_UECC_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Word size (4 bytes considering 32-bits architectures) */ +#define uECC_WORD_SIZE 4 + +/* setting max number of calls to prng: */ +#ifndef uECC_RNG_MAX_TRIES +#define uECC_RNG_MAX_TRIES 64 +#endif + +/* defining data types to store word and bit counts: */ +typedef int8_t wordcount_t; +typedef int16_t bitcount_t; +/* defining data type for comparison result: */ +typedef int8_t cmpresult_t; +/* defining data type to store ECC coordinate/point in 32bits words: */ +typedef unsigned int uECC_word_t; +/* defining data type to store an ECC coordinate/point in 64bits words: */ +typedef uint64_t uECC_dword_t; + +/* defining masks useful for ecc computations: */ +#define HIGH_BIT_SET 0x80000000 +#define uECC_WORD_BITS 32 +#define uECC_WORD_BITS_SHIFT 5 +#define uECC_WORD_BITS_MASK 0x01F + +/* Number of words of 32 bits to represent an element of the the curve p-256: */ +#define NUM_ECC_WORDS 8 +/* Number of bytes to represent an element of the the curve p-256: */ +#define NUM_ECC_BYTES (uECC_WORD_SIZE*NUM_ECC_WORDS) + +/* structure that represents an elliptic curve (e.g. p256):*/ +struct uECC_Curve_t; +typedef const struct uECC_Curve_t * uECC_Curve; +struct uECC_Curve_t { + wordcount_t num_words; + wordcount_t num_bytes; + bitcount_t num_n_bits; + uECC_word_t p[NUM_ECC_WORDS]; + uECC_word_t n[NUM_ECC_WORDS]; + uECC_word_t G[NUM_ECC_WORDS * 2]; + uECC_word_t b[NUM_ECC_WORDS]; + void (*double_jacobian)(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * Z1, + uECC_Curve curve); + void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve); + void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product); +}; + +/* + * @brief computes doubling of point ion jacobian coordinates, in place. + * @param X1 IN/OUT -- x coordinate + * @param Y1 IN/OUT -- y coordinate + * @param Z1 IN/OUT -- z coordinate + * @param curve IN -- elliptic curve + */ +void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * Z1, uECC_Curve curve); + +/* + * @brief Computes x^3 + ax + b. result must not overlap x. + * @param result OUT -- x^3 + ax + b + * @param x IN -- value of x + * @param curve IN -- elliptic curve + */ +void x_side_default(uECC_word_t *result, const uECC_word_t *x, + uECC_Curve curve); + +/* + * @brief Computes result = product % curve_p + * from http://www.nsa.gov/ia/_files/nist-routines.pdf + * @param result OUT -- product % curve_p + * @param product IN -- value to be reduced mod curve_p + */ +void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int *product); + +/* Bytes to words ordering: */ +#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e +#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a +#define BITS_TO_WORDS(num_bits) \ + ((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8)) +#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8) + +/* definition of curve NIST p-256: */ +static const struct uECC_Curve_t curve_secp256r1 = { + NUM_ECC_WORDS, + NUM_ECC_BYTES, + 256, /* num_n_bits */ { + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF) + }, { + BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3), + BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF) + }, { + BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4), + BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77), + BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8), + BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B), + + BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB), + BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B), + BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E), + BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F) + }, { + BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B), + BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65), + BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3), + BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A) + }, + &double_jacobian_default, + &x_side_default, + &vli_mmod_fast_secp256r1 +}; + +uECC_Curve uECC_secp256r1(void); + +/* + * @brief Generates a random integer in the range 0 < random < top. + * Both random and top have num_words words. + * @param random OUT -- random integer in the range 0 < random < top + * @param top IN -- upper limit + * @param num_words IN -- number of words + * @return a random integer in the range 0 < random < top + */ +int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, + wordcount_t num_words); + + +/* uECC_RNG_Function type + * The RNG function should fill 'size' random bytes into 'dest'. It should + * return 1 if 'dest' was filled with random data, or 0 if the random data could + * not be generated. The filled-in values should be either truly random, or from + * a cryptographically-secure PRNG. + * + * A correctly functioning RNG function must be set (using uECC_set_rng()) + * before calling uECC_make_key() or uECC_sign(). + * + * Setting a correctly functioning RNG function improves the resistance to + * side-channel attacks for uECC_shared_secret(). + * + * A correct RNG function is set by default. If you are building on another + * POSIX-compliant system that supports /dev/random or /dev/urandom, you can + * define uECC_POSIX to use the predefined RNG. + */ +typedef int(*uECC_RNG_Function)(uint8_t *dest, unsigned int size); + +/* + * @brief Set the function that will be used to generate random bytes. The RNG + * function should return 1 if the random data was generated, or 0 if the random + * data could not be generated. + * + * @note On platforms where there is no predefined RNG function, this must be + * called before uECC_make_key() or uECC_sign() are used. + * + * @param rng_function IN -- function that will be used to generate random bytes + */ +void uECC_set_rng(uECC_RNG_Function rng_function); + +/* + * @brief provides current uECC_RNG_Function. + * @return Returns the function that will be used to generate random bytes. + */ +uECC_RNG_Function uECC_get_rng(void); + +/* + * @brief computes the size of a private key for the curve in bytes. + * @param curve IN -- elliptic curve + * @return size of a private key for the curve in bytes. + */ +int uECC_curve_private_key_size(uECC_Curve curve); + +/* + * @brief computes the size of a public key for the curve in bytes. + * @param curve IN -- elliptic curve + * @return the size of a public key for the curve in bytes. + */ +int uECC_curve_public_key_size(uECC_Curve curve); + +/* + * @brief Compute the corresponding public key for a private key. + * @param private_key IN -- The private key to compute the public key for + * @param public_key OUT -- Will be filled in with the corresponding public key + * @param curve + * @return Returns 1 if key was computed successfully, 0 if an error occurred. + */ +int uECC_compute_public_key(const uint8_t *private_key, + uint8_t *public_key, uECC_Curve curve); + +/* + * @brief Compute public-key. + * @return corresponding public-key. + * @param result OUT -- public-key + * @param private_key IN -- private-key + * @param curve IN -- elliptic curve + */ +uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, + uECC_word_t *private_key, uECC_Curve curve); + +/* + * @brief Regularize the bitcount for the private key so that attackers cannot + * use a side channel attack to learn the number of leading zeros. + * @return Regularized k + * @param k IN -- private-key + * @param k0 IN/OUT -- regularized k + * @param k1 IN/OUT -- regularized k + * @param curve IN -- elliptic curve + */ +uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, + uECC_word_t *k1, uECC_Curve curve); + +/* + * @brief Point multiplication algorithm using Montgomery's ladder with co-Z + * coordinates. See http://eprint.iacr.org/2011/338.pdf. + * @note Result may overlap point. + * @param result OUT -- returns scalar*point + * @param point IN -- elliptic curve point + * @param scalar IN -- scalar + * @param initial_Z IN -- initial value for z + * @param num_bits IN -- number of bits in scalar + * @param curve IN -- elliptic curve + */ +void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, + const uECC_word_t * scalar, const uECC_word_t * initial_Z, + bitcount_t num_bits, uECC_Curve curve); + +/* + * @brief Constant-time comparison to zero - secure way to compare long integers + * @param vli IN -- very long integer + * @param num_words IN -- number of words in the vli + * @return 1 if vli == 0, 0 otherwise. + */ +uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words); + +/* + * @brief Check if 'point' is the point at infinity + * @param point IN -- elliptic curve point + * @param curve IN -- elliptic curve + * @return if 'point' is the point at infinity, 0 otherwise. + */ +uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve); + +/* + * @brief computes the sign of left - right, in constant time. + * @param left IN -- left term to be compared + * @param right IN -- right term to be compared + * @param num_words IN -- number of words + * @return the sign of left - right + */ +cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, + wordcount_t num_words); + +/* + * @brief computes sign of left - right, not in constant time. + * @note should not be used if inputs are part of a secret + * @param left IN -- left term to be compared + * @param right IN -- right term to be compared + * @param num_words IN -- number of words + * @return the sign of left - right + */ +cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right, + wordcount_t num_words); + +/* + * @brief Computes result = (left - right) % mod. + * @note Assumes that (left < mod) and (right < mod), and that result does not + * overlap mod. + * @param result OUT -- (left - right) % mod + * @param left IN -- leftright term in modular subtraction + * @param right IN -- right term in modular subtraction + * @param mod IN -- mod + * @param num_words IN -- number of words + */ +void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, const uECC_word_t *mod, + wordcount_t num_words); + +/* + * @brief Computes P' = (x1', y1', Z3), P + Q = (x3, y3, Z3) or + * P => P', Q => P + Q + * @note assumes Input P = (x1, y1, Z), Q = (x2, y2, Z) + * @param X1 IN -- x coordinate of P + * @param Y1 IN -- y coordinate of P + * @param X2 IN -- x coordinate of Q + * @param Y2 IN -- y coordinate of Q + * @param curve IN -- elliptic curve + */ +void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2, + uECC_word_t * Y2, uECC_Curve curve); + +/* + * @brief Computes (x1 * z^2, y1 * z^3) + * @param X1 IN -- previous x1 coordinate + * @param Y1 IN -- previous y1 coordinate + * @param Z IN -- z value + * @param curve IN -- elliptic curve + */ +void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z, + uECC_Curve curve); + +/* + * @brief Check if bit is set. + * @return Returns nonzero if bit 'bit' of vli is set. + * @warning It is assumed that the value provided in 'bit' is within the + * boundaries of the word-array 'vli'. + * @note The bit ordering layout assumed for vli is: {31, 30, ..., 0}, + * {63, 62, ..., 32}, {95, 94, ..., 64}, {127, 126,..., 96} for a vli consisting + * of 4 uECC_word_t elements. + */ +uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit); + +/* + * @brief Computes result = product % mod, where product is 2N words long. + * @param result OUT -- product % mod + * @param mod IN -- module + * @param num_words IN -- number of words + * @warning Currently only designed to work for curve_p or curve_n. + */ +void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, + const uECC_word_t *mod, wordcount_t num_words); + +/* + * @brief Computes modular product (using curve->mmod_fast) + * @param result OUT -- (left * right) mod % curve_p + * @param left IN -- left term in product + * @param right IN -- right term in product + * @param curve IN -- elliptic curve + */ +void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, uECC_Curve curve); + +/* + * @brief Computes result = left - right. + * @note Can modify in place. + * @param result OUT -- left - right + * @param left IN -- left term in subtraction + * @param right IN -- right term in subtraction + * @param num_words IN -- number of words + * @return borrow + */ +uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, wordcount_t num_words); + +/* + * @brief Constant-time comparison function(secure way to compare long ints) + * @param left IN -- left term in comparison + * @param right IN -- right term in comparison + * @param num_words IN -- number of words + * @return Returns 0 if left == right, 1 otherwise. + */ +uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right, + wordcount_t num_words); + +/* + * @brief Computes (left * right) % mod + * @param result OUT -- (left * right) % mod + * @param left IN -- left term in product + * @param right IN -- right term in product + * @param mod IN -- mod + * @param num_words IN -- number of words + */ +void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, const uECC_word_t *mod, + wordcount_t num_words); + +/* + * @brief Computes (1 / input) % mod + * @note All VLIs are the same size. + * @note See "Euclid's GCD to Montgomery Multiplication to the Great Divide" + * @param result OUT -- (1 / input) % mod + * @param input IN -- value to be modular inverted + * @param mod IN -- mod + * @param num_words -- number of words + */ +void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, + const uECC_word_t *mod, wordcount_t num_words); + +/* + * @brief Sets dest = src. + * @param dest OUT -- destination buffer + * @param src IN -- origin buffer + * @param num_words IN -- number of words + */ +void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, + wordcount_t num_words); + +/* + * @brief Computes (left + right) % mod. + * @note Assumes that (left < mod) and right < mod), and that result does not + * overlap mod. + * @param result OUT -- (left + right) % mod. + * @param left IN -- left term in addition + * @param right IN -- right term in addition + * @param mod IN -- mod + * @param num_words IN -- number of words + */ +void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, const uECC_word_t *mod, + wordcount_t num_words); + +/* + * @brief Counts the number of bits required to represent vli. + * @param vli IN -- very long integer + * @param max_words IN -- number of words + * @return number of bits in given vli + */ +bitcount_t uECC_vli_numBits(const uECC_word_t *vli, + const wordcount_t max_words); + +/* + * @brief Erases (set to 0) vli + * @param vli IN -- very long integer + * @param num_words IN -- number of words + */ +void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words); + +/* + * @brief check if it is a valid point in the curve + * @param point IN -- point to be checked + * @param curve IN -- elliptic curve + * @return 0 if point is valid + * @exception returns -1 if it is a point at infinity + * @exception returns -2 if x or y is smaller than p, + * @exception returns -3 if y^2 != x^3 + ax + b. + */ +int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve); + +/* + * @brief Check if a public key is valid. + * @param public_key IN -- The public key to be checked. + * @return returns 0 if the public key is valid + * @exception returns -1 if it is a point at infinity + * @exception returns -2 if x or y is smaller than p, + * @exception returns -3 if y^2 != x^3 + ax + b. + * @exception returns -4 if public key is the group generator. + * + * @note Note that you are not required to check for a valid public key before + * using any other uECC functions. However, you may wish to avoid spending CPU + * time computing a shared secret or verifying a signature using an invalid + * public key. + */ +int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve); + + /* + * @brief Converts an integer in uECC native format to big-endian bytes. + * @param bytes OUT -- bytes representation + * @param num_bytes IN -- number of bytes + * @param native IN -- uECC native representation + */ +void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, + const unsigned int *native); + +/* + * @brief Converts big-endian bytes to an integer in uECC native format. + * @param native OUT -- uECC native representation + * @param bytes IN -- bytes representation + * @param num_bytes IN -- number of bytes + */ +void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes, + int num_bytes); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_UECC_H__ */ diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/ecc_dh.h b/lib/bt/common/tinycrypt/include/tinycrypt/ecc_dh.h new file mode 100644 index 00000000..e28e8a65 --- /dev/null +++ b/lib/bt/common/tinycrypt/include/tinycrypt/ecc_dh.h @@ -0,0 +1,135 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief -- Interface to EC-DH implementation. + * + * Overview: This software is an implementation of EC-DH. This implementation + * uses curve NIST p-256. + * + * Security: The curve NIST p-256 provides approximately 128 bits of security. + */ + +#ifndef __TC_ECC_DH_H__ +#define __TC_ECC_DH_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Create a public/private key pair. + * @return returns TC_CRYPTO_SUCCESS (1) if the key pair was generated successfully + * returns TC_CRYPTO_FAIL (0) if error while generating key pair + * + * @param p_public_key OUT -- Will be filled in with the public key. Must be at + * least 2 * the curve size (in bytes) long. For curve secp256r1, p_public_key + * must be 64 bytes long. + * @param p_private_key OUT -- Will be filled in with the private key. Must be as + * long as the curve order (for secp256r1, p_private_key must be 32 bytes long). + * + * @note side-channel countermeasure: algorithm strengthened against timing + * attack. + * @warning A cryptographically-secure PRNG function must be set (using + * uECC_set_rng()) before calling uECC_make_key(). + */ +int uECC_make_key(uint8_t *p_public_key, uint8_t *p_private_key, uECC_Curve curve); + +#ifdef ENABLE_TESTS + +/** + * @brief Create a public/private key pair given a specific d. + * + * @note THIS FUNCTION SHOULD BE CALLED ONLY FOR TEST PURPOSES. Refer to + * uECC_make_key() function for real applications. + */ +int uECC_make_key_with_d(uint8_t *p_public_key, uint8_t *p_private_key, + unsigned int *d, uECC_Curve curve); +#endif + +/** + * @brief Compute a shared secret given your secret key and someone else's + * public key. + * @return returns TC_CRYPTO_SUCCESS (1) if the shared secret was computed successfully + * returns TC_CRYPTO_FAIL (0) otherwise + * + * @param p_secret OUT -- Will be filled in with the shared secret value. Must be + * the same size as the curve size (for curve secp256r1, secret must be 32 bytes + * long. + * @param p_public_key IN -- The public key of the remote party. + * @param p_private_key IN -- Your private key. + * + * @warning It is recommended to use the output of uECC_shared_secret() as the + * input of a recommended Key Derivation Function (see NIST SP 800-108) in + * order to produce a cryptographically secure symmetric key. + */ +int uECC_shared_secret(const uint8_t *p_public_key, const uint8_t *p_private_key, + uint8_t *p_secret, uECC_Curve curve); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_ECC_DH_H__ */ diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/ecc_dsa.h b/lib/bt/common/tinycrypt/include/tinycrypt/ecc_dsa.h new file mode 100644 index 00000000..76181088 --- /dev/null +++ b/lib/bt/common/tinycrypt/include/tinycrypt/ecc_dsa.h @@ -0,0 +1,145 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* ecc_dh.h - TinyCrypt interface to EC-DSA implementation */ + +/* + * Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief -- Interface to EC-DSA implementation. + * + * Overview: This software is an implementation of EC-DSA. This implementation + * uses curve NIST p-256. + * + * Security: The curve NIST p-256 provides approximately 128 bits of security. + * + * Usage: - To sign: Compute a hash of the data you wish to sign (SHA-2 is + * recommended) and pass it in to ecdsa_sign function along with your + * private key and a random number. You must use a new non-predictable + * random number to generate each new signature. + * - To verify a signature: Compute the hash of the signed data using + * the same hash as the signer and pass it to this function along with + * the signer's public key and the signature values (r and s). + */ + +#ifndef __TC_ECC_DSA_H__ +#define __TC_ECC_DSA_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Generate an ECDSA signature for a given hash value. + * @return returns TC_CRYPTO_SUCCESS (1) if the signature generated successfully + * returns TC_CRYPTO_FAIL (0) if an error occurred. + * + * @param p_private_key IN -- Your private key. + * @param p_message_hash IN -- The hash of the message to sign. + * @param p_hash_size IN -- The size of p_message_hash in bytes. + * @param p_signature OUT -- Will be filled in with the signature value. Must be + * at least 2 * curve size long (for secp256r1, signature must be 64 bytes long). + * + * @warning A cryptographically-secure PRNG function must be set (using + * uECC_set_rng()) before calling uECC_sign(). + * @note Usage: Compute a hash of the data you wish to sign (SHA-2 is + * recommended) and pass it in to this function along with your private key. + * @note side-channel countermeasure: algorithm strengthened against timing + * attack. + */ +int uECC_sign(const uint8_t *p_private_key, const uint8_t *p_message_hash, + unsigned p_hash_size, uint8_t *p_signature, uECC_Curve curve); + +#ifdef ENABLE_TESTS +/* + * THIS FUNCTION SHOULD BE CALLED FOR TEST PURPOSES ONLY. + * Refer to uECC_sign() function for real applications. + */ +int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, + unsigned int hash_size, uECC_word_t *k, uint8_t *signature, + uECC_Curve curve); +#endif + +/** + * @brief Verify an ECDSA signature. + * @return returns TC_SUCCESS (1) if the signature is valid + * returns TC_FAIL (0) if the signature is invalid. + * + * @param p_public_key IN -- The signer's public key. + * @param p_message_hash IN -- The hash of the signed data. + * @param p_hash_size IN -- The size of p_message_hash in bytes. + * @param p_signature IN -- The signature values. + * + * @note Usage: Compute the hash of the signed data using the same hash as the + * signer and pass it to this function along with the signer's public key and + * the signature values (hash_size and signature). + */ +int uECC_verify(const uint8_t *p_public_key, const uint8_t *p_message_hash, + unsigned int p_hash_size, const uint8_t *p_signature, uECC_Curve curve); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_ECC_DSA_H__ */ diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/ecc_platform_specific.h b/lib/bt/common/tinycrypt/include/tinycrypt/ecc_platform_specific.h new file mode 100644 index 00000000..553c8a03 --- /dev/null +++ b/lib/bt/common/tinycrypt/include/tinycrypt/ecc_platform_specific.h @@ -0,0 +1,85 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.*/ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * uECC_platform_specific.h -- Interface to platform specific functions + */ + +#ifndef __UECC_PLATFORM_SPECIFIC_H_ +#define __UECC_PLATFORM_SPECIFIC_H_ + +/* + * The RNG function should fill 'size' random bytes into 'dest'. It should + * return 1 if 'dest' was filled with random data, or 0 if the random data could + * not be generated. The filled-in values should be either truly random, or from + * a cryptographically-secure PRNG. + * + * A cryptographically-secure PRNG function must be set (using uECC_set_rng()) + * before calling uECC_make_key() or uECC_sign(). + * + * Setting a cryptographically-secure PRNG function improves the resistance to + * side-channel attacks for uECC_shared_secret(). + * + * A correct PRNG function is set by default (default_RNG_defined = 1) and works + * for some platforms, such as Unix and Linux. For other platforms, you may need + * to provide another PRNG function. +*/ +#define default_RNG_defined 0 + +int default_CSPRNG(uint8_t *dest, unsigned int size); + +#endif /* __UECC_PLATFORM_SPECIFIC_H_ */ diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/hmac.h b/lib/bt/common/tinycrypt/include/tinycrypt/hmac.h new file mode 100644 index 00000000..1f624ef8 --- /dev/null +++ b/lib/bt/common/tinycrypt/include/tinycrypt/hmac.h @@ -0,0 +1,143 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to an HMAC implementation. + * + * Overview: HMAC is a message authentication code based on hash functions. + * TinyCrypt hard codes SHA-256 as the hash function. A message + * authentication code based on hash functions is also called a + * keyed cryptographic hash function since it performs a + * transformation specified by a key in an arbitrary length data + * set into a fixed length data set (also called tag). + * + * Security: The security of the HMAC depends on the length of the key and + * on the security of the hash function. Note that HMAC primitives + * are much less affected by collision attacks than their + * corresponding hash functions. + * + * Requires: SHA-256 + * + * Usage: 1) call tc_hmac_set_key to set the HMAC key. + * + * 2) call tc_hmac_init to initialize a struct hash_state before + * processing the data. + * + * 3) call tc_hmac_update to process the next input segment; + * tc_hmac_update can be called as many times as needed to process + * all of the segments of the input; the order is important. + * + * 4) call tc_hmac_final to out put the tag. + */ + +#ifndef __TC_HMAC_H__ +#define __TC_HMAC_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct tc_hmac_state_struct { + /* the internal state required by h */ + struct tc_sha256_state_struct hash_state; + /* HMAC key schedule */ + uint8_t key[2*TC_SHA256_BLOCK_SIZE]; +}; +typedef struct tc_hmac_state_struct *TCHmacState_t; + +/** + * @brief HMAC set key procedure + * Configures ctx to use key + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if + * ctx == NULL or + * key == NULL or + * key_size == 0 + * @param ctx IN/OUT -- the struct tc_hmac_state_struct to initial + * @param key IN -- the HMAC key to configure + * @param key_size IN -- the HMAC key size + */ +int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key, + unsigned int key_size); + +/** + * @brief HMAC init procedure + * Initializes ctx to begin the next HMAC operation + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL + * @param ctx IN/OUT -- struct tc_hmac_state_struct buffer to init + */ +int tc_hmac_init(TCHmacState_t ctx); + +/** + * @brief HMAC update procedure + * Mixes data_length bytes addressed by data into state + * @return returns TC_CRYPTO_SUCCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL + * @note Assumes state has been initialized by tc_hmac_init + * @param ctx IN/OUT -- state of HMAC computation so far + * @param data IN -- data to incorporate into state + * @param data_length IN -- size of data in bytes + */ +int tc_hmac_update(TCHmacState_t ctx, const void *data, + unsigned int data_length); + +/** + * @brief HMAC final procedure + * Writes the HMAC tag into the tag buffer + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * tag == NULL or + * ctx == NULL or + * key == NULL or + * taglen != TC_SHA256_DIGEST_SIZE + * @note ctx is erased before exiting. This should never be changed/removed. + * @note Assumes the tag buffer is at least sizeof(hmac_tag_size(state)) bytes + * state has been initialized by tc_hmac_init + * @param tag IN/OUT -- buffer to receive computed HMAC tag + * @param taglen IN -- size of tag in bytes + * @param ctx IN/OUT -- the HMAC state for computing tag + */ +int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx); + +#ifdef __cplusplus +} +#endif + +#endif /*__TC_HMAC_H__*/ diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/hmac_prng.h b/lib/bt/common/tinycrypt/include/tinycrypt/hmac_prng.h new file mode 100644 index 00000000..98c2e70c --- /dev/null +++ b/lib/bt/common/tinycrypt/include/tinycrypt/hmac_prng.h @@ -0,0 +1,168 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to an HMAC-PRNG implementation. + * + * Overview: A pseudo-random number generator (PRNG) generates a sequence + * of numbers that have a distribution close to the one expected + * for a sequence of truly random numbers. The NIST Special + * Publication 800-90A specifies several mechanisms to generate + * sequences of pseudo random numbers, including the HMAC-PRNG one + * which is based on HMAC. TinyCrypt implements HMAC-PRNG with + * certain modifications from the NIST SP 800-90A spec. + * + * Security: A cryptographically secure PRNG depends on the existence of an + * entropy source to provide a truly random seed as well as the + * security of the primitives used as the building blocks (HMAC and + * SHA256, for TinyCrypt). + * + * The NIST SP 800-90A standard tolerates a null personalization, + * while TinyCrypt requires a non-null personalization. This is + * because a personalization string (the host name concatenated + * with a time stamp, for example) is easily computed and might be + * the last line of defense against failure of the entropy source. + * + * Requires: - SHA-256 + * - HMAC + * + * Usage: 1) call tc_hmac_prng_init to set the HMAC key and process the + * personalization data. + * + * 2) call tc_hmac_prng_reseed to process the seed and additional + * input. + * + * 3) call tc_hmac_prng_generate to out put the pseudo-random data. + */ + +#ifndef __TC_HMAC_PRNG_H__ +#define __TC_HMAC_PRNG_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define TC_HMAC_PRNG_RESEED_REQ -1 + +struct tc_hmac_prng_struct { + /* the HMAC instance for this PRNG */ + struct tc_hmac_state_struct h; + /* the PRNG key */ + uint8_t key[TC_SHA256_DIGEST_SIZE]; + /* PRNG state */ + uint8_t v[TC_SHA256_DIGEST_SIZE]; + /* calls to tc_hmac_prng_generate left before re-seed */ + unsigned int countdown; +}; + +typedef struct tc_hmac_prng_struct *TCHmacPrng_t; + +/** + * @brief HMAC-PRNG initialization procedure + * Initializes prng with personalization, disables tc_hmac_prng_generate + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * prng == NULL, + * personalization == NULL, + * plen > MAX_PLEN + * @note Assumes: - personalization != NULL. + * The personalization is a platform unique string (e.g., the host + * name) and is the last line of defense against failure of the + * entropy source + * @warning NIST SP 800-90A specifies 3 items as seed material during + * initialization: entropy seed, personalization, and an optional + * nonce. TinyCrypts requires instead a non-null personalization + * (which is easily computed) and indirectly requires an entropy + * seed (since the reseed function is mandatorily called after + * init) + * @param prng IN/OUT -- the PRNG state to initialize + * @param personalization IN -- personalization string + * @param plen IN -- personalization length in bytes + */ +int tc_hmac_prng_init(TCHmacPrng_t prng, + const uint8_t *personalization, + unsigned int plen); + +/** + * @brief HMAC-PRNG reseed procedure + * Mixes seed into prng, enables tc_hmac_prng_generate + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * prng == NULL, + * seed == NULL, + * seedlen < MIN_SLEN, + * seendlen > MAX_SLEN, + * additional_input != (const uint8_t *) 0 && additionallen == 0, + * additional_input != (const uint8_t *) 0 && additionallen > MAX_ALEN + * @note Assumes:- tc_hmac_prng_init has been called for prng + * - seed has sufficient entropy. + * + * @param prng IN/OUT -- the PRNG state + * @param seed IN -- entropy to mix into the prng + * @param seedlen IN -- length of seed in bytes + * @param additional_input IN -- additional input to the prng + * @param additionallen IN -- additional input length in bytes + */ +int tc_hmac_prng_reseed(TCHmacPrng_t prng, const uint8_t *seed, + unsigned int seedlen, const uint8_t *additional_input, + unsigned int additionallen); + +/** + * @brief HMAC-PRNG generate procedure + * Generates outlen pseudo-random bytes into out buffer, updates prng + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_HMAC_PRNG_RESEED_REQ (-1) if a reseed is needed + * returns TC_CRYPTO_FAIL (0) if: + * out == NULL, + * prng == NULL, + * outlen == 0, + * outlen >= MAX_OUT + * @note Assumes tc_hmac_prng_init has been called for prng + * @param out IN/OUT -- buffer to receive output + * @param outlen IN -- size of out buffer in bytes + * @param prng IN/OUT -- the PRNG state + */ +int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_HMAC_PRNG_H__ */ diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/sha256.h b/lib/bt/common/tinycrypt/include/tinycrypt/sha256.h new file mode 100644 index 00000000..860665ee --- /dev/null +++ b/lib/bt/common/tinycrypt/include/tinycrypt/sha256.h @@ -0,0 +1,135 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* sha256.h - TinyCrypt interface to a SHA-256 implementation */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to a SHA-256 implementation. + * + * Overview: SHA-256 is a NIST approved cryptographic hashing algorithm + * specified in FIPS 180. A hash algorithm maps data of arbitrary + * size to data of fixed length. + * + * Security: SHA-256 provides 128 bits of security against collision attacks + * and 256 bits of security against pre-image attacks. SHA-256 does + * NOT behave like a random oracle, but it can be used as one if + * the string being hashed is prefix-free encoded before hashing. + * + * Usage: 1) call tc_sha256_init to initialize a struct + * tc_sha256_state_struct before hashing a new string. + * + * 2) call tc_sha256_update to hash the next string segment; + * tc_sha256_update can be called as many times as needed to hash + * all of the segments of a string; the order is important. + * + * 3) call tc_sha256_final to out put the digest from a hashing + * operation. + */ + +#ifndef __TC_SHA256_H__ +#define __TC_SHA256_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define TC_SHA256_BLOCK_SIZE (64) +#define TC_SHA256_DIGEST_SIZE (32) +#define TC_SHA256_STATE_BLOCKS (TC_SHA256_DIGEST_SIZE/4) + +struct tc_sha256_state_struct { + unsigned int iv[TC_SHA256_STATE_BLOCKS]; + uint64_t bits_hashed; + uint8_t leftover[TC_SHA256_BLOCK_SIZE]; + size_t leftover_offset; +}; + +typedef struct tc_sha256_state_struct *TCSha256State_t; + +/** + * @brief SHA256 initialization procedure + * Initializes s + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if s == NULL + * @param s Sha256 state struct + */ +int tc_sha256_init(TCSha256State_t s); + +/** + * @brief SHA256 update procedure + * Hashes data_length bytes addressed by data into state s + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * s == NULL, + * s->iv == NULL, + * data == NULL + * @note Assumes s has been initialized by tc_sha256_init + * @warning The state buffer 'leftover' is left in memory after processing + * If your application intends to have sensitive data in this + * buffer, remind to erase it after the data has been processed + * @param s Sha256 state struct + * @param data message to hash + * @param datalen length of message to hash + */ +int tc_sha256_update (TCSha256State_t s, const uint8_t *data, size_t datalen); + +/** + * @brief SHA256 final procedure + * Inserts the completed hash computation into digest + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * s == NULL, + * s->iv == NULL, + * digest == NULL + * @note Assumes: s has been initialized by tc_sha256_init + * digest points to at least TC_SHA256_DIGEST_SIZE bytes + * @warning The state buffer 'leftover' is left in memory after processing + * If your application intends to have sensitive data in this + * buffer, remind to erase it after the data has been processed + * @param digest unsigned eight bit integer + * @param Sha256 state struct + */ +int tc_sha256_final(uint8_t *digest, TCSha256State_t s); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_SHA256_H__ */ diff --git a/lib/bt/common/tinycrypt/include/tinycrypt/utils.h b/lib/bt/common/tinycrypt/include/tinycrypt/utils.h new file mode 100644 index 00000000..18224c89 --- /dev/null +++ b/lib/bt/common/tinycrypt/include/tinycrypt/utils.h @@ -0,0 +1,101 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* utils.h - TinyCrypt interface to platform-dependent run-time operations */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to platform-dependent run-time operations. + * + */ + +#ifndef __TC_UTILS_H__ +#define __TC_UTILS_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Copy the the buffer 'from' to the buffer 'to'. + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * from_len > to_len. + * + * @param to OUT -- destination buffer + * @param to_len IN -- length of destination buffer + * @param from IN -- origin buffer + * @param from_len IN -- length of origin buffer + */ +unsigned int _copy(uint8_t *to, unsigned int to_len, + const uint8_t *from, unsigned int from_len); + +/** + * @brief Set the value 'val' into the buffer 'to', 'len' times. + * + * @param to OUT -- destination buffer + * @param val IN -- value to be set in 'to' + * @param len IN -- number of times the value will be copied + */ +void _set(void *to, uint8_t val, unsigned int len); + +/* + * @brief AES specific doubling function, which utilizes + * the finite field used by AES. + * @return Returns a^2 + * + * @param a IN/OUT -- value to be doubled + */ +uint8_t _double_byte(uint8_t a); + +/* + * @brief Constant-time algorithm to compare if two sequences of bytes are equal + * @return Returns 0 if equal, and non-zero otherwise + * + * @param a IN -- sequence of bytes a + * @param b IN -- sequence of bytes b + * @param size IN -- size of sequences a and b + */ +int _compare(const uint8_t *a, const uint8_t *b, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_UTILS_H__ */ diff --git a/lib/bt/common/tinycrypt/port/esp_tinycrypt_port.c b/lib/bt/common/tinycrypt/port/esp_tinycrypt_port.c new file mode 100644 index 00000000..c4424c56 --- /dev/null +++ b/lib/bt/common/tinycrypt/port/esp_tinycrypt_port.c @@ -0,0 +1,87 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "esp_tinycrypt_port.h" + +#include "esp_crypto_lock.h" +#include "esp_private/esp_crypto_lock_internal.h" + +#if SOC_ECC_SUPPORTED +#include "hal/ecc_hal.h" +#include "hal/ecc_ll.h" +#endif /* SOC_ECC_SUPPORTED */ + + +#if SOC_ECC_SUPPORTED +static void esp_tinycrypt_acquire_ecc_hardware(void) +{ + esp_crypto_ecc_lock_acquire(); + + ECC_RCC_ATOMIC() { + ecc_ll_enable_bus_clock(true); + ecc_ll_power_up(); + ecc_ll_reset_register(); + } +} + +static void esp_tinycrypt_release_ecc_hardware(void) +{ + ECC_RCC_ATOMIC() { + ecc_ll_enable_bus_clock(false); + ecc_ll_power_down(); + } + + esp_crypto_ecc_lock_release(); +} + +int esp_tinycrypt_verify_ecc_point(const uint8_t *pk_x, const uint8_t *pk_y, uint8_t length) +{ + int result; + + esp_tinycrypt_acquire_ecc_hardware(); + + ecc_hal_write_verify_param(pk_x, pk_y, length); + ecc_hal_set_mode(ECC_MODE_VERIFY); + ecc_hal_start_calc(); + while (!ecc_hal_is_calc_finished()); + result = ecc_hal_read_verify_result(); + + esp_tinycrypt_release_ecc_hardware(); + + if (result == 1) { + return 0; + } else { + return -1; + } +} + +int esp_tinycrypt_calc_ecc_mult(const uint8_t *p_x, const uint8_t *p_y, const uint8_t *scalar, + uint8_t *r_x, uint8_t *r_y, uint8_t num_bytes, bool verify_first) +{ + int ret = -1; + ecc_mode_t work_mode = verify_first ? ECC_MODE_VERIFY_THEN_POINT_MUL : ECC_MODE_POINT_MUL; + + esp_tinycrypt_acquire_ecc_hardware(); + + ecc_hal_write_mul_param(scalar, p_x, p_y, num_bytes); + ecc_hal_set_mode(work_mode); + /* + * Enable constant-time point multiplication operations for the ECC hardware accelerator, + * if supported for the given target. This protects the ECC multiplication operation from + * timing attacks. This increases the time taken (by almost 50%) for some point + * multiplication operations performed by the ECC hardware accelerator. + */ + ecc_hal_enable_constant_time_point_mul(true); + ecc_hal_start_calc(); + + while (!ecc_hal_is_calc_finished()); + + ret = ecc_hal_read_mul_result(r_x, r_y, num_bytes); + + esp_tinycrypt_release_ecc_hardware(); + + return ret; +} +#endif /* SOC_ECC_SUPPORTED */ diff --git a/lib/bt/common/tinycrypt/port/esp_tinycrypt_port.h b/lib/bt/common/tinycrypt/port/esp_tinycrypt_port.h new file mode 100644 index 00000000..4fdf82c2 --- /dev/null +++ b/lib/bt/common/tinycrypt/port/esp_tinycrypt_port.h @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "soc/soc_caps.h" + +#if SOC_ECC_SUPPORTED +int esp_tinycrypt_verify_ecc_point(const uint8_t *pk_x, const uint8_t *pk_y, uint8_t length); + +int esp_tinycrypt_calc_ecc_mult(const uint8_t *p_x, const uint8_t *p_y, const uint8_t *scalar, + uint8_t *r_x, uint8_t *r_y, uint8_t num_bytes, bool verify_first); +#endif /* SOC_ECC_SUPPORTED */ diff --git a/lib/bt/common/tinycrypt/src/aes_decrypt.c b/lib/bt/common/tinycrypt/src/aes_decrypt.c new file mode 100644 index 00000000..7da52349 --- /dev/null +++ b/lib/bt/common/tinycrypt/src/aes_decrypt.c @@ -0,0 +1,170 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* aes_decrypt.c - TinyCrypt implementation of AES decryption procedure */ + +#include +#include +#include + +static const uint8_t inv_sbox[256] = { + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, + 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, + 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, + 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, + 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, + 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, + 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, + 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, + 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, + 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, + 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, + 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, + 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, + 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0c, 0x7d +}; + +int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k) +{ + return tc_aes128_set_encrypt_key(s, k); +} + +#define mult8(a)(_double_byte(_double_byte(_double_byte(a)))) +#define mult9(a)(mult8(a)^(a)) +#define multb(a)(mult8(a)^_double_byte(a)^(a)) +#define multd(a)(mult8(a)^_double_byte(_double_byte(a))^(a)) +#define multe(a)(mult8(a)^_double_byte(_double_byte(a))^_double_byte(a)) + +static inline void mult_row_column(uint8_t *out, const uint8_t *in) +{ + out[0] = multe(in[0]) ^ multb(in[1]) ^ multd(in[2]) ^ mult9(in[3]); + out[1] = mult9(in[0]) ^ multe(in[1]) ^ multb(in[2]) ^ multd(in[3]); + out[2] = multd(in[0]) ^ mult9(in[1]) ^ multe(in[2]) ^ multb(in[3]); + out[3] = multb(in[0]) ^ multd(in[1]) ^ mult9(in[2]) ^ multe(in[3]); +} + +static inline void inv_mix_columns(uint8_t *s) +{ + uint8_t t[Nb*Nk]; + + mult_row_column(t, s); + mult_row_column(&t[Nb], s+Nb); + mult_row_column(&t[2*Nb], s+(2*Nb)); + mult_row_column(&t[3*Nb], s+(3*Nb)); + (void)_copy(s, sizeof(t), t, sizeof(t)); +} + +static inline void add_round_key(uint8_t *s, const unsigned int *k) +{ + s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16); + s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]); + s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16); + s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]); + s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16); + s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]); + s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16); + s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]); +} + +static inline void inv_sub_bytes(uint8_t *s) +{ + unsigned int i; + + for (i = 0; i < (Nb*Nk); ++i) { + s[i] = inv_sbox[s[i]]; + } +} + +/* + * This inv_shift_rows also implements the matrix flip required for + * inv_mix_columns, but performs it here to reduce the number of memory + * operations. + */ +static inline void inv_shift_rows(uint8_t *s) +{ + uint8_t t[Nb*Nk]; + + t[0] = s[0]; t[1] = s[13]; t[2] = s[10]; t[3] = s[7]; + t[4] = s[4]; t[5] = s[1]; t[6] = s[14]; t[7] = s[11]; + t[8] = s[8]; t[9] = s[5]; t[10] = s[2]; t[11] = s[15]; + t[12] = s[12]; t[13] = s[9]; t[14] = s[6]; t[15] = s[3]; + (void)_copy(s, sizeof(t), t, sizeof(t)); +} + +int tc_aes_decrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s) +{ + uint8_t state[Nk*Nb]; + unsigned int i; + + if (out == (uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } else if (in == (const uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } else if (s == (TCAesKeySched_t) 0) { + return TC_CRYPTO_FAIL; + } + + (void)_copy(state, sizeof(state), in, sizeof(state)); + + add_round_key(state, s->words + Nb*Nr); + + for (i = Nr - 1; i > 0; --i) { + inv_shift_rows(state); + inv_sub_bytes(state); + add_round_key(state, s->words + Nb*i); + inv_mix_columns(state); + } + + inv_shift_rows(state); + inv_sub_bytes(state); + add_round_key(state, s->words); + + (void)_copy(out, sizeof(state), state, sizeof(state)); + + /*zeroing out the state buffer */ + _set(state, TC_ZERO_BYTE, sizeof(state)); + + + return TC_CRYPTO_SUCCESS; +} diff --git a/lib/bt/common/tinycrypt/src/aes_encrypt.c b/lib/bt/common/tinycrypt/src/aes_encrypt.c new file mode 100644 index 00000000..7095695d --- /dev/null +++ b/lib/bt/common/tinycrypt/src/aes_encrypt.c @@ -0,0 +1,197 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* aes_encrypt.c - TinyCrypt implementation of AES encryption procedure */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +static const uint8_t sbox[256] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, + 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, + 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, + 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, + 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, + 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, + 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, + 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, + 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, + 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, + 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, + 0xb0, 0x54, 0xbb, 0x16 +}; + +static inline unsigned int rotword(unsigned int a) +{ + return (((a) >> 24)|((a) << 8)); +} + +#define subbyte(a, o)(sbox[((a) >> (o))&0xff] << (o)) +#define subword(a)(subbyte(a, 24)|subbyte(a, 16)|subbyte(a, 8)|subbyte(a, 0)) + +int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k) +{ + const unsigned int rconst[11] = { + 0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, + 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000 + }; + unsigned int i; + unsigned int t; + + if (s == (TCAesKeySched_t) 0) { + return TC_CRYPTO_FAIL; + } else if (k == (const uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } + + for (i = 0; i < Nk; ++i) { + s->words[i] = (k[Nb*i]<<24) | (k[Nb*i+1]<<16) | + (k[Nb*i+2]<<8) | (k[Nb*i+3]); + } + + for (; i < (Nb * (Nr + 1)); ++i) { + t = s->words[i-1]; + if ((i % Nk) == 0) { + t = subword(rotword(t)) ^ rconst[i/Nk]; + } + s->words[i] = s->words[i-Nk] ^ t; + } + + return TC_CRYPTO_SUCCESS; +} + +static inline void add_round_key(uint8_t *s, const unsigned int *k) +{ + s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16); + s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]); + s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16); + s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]); + s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16); + s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]); + s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16); + s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]); +} + +static inline void sub_bytes(uint8_t *s) +{ + unsigned int i; + + for (i = 0; i < (Nb * Nk); ++i) { + s[i] = sbox[s[i]]; + } +} + +#define triple(a)(_double_byte(a)^(a)) + +static inline void mult_row_column(uint8_t *out, const uint8_t *in) +{ + out[0] = _double_byte(in[0]) ^ triple(in[1]) ^ in[2] ^ in[3]; + out[1] = in[0] ^ _double_byte(in[1]) ^ triple(in[2]) ^ in[3]; + out[2] = in[0] ^ in[1] ^ _double_byte(in[2]) ^ triple(in[3]); + out[3] = triple(in[0]) ^ in[1] ^ in[2] ^ _double_byte(in[3]); +} + +static inline void mix_columns(uint8_t *s) +{ + uint8_t t[Nb*Nk]; + + mult_row_column(t, s); + mult_row_column(&t[Nb], s+Nb); + mult_row_column(&t[2 * Nb], s + (2 * Nb)); + mult_row_column(&t[3 * Nb], s + (3 * Nb)); + (void) _copy(s, sizeof(t), t, sizeof(t)); +} + +/* + * This shift_rows also implements the matrix flip required for mix_columns, but + * performs it here to reduce the number of memory operations. + */ +static inline void shift_rows(uint8_t *s) +{ + uint8_t t[Nb * Nk]; + + t[0] = s[0]; t[1] = s[5]; t[2] = s[10]; t[3] = s[15]; + t[4] = s[4]; t[5] = s[9]; t[6] = s[14]; t[7] = s[3]; + t[8] = s[8]; t[9] = s[13]; t[10] = s[2]; t[11] = s[7]; + t[12] = s[12]; t[13] = s[1]; t[14] = s[6]; t[15] = s[11]; + (void) _copy(s, sizeof(t), t, sizeof(t)); +} + +int tc_aes_encrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s) +{ + uint8_t state[Nk*Nb]; + unsigned int i; + + if (out == (uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } else if (in == (const uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } else if (s == (TCAesKeySched_t) 0) { + return TC_CRYPTO_FAIL; + } + + (void)_copy(state, sizeof(state), in, sizeof(state)); + add_round_key(state, s->words); + + for (i = 0; i < (Nr - 1); ++i) { + sub_bytes(state); + shift_rows(state); + mix_columns(state); + add_round_key(state, s->words + Nb*(i+1)); + } + + sub_bytes(state); + shift_rows(state); + add_round_key(state, s->words + Nb*(i+1)); + + (void)_copy(out, sizeof(state), state, sizeof(state)); + + /* zeroing out the state buffer */ + _set(state, TC_ZERO_BYTE, sizeof(state)); + + return TC_CRYPTO_SUCCESS; +} diff --git a/lib/bt/common/tinycrypt/src/cbc_mode.c b/lib/bt/common/tinycrypt/src/cbc_mode.c new file mode 100644 index 00000000..86a00c8d --- /dev/null +++ b/lib/bt/common/tinycrypt/src/cbc_mode.c @@ -0,0 +1,118 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, + unsigned int inlen, const uint8_t *iv, + const TCAesKeySched_t sched) +{ + + uint8_t buffer[TC_AES_BLOCK_SIZE]; + unsigned int n, m; + + /* input sanity check: */ + if (out == (uint8_t *) 0 || + in == (const uint8_t *) 0 || + sched == (TCAesKeySched_t) 0 || + inlen == 0 || + outlen == 0 || + (inlen % TC_AES_BLOCK_SIZE) != 0 || + (outlen % TC_AES_BLOCK_SIZE) != 0 || + outlen != inlen + TC_AES_BLOCK_SIZE) { + return TC_CRYPTO_FAIL; + } + + /* copy iv to the buffer */ + (void)_copy(buffer, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE); + /* copy iv to the output buffer */ + (void)_copy(out, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE); + out += TC_AES_BLOCK_SIZE; + + for (n = m = 0; n < inlen; ++n) { + buffer[m++] ^= *in++; + if (m == TC_AES_BLOCK_SIZE) { + (void)tc_aes_encrypt(buffer, buffer, sched); + (void)_copy(out, TC_AES_BLOCK_SIZE, + buffer, TC_AES_BLOCK_SIZE); + out += TC_AES_BLOCK_SIZE; + m = 0; + } + } + + return TC_CRYPTO_SUCCESS; +} + +int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, + unsigned int inlen, const uint8_t *iv, + const TCAesKeySched_t sched) +{ + + uint8_t buffer[TC_AES_BLOCK_SIZE]; + const uint8_t *p; + unsigned int n, m; + + /* sanity check the inputs */ + if (out == (uint8_t *) 0 || + in == (const uint8_t *) 0 || + sched == (TCAesKeySched_t) 0 || + inlen == 0 || + outlen == 0 || + (inlen % TC_AES_BLOCK_SIZE) != 0 || + (outlen % TC_AES_BLOCK_SIZE) != 0 || + outlen != inlen - TC_AES_BLOCK_SIZE) { + return TC_CRYPTO_FAIL; + } + + /* + * Note that in == iv + ciphertext, i.e. the iv and the ciphertext are + * contiguous. This allows for a very efficient decryption algorithm + * that would not otherwise be possible. + */ + p = iv; + for (n = m = 0; n < inlen; ++n) { + if ((n % TC_AES_BLOCK_SIZE) == 0) { + (void)tc_aes_decrypt(buffer, in, sched); + in += TC_AES_BLOCK_SIZE; + m = 0; + } + *out++ = buffer[m++] ^ *p++; + } + + return TC_CRYPTO_SUCCESS; +} diff --git a/lib/bt/common/tinycrypt/src/ccm_mode.c b/lib/bt/common/tinycrypt/src/ccm_mode.c new file mode 100644 index 00000000..4017d249 --- /dev/null +++ b/lib/bt/common/tinycrypt/src/ccm_mode.c @@ -0,0 +1,272 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* ccm_mode.c - TinyCrypt implementation of CCM mode */ + +#include +#include +#include + +#include + +int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce, + unsigned int nlen, unsigned int mlen) +{ + + /* input sanity check: */ + if (c == (TCCcmMode_t) 0 || + sched == (TCAesKeySched_t) 0 || + nonce == (uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } else if (nlen != 13) { + return TC_CRYPTO_FAIL; /* The allowed nonce size is: 13. See documentation.*/ + } else if ((mlen < 4) || (mlen > 16) || (mlen & 1)) { + return TC_CRYPTO_FAIL; /* The allowed mac sizes are: 4, 6, 8, 10, 12, 14, 16.*/ + } + + c->mlen = mlen; + c->sched = sched; + c->nonce = nonce; + + return TC_CRYPTO_SUCCESS; +} + +/** + * Variation of CBC-MAC mode used in CCM. + */ +static void ccm_cbc_mac(uint8_t *T, const uint8_t *data, unsigned int dlen, + unsigned int flag, TCAesKeySched_t sched) +{ + + unsigned int i; + + if (flag > 0) { + T[0] ^= (uint8_t)(dlen >> 8); + T[1] ^= (uint8_t)(dlen); + dlen += 2; i = 2; + } else { + i = 0; + } + + while (i < dlen) { + T[i++ % (Nb * Nk)] ^= *data++; + if (((i % (Nb * Nk)) == 0) || dlen == i) { + (void) tc_aes_encrypt(T, T, sched); + } + } +} + +/** + * Variation of CTR mode used in CCM. + * The CTR mode used by CCM is slightly different than the conventional CTR + * mode (the counter is increased before encryption, instead of after + * encryption). Besides, it is assumed that the counter is stored in the last + * 2 bytes of the nonce. + */ +static int ccm_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, + unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched) +{ + + uint8_t buffer[TC_AES_BLOCK_SIZE]; + uint8_t nonce[TC_AES_BLOCK_SIZE]; + uint16_t block_num; + unsigned int i; + + /* input sanity check: */ + if (out == (uint8_t *) 0 || + in == (uint8_t *) 0 || + ctr == (uint8_t *) 0 || + sched == (TCAesKeySched_t) 0 || + inlen == 0 || + outlen == 0 || + outlen != inlen) { + return TC_CRYPTO_FAIL; + } + + /* copy the counter to the nonce */ + (void) _copy(nonce, sizeof(nonce), ctr, sizeof(nonce)); + + /* select the last 2 bytes of the nonce to be incremented */ + block_num = (uint16_t) ((nonce[14] << 8)|(nonce[15])); + for (i = 0; i < inlen; ++i) { + if ((i % (TC_AES_BLOCK_SIZE)) == 0) { + block_num++; + nonce[14] = (uint8_t)(block_num >> 8); + nonce[15] = (uint8_t)(block_num); + if (!tc_aes_encrypt(buffer, nonce, sched)) { + return TC_CRYPTO_FAIL; + } + } + /* update the output */ + *out++ = buffer[i % (TC_AES_BLOCK_SIZE)] ^ *in++; + } + + /* update the counter */ + ctr[14] = nonce[14]; ctr[15] = nonce[15]; + + return TC_CRYPTO_SUCCESS; +} + +int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen, + const uint8_t *associated_data, + unsigned int alen, const uint8_t *payload, + unsigned int plen, TCCcmMode_t c) +{ + + /* input sanity check: */ + if ((out == (uint8_t *) 0) || + (c == (TCCcmMode_t) 0) || + ((plen > 0) && (payload == (uint8_t *) 0)) || + ((alen > 0) && (associated_data == (uint8_t *) 0)) || + (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */ + (plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */ + (olen < (plen + c->mlen))) { /* invalid output buffer size */ + return TC_CRYPTO_FAIL; + } + + uint8_t b[Nb * Nk]; + uint8_t tag[Nb * Nk]; + unsigned int i; + + /* GENERATING THE AUTHENTICATION TAG: */ + + /* formatting the sequence b for authentication: */ + b[0] = ((alen > 0) ? 0x40:0) | (((c->mlen - 2) / 2 << 3)) | (1); + for (i = 1; i <= 13; ++i) { + b[i] = c->nonce[i - 1]; + } + b[14] = (uint8_t)(plen >> 8); + b[15] = (uint8_t)(plen); + + /* computing the authentication tag using cbc-mac: */ + (void) tc_aes_encrypt(tag, b, c->sched); + if (alen > 0) { + ccm_cbc_mac(tag, associated_data, alen, 1, c->sched); + } + if (plen > 0) { + ccm_cbc_mac(tag, payload, plen, 0, c->sched); + } + + /* ENCRYPTION: */ + + /* formatting the sequence b for encryption: */ + b[0] = 1; /* q - 1 = 2 - 1 = 1 */ + b[14] = b[15] = TC_ZERO_BYTE; + + /* encrypting payload using ctr mode: */ + ccm_ctr_mode(out, plen, payload, plen, b, c->sched); + + b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter for ctr_mode (0):*/ + + /* encrypting b and adding the tag to the output: */ + (void) tc_aes_encrypt(b, b, c->sched); + out += plen; + for (i = 0; i < c->mlen; ++i) { + *out++ = tag[i] ^ b[i]; + } + + return TC_CRYPTO_SUCCESS; +} + +int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen, + const uint8_t *associated_data, + unsigned int alen, const uint8_t *payload, + unsigned int plen, TCCcmMode_t c) +{ + + /* input sanity check: */ + if ((out == (uint8_t *) 0) || + (c == (TCCcmMode_t) 0) || + ((plen > 0) && (payload == (uint8_t *) 0)) || + ((alen > 0) && (associated_data == (uint8_t *) 0)) || + (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */ + (plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */ + (olen < plen - c->mlen)) { /* invalid output buffer size */ + return TC_CRYPTO_FAIL; + } + + uint8_t b[Nb * Nk]; + uint8_t tag[Nb * Nk]; + unsigned int i; + + /* DECRYPTION: */ + + /* formatting the sequence b for decryption: */ + b[0] = 1; /* q - 1 = 2 - 1 = 1 */ + for (i = 1; i < 14; ++i) { + b[i] = c->nonce[i - 1]; + } + b[14] = b[15] = TC_ZERO_BYTE; /* initial counter value is 0 */ + + /* decrypting payload using ctr mode: */ + ccm_ctr_mode(out, plen - c->mlen, payload, plen - c->mlen, b, c->sched); + + b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter value (0) */ + + /* encrypting b and restoring the tag from input: */ + (void) tc_aes_encrypt(b, b, c->sched); + for (i = 0; i < c->mlen; ++i) { + tag[i] = *(payload + plen - c->mlen + i) ^ b[i]; + } + + /* VERIFYING THE AUTHENTICATION TAG: */ + + /* formatting the sequence b for authentication: */ + b[0] = ((alen > 0) ? 0x40:0)|(((c->mlen - 2) / 2 << 3)) | (1); + for (i = 1; i < 14; ++i) { + b[i] = c->nonce[i - 1]; + } + b[14] = (uint8_t)((plen - c->mlen) >> 8); + b[15] = (uint8_t)(plen - c->mlen); + + /* computing the authentication tag using cbc-mac: */ + (void) tc_aes_encrypt(b, b, c->sched); + if (alen > 0) { + ccm_cbc_mac(b, associated_data, alen, 1, c->sched); + } + if (plen > 0) { + ccm_cbc_mac(b, out, plen - c->mlen, 0, c->sched); + } + + /* comparing the received tag and the computed one: */ + if (_compare(b, tag, c->mlen) == 0) { + return TC_CRYPTO_SUCCESS; + } else { + /* erase the decrypted buffer in case of mac validation failure: */ + _set(out, 0, plen - c->mlen); + return TC_CRYPTO_FAIL; + } +} diff --git a/lib/bt/common/tinycrypt/src/cmac_mode.c b/lib/bt/common/tinycrypt/src/cmac_mode.c new file mode 100644 index 00000000..c3e2c4ee --- /dev/null +++ b/lib/bt/common/tinycrypt/src/cmac_mode.c @@ -0,0 +1,258 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +/* max number of calls until change the key (2^48).*/ +const static uint64_t MAX_CALLS = ((uint64_t)1 << 48); + +/* + * gf_wrap -- In our implementation, GF(2^128) is represented as a 16 byte + * array with byte 0 the most significant and byte 15 the least significant. + * High bit carry reduction is based on the primitive polynomial + * + * X^128 + X^7 + X^2 + X + 1, + * + * which leads to the reduction formula X^128 = X^7 + X^2 + X + 1. Indeed, + * since 0 = (X^128 + X^7 + X^2 + 1) mod (X^128 + X^7 + X^2 + X + 1) and since + * addition of polynomials with coefficients in Z/Z(2) is just XOR, we can + * add X^128 to both sides to get + * + * X^128 = (X^7 + X^2 + X + 1) mod (X^128 + X^7 + X^2 + X + 1) + * + * and the coefficients of the polynomial on the right hand side form the + * string 1000 0111 = 0x87, which is the value of gf_wrap. + * + * This gets used in the following way. Doubling in GF(2^128) is just a left + * shift by 1 bit, except when the most significant bit is 1. In the latter + * case, the relation X^128 = X^7 + X^2 + X + 1 says that the high order bit + * that overflows beyond 128 bits can be replaced by addition of + * X^7 + X^2 + X + 1 <--> 0x87 to the low order 128 bits. Since addition + * in GF(2^128) is represented by XOR, we therefore only have to XOR 0x87 + * into the low order byte after a left shift when the starting high order + * bit is 1. + */ +const unsigned char gf_wrap = 0x87; + +/* + * assumes: out != NULL and points to a GF(2^n) value to receive the + * doubled value; + * in != NULL and points to a 16 byte GF(2^n) value + * to double; + * the in and out buffers do not overlap. + * effects: doubles the GF(2^n) value pointed to by "in" and places + * the result in the GF(2^n) value pointed to by "out." + */ +void gf_double(uint8_t *out, uint8_t *in) +{ + + /* start with low order byte */ + uint8_t *x = in + (TC_AES_BLOCK_SIZE - 1); + + /* if msb == 1, we need to add the gf_wrap value, otherwise add 0 */ + uint8_t carry = (in[0] >> 7) ? gf_wrap : 0; + + out += (TC_AES_BLOCK_SIZE - 1); + for (;;) { + *out-- = (*x << 1) ^ carry; + if (x == in) { + break; + } + carry = *x-- >> 7; + } +} + +int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, TCAesKeySched_t sched) +{ + + /* input sanity check: */ + if (s == (TCCmacState_t) 0 || + key == (const uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } + + /* put s into a known state */ + _set(s, 0, sizeof(*s)); + s->sched = sched; + + /* configure the encryption key used by the underlying block cipher */ + tc_aes128_set_encrypt_key(s->sched, key); + + /* compute s->K1 and s->K2 from s->iv using s->keyid */ + _set(s->iv, 0, TC_AES_BLOCK_SIZE); + tc_aes_encrypt(s->iv, s->iv, s->sched); + gf_double (s->K1, s->iv); + gf_double (s->K2, s->K1); + + /* reset s->iv to 0 in case someone wants to compute now */ + tc_cmac_init(s); + + return TC_CRYPTO_SUCCESS; +} + +int tc_cmac_erase(TCCmacState_t s) +{ + if (s == (TCCmacState_t) 0) { + return TC_CRYPTO_FAIL; + } + + /* destroy the current state */ + _set(s, 0, sizeof(*s)); + + return TC_CRYPTO_SUCCESS; +} + +int tc_cmac_init(TCCmacState_t s) +{ + /* input sanity check: */ + if (s == (TCCmacState_t) 0) { + return TC_CRYPTO_FAIL; + } + + /* CMAC starts with an all zero initialization vector */ + _set(s->iv, 0, TC_AES_BLOCK_SIZE); + + /* and the leftover buffer is empty */ + _set(s->leftover, 0, TC_AES_BLOCK_SIZE); + s->leftover_offset = 0; + + /* Set countdown to max number of calls allowed before re-keying: */ + s->countdown = MAX_CALLS; + + return TC_CRYPTO_SUCCESS; +} + +int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t data_length) +{ + unsigned int i; + + /* input sanity check: */ + if (s == (TCCmacState_t) 0) { + return TC_CRYPTO_FAIL; + } + if (data_length == 0) { + return TC_CRYPTO_SUCCESS; + } + if (data == (const uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } + + if (s->countdown == 0) { + return TC_CRYPTO_FAIL; + } + + s->countdown--; + + if (s->leftover_offset > 0) { + /* last data added to s didn't end on a TC_AES_BLOCK_SIZE byte boundary */ + size_t remaining_space = TC_AES_BLOCK_SIZE - s->leftover_offset; + + if (data_length < remaining_space) { + /* still not enough data to encrypt this time either */ + _copy(&s->leftover[s->leftover_offset], data_length, data, data_length); + s->leftover_offset += data_length; + return TC_CRYPTO_SUCCESS; + } + /* leftover block is now full; encrypt it first */ + _copy(&s->leftover[s->leftover_offset], + remaining_space, + data, + remaining_space); + data_length -= remaining_space; + data += remaining_space; + s->leftover_offset = 0; + + for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) { + s->iv[i] ^= s->leftover[i]; + } + tc_aes_encrypt(s->iv, s->iv, s->sched); + } + + /* CBC encrypt each (except the last) of the data blocks */ + while (data_length > TC_AES_BLOCK_SIZE) { + for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) { + s->iv[i] ^= data[i]; + } + tc_aes_encrypt(s->iv, s->iv, s->sched); + data += TC_AES_BLOCK_SIZE; + data_length -= TC_AES_BLOCK_SIZE; + } + + if (data_length > 0) { + /* save leftover data for next time */ + _copy(s->leftover, data_length, data, data_length); + s->leftover_offset = data_length; + } + + return TC_CRYPTO_SUCCESS; +} + +int tc_cmac_final(uint8_t *tag, TCCmacState_t s) +{ + uint8_t *k; + unsigned int i; + + /* input sanity check: */ + if (tag == (uint8_t *) 0 || + s == (TCCmacState_t) 0) { + return TC_CRYPTO_FAIL; + } + + if (s->leftover_offset == TC_AES_BLOCK_SIZE) { + /* the last message block is a full-sized block */ + k = (uint8_t *) s->K1; + } else { + /* the final message block is not a full-sized block */ + size_t remaining = TC_AES_BLOCK_SIZE - s->leftover_offset; + + _set(&s->leftover[s->leftover_offset], 0, remaining); + s->leftover[s->leftover_offset] = TC_CMAC_PADDING; + k = (uint8_t *) s->K2; + } + for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) { + s->iv[i] ^= s->leftover[i] ^ k[i]; + } + + tc_aes_encrypt(tag, s->iv, s->sched); + + /* erasing state: */ + tc_cmac_erase(s); + + return TC_CRYPTO_SUCCESS; +} diff --git a/lib/bt/common/tinycrypt/src/ctr_mode.c b/lib/bt/common/tinycrypt/src/ctr_mode.c new file mode 100644 index 00000000..96d03a5b --- /dev/null +++ b/lib/bt/common/tinycrypt/src/ctr_mode.c @@ -0,0 +1,91 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* ctr_mode.c - TinyCrypt CTR mode implementation */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, + unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched) +{ + + uint8_t buffer[TC_AES_BLOCK_SIZE]; + uint8_t nonce[TC_AES_BLOCK_SIZE]; + unsigned int block_num; + unsigned int i; + + /* input sanity check: */ + if (out == (uint8_t *) 0 || + in == (uint8_t *) 0 || + ctr == (uint8_t *) 0 || + sched == (TCAesKeySched_t) 0 || + inlen == 0 || + outlen == 0 || + outlen != inlen) { + return TC_CRYPTO_FAIL; + } + + /* copy the ctr to the nonce */ + (void)_copy(nonce, sizeof(nonce), ctr, sizeof(nonce)); + + /* select the last 4 bytes of the nonce to be incremented */ + block_num = (nonce[12] << 24) | (nonce[13] << 16) | + (nonce[14] << 8) | (nonce[15]); + for (i = 0; i < inlen; ++i) { + if ((i % (TC_AES_BLOCK_SIZE)) == 0) { + /* encrypt data using the current nonce */ + if (tc_aes_encrypt(buffer, nonce, sched)) { + block_num++; + nonce[12] = (uint8_t)(block_num >> 24); + nonce[13] = (uint8_t)(block_num >> 16); + nonce[14] = (uint8_t)(block_num >> 8); + nonce[15] = (uint8_t)(block_num); + } else { + return TC_CRYPTO_FAIL; + } + } + /* update the output */ + *out++ = buffer[i%(TC_AES_BLOCK_SIZE)] ^ *in++; + } + + /* update the counter */ + ctr[12] = nonce[12]; ctr[13] = nonce[13]; + ctr[14] = nonce[14]; ctr[15] = nonce[15]; + + return TC_CRYPTO_SUCCESS; +} diff --git a/lib/bt/common/tinycrypt/src/ctr_prng.c b/lib/bt/common/tinycrypt/src/ctr_prng.c new file mode 100644 index 00000000..009c7de2 --- /dev/null +++ b/lib/bt/common/tinycrypt/src/ctr_prng.c @@ -0,0 +1,283 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (c) 2016, Chris Morrison + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +/* + * This PRNG is based on the CTR_DRBG described in Recommendation for Random + * Number Generation Using Deterministic Random Bit Generators, + * NIST SP 800-90A Rev. 1. + * + * Annotations to particular steps (e.g. 10.2.1.2 Step 1) refer to the steps + * described in that document. + * + */ + +/** + * @brief Array incrementer + * Treats the supplied array as one contiguous number (MSB in arr[0]), and + * increments it by one + * @return none + * @param arr IN/OUT -- array to be incremented + * @param len IN -- size of arr in bytes + */ +static void arrInc(uint8_t arr[], unsigned int len) +{ + unsigned int i; + if (0 != arr) { + for (i = len; i > 0U; i--) { + if (++arr[i-1] != 0U) { + break; + } + } + } +} + +/** + * @brief CTR PRNG update + * Updates the internal state of supplied the CTR PRNG context + * increments it by one + * @return none + * @note Assumes: providedData is (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes long + * @param ctx IN/OUT -- CTR PRNG state + * @param providedData IN -- data used when updating the internal state + */ +static void tc_ctr_prng_update(TCCtrPrng_t * const ctx, uint8_t const * const providedData) +{ + if (0 != ctx) { + /* 10.2.1.2 step 1 */ + uint8_t temp[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE]; + unsigned int len = 0U; + + /* 10.2.1.2 step 2 */ + while (len < sizeof temp) { + unsigned int blocklen = sizeof(temp) - len; + uint8_t output_block[TC_AES_BLOCK_SIZE]; + + /* 10.2.1.2 step 2.1 */ + arrInc(ctx->V, sizeof ctx->V); + + /* 10.2.1.2 step 2.2 */ + if (blocklen > TC_AES_BLOCK_SIZE) { + blocklen = TC_AES_BLOCK_SIZE; + } + (void)tc_aes_encrypt(output_block, ctx->V, &ctx->key); + + /* 10.2.1.2 step 2.3/step 3 */ + memcpy(&(temp[len]), output_block, blocklen); + + len += blocklen; + } + + /* 10.2.1.2 step 4 */ + if (0 != providedData) { + unsigned int i; + for (i = 0U; i < sizeof temp; i++) { + temp[i] ^= providedData[i]; + } + } + + /* 10.2.1.2 step 5 */ + (void)tc_aes128_set_encrypt_key(&ctx->key, temp); + + /* 10.2.1.2 step 6 */ + memcpy(ctx->V, &(temp[TC_AES_KEY_SIZE]), TC_AES_BLOCK_SIZE); + } +} + +int tc_ctr_prng_init(TCCtrPrng_t * const ctx, + uint8_t const * const entropy, + unsigned int entropyLen, + uint8_t const * const personalization, + unsigned int pLen) +{ + int result = TC_CRYPTO_FAIL; + unsigned int i; + uint8_t personalization_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U}; + uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE]; + uint8_t zeroArr[TC_AES_BLOCK_SIZE] = {0U}; + + if (0 != personalization) { + /* 10.2.1.3.1 step 1 */ + unsigned int len = pLen; + if (len > sizeof personalization_buf) { + len = sizeof personalization_buf; + } + + /* 10.2.1.3.1 step 2 */ + memcpy(personalization_buf, personalization, len); + } + + if ((0 != ctx) && (0 != entropy) && (entropyLen >= sizeof seed_material)) { + /* 10.2.1.3.1 step 3 */ + memcpy(seed_material, entropy, sizeof seed_material); + for (i = 0U; i < sizeof seed_material; i++) { + seed_material[i] ^= personalization_buf[i]; + } + + /* 10.2.1.3.1 step 4 */ + (void)tc_aes128_set_encrypt_key(&ctx->key, zeroArr); + + /* 10.2.1.3.1 step 5 */ + memset(ctx->V, 0x00, sizeof ctx->V); + + /* 10.2.1.3.1 step 6 */ + tc_ctr_prng_update(ctx, seed_material); + + /* 10.2.1.3.1 step 7 */ + ctx->reseedCount = 1U; + + result = TC_CRYPTO_SUCCESS; + } + return result; +} + +int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx, + uint8_t const * const entropy, + unsigned int entropyLen, + uint8_t const * const additional_input, + unsigned int additionallen) +{ + unsigned int i; + int result = TC_CRYPTO_FAIL; + uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U}; + uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE]; + + if (0 != additional_input) { + /* 10.2.1.4.1 step 1 */ + unsigned int len = additionallen; + if (len > sizeof additional_input_buf) { + len = sizeof additional_input_buf; + } + + /* 10.2.1.4.1 step 2 */ + memcpy(additional_input_buf, additional_input, len); + } + + unsigned int seedlen = (unsigned int)TC_AES_KEY_SIZE + (unsigned int)TC_AES_BLOCK_SIZE; + if ((0 != ctx) && (entropyLen >= seedlen)) { + /* 10.2.1.4.1 step 3 */ + memcpy(seed_material, entropy, sizeof seed_material); + for (i = 0U; i < sizeof seed_material; i++) { + seed_material[i] ^= additional_input_buf[i]; + } + + /* 10.2.1.4.1 step 4 */ + tc_ctr_prng_update(ctx, seed_material); + + /* 10.2.1.4.1 step 5 */ + ctx->reseedCount = 1U; + + result = TC_CRYPTO_SUCCESS; + } + return result; +} + +int tc_ctr_prng_generate(TCCtrPrng_t * const ctx, + uint8_t const * const additional_input, + unsigned int additionallen, + uint8_t * const out, + unsigned int outlen) +{ + /* 2^48 - see section 10.2.1 */ + static const uint64_t MAX_REQS_BEFORE_RESEED = 0x1000000000000ULL; + + /* 2^19 bits - see section 10.2.1 */ + static const unsigned int MAX_BYTES_PER_REQ = 65536U; + + unsigned int result = TC_CRYPTO_FAIL; + + if ((0 != ctx) && (0 != out) && (outlen < MAX_BYTES_PER_REQ)) { + /* 10.2.1.5.1 step 1 */ + if (ctx->reseedCount > MAX_REQS_BEFORE_RESEED) { + result = TC_CTR_PRNG_RESEED_REQ; + } else { + uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U}; + if (0 != additional_input) { + /* 10.2.1.5.1 step 2 */ + unsigned int len = additionallen; + if (len > sizeof additional_input_buf) { + len = sizeof additional_input_buf; + } + memcpy(additional_input_buf, additional_input, len); + tc_ctr_prng_update(ctx, additional_input_buf); + } + + /* 10.2.1.5.1 step 3 - implicit */ + + /* 10.2.1.5.1 step 4 */ + unsigned int len = 0U; + while (len < outlen) { + unsigned int blocklen = outlen - len; + uint8_t output_block[TC_AES_BLOCK_SIZE]; + + /* 10.2.1.5.1 step 4.1 */ + arrInc(ctx->V, sizeof ctx->V); + + /* 10.2.1.5.1 step 4.2 */ + (void)tc_aes_encrypt(output_block, ctx->V, &ctx->key); + + /* 10.2.1.5.1 step 4.3/step 5 */ + if (blocklen > TC_AES_BLOCK_SIZE) { + blocklen = TC_AES_BLOCK_SIZE; + } + memcpy(&(out[len]), output_block, blocklen); + + len += blocklen; + } + + /* 10.2.1.5.1 step 6 */ + tc_ctr_prng_update(ctx, additional_input_buf); + + /* 10.2.1.5.1 step 7 */ + ctx->reseedCount++; + + /* 10.2.1.5.1 step 8 */ + result = TC_CRYPTO_SUCCESS; + } + } + + return result; +} + +void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx) +{ + if (0 != ctx) { + memset(ctx->key.words, 0x00, sizeof ctx->key.words); + memset(ctx->V, 0x00, sizeof ctx->V); + ctx->reseedCount = 0U; + } +} diff --git a/lib/bt/common/tinycrypt/src/ecc.c b/lib/bt/common/tinycrypt/src/ecc.c new file mode 100644 index 00000000..1027c9a2 --- /dev/null +++ b/lib/bt/common/tinycrypt/src/ecc.c @@ -0,0 +1,972 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "esp_tinycrypt_port.h" + +/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform + * has access to enough entropy in order to feed the PRNG regularly. */ +#if default_RNG_defined +static uECC_RNG_Function g_rng_function = &default_CSPRNG; +#else +static uECC_RNG_Function g_rng_function = 0; +#endif + +void uECC_set_rng(uECC_RNG_Function rng_function) +{ + g_rng_function = rng_function; +} + +uECC_RNG_Function uECC_get_rng(void) +{ + return g_rng_function; +} + +int uECC_curve_private_key_size(uECC_Curve curve) +{ + return BITS_TO_BYTES(curve->num_n_bits); +} + +int uECC_curve_public_key_size(uECC_Curve curve) +{ + return 2 * curve->num_bytes; +} + +void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) +{ + wordcount_t i; + for (i = 0; i < num_words; ++i) { + vli[i] = 0; + } +} + +uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words) +{ + uECC_word_t bits = 0; + wordcount_t i; + for (i = 0; i < num_words; ++i) { + bits |= vli[i]; + } + return (bits == 0); +} + +uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit) +{ + return (vli[bit >> uECC_WORD_BITS_SHIFT] & + ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK))); +} + +/* Counts the number of words in vli. */ +static wordcount_t vli_numDigits(const uECC_word_t *vli, + const wordcount_t max_words) +{ + + wordcount_t i; + /* Search from the end until we find a non-zero digit. We do it in reverse + * because we expect that most digits will be nonzero. */ + for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) { + } + + return (i + 1); +} + +bitcount_t uECC_vli_numBits(const uECC_word_t *vli, + const wordcount_t max_words) +{ + + uECC_word_t i; + uECC_word_t digit; + + wordcount_t num_digits = vli_numDigits(vli, max_words); + if (num_digits == 0) { + return 0; + } + + digit = vli[num_digits - 1]; + for (i = 0; digit; ++i) { + digit >>= 1; + } + + return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i); +} + +void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, + wordcount_t num_words) +{ + wordcount_t i; + + for (i = 0; i < num_words; ++i) { + dest[i] = src[i]; + } +} + +cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) +{ + wordcount_t i; + + for (i = num_words - 1; i >= 0; --i) { + if (left[i] > right[i]) { + return 1; + } else if (left[i] < right[i]) { + return -1; + } + } + return 0; +} + +uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right, + wordcount_t num_words) +{ + + uECC_word_t diff = 0; + wordcount_t i; + + for (i = num_words - 1; i >= 0; --i) { + diff |= (left[i] ^ right[i]); + } + return !(diff == 0); +} + +uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond) +{ + return (p_true*(cond)) | (p_false*(!cond)); +} + +/* Computes result = left - right, returning borrow, in constant time. + * Can modify in place. */ +uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, wordcount_t num_words) +{ + uECC_word_t borrow = 0; + wordcount_t i; + for (i = 0; i < num_words; ++i) { + uECC_word_t diff = left[i] - right[i] - borrow; + uECC_word_t val = (diff > left[i]); + borrow = cond_set(val, borrow, (diff != left[i])); + + result[i] = diff; + } + return borrow; +} + +/* Computes result = left + right, returning carry, in constant time. + * Can modify in place. */ +static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, wordcount_t num_words) +{ + uECC_word_t carry = 0; + wordcount_t i; + for (i = 0; i < num_words; ++i) { + uECC_word_t sum = left[i] + right[i] + carry; + uECC_word_t val = (sum < left[i]); + carry = cond_set(val, carry, (sum != left[i])); + result[i] = sum; + } + return carry; +} + +cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, + wordcount_t num_words) +{ + uECC_word_t tmp[NUM_ECC_WORDS]; + uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words); + uECC_word_t equal = uECC_vli_isZero(tmp, num_words); + return (!equal - 2 * neg); +} + +/* Computes vli = vli >> 1. */ +static void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) +{ + uECC_word_t *end = vli; + uECC_word_t carry = 0; + + vli += num_words; + while (vli-- > end) { + uECC_word_t temp = *vli; + *vli = (temp >> 1) | carry; + carry = temp << (uECC_WORD_BITS - 1); + } +} + +static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0, + uECC_word_t *r1, uECC_word_t *r2) +{ + + uECC_dword_t p = (uECC_dword_t)a * b; + uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0; + r01 += p; + *r2 += (r01 < p); + *r1 = r01 >> uECC_WORD_BITS; + *r0 = (uECC_word_t)r01; + +} + +/* Computes result = left * right. Result must be 2 * num_words long. */ +static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, wordcount_t num_words) +{ + + uECC_word_t r0 = 0; + uECC_word_t r1 = 0; + uECC_word_t r2 = 0; + wordcount_t i, k; + + /* Compute each digit of result in sequence, maintaining the carries. */ + for (k = 0; k < num_words; ++k) { + + for (i = 0; i <= k; ++i) { + muladd(left[i], right[k - i], &r0, &r1, &r2); + } + + result[k] = r0; + r0 = r1; + r1 = r2; + r2 = 0; + } + + for (k = num_words; k < num_words * 2 - 1; ++k) { + + for (i = (k + 1) - num_words; i < num_words; ++i) { + muladd(left[i], right[k - i], &r0, &r1, &r2); + } + result[k] = r0; + r0 = r1; + r1 = r2; + r2 = 0; + } + result[num_words * 2 - 1] = r0; +} + +void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, const uECC_word_t *mod, + wordcount_t num_words) +{ + uECC_word_t carry = uECC_vli_add(result, left, right, num_words); + if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) { + /* result > mod (result = mod + remainder), so subtract mod to get + * remainder. */ + uECC_vli_sub(result, result, mod, num_words); + } +} + +void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, const uECC_word_t *mod, + wordcount_t num_words) +{ + uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words); + if (l_borrow) { + /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x, + * we can get the correct result from result + mod (with overflow). */ + uECC_vli_add(result, result, mod, num_words); + } +} + +/* Computes result = product % mod, where product is 2N words long. */ +/* Currently only designed to work for curve_p or curve_n. */ +void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, + const uECC_word_t *mod, wordcount_t num_words) +{ + uECC_word_t mod_multiple[2 * NUM_ECC_WORDS]; + uECC_word_t tmp[2 * NUM_ECC_WORDS]; + uECC_word_t *v[2] = {tmp, product}; + uECC_word_t index; + + /* Shift mod so its highest set bit is at the maximum position. */ + bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - + uECC_vli_numBits(mod, num_words); + wordcount_t word_shift = shift / uECC_WORD_BITS; + wordcount_t bit_shift = shift % uECC_WORD_BITS; + uECC_word_t carry = 0; + uECC_vli_clear(mod_multiple, word_shift); + if (bit_shift > 0) { + for(index = 0; index < (uECC_word_t)num_words; ++index) { + mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry; + carry = mod[index] >> (uECC_WORD_BITS - bit_shift); + } + } else { + uECC_vli_set(mod_multiple + word_shift, mod, num_words); + } + + for (index = 1; shift >= 0; --shift) { + uECC_word_t borrow = 0; + wordcount_t i; + for (i = 0; i < num_words * 2; ++i) { + uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow; + if (diff != v[index][i]) { + borrow = (diff > v[index][i]); + } + v[1 - index][i] = diff; + } + /* Swap the index if there was no borrow */ + index = !(index ^ borrow); + uECC_vli_rshift1(mod_multiple, num_words); + mod_multiple[num_words - 1] |= mod_multiple[num_words] << + (uECC_WORD_BITS - 1); + uECC_vli_rshift1(mod_multiple + num_words, num_words); + } + uECC_vli_set(result, v[index], num_words); +} + +void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, const uECC_word_t *mod, + wordcount_t num_words) +{ + uECC_word_t product[2 * NUM_ECC_WORDS]; + uECC_vli_mult(product, left, right, num_words); + uECC_vli_mmod(result, product, mod, num_words); +} + +void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, uECC_Curve curve) +{ + uECC_word_t product[2 * NUM_ECC_WORDS]; + uECC_vli_mult(product, left, right, curve->num_words); + + curve->mmod_fast(result, product); +} + +static void uECC_vli_modSquare_fast(uECC_word_t *result, + const uECC_word_t *left, + uECC_Curve curve) +{ + uECC_vli_modMult_fast(result, left, left, curve); +} + + +#define EVEN(vli) (!(vli[0] & 1)) + +static void vli_modInv_update(uECC_word_t *uv, + const uECC_word_t *mod, + wordcount_t num_words) +{ + + uECC_word_t carry = 0; + + if (!EVEN(uv)) { + carry = uECC_vli_add(uv, uv, mod, num_words); + } + uECC_vli_rshift1(uv, num_words); + if (carry) { + uv[num_words - 1] |= HIGH_BIT_SET; + } +} + +void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, + const uECC_word_t *mod, wordcount_t num_words) +{ + uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS]; + uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS]; + cmpresult_t cmpResult; + + if (uECC_vli_isZero(input, num_words)) { + uECC_vli_clear(result, num_words); + return; + } + + uECC_vli_set(a, input, num_words); + uECC_vli_set(b, mod, num_words); + uECC_vli_clear(u, num_words); + u[0] = 1; + uECC_vli_clear(v, num_words); + while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) { + if (EVEN(a)) { + uECC_vli_rshift1(a, num_words); + vli_modInv_update(u, mod, num_words); + } else if (EVEN(b)) { + uECC_vli_rshift1(b, num_words); + vli_modInv_update(v, mod, num_words); + } else if (cmpResult > 0) { + uECC_vli_sub(a, a, b, num_words); + uECC_vli_rshift1(a, num_words); + if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) { + uECC_vli_add(u, u, mod, num_words); + } + uECC_vli_sub(u, u, v, num_words); + vli_modInv_update(u, mod, num_words); + } else { + uECC_vli_sub(b, b, a, num_words); + uECC_vli_rshift1(b, num_words); + if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) { + uECC_vli_add(v, v, mod, num_words); + } + uECC_vli_sub(v, v, u, num_words); + vli_modInv_update(v, mod, num_words); + } + } + uECC_vli_set(result, u, num_words); +} + +/* ------ Point operations ------ */ + +void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * Z1, uECC_Curve curve) +{ + /* t1 = X, t2 = Y, t3 = Z */ + uECC_word_t t4[NUM_ECC_WORDS]; + uECC_word_t t5[NUM_ECC_WORDS]; + wordcount_t num_words = curve->num_words; + + if (uECC_vli_isZero(Z1, num_words)) { + return; + } + + uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */ + uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */ + uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */ + uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */ + uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */ + + uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */ + uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */ + uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */ + uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */ + + uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */ + uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */ + if (uECC_vli_testBit(X1, 0)) { + uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words); + uECC_vli_rshift1(X1, num_words); + X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1); + } else { + uECC_vli_rshift1(X1, num_words); + } + + /* t1 = 3/2*(x1^2 - z1^4) = B */ + uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */ + uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */ + uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */ + uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */ + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */ + /* t4 = B * (A - x3) - y1^4 = y3: */ + uECC_vli_modSub(t4, X1, t4, curve->p, num_words); + + uECC_vli_set(X1, Z1, num_words); + uECC_vli_set(Z1, Y1, num_words); + uECC_vli_set(Y1, t4, num_words); +} + +void x_side_default(uECC_word_t *result, + const uECC_word_t *x, + uECC_Curve curve) +{ + uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */ + wordcount_t num_words = curve->num_words; + + uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */ + uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */ + uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */ + /* r = x^3 - 3x + b: */ + uECC_vli_modAdd(result, result, curve->b, curve->p, num_words); +} + +uECC_Curve uECC_secp256r1(void) +{ + return &curve_secp256r1; +} + +void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) +{ + unsigned int tmp[NUM_ECC_WORDS]; + int carry; + + /* t */ + uECC_vli_set(result, product, NUM_ECC_WORDS); + + /* s1 */ + tmp[0] = tmp[1] = tmp[2] = 0; + tmp[3] = product[11]; + tmp[4] = product[12]; + tmp[5] = product[13]; + tmp[6] = product[14]; + tmp[7] = product[15]; + carry = uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS); + carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); + + /* s2 */ + tmp[3] = product[12]; + tmp[4] = product[13]; + tmp[5] = product[14]; + tmp[6] = product[15]; + tmp[7] = 0; + carry += uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS); + carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); + + /* s3 */ + tmp[0] = product[8]; + tmp[1] = product[9]; + tmp[2] = product[10]; + tmp[3] = tmp[4] = tmp[5] = 0; + tmp[6] = product[14]; + tmp[7] = product[15]; + carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); + + /* s4 */ + tmp[0] = product[9]; + tmp[1] = product[10]; + tmp[2] = product[11]; + tmp[3] = product[13]; + tmp[4] = product[14]; + tmp[5] = product[15]; + tmp[6] = product[13]; + tmp[7] = product[8]; + carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); + + /* d1 */ + tmp[0] = product[11]; + tmp[1] = product[12]; + tmp[2] = product[13]; + tmp[3] = tmp[4] = tmp[5] = 0; + tmp[6] = product[8]; + tmp[7] = product[10]; + carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); + + /* d2 */ + tmp[0] = product[12]; + tmp[1] = product[13]; + tmp[2] = product[14]; + tmp[3] = product[15]; + tmp[4] = tmp[5] = 0; + tmp[6] = product[9]; + tmp[7] = product[11]; + carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); + + /* d3 */ + tmp[0] = product[13]; + tmp[1] = product[14]; + tmp[2] = product[15]; + tmp[3] = product[8]; + tmp[4] = product[9]; + tmp[5] = product[10]; + tmp[6] = 0; + tmp[7] = product[12]; + carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); + + /* d4 */ + tmp[0] = product[14]; + tmp[1] = product[15]; + tmp[2] = 0; + tmp[3] = product[9]; + tmp[4] = product[10]; + tmp[5] = product[11]; + tmp[6] = 0; + tmp[7] = product[13]; + carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); + + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_secp256r1.p, NUM_ECC_WORDS); + } + while (carry < 0); + } else { + while (carry || + uECC_vli_cmp_unsafe(curve_secp256r1.p, result, NUM_ECC_WORDS) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp256r1.p, NUM_ECC_WORDS); + } + } +} + +uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve) +{ + return uECC_vli_isZero(point, curve->num_words * 2); +} + +void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z, + uECC_Curve curve) +{ + uECC_word_t t1[NUM_ECC_WORDS]; + + uECC_vli_modSquare_fast(t1, Z, curve); /* z^2 */ + uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */ + uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */ + uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */ +} + +#if !SOC_ECC_SUPPORTED +/* P = (x1, y1) => 2P, (x2, y2) => P' */ +static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * X2, uECC_word_t * Y2, + const uECC_word_t * const initial_Z, + uECC_Curve curve) +{ + uECC_word_t z[NUM_ECC_WORDS]; + wordcount_t num_words = curve->num_words; + if (initial_Z) { + uECC_vli_set(z, initial_Z, num_words); + } else { + uECC_vli_clear(z, num_words); + z[0] = 1; + } + + uECC_vli_set(X2, X1, num_words); + uECC_vli_set(Y2, Y1, num_words); + + apply_z(X1, Y1, z, curve); + curve->double_jacobian(X1, Y1, z, curve); + apply_z(X2, Y2, z, curve); +} + + +/* Input P = (x1, y1, Z), Q = (x2, y2, Z) + Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3) + or P => P - Q, Q => P + Q + */ +static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * X2, uECC_word_t * Y2, + uECC_Curve curve) +{ + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[NUM_ECC_WORDS]; + uECC_word_t t6[NUM_ECC_WORDS]; + uECC_word_t t7[NUM_ECC_WORDS]; + wordcount_t num_words = curve->num_words; + + uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ + uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ + uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ + + uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */ + uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */ + uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */ + uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */ + uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */ + + uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */ + uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */ + /* t4 = (y2 - y1)*(B - x3) - E = y3: */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); + + uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */ + uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */ + uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */ + uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */ + /* t2 = (y2+y1)*(x3' - B) - E = y3': */ + uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words); + + uECC_vli_set(X1, t7, num_words); +} +#endif /* !SOC_ECC_SUPPORTED */ + +void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * X2, uECC_word_t * Y2, + uECC_Curve curve) +{ + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[NUM_ECC_WORDS]; + wordcount_t num_words = curve->num_words; + + uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ + uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ + uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */ + + uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */ + uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */ + uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */ + uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */ + uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */ + uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */ + + uECC_vli_set(X2, t5, num_words); +} + +void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, + const uECC_word_t * scalar, + const uECC_word_t * initial_Z, + bitcount_t num_bits, uECC_Curve curve) +{ +#if SOC_ECC_SUPPORTED + wordcount_t num_words = curve->num_words; + + /* Only p256r1 is supported currently. */ + assert (curve == uECC_secp256r1()); + + esp_tinycrypt_calc_ecc_mult((const uint8_t *)&point[0], (const uint8_t *)&point[num_words], + (uint8_t *)scalar, (uint8_t *)&result[0], (uint8_t *)&result[num_words], + num_words * uECC_WORD_SIZE, false); +#else + /* R0 and R1 */ + uECC_word_t Rx[2][NUM_ECC_WORDS]; + uECC_word_t Ry[2][NUM_ECC_WORDS]; + uECC_word_t z[NUM_ECC_WORDS]; + bitcount_t i; + uECC_word_t nb; + wordcount_t num_words = curve->num_words; + + uECC_vli_set(Rx[1], point, num_words); + uECC_vli_set(Ry[1], point + num_words, num_words); + + XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve); + + for (i = num_bits - 2; i > 0; --i) { + nb = !uECC_vli_testBit(scalar, i); + XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); + XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); + } + + nb = !uECC_vli_testBit(scalar, 0); + XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); + + /* Find final 1/Z value. */ + uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */ + uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */ + uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */ + uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0))*/ + /* yP / (xP * Yb * (X1 - X0)) */ + uECC_vli_modMult_fast(z, z, point + num_words, curve); + /* Xb * yP / (xP * Yb * (X1 - X0)) */ + uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve); + /* End 1/Z calculation */ + + XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); + apply_z(Rx[0], Ry[0], z, curve); + + uECC_vli_set(result, Rx[0], num_words); + uECC_vli_set(result + num_words, Ry[0], num_words); +#endif /* SOC_ECC_SUPPORTED */ +} + +uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, + uECC_word_t *k1, uECC_Curve curve) +{ + + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + + bitcount_t num_n_bits = curve->num_n_bits; + + uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) || + (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) && + uECC_vli_testBit(k0, num_n_bits)); + + uECC_vli_add(k1, k0, curve->n, num_n_words); + + return carry; +} + +uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, + uECC_word_t *private_key, + uECC_Curve curve) +{ + + uECC_word_t tmp1[NUM_ECC_WORDS]; + uECC_word_t tmp2[NUM_ECC_WORDS]; + uECC_word_t *p2[2] = {tmp1, tmp2}; + uECC_word_t carry; + + /* Regularize the bitcount for the private key so that attackers cannot + * use a side channel attack to learn the number of leading zeros. */ + carry = regularize_k(private_key, tmp1, tmp2, curve); + + EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve); + + if (EccPoint_isZero(result, curve)) { + return 0; + } + return 1; +} + +/* Converts an integer in uECC native format to big-endian bytes. */ +void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, + const unsigned int *native) +{ + wordcount_t i; + for (i = 0; i < num_bytes; ++i) { + unsigned b = num_bytes - 1 - i; + bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)); + } +} + +/* Converts big-endian bytes to an integer in uECC native format. */ +void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes, + int num_bytes) +{ + wordcount_t i; + uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE); + for (i = 0; i < num_bytes; ++i) { + unsigned b = num_bytes - 1 - i; + native[b / uECC_WORD_SIZE] |= + (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE)); + } +} + +int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, + wordcount_t num_words) +{ + uECC_word_t mask = (uECC_word_t)-1; + uECC_word_t tries; + bitcount_t num_bits = uECC_vli_numBits(top, num_words); + + if (!g_rng_function) { + return 0; + } + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) { + return 0; + } + random[num_words - 1] &= + mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); + if (!uECC_vli_isZero(random, num_words) && + uECC_vli_cmp(top, random, num_words) == 1) { + return 1; + } + } + return 0; +} + + +int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) +{ + wordcount_t num_words = curve->num_words; + + /* The point at infinity is invalid. */ + if (EccPoint_isZero(point, curve)) { + return -1; + } + + /* x and y must be smaller than p. */ + if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 || + uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) { + return -2; + } + +#if SOC_ECC_SUPPORTED + /* Only p256r1 is supported currently. */ + if (curve != uECC_secp256r1()) { + return -5; + } + + if (esp_tinycrypt_verify_ecc_point((const uint8_t *)&point[0], + (const uint8_t *)&point[num_words], + num_words * uECC_WORD_SIZE)) { + return -3; + } +#else + uECC_word_t tmp1[NUM_ECC_WORDS]; + uECC_word_t tmp2[NUM_ECC_WORDS]; + + uECC_vli_modSquare_fast(tmp1, point + num_words, curve); + curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */ + + /* Make sure that y^2 == x^3 + ax + b */ + if (uECC_vli_equal(tmp1, tmp2, num_words) != 0) + return -3; +#endif /* SOC_ECC_SUPPORTED */ + + return 0; +} + +int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve) +{ + uECC_word_t _public[NUM_ECC_WORDS * 2]; + + uECC_vli_bytesToNative(_public, public_key, curve->num_bytes); + uECC_vli_bytesToNative( + _public + curve->num_words, + public_key + curve->num_bytes, + curve->num_bytes); + + if (uECC_vli_cmp_unsafe(_public, curve->G, NUM_ECC_WORDS * 2) == 0) { + return -4; + } + + return uECC_valid_point(_public, curve); +} + +int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, + uECC_Curve curve) +{ + uECC_word_t _private[NUM_ECC_WORDS]; + uECC_word_t _public[NUM_ECC_WORDS * 2]; + + uECC_vli_bytesToNative( + _private, + private_key, + BITS_TO_BYTES(curve->num_n_bits)); + + /* Make sure the private key is in the range [1, n-1]. */ + if (uECC_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) { + return 0; + } + + if (uECC_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) != 1) { + return 0; + } + + /* Compute public key. */ + if (!EccPoint_compute_public_key(_public, _private, curve)) { + return 0; + } + + uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public); + uECC_vli_nativeToBytes( + public_key + + curve->num_bytes, curve->num_bytes, _public + curve->num_words); + return 1; +} diff --git a/lib/bt/common/tinycrypt/src/ecc_dh.c b/lib/bt/common/tinycrypt/src/ecc_dh.c new file mode 100644 index 00000000..fab692da --- /dev/null +++ b/lib/bt/common/tinycrypt/src/ecc_dh.c @@ -0,0 +1,204 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include + +#if default_RNG_defined +static uECC_RNG_Function g_rng_function = &default_CSPRNG; +#else +static uECC_RNG_Function g_rng_function = 0; +#endif + +int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key, + unsigned int *d, uECC_Curve curve) +{ + + uECC_word_t _private[NUM_ECC_WORDS]; + uECC_word_t _public[NUM_ECC_WORDS * 2]; + + /* This function is designed for test purposes-only (such as validating NIST + * test vectors) as it uses a provided value for d instead of generating + * it uniformly at random. */ + memcpy (_private, d, NUM_ECC_BYTES); + + /* Computing public-key from private: */ + if (EccPoint_compute_public_key(_public, _private, curve)) { + + /* Converting buffers to correct bit order: */ + uECC_vli_nativeToBytes(private_key, + BITS_TO_BYTES(curve->num_n_bits), + _private); + uECC_vli_nativeToBytes(public_key, + curve->num_bytes, + _public); + uECC_vli_nativeToBytes(public_key + curve->num_bytes, + curve->num_bytes, + _public + curve->num_words); + + /* erasing temporary buffer used to store secret: */ + memset(_private, 0, NUM_ECC_BYTES); + + return 1; + } + return 0; +} + +int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve) +{ + + uECC_word_t _random[NUM_ECC_WORDS * 2]; + uECC_word_t _private[NUM_ECC_WORDS]; + uECC_word_t _public[NUM_ECC_WORDS * 2]; + uECC_word_t tries; + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + /* Generating _private uniformly at random: */ + uECC_RNG_Function rng_function = uECC_get_rng(); + if (!rng_function || + !rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS*uECC_WORD_SIZE)) { + return 0; + } + + /* computing modular reduction of _random (see FIPS 186.4 B.4.1): */ + uECC_vli_mmod(_private, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits)); + + /* Computing public-key from private: */ + if (EccPoint_compute_public_key(_public, _private, curve)) { + + /* Converting buffers to correct bit order: */ + uECC_vli_nativeToBytes(private_key, + BITS_TO_BYTES(curve->num_n_bits), + _private); + uECC_vli_nativeToBytes(public_key, + curve->num_bytes, + _public); + uECC_vli_nativeToBytes(public_key + curve->num_bytes, + curve->num_bytes, + _public + curve->num_words); + + /* erasing temporary buffer that stored secret: */ + memset(_private, 0, NUM_ECC_BYTES); + + return 1; + } + } + return 0; +} + +int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, + uint8_t *secret, uECC_Curve curve) +{ + + uECC_word_t _public[NUM_ECC_WORDS * 2]; + uECC_word_t _private[NUM_ECC_WORDS]; + + uECC_word_t tmp[NUM_ECC_WORDS]; + uECC_word_t *p2[2] = {_private, tmp}; + uECC_word_t *initial_Z = 0; + uECC_word_t carry; + wordcount_t num_words = curve->num_words; + wordcount_t num_bytes = curve->num_bytes; + int r; + + /* Converting buffers to correct bit order: */ + uECC_vli_bytesToNative(_private, + private_key, + BITS_TO_BYTES(curve->num_n_bits)); + uECC_vli_bytesToNative(_public, + public_key, + num_bytes); + uECC_vli_bytesToNative(_public + num_words, + public_key + num_bytes, + num_bytes); + + /* Regularize the bitcount for the private key so that attackers cannot use a + * side channel attack to learn the number of leading zeros. */ + carry = regularize_k(_private, _private, tmp, curve); + + /* If an RNG function was specified, try to get a random initial Z value to + * improve protection against side-channel attacks. */ + if (g_rng_function) { + if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) { + r = 0; + goto clear_and_out; + } + initial_Z = p2[carry]; + } + + EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1, + curve); + + uECC_vli_nativeToBytes(secret, num_bytes, _public); + r = !EccPoint_isZero(_public, curve); + +clear_and_out: + /* erasing temporary buffer used to store secret: */ + memset(p2, 0, sizeof(p2)); + __asm__ __volatile__("" :: "g"(p2) : "memory"); + memset(tmp, 0, sizeof(tmp)); + __asm__ __volatile__("" :: "g"(tmp) : "memory"); + memset(_private, 0, sizeof(_private)); + __asm__ __volatile__("" :: "g"(_private) : "memory"); + + return r; +} diff --git a/lib/bt/common/tinycrypt/src/ecc_dsa.c b/lib/bt/common/tinycrypt/src/ecc_dsa.c new file mode 100644 index 00000000..03a91f09 --- /dev/null +++ b/lib/bt/common/tinycrypt/src/ecc_dsa.c @@ -0,0 +1,298 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.*/ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#if default_RNG_defined +static uECC_RNG_Function g_rng_function = &default_CSPRNG; +#else +static uECC_RNG_Function g_rng_function = 0; +#endif + +static void bits2int(uECC_word_t *native, const uint8_t *bits, + unsigned bits_size, uECC_Curve curve) +{ + unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits); + unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits); + int shift; + uECC_word_t carry; + uECC_word_t *ptr; + + if (bits_size > num_n_bytes) { + bits_size = num_n_bytes; + } + + uECC_vli_clear(native, num_n_words); + uECC_vli_bytesToNative(native, bits, bits_size); + if (bits_size * 8 <= (unsigned)curve->num_n_bits) { + return; + } + shift = bits_size * 8 - curve->num_n_bits; + carry = 0; + ptr = native + num_n_words; + while (ptr-- > native) { + uECC_word_t temp = *ptr; + *ptr = (temp >> shift) | carry; + carry = temp << (uECC_WORD_BITS - shift); + } + + /* Reduce mod curve_n */ + if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) { + uECC_vli_sub(native, native, curve->n, num_n_words); + } +} + +int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, + unsigned hash_size, uECC_word_t *k, uint8_t *signature, + uECC_Curve curve) +{ + + uECC_word_t tmp[NUM_ECC_WORDS]; + uECC_word_t s[NUM_ECC_WORDS]; + uECC_word_t *k2[2] = {tmp, s}; + uECC_word_t p[NUM_ECC_WORDS * 2]; + uECC_word_t carry; + wordcount_t num_words = curve->num_words; + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + bitcount_t num_n_bits = curve->num_n_bits; + + /* Make sure 0 < k < curve_n */ + if (uECC_vli_isZero(k, num_words) || + uECC_vli_cmp(curve->n, k, num_n_words) != 1) { + return 0; + } + + carry = regularize_k(k, tmp, s, curve); + EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve); + if (uECC_vli_isZero(p, num_words)) { + return 0; + } + + /* If an RNG function was specified, get a random number + to prevent side channel analysis of k. */ + if (!g_rng_function) { + uECC_vli_clear(tmp, num_n_words); + tmp[0] = 1; + } + else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) { + return 0; + } + + /* Prevent side channel analysis of uECC_vli_modInv() to determine + bits of k / the private key by premultiplying by a random number */ + uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */ + uECC_vli_modInv(k, k, curve->n, num_n_words); /* k = 1 / k' */ + uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */ + + uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */ + + /* tmp = d: */ + uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits)); + + s[num_n_words - 1] = 0; + uECC_vli_set(s, p, num_words); + uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */ + + bits2int(tmp, message_hash, hash_size, curve); + uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */ + uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */ + if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) { + return 0; + } + + uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s); + return 1; +} + +int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash, + unsigned hash_size, uint8_t *signature, uECC_Curve curve) +{ + uECC_word_t _random[2*NUM_ECC_WORDS]; + uECC_word_t k[NUM_ECC_WORDS]; + uECC_word_t tries; + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + /* Generating _random uniformly at random: */ + uECC_RNG_Function rng_function = uECC_get_rng(); + if (!rng_function || + !rng_function((uint8_t *)_random, 2*NUM_ECC_WORDS*uECC_WORD_SIZE)) { + return 0; + } + + // computing k as modular reduction of _random (see FIPS 186.4 B.5.1): + uECC_vli_mmod(k, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits)); + + if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature, + curve)) { + return 1; + } + } + return 0; +} + +static bitcount_t smax(bitcount_t a, bitcount_t b) +{ + return (a > b ? a : b); +} + +int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, + unsigned hash_size, const uint8_t *signature, + uECC_Curve curve) +{ + + uECC_word_t u1[NUM_ECC_WORDS], u2[NUM_ECC_WORDS]; + uECC_word_t z[NUM_ECC_WORDS]; + uECC_word_t sum[NUM_ECC_WORDS * 2]; + uECC_word_t rx[NUM_ECC_WORDS]; + uECC_word_t ry[NUM_ECC_WORDS]; + uECC_word_t tx[NUM_ECC_WORDS]; + uECC_word_t ty[NUM_ECC_WORDS]; + uECC_word_t tz[NUM_ECC_WORDS]; + const uECC_word_t *points[4]; + const uECC_word_t *point; + bitcount_t num_bits; + bitcount_t i; + + uECC_word_t _public[NUM_ECC_WORDS * 2]; + uECC_word_t r[NUM_ECC_WORDS], s[NUM_ECC_WORDS]; + wordcount_t num_words = curve->num_words; + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + + rx[num_n_words - 1] = 0; + r[num_n_words - 1] = 0; + s[num_n_words - 1] = 0; + + uECC_vli_bytesToNative(_public, public_key, curve->num_bytes); + uECC_vli_bytesToNative(_public + num_words, public_key + curve->num_bytes, + curve->num_bytes); + uECC_vli_bytesToNative(r, signature, curve->num_bytes); + uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes); + + /* r, s must not be 0. */ + if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) { + return 0; + } + + /* r, s must be < n. */ + if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 || + uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) { + return 0; + } + + /* Calculate u1 and u2. */ + uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */ + u1[num_n_words - 1] = 0; + bits2int(u1, message_hash, hash_size, curve); + uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */ + uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */ + + /* Calculate sum = G + Q. */ + uECC_vli_set(sum, _public, num_words); + uECC_vli_set(sum + num_words, _public + num_words, num_words); + uECC_vli_set(tx, curve->G, num_words); + uECC_vli_set(ty, curve->G + num_words, num_words); + uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */ + XYcZ_add(tx, ty, sum, sum + num_words, curve); + uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */ + apply_z(sum, sum + num_words, z, curve); + + /* Use Shamir's trick to calculate u1*G + u2*Q */ + points[0] = 0; + points[1] = curve->G; + points[2] = _public; + points[3] = sum; + num_bits = smax(uECC_vli_numBits(u1, num_n_words), + uECC_vli_numBits(u2, num_n_words)); + + point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | + ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; + uECC_vli_set(rx, point, num_words); + uECC_vli_set(ry, point + num_words, num_words); + uECC_vli_clear(z, num_words); + z[0] = 1; + + for (i = num_bits - 2; i >= 0; --i) { + uECC_word_t index; + curve->double_jacobian(rx, ry, z, curve); + + index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1); + point = points[index]; + if (point) { + uECC_vli_set(tx, point, num_words); + uECC_vli_set(ty, point + num_words, num_words); + apply_z(tx, ty, z, curve); + uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */ + XYcZ_add(tx, ty, rx, ry, curve); + uECC_vli_modMult_fast(z, z, tz, curve); + } + } + + uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */ + apply_z(rx, ry, z, curve); + + /* v = x1 (mod n) */ + if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) { + uECC_vli_sub(rx, rx, curve->n, num_n_words); + } + + /* Accept only if v == r. */ + return (int)(uECC_vli_equal(rx, r, num_words) == 0); +} diff --git a/lib/bt/common/tinycrypt/src/ecc_platform_specific.c b/lib/bt/common/tinycrypt/src/ecc_platform_specific.c new file mode 100644 index 00000000..b76ea994 --- /dev/null +++ b/lib/bt/common/tinycrypt/src/ecc_platform_specific.c @@ -0,0 +1,110 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* uECC_platform_specific.c - Implementation of platform specific functions*/ + +/* Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.*/ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * uECC_platform_specific.c -- Implementation of platform specific functions + */ + + +#if defined(unix) || defined(__linux__) || defined(__unix__) || \ + defined(__unix) | (defined(__APPLE__) && defined(__MACH__)) || \ + defined(uECC_POSIX) + +/* Some POSIX-like system with /dev/urandom or /dev/random. */ +#include +#include +#include + +#include + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +int default_CSPRNG(uint8_t *dest, unsigned int size) { + + /* input sanity check: */ + if (dest == (uint8_t *) 0 || (size <= 0)) + return 0; + + int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); + if (fd == -1) { + fd = open("/dev/random", O_RDONLY | O_CLOEXEC); + if (fd == -1) { + return 0; + } + } + + char *ptr = (char *)dest; + size_t left = (size_t) size; + while (left > 0) { + ssize_t bytes_read = read(fd, ptr, left); + if (bytes_read <= 0) { // read failed + close(fd); + return 0; + } + left -= bytes_read; + ptr += bytes_read; + } + + close(fd); + return 1; +} + +#endif /* platform */ diff --git a/lib/bt/common/tinycrypt/src/hmac.c b/lib/bt/common/tinycrypt/src/hmac.c new file mode 100644 index 00000000..77232434 --- /dev/null +++ b/lib/bt/common/tinycrypt/src/hmac.c @@ -0,0 +1,152 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size) +{ + const uint8_t inner_pad = (uint8_t) 0x36; + const uint8_t outer_pad = (uint8_t) 0x5c; + unsigned int i; + + for (i = 0; i < key_size; ++i) { + key[i] = inner_pad ^ new_key[i]; + key[i + TC_SHA256_BLOCK_SIZE] = outer_pad ^ new_key[i]; + } + for (; i < TC_SHA256_BLOCK_SIZE; ++i) { + key[i] = inner_pad; key[i + TC_SHA256_BLOCK_SIZE] = outer_pad; + } +} + +int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key, + unsigned int key_size) +{ + + /* input sanity check: */ + if (ctx == (TCHmacState_t) 0 || + key == (const uint8_t *) 0 || + key_size == 0) { + return TC_CRYPTO_FAIL; + } + + const uint8_t dummy_key[key_size]; + struct tc_hmac_state_struct dummy_state; + + if (key_size <= TC_SHA256_BLOCK_SIZE) { + /* + * The next three lines consist of dummy calls just to avoid + * certain timing attacks. Without these dummy calls, + * adversaries would be able to learn whether the key_size is + * greater than TC_SHA256_BLOCK_SIZE by measuring the time + * consumed in this process. + */ + (void)tc_sha256_init(&dummy_state.hash_state); + (void)tc_sha256_update(&dummy_state.hash_state, + dummy_key, + key_size); + (void)tc_sha256_final(&dummy_state.key[TC_SHA256_DIGEST_SIZE], + &dummy_state.hash_state); + + /* Actual code for when key_size <= TC_SHA256_BLOCK_SIZE: */ + rekey(ctx->key, key, key_size); + } else { + (void)tc_sha256_init(&ctx->hash_state); + (void)tc_sha256_update(&ctx->hash_state, key, key_size); + (void)tc_sha256_final(&ctx->key[TC_SHA256_DIGEST_SIZE], + &ctx->hash_state); + rekey(ctx->key, + &ctx->key[TC_SHA256_DIGEST_SIZE], + TC_SHA256_DIGEST_SIZE); + } + + return TC_CRYPTO_SUCCESS; +} + +int tc_hmac_init(TCHmacState_t ctx) +{ + + /* input sanity check: */ + if (ctx == (TCHmacState_t) 0) { + return TC_CRYPTO_FAIL; + } + + (void) tc_sha256_init(&ctx->hash_state); + (void) tc_sha256_update(&ctx->hash_state, ctx->key, TC_SHA256_BLOCK_SIZE); + + return TC_CRYPTO_SUCCESS; +} + +int tc_hmac_update(TCHmacState_t ctx, + const void *data, + unsigned int data_length) +{ + + /* input sanity check: */ + if (ctx == (TCHmacState_t) 0) { + return TC_CRYPTO_FAIL; + } + + (void)tc_sha256_update(&ctx->hash_state, data, data_length); + + return TC_CRYPTO_SUCCESS; +} + +int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx) +{ + + /* input sanity check: */ + if (tag == (uint8_t *) 0 || + taglen != TC_SHA256_DIGEST_SIZE || + ctx == (TCHmacState_t) 0) { + return TC_CRYPTO_FAIL; + } + + (void) tc_sha256_final(tag, &ctx->hash_state); + + (void)tc_sha256_init(&ctx->hash_state); + (void)tc_sha256_update(&ctx->hash_state, + &ctx->key[TC_SHA256_BLOCK_SIZE], + TC_SHA256_BLOCK_SIZE); + (void)tc_sha256_update(&ctx->hash_state, tag, TC_SHA256_DIGEST_SIZE); + (void)tc_sha256_final(tag, &ctx->hash_state); + + /* destroy the current state */ + _set(ctx, 0, sizeof(*ctx)); + + return TC_CRYPTO_SUCCESS; +} diff --git a/lib/bt/common/tinycrypt/src/hmac_prng.c b/lib/bt/common/tinycrypt/src/hmac_prng.c new file mode 100644 index 00000000..1e3a52fb --- /dev/null +++ b/lib/bt/common/tinycrypt/src/hmac_prng.c @@ -0,0 +1,218 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* hmac_prng.c - TinyCrypt implementation of HMAC-PRNG */ + +#include +#include +#include +#include + +/* + * min bytes in the seed string. + * MIN_SLEN*8 must be at least the expected security level. + */ +static const unsigned int MIN_SLEN = 32; + +/* + * max bytes in the seed string; + * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes). + */ +static const unsigned int MAX_SLEN = UINT32_MAX; + +/* + * max bytes in the personalization string; + * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes). + */ +static const unsigned int MAX_PLEN = UINT32_MAX; + +/* + * max bytes in the additional_info string; + * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes). + */ +static const unsigned int MAX_ALEN = UINT32_MAX; + +/* + * max number of generates between re-seeds; + * TinyCrypt accepts up to (2^32 - 1) which is the maximal value of + * a 32-bit unsigned int variable, while SP800-90A specifies a maximum of 2^48. + */ +static const unsigned int MAX_GENS = UINT32_MAX; + +/* + * maximum bytes per generate call; + * SP800-90A specifies a maximum up to 2^19. + */ +static const unsigned int MAX_OUT = (1 << 19); + +/* + * Assumes: prng != NULL, e != NULL, len >= 0. + */ +static void update(TCHmacPrng_t prng, const uint8_t *e, unsigned int len) +{ + const uint8_t separator0 = 0x00; + const uint8_t separator1 = 0x01; + + /* use current state, e and separator 0 to compute a new prng key: */ + (void)tc_hmac_init(&prng->h); + (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); + (void)tc_hmac_update(&prng->h, &separator0, sizeof(separator0)); + (void)tc_hmac_update(&prng->h, e, len); + (void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h); + /* configure the new prng key into the prng's instance of hmac */ + (void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); + + /* use the new key to compute a new state variable v */ + (void)tc_hmac_init(&prng->h); + (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); + (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h); + + /* use current state, e and separator 1 to compute a new prng key: */ + (void)tc_hmac_init(&prng->h); + (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); + (void)tc_hmac_update(&prng->h, &separator1, sizeof(separator1)); + (void)tc_hmac_update(&prng->h, e, len); + (void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h); + /* configure the new prng key into the prng's instance of hmac */ + (void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); + + /* use the new key to compute a new state variable v */ + (void)tc_hmac_init(&prng->h); + (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); + (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h); +} + +int tc_hmac_prng_init(TCHmacPrng_t prng, + const uint8_t *personalization, + unsigned int plen) +{ + + /* input sanity check: */ + if (prng == (TCHmacPrng_t) 0 || + personalization == (uint8_t *) 0 || + plen > MAX_PLEN) { + return TC_CRYPTO_FAIL; + } + + /* put the generator into a known state: */ + _set(prng->key, 0x00, sizeof(prng->key)); + _set(prng->v, 0x01, sizeof(prng->v)); + tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); + /* update assumes SOME key has been configured into HMAC */ + + update(prng, personalization, plen); + + /* force a reseed before allowing tc_hmac_prng_generate to succeed: */ + prng->countdown = 0; + + return TC_CRYPTO_SUCCESS; +} + +int tc_hmac_prng_reseed(TCHmacPrng_t prng, + const uint8_t *seed, + unsigned int seedlen, + const uint8_t *additional_input, + unsigned int additionallen) +{ + + /* input sanity check: */ + if (prng == (TCHmacPrng_t) 0 || + seed == (const uint8_t *) 0 || + seedlen < MIN_SLEN || + seedlen > MAX_SLEN) { + return TC_CRYPTO_FAIL; + } + + if (additional_input != (const uint8_t *) 0) { + /* + * Abort if additional_input is provided but has inappropriate + * length + */ + if (additionallen == 0 || + additionallen > MAX_ALEN) { + return TC_CRYPTO_FAIL; + } else { + /* call update for the seed and additional_input */ + update(prng, seed, seedlen); + update(prng, additional_input, additionallen); + } + } else { + /* call update only for the seed */ + update(prng, seed, seedlen); + } + + /* ... and enable hmac_prng_generate */ + prng->countdown = MAX_GENS; + + return TC_CRYPTO_SUCCESS; +} + +int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng) +{ + unsigned int bufferlen; + + /* input sanity check: */ + if (out == (uint8_t *) 0 || + prng == (TCHmacPrng_t) 0 || + outlen == 0 || + outlen > MAX_OUT) { + return TC_CRYPTO_FAIL; + } else if (prng->countdown == 0) { + return TC_HMAC_PRNG_RESEED_REQ; + } + + prng->countdown--; + + while (outlen != 0) { + /* operate HMAC in OFB mode to create "random" outputs */ + (void)tc_hmac_init(&prng->h); + (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); + (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h); + + bufferlen = (TC_SHA256_DIGEST_SIZE > outlen) ? + outlen : TC_SHA256_DIGEST_SIZE; + (void)_copy(out, bufferlen, prng->v, bufferlen); + + out += bufferlen; + outlen = (outlen > TC_SHA256_DIGEST_SIZE) ? + (outlen - TC_SHA256_DIGEST_SIZE) : 0; + } + + /* block future PRNG compromises from revealing past state */ + update(prng, prng->v, TC_SHA256_DIGEST_SIZE); + + return TC_CRYPTO_SUCCESS; +} diff --git a/lib/bt/common/tinycrypt/src/sha256.c b/lib/bt/common/tinycrypt/src/sha256.c new file mode 100644 index 00000000..53fd6191 --- /dev/null +++ b/lib/bt/common/tinycrypt/src/sha256.c @@ -0,0 +1,221 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +static void compress(unsigned int *iv, const uint8_t *data); + +int tc_sha256_init(TCSha256State_t s) +{ + /* input sanity check: */ + if (s == (TCSha256State_t) 0) { + return TC_CRYPTO_FAIL; + } + + /* + * Setting the initial state values. + * These values correspond to the first 32 bits of the fractional parts + * of the square roots of the first 8 primes: 2, 3, 5, 7, 11, 13, 17 + * and 19. + */ + _set((uint8_t *) s, 0x00, sizeof(*s)); + s->iv[0] = 0x6a09e667; + s->iv[1] = 0xbb67ae85; + s->iv[2] = 0x3c6ef372; + s->iv[3] = 0xa54ff53a; + s->iv[4] = 0x510e527f; + s->iv[5] = 0x9b05688c; + s->iv[6] = 0x1f83d9ab; + s->iv[7] = 0x5be0cd19; + + return TC_CRYPTO_SUCCESS; +} + +int tc_sha256_update(TCSha256State_t s, const uint8_t *data, size_t datalen) +{ + /* input sanity check: */ + if (s == (TCSha256State_t) 0 || + data == (void *) 0) { + return TC_CRYPTO_FAIL; + } else if (datalen == 0) { + return TC_CRYPTO_SUCCESS; + } + + while (datalen-- > 0) { + s->leftover[s->leftover_offset++] = *(data++); + if (s->leftover_offset >= TC_SHA256_BLOCK_SIZE) { + compress(s->iv, s->leftover); + s->leftover_offset = 0; + s->bits_hashed += (TC_SHA256_BLOCK_SIZE << 3); + } + } + + return TC_CRYPTO_SUCCESS; +} + +int tc_sha256_final(uint8_t *digest, TCSha256State_t s) +{ + unsigned int i; + + /* input sanity check: */ + if (digest == (uint8_t *) 0 || + s == (TCSha256State_t) 0) { + return TC_CRYPTO_FAIL; + } + + s->bits_hashed += (s->leftover_offset << 3); + + s->leftover[s->leftover_offset++] = 0x80; /* always room for one byte */ + if (s->leftover_offset > (sizeof(s->leftover) - 8)) { + /* there is not room for all the padding in this block */ + _set(s->leftover + s->leftover_offset, 0x00, + sizeof(s->leftover) - s->leftover_offset); + compress(s->iv, s->leftover); + s->leftover_offset = 0; + } + + /* add the padding and the length in big-Endian format */ + _set(s->leftover + s->leftover_offset, 0x00, + sizeof(s->leftover) - 8 - s->leftover_offset); + s->leftover[sizeof(s->leftover) - 1] = (uint8_t)(s->bits_hashed); + s->leftover[sizeof(s->leftover) - 2] = (uint8_t)(s->bits_hashed >> 8); + s->leftover[sizeof(s->leftover) - 3] = (uint8_t)(s->bits_hashed >> 16); + s->leftover[sizeof(s->leftover) - 4] = (uint8_t)(s->bits_hashed >> 24); + s->leftover[sizeof(s->leftover) - 5] = (uint8_t)(s->bits_hashed >> 32); + s->leftover[sizeof(s->leftover) - 6] = (uint8_t)(s->bits_hashed >> 40); + s->leftover[sizeof(s->leftover) - 7] = (uint8_t)(s->bits_hashed >> 48); + s->leftover[sizeof(s->leftover) - 8] = (uint8_t)(s->bits_hashed >> 56); + + /* hash the padding and length */ + compress(s->iv, s->leftover); + + /* copy the iv out to digest */ + for (i = 0; i < TC_SHA256_STATE_BLOCKS; ++i) { + unsigned int t = *((unsigned int *) &s->iv[i]); + *digest++ = (uint8_t)(t >> 24); + *digest++ = (uint8_t)(t >> 16); + *digest++ = (uint8_t)(t >> 8); + *digest++ = (uint8_t)(t); + } + + /* destroy the current state */ + _set(s, 0, sizeof(*s)); + + return TC_CRYPTO_SUCCESS; +} + +/* + * Initializing SHA-256 Hash constant words K. + * These values correspond to the first 32 bits of the fractional parts of the + * cube roots of the first 64 primes between 2 and 311. + */ +static const unsigned int k256[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, + 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, + 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, + 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, + 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +static inline unsigned int ROTR(unsigned int a, unsigned int n) +{ + return (((a) >> n) | ((a) << (32 - n))); +} + +#define Sigma0(a)(ROTR((a), 2) ^ ROTR((a), 13) ^ ROTR((a), 22)) +#define Sigma1(a)(ROTR((a), 6) ^ ROTR((a), 11) ^ ROTR((a), 25)) +#define sigma0(a)(ROTR((a), 7) ^ ROTR((a), 18) ^ ((a) >> 3)) +#define sigma1(a)(ROTR((a), 17) ^ ROTR((a), 19) ^ ((a) >> 10)) + +#define Ch(a, b, c)(((a) & (b)) ^ ((~(a)) & (c))) +#define Maj(a, b, c)(((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c))) + +static inline unsigned int BigEndian(const uint8_t **c) +{ + unsigned int n = 0; + + n = (((unsigned int)(*((*c)++))) << 24); + n |= ((unsigned int)(*((*c)++)) << 16); + n |= ((unsigned int)(*((*c)++)) << 8); + n |= ((unsigned int)(*((*c)++))); + return n; +} + +static void compress(unsigned int *iv, const uint8_t *data) +{ + unsigned int a, b, c, d, e, f, g, h; + unsigned int s0, s1; + unsigned int t1, t2; + unsigned int work_space[16]; + unsigned int n; + unsigned int i; + + a = iv[0]; b = iv[1]; c = iv[2]; d = iv[3]; + e = iv[4]; f = iv[5]; g = iv[6]; h = iv[7]; + + for (i = 0; i < 16; ++i) { + n = BigEndian(&data); + t1 = work_space[i] = n; + t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i]; + t2 = Sigma0(a) + Maj(a, b, c); + h = g; g = f; f = e; e = d + t1; + d = c; c = b; b = a; a = t1 + t2; + } + + for ( ; i < 64; ++i) { + s0 = work_space[(i+1)&0x0f]; + s0 = sigma0(s0); + s1 = work_space[(i+14)&0x0f]; + s1 = sigma1(s1); + + t1 = work_space[i&0xf] += s0 + s1 + work_space[(i+9)&0xf]; + t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i]; + t2 = Sigma0(a) + Maj(a, b, c); + h = g; g = f; f = e; e = d + t1; + d = c; c = b; b = a; a = t1 + t2; + } + + iv[0] += a; iv[1] += b; iv[2] += c; iv[3] += d; + iv[4] += e; iv[5] += f; iv[6] += g; iv[7] += h; +} diff --git a/lib/bt/common/tinycrypt/src/utils.c b/lib/bt/common/tinycrypt/src/utils.c new file mode 100644 index 00000000..8f8278bb --- /dev/null +++ b/lib/bt/common/tinycrypt/src/utils.c @@ -0,0 +1,80 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* utils.c - TinyCrypt platform-dependent run-time operations */ + +#include +#include + +#include + +#define MASK_TWENTY_SEVEN 0x1b + +unsigned int _copy(uint8_t *to, unsigned int to_len, + const uint8_t *from, unsigned int from_len) +{ + if (from_len <= to_len) { + (void)memcpy(to, from, from_len); + return from_len; + } else { + return TC_CRYPTO_FAIL; + } +} + +void _set(void *to, uint8_t val, unsigned int len) +{ + (void)memset(to, val, len); +} + +/* + * Doubles the value of a byte for values up to 127. + */ +uint8_t _double_byte(uint8_t a) +{ + return ((a<<1) ^ ((a>>7) * MASK_TWENTY_SEVEN)); +} + +int _compare(const uint8_t *a, const uint8_t *b, size_t size) +{ + const uint8_t *tempa = a; + const uint8_t *tempb = b; + uint8_t result = 0; + + for (unsigned int i = 0; i < size; i++) { + result |= tempa[i] ^ tempb[i]; + } + return result; +} diff --git a/lib/bt/controller/esp32/Kconfig.in b/lib/bt/controller/esp32/Kconfig.in index 7254a6ae..d3c04a11 100644 --- a/lib/bt/controller/esp32/Kconfig.in +++ b/lib/bt/controller/esp32/Kconfig.in @@ -23,6 +23,14 @@ config BTDM_CTRL_BLE_MAX_CONN BLE maximum connections of bluetooth controller. Each connection uses 1KB static DRAM whenever the BT controller is enabled. +config BTDM_CTRL_BR_EDR_MIN_ENC_KEY_SZ_DFT + int "BR/EDR default minimum size of encryption key" + depends on BTDM_CTRL_MODE_BR_EDR_ONLY || BTDM_CTRL_MODE_BTDM + default 7 + range 7 16 + help + BR/EDR default minimum size of encryption key when start encryption. + config BTDM_CTRL_BR_EDR_MAX_ACL_CONN int "BR/EDR ACL Max Connections" depends on BTDM_CTRL_MODE_BR_EDR_ONLY || BTDM_CTRL_MODE_BTDM @@ -67,7 +75,7 @@ config BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF default 0 menuconfig BTDM_CTRL_PCM_ROLE_EDGE_CONFIG - bool "PCM Signal Config (Role and Polar)" + bool "PCM Signal Configurations: Role, Polar and Channel Mode(Stereo/Mono)" depends on BTDM_CTRL_BR_EDR_SCO_DATA_PATH_PCM default y @@ -95,6 +103,37 @@ choice BTDM_CTRL_PCM_POLAR bool "Rising Edge" endchoice +choice BTDM_CTRL_PCM_FSYNCSHP + prompt "Channel Mode(Stereo/Mono)" + depends on BTDM_CTRL_PCM_ROLE_EDGE_CONFIG + default BTDM_CTRL_PCM_FSYNCSHP_STEREO_MODE + help + PCM frame synchronization signal shape can be configured as Stereo Mode or Mono Mode. + (There are detailed instructions under the path examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md) + + config BTDM_CTRL_PCM_FSYNCSHP_STEREO_MODE + bool "Stereo Mode" + help + Stereo Mode(Dual channel): FSYNC and DOUT signals both change simultaneously on the edge of CLK. + The FSYNC signal continues until the end of the current channel-data transmission. + (There is a waveform graph under the path examples/bluetooth/bluedroid/classic_bt/hfp_ag/image) + + config BTDM_CTRL_PCM_FSYNCSHP_MONO_MODE_LF + bool "Mono Mode 1" + help + Mono Mode 1(Single channel): FSYNC signal starts to change a CLK clock cycle earlier than the DOUT signal. + The FSYNC signal continues for one extra CLK clock cycle. + (There is a waveform graph under the path examples/bluetooth/bluedroid/classic_bt/hfp_ag/image) + + config BTDM_CTRL_PCM_FSYNCSHP_MONO_MODE_FF + bool "Mono Mode 2" + help + Mono Mode 2(Single channel): FSYNC and DOUT signals both change simultaneously on the edge of CLK. + The FSYNC signal continues for one extra CLK clock cycle. + (There is a waveform graph under the path examples/bluetooth/bluedroid/classic_bt/hfp_ag/image) + +endchoice + config BTDM_CTRL_PCM_ROLE_EFF int default 0 if BTDM_CTRL_PCM_ROLE_MASTER @@ -107,6 +146,13 @@ config BTDM_CTRL_PCM_POLAR_EFF default 1 if BTDM_CTRL_PCM_POLAR_RISING_EDGE default 0 +config BTDM_CTRL_PCM_FSYNCSHP_EFF + int + default 0 if BTDM_CTRL_PCM_FSYNCSHP_STEREO_MODE + default 1 if BTDM_CTRL_PCM_FSYNCSHP_MONO_MODE_LF + default 2 if BTDM_CTRL_PCM_FSYNCSHP_MONO_MODE_FF + default 0 + config BTDM_CTRL_AUTO_LATENCY bool "Auto latency" depends on BTDM_CTRL_MODE_BTDM @@ -139,6 +185,11 @@ config BTDM_CTRL_BLE_MAX_CONN_EFF default BTDM_CTRL_BLE_MAX_CONN if BTDM_CTRL_MODE_BLE_ONLY || BTDM_CTRL_MODE_BTDM default 0 +config BTDM_CTRL_BR_EDR_MIN_ENC_KEY_SZ_DFT_EFF + int + default BTDM_CTRL_BR_EDR_MIN_ENC_KEY_SZ_DFT if BTDM_CTRL_MODE_BR_EDR_ONLY || BTDM_CTRL_MODE_BTDM + default 0 + config BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF int default BTDM_CTRL_BR_EDR_MAX_ACL_CONN if BTDM_CTRL_MODE_BR_EDR_ONLY || BTDM_CTRL_MODE_BTDM @@ -262,10 +313,10 @@ menu "MODEM SLEEP Options" the bluetooth low power clock source. config BTDM_CTRL_LPCLK_SEL_EXT_32K_XTAL - bool "External 32kHz crystal" - depends on RTC_CLK_SRC_EXT_CRYS + bool "External 32kHz crystal/oscillator" + depends on RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC help - External 32kHz crystal has a nominal frequency of 32.768kHz and provides good frequency + External 32kHz crystal/oscillator has a nominal frequency of 32.768kHz and provides good frequency stability. If used as Bluetooth low power clock, External 32kHz can support Bluetooth modem sleep to be used with both DFS and light sleep. endchoice @@ -282,7 +333,7 @@ choice BTDM_BLE_SLEEP_CLOCK_ACCURACY needs a larger RX window to synchronize with master in each anchor point, thus resulting in an increase of power consumption but a higher level of robustness in keeping connected. According to the requirements of Bluetooth Core specification 4.2, the worst-case accuracy of Classic - Bluetooth low power oscialltor(LPO) is +/-250ppm in STANDBY and in low power modes such as + Bluetooth Low Power Oscillator (LPO) is +/-250ppm in STANDBY and in low power modes such as sniff. For BLE the worst-case SCA is +/-500ppm. - "151ppm to 250ppm" option is the default value for Bluetooth Dual mode @@ -403,9 +454,18 @@ config BTDM_CTRL_SCAN_BACKOFF_UPPERLIMITMAX default n help Disable active scan backoff. The bluetooth spec requires that scanners should run a backoff procedure to - minimize collision of scan request PDUs from nultiple scanners. If scan backoff is disabled, in active + minimize collision of scan request PDUs from multiple scanners. If scan backoff is disabled, in active scanning, scan request PDU will be sent every time when HW receives scannable ADV PDU. +config BTDM_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS + bool "Enable enhanced Access Address check in CONNECT_IND" + default n + help + Enabling this option will add stricter verification of the Access Address in the CONNECT_IND PDU. + This improves security by ensuring that only connection requests with valid Access Addresses are accepted. + If disabled, only basic checks are applied, improving compatibility. + + config BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP bool "BLE adv report flow control supported" depends on (BTDM_CTRL_MODE_BTDM || BTDM_CTRL_MODE_BLE_ONLY) @@ -440,6 +500,48 @@ config BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD If you set `BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD` to a small value or printf every adv lost event, it may cause adv packets lost more. +menu "BLE disconnects when Instant Passed (0x28) occurs" + config BTDM_BLE_LLCP_CONN_UPDATE + bool "BLE ACL connection update procedure" + depends on (BTDM_CTRL_MODE_BLE_ONLY || BTDM_CTRL_MODE_BTDM) + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs during connection update procedure. + + config BTDM_BLE_LLCP_CHAN_MAP_UPDATE + bool "BLE ACL channel map update procedure" + depends on (BTDM_CTRL_MODE_BLE_ONLY || BTDM_CTRL_MODE_BTDM) + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs in channel map update procedure. +endmenu + +config BTDM_BLE_CHAN_ASS_EN + bool "Enable channel assessment" + depends on (BTDM_CTRL_MODE_BLE_ONLY || BTDM_CTRL_MODE_BTDM) + default y + help + If this option is enabled, The Controller will records the communication quality + for each channel and then start a timer to check and update the channel map every 4 seconds. + +config BTDM_BLE_PING_EN + bool "Enable LE Ping procedure" + depends on (BTDM_CTRL_MODE_BTDM || BTDM_CTRL_MODE_BLE_ONLY) + default y + help + If this option is disabled, The Controller will not start the LE authenticated payload timer. + This option is used for some compatibility problems related to LE ping procedure. + +config BTDM_CTRL_CONTROLLER_DEBUG_MODE_1 + bool "Enable Bluetooth controller debugging mode 1 (for internal use only)" + default n + depends on BT_ENABLED + help + Enables specific debugging features for the Bluetooth controller. + This option is strictly for internal debugging purposes and should not be enabled in production environments, + as it may impact performance and stability. config BTDM_RESERVE_DRAM hex diff --git a/lib/bt/controller/esp32/bt.c b/lib/bt/controller/esp32/bt.c index f26dd4bc..4f95d120 100644 --- a/lib/bt/controller/esp32/bt.c +++ b/lib/bt/controller/esp32/bt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -48,6 +48,10 @@ #include "esp_rom_sys.h" #include "hli_api.h" +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED +#include "ble_log/ble_log_spi_out.h" +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + #if CONFIG_BT_ENABLED /* Macro definition @@ -96,6 +100,7 @@ do{\ #define OSI_VERSION 0x00010005 #define OSI_MAGIC_VALUE 0xFADEBEAD +#define BLE_CONTROLLER_MALLOC_CAPS (MALLOC_CAP_8BIT|MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL) /* Types definition ************************************************************************ */ @@ -248,6 +253,16 @@ extern void config_bt_funcs_reset(void); extern void config_ble_funcs_reset(void); extern void config_btdm_funcs_reset(void); +#ifdef CONFIG_BT_BLUEDROID_ENABLED +extern void bt_stack_enableSecCtrlVsCmd(bool en); +#endif // CONFIG_BT_BLUEDROID_ENABLED +#if defined(CONFIG_BT_NIMBLE_ENABLED) || defined(CONFIG_BT_BLUEDROID_ENABLED) +extern void bt_stack_enableCoexVsCmd(bool en); +extern void scan_stack_enableAdvFlowCtrlVsCmd(bool en); +extern void adv_stack_enableClearLegacyAdvVsCmd(bool en); +extern void advFilter_stack_enableDupExcListVsCmd(bool en); +#endif // (CONFIG_BT_NIMBLE_ENABLED) || (CONFIG_BT_BLUEDROID_ENABLED) + /* Local Function Declare ********************************************************************* */ @@ -448,7 +463,11 @@ static DRAM_ATTR uint8_t btdm_lpcycle_us_frac = 0; // number of fractional bit f #if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG // used low power clock -static DRAM_ATTR uint8_t btdm_lpclk_sel; +#if CONFIG_BTDM_CTRL_LPCLK_SEL_EXT_32K_XTAL +static DRAM_ATTR uint8_t btdm_lpclk_sel = ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL; +#else +static DRAM_ATTR uint8_t btdm_lpclk_sel = ESP_BT_SLEEP_CLOCK_MAIN_XTAL; +#endif /* CONFIG_BTDM_CTRL_LPCLK_SEL_EXT_32K_XTAL */ #endif /* #ifdef CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG */ static DRAM_ATTR QueueHandle_t s_wakeup_req_sem = NULL; @@ -868,7 +887,21 @@ static int IRAM_ATTR cause_sw_intr_to_core_wrapper(int core_id, int intr_no) static void *malloc_internal_wrapper(size_t size) { - return heap_caps_malloc(size, MALLOC_CAP_8BIT|MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL); + return heap_caps_malloc(size, BLE_CONTROLLER_MALLOC_CAPS); +} + +void *malloc_ble_controller_mem(size_t size) +{ + void *p = heap_caps_malloc(size, BLE_CONTROLLER_MALLOC_CAPS); + if(p == NULL) { + ESP_LOGE(BTDM_LOG_TAG, "Malloc failed"); + } + return p; +} + +uint32_t get_ble_controller_free_heap_size(void) +{ + return heap_caps_get_free_size(BLE_CONTROLLER_MALLOC_CAPS); } static int32_t IRAM_ATTR read_mac_wrapper(uint8_t mac[6]) @@ -932,7 +965,7 @@ static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles) assert(us_to_sleep > BTDM_MIN_TIMER_UNCERTAINTY_US); // allow a maximum time uncertainty to be about 488ppm(1/2048) at least as clock drift // and set the timer in advance - uint32_t uncertainty = (us_to_sleep >> 11); + uint32_t uncertainty = (us_to_sleep / 1000); if (uncertainty < BTDM_MIN_TIMER_UNCERTAINTY_US) { uncertainty = BTDM_MIN_TIMER_UNCERTAINTY_US; } @@ -1027,9 +1060,8 @@ static bool async_wakeup_request(int event) switch (event) { case BTDM_ASYNC_WAKEUP_REQ_HCI: - btdm_in_wakeup_requesting_set(true); - // NO break case BTDM_ASYNC_WAKEUP_REQ_CTRL_DISA: + btdm_in_wakeup_requesting_set(true); if (!btdm_power_state_active()) { do_wakeup_request = true; @@ -1062,10 +1094,10 @@ static void async_wakeup_request_end(int event) bool request_lock = false; switch (event) { case BTDM_ASYNC_WAKEUP_REQ_HCI: + case BTDM_ASYNC_WAKEUP_REQ_CTRL_DISA: request_lock = true; break; case BTDM_ASYNC_WAKEUP_REQ_COEX: - case BTDM_ASYNC_WAKEUP_REQ_CTRL_DISA: request_lock = false; break; default: @@ -1330,7 +1362,8 @@ static esp_err_t esp_bt_controller_rom_mem_release(esp_bt_mode_t mode) //already released if (!(mode & btdm_dram_available_region[0].mode)) { - return ESP_ERR_INVALID_STATE; + ESP_LOGW(BTDM_LOG_TAG, "%s already released, mode %d",__func__, mode); + return ESP_OK; } for (int i = 0; i < sizeof(btdm_dram_available_region)/sizeof(btdm_dram_available_region_t); i++) { @@ -1432,6 +1465,14 @@ esp_err_t esp_bt_mem_release(esp_bt_mode_t mode) .name = "BT Controller Data" }; + /* + * Free data and BSS section for Bluetooth controller ROM code. + * Note that rom mem release must be performed before section _bt_data_start to _bt_data_end is released, + * otherwise `btdm_dram_available_region` will no longer be available when performing rom mem release and + * thus causing heap corruption. + */ + ret = esp_bt_controller_rom_mem_release(mode); + if (mode == ESP_BT_MODE_BTDM) { /* Start by freeing Bluetooth BSS section */ if (ret == ESP_OK) { @@ -1444,11 +1485,6 @@ esp_err_t esp_bt_mem_release(esp_bt_mode_t mode) } } - /* free data and BSS section for Bluetooth controller ROM code */ - if (ret == ESP_OK) { - ret = esp_bt_controller_rom_mem_release(mode); - } - return ret; } @@ -1472,6 +1508,117 @@ static void hli_queue_setup_pinned_to_core(int core_id) } #endif /* CONFIG_BTDM_CTRL_HLI */ +// init low-power control resources +static esp_err_t btdm_low_power_mode_init(void) +{ + esp_err_t err = ESP_OK; + +#ifdef CONFIG_PM_ENABLE + s_btdm_allow_light_sleep = false; +#endif + + // set default sleep clock cycle and its fractional bits + btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; + btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); + +#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG + if (btdm_lpclk_sel == ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL) { + // check whether or not EXT_CRYS is working + if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { +#ifdef CONFIG_PM_ENABLE + s_btdm_allow_light_sleep = true; +#endif + } else { + ESP_LOGW(BTDM_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock\n" + "light sleep mode will not be able to apply when bluetooth is enabled"); + btdm_lpclk_sel = ESP_BT_SLEEP_CLOCK_MAIN_XTAL; // set default value + } + } else if (btdm_lpclk_sel != ESP_BT_SLEEP_CLOCK_MAIN_XTAL) { + assert(0); + } + + bool select_src_ret __attribute__((unused)); + bool set_div_ret __attribute__((unused)); + if (btdm_lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL) { + select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL); + set_div_ret = btdm_lpclk_set_div(esp_clk_xtal_freq() * 2 / MHZ - 1); + assert(select_src_ret && set_div_ret); + btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; + btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); + } else { // btdm_lpclk_sel == BTDM_LPCLK_SEL_XTAL32K + select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL32K); + set_div_ret = btdm_lpclk_set_div(0); + assert(select_src_ret && set_div_ret); + btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; + btdm_lpcycle_us = (RTC_CLK_CAL_FRACT > 15) ? (1000000 << (RTC_CLK_CAL_FRACT - 15)) : + (1000000 >> (15 - RTC_CLK_CAL_FRACT)); + assert(btdm_lpcycle_us != 0); + } + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_ORIG); + +#elif CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_EVED + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_EVED); +#else + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); +#endif + +#ifdef CONFIG_PM_ENABLE + if (!s_btdm_allow_light_sleep) { + if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) { + return err; + } + } + if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) { + return err; + } + esp_timer_create_args_t create_args = { + .callback = btdm_slp_tmr_callback, + .arg = NULL, + .name = "btSlp" + }; + if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) { + return err; + } + + s_pm_lock_acquired = true; +#endif + + return err; +} + +esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void) +{ +#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG + if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED && + btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return ESP_BT_SLEEP_CLOCK_NONE; + } + return btdm_lpclk_sel; +#else + return ESP_BT_SLEEP_CLOCK_NONE; +#endif +} + +esp_err_t esp_bt_set_lpclk_src(esp_bt_sleep_clock_t lpclk) +{ +#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG + if (lpclk < ESP_BT_SLEEP_CLOCK_MAIN_XTAL || lpclk > ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL) { + return ESP_ERR_INVALID_ARG; + } + + if (btdm_controller_status == ESP_BT_CONTROLLER_STATUS_INITED || + btdm_controller_status == ESP_BT_CONTROLLER_STATUS_ENABLED) { + ESP_LOGW(BTDM_LOG_TAG, "Please set the Bluetooth sleep clock source before Bluetooth initialization"); + return ESP_ERR_INVALID_STATE; + } + + btdm_lpclk_sel = lpclk; + return ESP_OK; +#else + return ESP_ERR_NOT_SUPPORTED; +#endif +} + esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) { esp_err_t err; @@ -1534,58 +1681,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) btdm_controller_mem_init(); periph_module_enable(PERIPH_BT_MODULE); - -#ifdef CONFIG_PM_ENABLE - s_btdm_allow_light_sleep = false; -#endif - - // set default sleep clock cycle and its fractional bits - btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; - btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); - -#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG - - btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value -#if CONFIG_BTDM_CTRL_LPCLK_SEL_EXT_32K_XTAL - // check whether or not EXT_CRYS is working - if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { - btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL32K; // External 32kHz XTAL -#ifdef CONFIG_PM_ENABLE - s_btdm_allow_light_sleep = true; -#endif - } else { - ESP_LOGW(BTDM_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock\n" - "light sleep mode will not be able to apply when bluetooth is enabled"); - btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value - } -#else - btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value -#endif - - bool select_src_ret __attribute__((unused)); - bool set_div_ret __attribute__((unused)); - if (btdm_lpclk_sel == BTDM_LPCLK_SEL_XTAL) { - select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL); - set_div_ret = btdm_lpclk_set_div(esp_clk_xtal_freq() * 2 / MHZ - 1); - assert(select_src_ret && set_div_ret); - btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; - btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); - } else { // btdm_lpclk_sel == BTDM_LPCLK_SEL_XTAL32K - select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL32K); - set_div_ret = btdm_lpclk_set_div(0); - assert(select_src_ret && set_div_ret); - btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; - btdm_lpcycle_us = (RTC_CLK_CAL_FRACT > 15) ? (1000000 << (RTC_CLK_CAL_FRACT - 15)) : - (1000000 >> (15 - RTC_CLK_CAL_FRACT)); - assert(btdm_lpcycle_us != 0); - } - btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_ORIG); - -#elif CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_EVED - btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_EVED); -#else - btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); -#endif + periph_module_reset(PERIPH_BT_MODULE); #if CONFIG_BTDM_CTRL_HCI_UART_FLOW_CTRL_EN sdk_config_set_uart_flow_ctrl_enable(true); @@ -1593,44 +1689,53 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) sdk_config_set_uart_flow_ctrl_enable(false); #endif -#ifdef CONFIG_PM_ENABLE - if (!s_btdm_allow_light_sleep) { - if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) { - goto error; - } - } - if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) { - goto error; - } - esp_timer_create_args_t create_args = { - .callback = btdm_slp_tmr_callback, - .arg = NULL, - .name = "btSlp" - }; - if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) { + if ((err = btdm_low_power_mode_init()) != ESP_OK) { + ESP_LOGE(BTDM_LOG_TAG, "Low power module initialization failed"); goto error; } - s_pm_lock_acquired = true; -#endif - #if CONFIG_SW_COEXIST_ENABLE coex_init(); #endif +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + if (ble_log_spi_out_init() != 0) { + ESP_LOGE(BTDM_LOG_TAG, "BLE Log SPI output init failed"); + err = ESP_ERR_NO_MEM; + goto error; + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + btdm_cfg_mask = btdm_config_mask_load(); - if (btdm_controller_init(btdm_cfg_mask, cfg) != 0) { + err = btdm_controller_init(btdm_cfg_mask, cfg); + + if (err != 0) { + ESP_LOGE(BTDM_LOG_TAG, "%s %d\n",__func__,err); err = ESP_ERR_NO_MEM; goto error; } +#ifdef CONFIG_BT_BLUEDROID_ENABLED + bt_stack_enableSecCtrlVsCmd(true); +#endif // CONFIG_BT_BLUEDROID_ENABLED +#if defined(CONFIG_BT_NIMBLE_ENABLED) || defined(CONFIG_BT_BLUEDROID_ENABLED) + bt_stack_enableCoexVsCmd(true); + scan_stack_enableAdvFlowCtrlVsCmd(true); + adv_stack_enableClearLegacyAdvVsCmd(true); + advFilter_stack_enableDupExcListVsCmd(true); +#endif // (CONFIG_BT_NIMBLE_ENABLED) || (CONFIG_BT_BLUEDROID_ENABLED) + btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; return ESP_OK; error: +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + bt_controller_deinit_internal(); return err; @@ -1642,17 +1747,30 @@ esp_err_t esp_bt_controller_deinit(void) return ESP_ERR_INVALID_STATE; } +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + btdm_controller_deinit(); bt_controller_deinit_internal(); +#ifdef CONFIG_BT_BLUEDROID_ENABLED + bt_stack_enableSecCtrlVsCmd(false); +#endif // CONFIG_BT_BLUEDROID_ENABLED +#if defined(CONFIG_BT_NIMBLE_ENABLED) || defined(CONFIG_BT_BLUEDROID_ENABLED) + bt_stack_enableCoexVsCmd(false); + scan_stack_enableAdvFlowCtrlVsCmd(false); + adv_stack_enableClearLegacyAdvVsCmd(false); + advFilter_stack_enableDupExcListVsCmd(false); +#endif // (CONFIG_BT_NIMBLE_ENABLED) || (CONFIG_BT_BLUEDROID_ENABLED) + return ESP_OK; } -static void bt_controller_deinit_internal(void) +// deinit low power control resources +static void btdm_low_power_mode_deinit(void) { - periph_module_disable(PERIPH_BT_MODULE); - #ifdef CONFIG_PM_ENABLE if (!s_btdm_allow_light_sleep) { esp_pm_lock_delete(s_light_sleep_pm_lock); @@ -1673,6 +1791,16 @@ static void bt_controller_deinit_internal(void) s_pm_lock_acquired = false; #endif + btdm_lpcycle_us = 0; + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); +} + +static void bt_controller_deinit_internal(void) +{ + periph_module_disable(PERIPH_BT_MODULE); + + btdm_low_power_mode_deinit(); + if (s_wakeup_req_sem) { semphr_delete_wrapper(s_wakeup_req_sem); s_wakeup_req_sem = NULL; @@ -1685,9 +1813,6 @@ static void bt_controller_deinit_internal(void) btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; - btdm_lpcycle_us = 0; - btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); - esp_bt_power_domain_off(); esp_phy_modem_deinit(); @@ -1798,6 +1923,7 @@ esp_err_t esp_bt_controller_disable(void) while (!btdm_power_state_active()) { esp_rom_delay_us(1000); } + async_wakeup_request_end(BTDM_ASYNC_WAKEUP_REQ_CTRL_DISA); } btdm_controller_disable(); @@ -1910,7 +2036,7 @@ esp_err_t esp_bredr_sco_datapath_set(esp_sco_data_path_t data_path) return ESP_OK; } -esp_err_t esp_ble_scan_dupilcate_list_flush(void) +esp_err_t esp_ble_scan_duplicate_list_flush(void) { if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { return ESP_ERR_INVALID_STATE; @@ -1919,6 +2045,11 @@ esp_err_t esp_ble_scan_dupilcate_list_flush(void) return ESP_OK; } +esp_err_t esp_ble_scan_dupilcate_list_flush(void) +{ + return esp_ble_scan_duplicate_list_flush(); +} + /** * This function re-write controller's function, * As coredump can not show parameters in function which is in a .a file. diff --git a/lib/bt/controller/esp32c2/Kconfig.in b/lib/bt/controller/esp32c2/Kconfig.in index 9a04ae63..c720fcb8 100644 --- a/lib/bt/controller/esp32c2/Kconfig.in +++ b/lib/bt/controller/esp32c2/Kconfig.in @@ -2,15 +2,15 @@ menu "HCI Config" choice BT_LE_HCI_INTERFACE - prompt "Select HCI interface" + prompt "HCI mode" default BT_LE_HCI_INTERFACE_USE_RAM config BT_LE_HCI_INTERFACE_USE_RAM - bool "ram" + bool "VHCI" help Use RAM as HCI interface config BT_LE_HCI_INTERFACE_USE_UART - bool "uart" + bool "UART(H4)" help Use UART as HCI interface endchoice @@ -73,12 +73,26 @@ menu "HCI Config" UART_PARITY_ODD endchoice - config BT_LE_HCI_UART_TASK_STACK_SIZE - int "HCI uart task stack size" - depends on BT_LE_HCI_INTERFACE_USE_UART - default 1000 + config BT_LE_HCI_UART_RX_BUFFER_SIZE + int "The size of rx ring buffer memory" + depends on !BT_LE_HCI_INTERFACE_USE_RAM + default 512 + help + The size of rx ring buffer memory + + config BT_LE_HCI_UART_TX_BUFFER_SIZE + int "The size of tx ring buffer memory" + depends on !BT_LE_HCI_INTERFACE_USE_RAM + default 256 + help + The size of tx ring buffer memory + + config BT_LE_HCI_TRANS_TASK_STACK_SIZE + int "HCI transport task stack size" + depends on !BT_LE_HCI_INTERFACE_USE_RAM + default 2048 help - Set the size of uart task stack + This configures stack size of hci transport task endmenu config BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT @@ -95,85 +109,99 @@ menuconfig BT_LE_50_FEATURE_SUPPORT help Enable BLE 5 feature -config BT_LE_LL_CFG_FEAT_LE_2M_PHY - bool "Enable 2M Phy" - depends on BT_LE_50_FEATURE_SUPPORT - default y - help - Enable 2M-PHY - -config BT_LE_LL_CFG_FEAT_LE_CODED_PHY - bool "Enable coded Phy" - depends on BT_LE_50_FEATURE_SUPPORT - default y - help - Enable coded-PHY - -config BT_LE_EXT_ADV - bool "Enable extended advertising" - depends on BT_LE_50_FEATURE_SUPPORT - default y - help - Enable this option to do extended advertising. Extended advertising - will be supported from BLE 5.0 onwards. - -if BT_LE_EXT_ADV - config BT_LE_MAX_EXT_ADV_INSTANCES - int "Maximum number of extended advertising instances." - range 0 4 - default 1 - depends on BT_LE_EXT_ADV - help - Change this option to set maximum number of extended advertising - instances. Minimum there is always one instance of - advertising. Enter how many more advertising instances you - want. - Each extended advertising instance will take about 0.5k DRAM. - - config BT_LE_EXT_ADV_MAX_SIZE - int "Maximum length of the advertising data." - range 0 1650 - default 1650 - depends on BT_LE_EXT_ADV +if BT_LE_50_FEATURE_SUPPORT + config BT_LE_LL_CFG_FEAT_LE_2M_PHY + bool "Enable 2M Phy" + depends on BT_LE_50_FEATURE_SUPPORT + default y help - Defines the length of the extended adv data. The value should not - exceed 1650. + Enable 2M-PHY - config BT_LE_ENABLE_PERIODIC_ADV - bool "Enable periodic advertisement." + config BT_LE_LL_CFG_FEAT_LE_CODED_PHY + bool "Enable coded Phy" + depends on BT_LE_50_FEATURE_SUPPORT default y - depends on BT_LE_EXT_ADV help - Enable this option to start periodic advertisement. + Enable coded-PHY - config BT_LE_PERIODIC_ADV_SYNC_TRANSFER - bool "Enable Transfer Sync Events" - depends on BT_LE_ENABLE_PERIODIC_ADV + config BT_LE_EXT_ADV + bool "Enable extended advertising" + depends on BT_LE_50_FEATURE_SUPPORT default y help - This enables controller transfer periodic sync events to host + Enable this option to do extended advertising. Extended advertising + will be supported from BLE 5.0 onwards. + + if BT_LE_EXT_ADV + config BT_LE_MAX_EXT_ADV_INSTANCES + int "Maximum number of extended advertising instances." + range 0 4 + default 1 + depends on BT_LE_EXT_ADV + help + Change this option to set maximum number of extended advertising + instances. Minimum there is always one instance of + advertising. Enter how many more advertising instances you + want. + Each extended advertising instance will take about 0.5k DRAM. + + config BT_LE_EXT_ADV_MAX_SIZE + int "Maximum length of the advertising data." + range 0 1650 + default 1650 + depends on BT_LE_EXT_ADV + help + Defines the length of the extended adv data. The value should not + exceed 1650. -endif + config BT_LE_ENABLE_PERIODIC_ADV + bool "Enable periodic advertisement." + default y + depends on BT_LE_EXT_ADV + help + Enable this option to start periodic advertisement. -config BT_LE_MAX_PERIODIC_SYNCS - int "Maximum number of periodic advertising syncs" - depends on BT_LE_50_FEATURE_SUPPORT && !BT_NIMBLE_ENABLED + config BT_LE_PERIODIC_ADV_SYNC_TRANSFER + bool "Enable Transfer Sync Events" + depends on BT_LE_ENABLE_PERIODIC_ADV + default y + help + This enables controller transfer periodic sync events to host + endif - range 0 3 - default 1 if BT_LE_ENABLE_PERIODIC_ADV - default 0 - help - Set this option to set the upper limit for number of periodic sync - connections. This should be less than maximum connections allowed by - controller. + config BT_LE_EXT_SCAN + bool "Enable extended scanning" + depends on BT_LE_50_FEATURE_SUPPORT && BT_LE_ROLE_OBSERVER_ENABLE + default y + help + Enable this option to do extended scanning. -config BT_LE_MAX_PERIODIC_ADVERTISER_LIST - int "Maximum number of periodic advertiser list" - depends on BT_LE_50_FEATURE_SUPPORT && !BT_NIMBLE_ENABLED - range 1 5 - default 5 - help - Set this option to set the upper limit for number of periodic advertiser list. + config BT_LE_ENABLE_PERIODIC_SYNC + bool "Enable periodic sync" + default y + depends on BT_LE_EXT_SCAN + help + Enable this option to receive periodic advertisement. + + if BT_LE_ENABLE_PERIODIC_SYNC + config BT_LE_MAX_PERIODIC_SYNCS + int "Maximum number of periodic advertising syncs" + range 0 3 + default 1 if BT_LE_ENABLE_PERIODIC_ADV + default 0 + help + Set this option to set the upper limit for number of periodic sync + connections. This should be less than maximum connections allowed by + controller. + + config BT_LE_MAX_PERIODIC_ADVERTISER_LIST + int "Maximum number of periodic advertiser list" + range 1 5 + default 5 + help + Set this option to set the upper limit for number of periodic advertiser list. + endif +endif menu "Memory Settings" depends on !BT_NIMBLE_ENABLED @@ -280,6 +308,33 @@ config BT_LE_CONTROLLER_LOG_DUMP_ONLY help Only operate in dump mode +config BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + bool "Output ble controller logs to SPI bus (Experimental)" + depends on BT_LE_CONTROLLER_LOG_ENABLED + depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY + select BT_BLE_LOG_SPI_OUT_ENABLED + default n + help + Output ble controller logs to SPI bus + +config BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + bool "Store ble controller logs to flash(Experimental)" + depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Store ble controller logs to flash memory. + +config BT_LE_CONTROLLER_LOG_PARTITION_SIZE + int "size of ble controller log partition(Multiples of 4K)" + depends on BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + default 65536 + help + The size of ble controller log partition shall be a multiples of 4K. + The name of log partition shall be "bt_ctrl_log". + The partition type shall be ESP_PARTITION_TYPE_DATA. + The partition sub_type shall be ESP_PARTITION_SUBTYPE_ANY. + config BT_LE_LOG_CTRL_BUF1_SIZE int "size of the first BLE controller LOG buffer" depends on BT_LE_CONTROLLER_LOG_ENABLED @@ -301,6 +356,19 @@ config BT_LE_LOG_HCI_BUF_SIZE help Configure the size of the BLE HCI LOG buffer. +config BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE + bool "Enable wrap panic handler" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Wrap esp_panic_handler to get controller logs when PC pointer exception crashes. + +config BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE + bool "Enable esp_task_wdt_isr_user_handler implementation" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Implement esp_task_wdt_isr_user_handler to get controller logs when task wdt issue is triggered. config BT_LE_LL_RESOLV_LIST_SIZE int "BLE LL Resolving list size" range 1 5 @@ -356,7 +424,7 @@ config BT_LE_CRYPTO_STACK_MBEDTLS config BT_LE_WHITELIST_SIZE int "BLE white list size" - range 1 15 + range 1 31 default 12 depends on !BT_NIMBLE_ENABLED @@ -377,6 +445,23 @@ config BT_LE_LL_SCA help Sleep clock accuracy of our device (in ppm) +config BT_LE_LL_PEER_SCA_SET_ENABLE + bool "Enable to set constant peer SCA" + default n + help + Enable setting of constant peer SCA, use this if peer device has SCA larger than 500 PPM. + Enable this option, the controller will always use BT_LE_LL_PEER_SCA as the peer SCA value + to calculate the window widening instead of the value received from peer device. + + +config BT_LE_LL_PEER_SCA + int "Constant peer sleep clock accuracy value" + range 0 10000 + depends on BT_LE_LL_PEER_SCA_SET_ENABLE + default 0 + help + Set the sleep clock accuracy of peer device + config BT_LE_MAX_CONNECTIONS int "Maximum number of concurrent connections" depends on !BT_NIMBLE_ENABLED @@ -491,14 +576,22 @@ config BT_LE_TX_CCA_ENABLED help Enable CCA feature to cancel sending the packet if the signal power is stronger than CCA threshold. +config BT_LE_DTM_ENABLED + bool "Enable Direct Test Mode (DTM) feature" + default n + config BT_LE_CCA_RSSI_THRESH int "CCA RSSI threshold value" depends on BT_LE_TX_CCA_ENABLED range 20 100 - default 20 + default 65 help Power threshold of CCA in unit of -1 dBm. +config BT_LE_FEAT_LL_ENCRYPTION + bool "Enable controller ACL encryption" + default y + config BT_LE_ROLE_CENTROL_ENABLE bool "Enable BLE Centrol role function" depends on !BT_NIMBLE_ENABLED @@ -526,3 +619,126 @@ config BT_LE_ROLE_OBSERVER_ENABLE default y help Enable observer role function. + +choice BT_LE_DFT_TX_POWER_LEVEL_DBM + prompt "BLE default Tx power level(dBm)" + default BT_LE_DFT_TX_POWER_LEVEL_P9 + help + Specify default Tx power level(dBm). + config BT_LE_DFT_TX_POWER_LEVEL_N24 + bool "-24dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N21 + bool "-21dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N18 + bool "-18dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N15 + bool "-15dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N12 + bool "-12dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N9 + bool "-9dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N6 + bool "-6dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N3 + bool "-3dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N0 + bool "0dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P3 + bool "+3dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P6 + bool "+6dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P9 + bool "+9dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P12 + bool "+12dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P15 + bool "+15dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P18 + bool "+18dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P20 + bool "+20dBm" +endchoice + +config BT_LE_DFT_TX_POWER_LEVEL_DBM_EFF + int + default -24 if BT_LE_DFT_TX_POWER_LEVEL_N24 + default -21 if BT_LE_DFT_TX_POWER_LEVEL_N21 + default -18 if BT_LE_DFT_TX_POWER_LEVEL_N18 + default -15 if BT_LE_DFT_TX_POWER_LEVEL_N15 + default -12 if BT_LE_DFT_TX_POWER_LEVEL_N12 + default -9 if BT_LE_DFT_TX_POWER_LEVEL_N9 + default -6 if BT_LE_DFT_TX_POWER_LEVEL_N6 + default -3 if BT_LE_DFT_TX_POWER_LEVEL_N3 + default 0 if BT_LE_DFT_TX_POWER_LEVEL_N0 + default 3 if BT_LE_DFT_TX_POWER_LEVEL_P3 + default 6 if BT_LE_DFT_TX_POWER_LEVEL_P6 + default 9 if BT_LE_DFT_TX_POWER_LEVEL_P9 + default 12 if BT_LE_DFT_TX_POWER_LEVEL_P12 + default 15 if BT_LE_DFT_TX_POWER_LEVEL_P15 + default 18 if BT_LE_DFT_TX_POWER_LEVEL_P18 + default 20 if BT_LE_DFT_TX_POWER_LEVEL_P20 + default 0 + +config BT_CTRL_RUN_IN_FLASH_ONLY + bool "Reduce BLE IRAM usage (READ DOCS FIRST) (EXPERIMENTAL)" + default n + help + Move most IRAM into flash. This will increase the usage of flash and reduce ble performance. + Because the code is moved to the flash, the execution speed of the code is reduced. + To have a small impact on performance, you need to enable flash suspend (SPI_FLASH_AUTO_SUSPEND). + + - Only one Tx-Rx can be performed in each connection interval. Therefore, reduce the connection interval + as much as possible to improve the throughput. If you want higher connection performance, you can + enable BT_LE_PLACE_CONN_RELATED_INTO_IRAM to put the connection-related code into iram. + - For HCI_LE_Extended_Create_Connection command, only 1M phy's connection parameters will be applied. + Other phys' will be ignored. + - For extended scanning, we may be unable to receive the extended adv with 300us MAFS. + - To match performance, phy needs to be reduced, you need to disable ESP_PHY_IRAM_OPT. + +config BT_LE_PLACE_CONN_RELATED_INTO_IRAM + bool "Place the connection-related code into IRAM" + depends on BT_CTRL_RUN_IN_FLASH_ONLY + default n + +config BT_LE_PLACE_SLEEP_RELATED_INTO_IRAM + bool + depends on BT_CTRL_RUN_IN_FLASH_ONLY && BT_LE_SLEEP_ENABLE + default y + +config BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS + bool "Enable enhanced Access Address check in CONNECT_IND" + default n + help + Enabling this option will add stricter verification of the Access Address in the CONNECT_IND PDU. + This improves security by ensuring that only connection requests with valid Access Addresses are accepted. + If disabled, only basic checks are applied, improving compatibility. + +menu "BLE disconnects when Instant Passed (0x28) occurs" + config BT_LE_CTRL_LLCP_CONN_UPDATE + bool "BLE ACL connection update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs during connection update procedure. + + config BT_LE_CTRL_LLCP_CHAN_MAP_UPDATE + bool "BLE ACL channel map update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs in channel map update procedure. + + config BT_LE_CTRL_LLCP_PHY_UPDATE + bool "BLE ACL PHY update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs in PHY update procedure. +endmenu + +config BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX + int "The value of upperlimitmax during scan backoff procedure" + range 1 256 + default 32 + help + The value of upperlimitmax needs to be a power of 2. diff --git a/lib/bt/controller/esp32c2/ble.c b/lib/bt/controller/esp32c2/ble.c new file mode 100644 index 00000000..dd6db35e --- /dev/null +++ b/lib/bt/controller/esp32c2/ble.c @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include "sdkconfig.h" +#include "esp_bt_cfg.h" + +/* External functions or variables + ************************************************************************ + */ +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) +void scan_stack_enableAdvFlowCtrlVsCmd(bool en); +void adv_stack_enableClearLegacyAdvVsCmd(bool en); +void chanSel_stack_enableSetCsaVsCmd(bool en); +void hci_stack_enableSetVsEvtMaskVsCmd(bool en); + +void adv_stack_enableScanReqRxdVsEvent(bool en); +void conn_stack_enableChanMapUpdCompVsEvent(bool en); +void sleep_stack_enableWakeupVsEvent(bool en); +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + +/* Local functions definition + *************************************************************************** + */ +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) +void ble_stack_enableVsCmds(bool en) +{ +#if DEFAULT_BT_LE_ROLE_BROADCASTER + adv_stack_enableClearLegacyAdvVsCmd(en); +#endif // DEFAULT_BT_LE_ROLE_BROADCASTER + +#if DEFAULT_BT_LE_ROLE_OBSERVER + scan_stack_enableAdvFlowCtrlVsCmd(en); +#endif // DEFAULT_BT_LE_ROLE_OBSERVER + + chanSel_stack_enableSetCsaVsCmd(en); + hci_stack_enableSetVsEvtMaskVsCmd(en); +} + +void ble_stack_enableVsEvents(bool en) +{ +#if DEFAULT_BT_LE_ROLE_BROADCASTER + adv_stack_enableScanReqRxdVsEvent(en); +#endif // DEFAULT_BT_LE_ROLE_BROADCASTER + conn_stack_enableChanMapUpdCompVsEvent(en); +#if CONFIG_BT_LE_SLEEP_ENABLE + sleep_stack_enableWakeupVsEvent(en); +#endif // CONFIG_BT_LE_SLEEP_ENABLE +} +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + +int ble_stack_enable(void) +{ +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + ble_stack_enableVsCmds(true); + ble_stack_enableVsEvents(true); +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + + return 0; +} + +void ble_stack_disable(void) +{ +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + ble_stack_enableVsEvents(false); + ble_stack_enableVsCmds(false); +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) +} diff --git a/lib/bt/controller/esp32c2/ble_priv.h b/lib/bt/controller/esp32c2/ble_priv.h new file mode 100644 index 00000000..024bb042 --- /dev/null +++ b/lib/bt/controller/esp32c2/ble_priv.h @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _BLE_PRIV_H_ +#define _BLE_PRIV_H_ + +int ble_stack_enable(void); + +void ble_stack_disable(void); + +#endif // _BLE_PRIV_H_ diff --git a/lib/bt/controller/esp32c2/bt.c b/lib/bt/controller/esp32c2/bt.c index 29c33326..a329881e 100644 --- a/lib/bt/controller/esp32c2/bt.c +++ b/lib/bt/controller/esp32c2/bt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -31,10 +31,11 @@ #endif #include "nimble/nimble_npl_os.h" -#include "ble_hci_trans.h" +#include "esp_hci_transport.h" #include "os/endian.h" #include "esp_bt.h" +#include "ble_priv.h" #include "esp_intr_alloc.h" #include "esp_sleep.h" #include "esp_pm.h" @@ -44,16 +45,13 @@ #include "soc/syscon_reg.h" #include "soc/modem_clkrst_reg.h" #include "esp_private/periph_ctrl.h" -#include "hci_uart.h" +#include "esp_private/esp_clk_tree_common.h" #include "bt_osi_mem.h" -#ifdef CONFIG_BT_BLUEDROID_ENABLED -#include "hci/hci_hal.h" -#endif - #if CONFIG_FREERTOS_USE_TICKLESS_IDLE #include "esp_private/sleep_modem.h" #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE +#include "esp_private/esp_modem_clock.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -67,6 +65,11 @@ #include "hal/efuse_ll.h" #include "soc/rtc.h" + +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED +#include "ble_log/ble_log_spi_out.h" +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + /* Macro definition ************************************************************************ */ @@ -79,17 +82,6 @@ #define EXT_FUNC_MAGIC_VALUE 0xA5A5A5A5 #define BT_ASSERT_PRINT ets_printf - -#ifdef CONFIG_BT_BLUEDROID_ENABLED -/* ACL_DATA_MBUF_LEADINGSPCAE: The leadingspace in user info header for ACL data */ -#define ACL_DATA_MBUF_LEADINGSPCAE 4 -#endif // CONFIG_BT_BLUEDROID_ENABLED - -typedef enum ble_rtc_slow_clk_src { - BT_SLOW_CLK_SRC_MAIN_XTAL, - BT_SLOW_CLK_SRC_32K_XTAL_ON_PIN0, -} ble_rtc_slow_clk_src_t; - /* Types definition ************************************************************************ */ @@ -108,12 +100,12 @@ struct ext_funcs_t { int (*_esp_intr_free)(void **ret_handle); void *(* _malloc)(size_t size); void (*_free)(void *p); - void (*_hal_uart_start_tx)(int); - int (*_hal_uart_init_cbs)(int, hci_uart_tx_char, hci_uart_tx_done, hci_uart_rx_char, void *); - int (*_hal_uart_config)(int, int32_t, uint8_t, uint8_t, uart_parity_t, uart_hw_flowcontrol_t); - int (*_hal_uart_close)(int); - void (*_hal_uart_blocking_tx)(int, uint8_t); - int (*_hal_uart_init)(int, void *); + void (*_rsv1)(int); + int (*_rsv2)(int, int (*)(void *arg), int (*)(void *arg, uint8_t byte), int (*)(void *arg, uint8_t byte), void *); + int (*_rsv3)(int, int32_t, uint8_t, uint8_t, int, int); + int (*_rsv4)(int); + void (*_rsv5)(int, uint8_t); + int (*_rsv6)(int, void *); int (* _task_create)(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id); void (* _task_delete)(void *task_handle); void (*_osi_assert)(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2); @@ -126,7 +118,12 @@ struct ext_funcs_t { }; #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -typedef void (*interface_func_t) (uint32_t len, const uint8_t*addr, bool end); +typedef void (*interface_func_t) (uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); + +enum { + BLE_LOG_INTERFACE_FLAG_CONTINUE = 0, + BLE_LOG_INTERFACE_FLAG_END, +}; #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* External functions or variables @@ -135,10 +132,12 @@ typedef void (*interface_func_t) (uint32_t len, const uint8_t*addr, bool end); extern int ble_osi_coex_funcs_register(struct osi_coex_funcs_t *coex_funcs); extern int ble_controller_init(esp_bt_controller_config_t *cfg); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -extern int ble_log_init_async(interface_func_t bt_controller_log_interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); +extern int ble_log_init_async(interface_func_t interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); extern int ble_log_deinit_async(void); +extern int ble_log_init_simple(interface_func_t interface, void *handler); +extern void ble_log_deinit_simple(void); extern void ble_log_async_output_dump_all(bool output); -extern void esp_panic_handler_reconfigure_wdts(uint32_t timeout_ms); +extern void esp_panic_handler_feed_wdts(void); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED extern int ble_controller_deinit(void); extern int ble_controller_enable(uint8_t mode); @@ -158,6 +157,9 @@ extern void r_ble_rtc_wake_up_state_clr(void); #if CONFIG_FREERTOS_USE_TICKLESS_IDLE extern void esp_ble_set_wakeup_overhead(uint32_t overhead); #endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#if CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE +extern void r_ble_ll_customize_peer_sca_set(uint16_t peer_sca); +#endif // CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE extern int os_msys_init(void); extern void os_msys_buf_free(void); extern int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, @@ -170,6 +172,10 @@ extern int ble_get_npl_element_info(esp_bt_controller_config_t *cfg, ble_npl_cou extern void bt_track_pll_cap(void); extern char *ble_controller_get_compile_version(void); extern const char *r_ble_controller_get_rom_compile_version(void); +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY +extern void ble_ll_supported_features_init(void); +#endif //CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + #if CONFIG_BT_RELEASE_IRAM extern uint32_t _iram_bt_text_start; extern uint32_t _bss_bt_end; @@ -191,16 +197,6 @@ static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status); static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status); static int task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id); static void task_delete_wrapper(void *task_handle); -#if CONFIG_BT_LE_HCI_INTERFACE_USE_UART -static void hci_uart_start_tx_wrapper(int uart_no); -static int hci_uart_init_cbs_wrapper(int uart_no, hci_uart_tx_char tx_func, - hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg); -static int hci_uart_config_wrapper(int uart_no, int32_t speed, uint8_t databits, uint8_t stopbits, - uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl); -static int hci_uart_close_wrapper(int uart_no); -static void hci_uart_blocking_tx_wrapper(int port, uint8_t data); -static int hci_uart_init_wrapper(int uart_no, void *cfg); -#endif // CONFIG_BT_LE_HCI_INTERFACE_USE_UART static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, void *arg, void **ret_handle_in); static int esp_intr_free_wrapper(void **ret_handle); @@ -211,16 +207,270 @@ static int esp_ecc_gen_key_pair(uint8_t *pub, uint8_t *priv); static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y, const uint8_t *our_priv_key, uint8_t *out_dhkey); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end); +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* Local variable definition *************************************************************************** */ +#if (CONFIG_ESP32C2_REV_MIN_FULL < 200) && (!CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) +void *g_ble_lll_rfmgmt_env_p; +#endif /* Static variable declare */ static DRAM_ATTR esp_bt_controller_status_t ble_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED const static uint32_t log_bufs_size[] = {CONFIG_BT_LE_LOG_CTRL_BUF1_SIZE, CONFIG_BT_LE_LOG_HCI_BUF_SIZE, CONFIG_BT_LE_LOG_CTRL_BUF2_SIZE}; +static bool log_is_inited = false; + +esp_err_t esp_bt_controller_log_init(void) +{ + if (log_is_inited) { + return ESP_OK; + } + +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + if (ble_log_spi_out_init() != 0) { + goto spi_out_init_failed; + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + if (ble_log_init_simple(ble_log_spi_out_ll_write, ble_log_spi_out_ll_log_ev_proc) != 0) { + goto log_init_failed; + } +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + uint8_t buffers = 0; +#if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED + buffers |= ESP_BLE_LOG_BUF_CONTROLLER; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED + buffers |= ESP_BLE_LOG_BUF_HCI; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED + + bool task_create = true; +#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY + task_create = false; +#elif CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_ctrl_log_partition_get_and_erase_first_block(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + + if (ble_log_init_async(esp_bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size) != 0) { + goto log_init_failed; + } +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + + log_is_inited = true; + return ESP_OK; + +log_init_failed: +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +spi_out_init_failed: +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + return ESP_FAIL; +} + +void esp_bt_controller_log_deinit(void) +{ +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + ble_log_deinit_simple(); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + ble_log_deinit_async(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + + log_is_inited = false; +} + +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +#include "esp_partition.h" +#include "hal/wdt_hal.h" + +#define MAX_STORAGE_SIZE (CONFIG_BT_LE_CONTROLLER_LOG_PARTITION_SIZE) +#define BLOCK_SIZE (4096) +#define THRESHOLD (3072) +#define PARTITION_NAME "bt_ctrl_log" + +static const esp_partition_t *log_partition; +static uint32_t write_index = 0; +static uint32_t next_erase_index = BLOCK_SIZE; +static bool block_erased = false; +static bool stop_write = false; +static bool is_filled = false; + +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void) +{ + log_partition = NULL; + assert(MAX_STORAGE_SIZE % BLOCK_SIZE == 0); + // Find the partition map in the partition table + log_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, PARTITION_NAME); + assert(log_partition != NULL); + // Prepare data to be read later using the mapped address + ESP_ERROR_CHECK(esp_partition_erase_range(log_partition, 0, BLOCK_SIZE)); + write_index = 0; + next_erase_index = BLOCK_SIZE; + block_erased = false; + is_filled = false; + stop_write = false; +} + +static int esp_bt_controller_log_storage(uint32_t len, const uint8_t *addr, bool end) +{ + if (len > MAX_STORAGE_SIZE) { + return -1; + } + + if (stop_write) { + return 0; + } + + assert(log_partition != NULL); + if (((write_index) % BLOCK_SIZE) >= THRESHOLD && !block_erased) { + // esp_rom_printf("Ers nxt: %d,%d\n", next_erase_index, write_index); + esp_partition_erase_range(log_partition, next_erase_index, BLOCK_SIZE); + next_erase_index = (next_erase_index + BLOCK_SIZE) % MAX_STORAGE_SIZE; + block_erased = true; + } + + if (((write_index + len) / BLOCK_SIZE) > (write_index / BLOCK_SIZE)) { + block_erased = false; + } + + if (write_index + len <= MAX_STORAGE_SIZE) { + esp_partition_write(log_partition, write_index, addr, len); + write_index = (write_index + len) % MAX_STORAGE_SIZE; + } else { + uint32_t first_part_len = MAX_STORAGE_SIZE - write_index; + esp_partition_write(log_partition, write_index, addr, first_part_len); + esp_partition_write(log_partition, 0, addr + first_part_len, len - first_part_len); + write_index = len - first_part_len; + is_filled = true; + // esp_rom_printf("old idx: %d,%d\n",next_erase_index, write_index); + } + + return 0; +} + +void esp_bt_read_ctrl_log_from_flash(bool output) +{ + esp_partition_mmap_handle_t mmap_handle; + uint32_t read_index; + const void *mapped_ptr; + const uint8_t *buffer; + uint32_t print_len; + uint32_t max_print_len; + esp_err_t err; + + print_len = 0; + max_print_len = 4096; + err = esp_partition_mmap(log_partition, 0, MAX_STORAGE_SIZE, ESP_PARTITION_MMAP_DATA, &mapped_ptr, &mmap_handle); + if (err != ESP_OK) { + ESP_LOGE("FLASH", "Mmap failed: %s", esp_err_to_name(err)); + return; + } + + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + ble_log_async_output_dump_all(true); + esp_bt_controller_log_deinit(); + stop_write = true; + + buffer = (const uint8_t *)mapped_ptr; + esp_panic_handler_feed_wdts(); + if (is_filled) { + read_index = next_erase_index; + } else { + read_index = 0; + } + + esp_rom_printf("\r\nREAD_CHECK:%ld,%ld,%d\r\n",read_index, write_index, is_filled); + esp_rom_printf("\r\n[DUMP_START:"); + while (read_index != write_index) { + esp_rom_printf("%02x ", buffer[read_index]); + if (print_len > max_print_len) { + esp_panic_handler_feed_wdts(); + print_len = 0; + } + + print_len++; + read_index = (read_index + 1) % MAX_STORAGE_SIZE; + } + esp_rom_printf(":DUMP_END]\r\n"); + portEXIT_CRITICAL_SAFE(&spinlock); + esp_partition_munmap(mmap_handle); + err = esp_bt_controller_log_init(); + assert(err == ESP_OK); + +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag) +{ + bool end = (flag & BIT(BLE_LOG_INTERFACE_FLAG_END)); +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_controller_log_storage(len, addr, end); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + + if (len && addr) { + for (int i = 0; i < len; i++) { esp_rom_printf("%02x ", addr[i]); } + } + if (len_append && addr_append) { + for (int i = 0; i < len_append; i++) { esp_rom_printf("%02x ", addr_append[i]); } + } + if (end) { esp_rom_printf("\n"); } + + portEXIT_CRITICAL_SAFE(&spinlock); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +} +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + +void esp_ble_controller_log_dump_all(bool output) +{ +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_dump_all(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_read_ctrl_log_from_flash(output); +#elif !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + BT_ASSERT_PRINT("\r\n[DUMP_START:"); + ble_log_async_output_dump_all(output); + BT_ASSERT_PRINT(":DUMP_END]\r\n"); + portEXIT_CRITICAL_SAFE(&spinlock); +#endif +} + +#if CONFIG_BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE +void esp_task_wdt_isr_user_handler(void) +{ + esp_ble_controller_log_dump_all(true); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE + +#if CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE +void __real_esp_panic_handler(void *info); +void __wrap_esp_panic_handler (void *info) +{ + esp_ble_controller_log_dump_all(true); + __real_esp_panic_handler(info); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* This variable tells if BLE is running */ @@ -229,9 +479,27 @@ static bool s_ble_active = false; static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL; #define BTDM_MIN_TIMER_UNCERTAINTY_US (200) #endif // CONFIG_PM_ENABLE +#ifdef CONFIG_XTAL_FREQ_26 +#define MAIN_XTAL_FREQ_HZ (26000000) +static DRAM_ATTR uint32_t s_bt_lpclk_freq = 40000; +#else +#define MAIN_XTAL_FREQ_HZ (40000000) +static DRAM_ATTR uint32_t s_bt_lpclk_freq = 32000; +#endif +static DRAM_ATTR modem_clock_lpclk_src_t s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_INVALID; #define BLE_RTC_DELAY_US (1800) +#define BLE_CONTROLLER_MALLOC_CAPS (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT|MALLOC_CAP_DMA) +void *malloc_ble_controller_mem(size_t size) +{ + return heap_caps_malloc(size, BLE_CONTROLLER_MALLOC_CAPS); +} + +uint32_t get_ble_controller_free_heap_size(void) +{ + return heap_caps_get_free_size(BLE_CONTROLLER_MALLOC_CAPS); +} static const struct osi_coex_funcs_t s_osi_coex_funcs_ro = { ._magic = OSI_COEX_MAGIC_VALUE, @@ -248,14 +516,6 @@ struct ext_funcs_t ext_funcs_ro = { ._esp_intr_free = esp_intr_free_wrapper, ._malloc = bt_osi_mem_malloc_internal, ._free = bt_osi_mem_free, -#if CONFIG_BT_LE_HCI_INTERFACE_USE_UART - ._hal_uart_start_tx = hci_uart_start_tx_wrapper, - ._hal_uart_init_cbs = hci_uart_init_cbs_wrapper, - ._hal_uart_config = hci_uart_config_wrapper, - ._hal_uart_close = hci_uart_close_wrapper, - ._hal_uart_blocking_tx = hci_uart_blocking_tx_wrapper, - ._hal_uart_init = hci_uart_init_wrapper, -#endif //CONFIG_BT_LE_HCI_INTERFACE_USE_UART ._task_create = task_create_wrapper, ._task_delete = task_delete_wrapper, ._osi_assert = osi_assert_wrapper, @@ -302,83 +562,6 @@ static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status) #endif // CONFIG_SW_COEXIST_ENABLE } -#ifdef CONFIG_BT_BLUEDROID_ENABLED -bool esp_vhci_host_check_send_available(void) -{ - if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { - return false; - } - return true; -} - -/** - * Allocates an mbuf for use by the nimble host. - */ -static struct os_mbuf *ble_hs_mbuf_gen_pkt(uint16_t leading_space) -{ - struct os_mbuf *om; - int rc; - - om = os_msys_get_pkthdr(0, 0); - if (om == NULL) { - return NULL; - } - - if (om->om_omp->omp_databuf_len < leading_space) { - rc = os_mbuf_free_chain(om); - assert(rc == 0); - return NULL; - } - - om->om_data += leading_space; - - return om; -} - -/** - * Allocates an mbuf suitable for an HCI ACL data packet. - * - * @return An empty mbuf on success; null on memory - * exhaustion. - */ -struct os_mbuf *ble_hs_mbuf_acl_pkt(void) -{ - return ble_hs_mbuf_gen_pkt(4 + 1); -} - -void esp_vhci_host_send_packet(uint8_t *data, uint16_t len) -{ - if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { - return; - } - - if (*(data) == DATA_TYPE_COMMAND) { - struct ble_hci_cmd *cmd = NULL; - cmd = (struct ble_hci_cmd *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD); - assert(cmd); - memcpy((uint8_t *)cmd, data + 1, len - 1); - ble_hci_trans_hs_cmd_tx((uint8_t *)cmd); - } - - if (*(data) == DATA_TYPE_ACL) { - struct os_mbuf *om = os_msys_get_pkthdr(len, ACL_DATA_MBUF_LEADINGSPCAE); - assert(om); - assert(os_mbuf_append(om, &data[1], len - 1) == 0); - ble_hci_trans_hs_acl_tx(om); - } -} - -esp_err_t esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback) -{ - if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { - return ESP_FAIL; - } - - ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL); - - return ESP_OK; -} -#endif // CONFIG_BT_BLUEDROID_ENABLED static int task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id) { return (uint32_t)xTaskCreatePinnedToCore(task_func, name, stack_depth, param, prio, task_handle, (core_id < CONFIG_FREERTOS_NUMBER_OF_CORES ? core_id : tskNO_AFFINITY)); @@ -408,78 +591,65 @@ static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer return rc; } -#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART -static void hci_uart_start_tx_wrapper(int uart_no) -{ - hci_uart_start_tx(uart_no); -} - -static int hci_uart_init_cbs_wrapper(int uart_no, hci_uart_tx_char tx_func, - hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg) +static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, void *arg, void **ret_handle_in) { - int rc = -1; - rc = hci_uart_init_cbs(uart_no, tx_func, tx_done, rx_func, arg); - return rc; -} - +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + int rc = esp_intr_alloc(source, flags, handler, arg, (intr_handle_t *)ret_handle_in); +#else + int rc = esp_intr_alloc(source, flags | ESP_INTR_FLAG_IRAM, handler, arg, (intr_handle_t *)ret_handle_in); +#endif -static int hci_uart_config_wrapper(int port_num, int32_t baud_rate, uint8_t data_bits, - uint8_t stop_bits,uart_parity_t parity, - uart_hw_flowcontrol_t flow_ctl) -{ - int rc = -1; - rc = hci_uart_config(port_num, baud_rate, data_bits, stop_bits, parity, flow_ctl); return rc; } -static int hci_uart_close_wrapper(int uart_no) +static int esp_intr_free_wrapper(void **ret_handle) { - int rc = -1; - rc = hci_uart_close(uart_no); + int rc = 0; + rc = esp_intr_free((intr_handle_t) * ret_handle); + *ret_handle = NULL; return rc; } -static void hci_uart_blocking_tx_wrapper(int port, uint8_t data) +modem_clock_lpclk_src_t esp_bt_get_lpclk_src(void) { - //This function is nowhere to use. + return s_bt_lpclk_src; } -static int hci_uart_init_wrapper(int uart_no, void *cfg) +void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src) { - //This function is nowhere to use. - return 0; -} + if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { + return; + } -#endif //CONFIG_BT_LE_HCI_INTERFACE_USE_UART + if (clk_src >= MODEM_CLOCK_LPCLK_SRC_MAX) { + return; + } -static int ble_hci_unregistered_hook(void*, void*) -{ - ESP_LOGD(NIMBLE_PORT_LOG_TAG,"%s ble hci rx_evt is not registered.",__func__); - return 0; + s_bt_lpclk_src = clk_src; } -static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, void *arg, void **ret_handle_in) +uint32_t esp_bt_get_lpclk_freq(void) { - int rc = esp_intr_alloc(source, flags | ESP_INTR_FLAG_IRAM, handler, arg, (intr_handle_t *)ret_handle_in); - return rc; + return s_bt_lpclk_freq; } -static int esp_intr_free_wrapper(void **ret_handle) +void esp_bt_set_lpclk_freq(uint32_t clk_freq) { - int rc = 0; - rc = esp_intr_free((intr_handle_t) * ret_handle); - *ret_handle = NULL; - return rc; -} + if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { + return; + } + if (!clk_freq) { + return; + } -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE -void sleep_modem_light_sleep_overhead_set(uint32_t overhead) -{ - esp_ble_set_wakeup_overhead(overhead); + if (MAIN_XTAL_FREQ_HZ % clk_freq) { + return; + } + + s_bt_lpclk_freq = clk_freq; } -#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ -IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) +void controller_sleep_cb(uint32_t enable_tick, void *arg) { if (!s_ble_active) { return; @@ -492,20 +662,27 @@ IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) s_ble_active = false; } -IRAM_ATTR void controller_wakeup_cb(void *arg) +void controller_wakeup_cb(void *arg) { if (s_ble_active) { return; } - esp_phy_enable(PHY_MODEM_BT); - // need to check if need to call pm lock here #ifdef CONFIG_PM_ENABLE + esp_pm_config_t pm_config; esp_pm_lock_acquire(s_pm_lock); + esp_pm_get_configuration(&pm_config); + assert(esp_rom_get_cpu_ticks_per_us() == pm_config.max_freq_mhz); #endif //CONFIG_PM_ENABLE + esp_phy_enable(PHY_MODEM_BT); + if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW) { + uint32_t *clk_freq = (uint32_t *)arg; + *clk_freq = esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED) / 5; + } + // need to check if need to call pm lock here s_ble_active = true; } -esp_err_t controller_sleep_init(ble_rtc_slow_clk_src_t slow_clk_src) +esp_err_t controller_sleep_init(modem_clock_lpclk_src_t slow_clk_src) { esp_err_t rc = 0; #ifdef CONFIG_BT_LE_SLEEP_ENABLE @@ -513,7 +690,7 @@ esp_err_t controller_sleep_init(ble_rtc_slow_clk_src_t slow_clk_src) r_ble_lll_rfmgmt_set_sleep_cb(controller_sleep_cb, controller_wakeup_cb, 0, 0, 500 + BLE_RTC_DELAY_US); #ifdef CONFIG_PM_ENABLE - if (slow_clk_src == BT_SLOW_CLK_SRC_MAIN_XTAL) { + if (slow_clk_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON); } else { esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_AUTO); @@ -532,7 +709,7 @@ esp_err_t controller_sleep_init(ble_rtc_slow_clk_src_t slow_clk_src) esp_sleep_enable_bt_wakeup(); ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer"); - rc = esp_pm_register_inform_out_light_sleep_overhead_callback(sleep_modem_light_sleep_overhead_set); + rc = esp_pm_register_inform_out_light_sleep_overhead_callback(esp_ble_set_wakeup_overhead); if (rc != ESP_OK) { goto error; } @@ -542,7 +719,7 @@ esp_err_t controller_sleep_init(ble_rtc_slow_clk_src_t slow_clk_src) error: #if CONFIG_FREERTOS_USE_TICKLESS_IDLE esp_sleep_disable_bt_wakeup(); - esp_pm_unregister_inform_out_light_sleep_overhead_callback(sleep_modem_light_sleep_overhead_set); + esp_pm_unregister_inform_out_light_sleep_overhead_callback(esp_ble_set_wakeup_overhead); #endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ /*lock should release first and then delete*/ if (s_pm_lock != NULL) { @@ -559,7 +736,7 @@ void controller_sleep_deinit(void) r_ble_rtc_wake_up_state_clr(); esp_sleep_disable_bt_wakeup(); esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_AUTO); - esp_pm_unregister_inform_out_light_sleep_overhead_callback(sleep_modem_light_sleep_overhead_set); + esp_pm_unregister_inform_out_light_sleep_overhead_callback(esp_ble_set_wakeup_overhead); #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE #ifdef CONFIG_PM_ENABLE /*lock should release first and then delete*/ @@ -568,23 +745,19 @@ void controller_sleep_deinit(void) #endif //CONFIG_PM_ENABLE } -static void esp_bt_rtc_slow_clk_select(ble_rtc_slow_clk_src_t slow_clk_src) +static void esp_bt_rtc_slow_clk_select(modem_clock_lpclk_src_t slow_clk_src) { /* Select slow clock source for BT momdule */ switch (slow_clk_src) { - case BT_SLOW_CLK_SRC_MAIN_XTAL: + case MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL: ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source"); SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_XTAL32K_S); SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 1, MODEM_CLKRST_LP_TIMER_SEL_XTAL_S); SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_8M_S); SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_RTC_SLOW_S); -#ifdef CONFIG_XTAL_FREQ_26 - SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM, 129, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM_S); -#else - SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM, 249, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM_S); -#endif // CONFIG_XTAL_FREQ_26 + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM, (MAIN_XTAL_FREQ_HZ/(5 * s_bt_lpclk_freq) - 1), MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM_S); break; - case BT_SLOW_CLK_SRC_32K_XTAL_ON_PIN0: + case MODEM_CLOCK_LPCLK_SRC_EXT32K: ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using external 32.768 kHz XTAL as clock source"); SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 1, MODEM_CLKRST_LP_TIMER_SEL_XTAL32K_S); SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_XTAL_S); @@ -592,6 +765,14 @@ static void esp_bt_rtc_slow_clk_select(ble_rtc_slow_clk_src_t slow_clk_src) SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_RTC_SLOW_S); SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM, 0, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM_S); break; + case MODEM_CLOCK_LPCLK_SRC_RC_SLOW: + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Using 136 kHz RC as clock source, use with caution as it may not maintain ACL or Sync process due to low clock accuracy!"); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_XTAL32K_S); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_XTAL_S); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_8M_S); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 1, MODEM_CLKRST_LP_TIMER_SEL_RTC_SLOW_S); + SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM, 0, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM_S); + break; default: ESP_LOGE(NIMBLE_PORT_LOG_TAG, "Unsupported slow clock"); assert(0); @@ -601,40 +782,43 @@ static void esp_bt_rtc_slow_clk_select(ble_rtc_slow_clk_src_t slow_clk_src) SET_PERI_REG_BITS(MODEM_CLKRST_ETM_CLK_CONF_REG, 1, 0, MODEM_CLKRST_ETM_CLK_SEL_S); } -static ble_rtc_slow_clk_src_t ble_rtc_clk_init(esp_bt_controller_config_t *cfg) +static modem_clock_lpclk_src_t ble_rtc_clk_init(esp_bt_controller_config_t *cfg) { - ble_rtc_slow_clk_src_t slow_clk_src; - + if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_INVALID) { #if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL -#ifdef CONFIG_XTAL_FREQ_26 - cfg->rtc_freq = 40000; + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL; #else - cfg->rtc_freq = 32000; -#endif // CONFIG_XTAL_FREQ_26 - slow_clk_src = BT_SLOW_CLK_SRC_MAIN_XTAL; -#else - if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) { - cfg->rtc_freq = 32768; - slow_clk_src = BT_SLOW_CLK_SRC_32K_XTAL_ON_PIN0; - } else { - ESP_LOGW(NIMBLE_PORT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock"); -#ifdef CONFIG_XTAL_FREQ_26 - cfg->rtc_freq = 40000; -#else - cfg->rtc_freq = 32000; -#endif // CONFIG_XTAL_FREQ_26 - slow_clk_src = BT_SLOW_CLK_SRC_MAIN_XTAL; +#if CONFIG_RTC_CLK_SRC_INT_RC + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_RC_SLOW; +#elif CONFIG_RTC_CLK_SRC_EXT_OSC + if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) { + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_EXT32K; + } else { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock"); + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL; + } +#endif // CONFIG_RTC_CLK_SRC_INT_RC +#endif // CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL } -#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */ - esp_bt_rtc_slow_clk_select(slow_clk_src); - return slow_clk_src; + + if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_EXT32K) { + cfg->rtc_freq = 32768; + } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { + cfg->rtc_freq = s_bt_lpclk_freq; + } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW) { + cfg->rtc_freq = esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED) / 5; + cfg->ble_ll_sca = 3000; + } + esp_bt_rtc_slow_clk_select(s_bt_lpclk_src); + return s_bt_lpclk_src; } esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) { esp_err_t ret = ESP_OK; ble_npl_count_info_t npl_info; - ble_rtc_slow_clk_src_t rtc_clk_src; + modem_clock_lpclk_src_t rtc_clk_src; + uint8_t hci_transport_mode; memset(&npl_info, 0, sizeof(ble_npl_count_info_t)); if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { @@ -655,6 +839,8 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) return ret; } + /* If we place the ble code into flash, don't need to initialize ROM. */ +#if !CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY #if DEFAULT_BT_LE_50_FEATURE_SUPPORT || DEFAULT_BT_LE_ROLE_CENTROL || DEFAULT_BT_LE_ROLE_OBSERVER extern int esp_ble_rom_func_ptr_init_all(void); esp_ble_rom_func_ptr_init_all(); @@ -663,6 +849,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) extern int esp_ble_rom_func_ptr_init_legacy_adv_and_slave(void); esp_ble_rom_func_ptr_init_legacy_adv_and_slave(); #endif +#endif //!CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY /* Initialize the function pointers for OS porting */ npl_freertos_funcs_init(); @@ -712,30 +899,26 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) #if CONFIG_SW_COEXIST_ENABLE coex_init(); #endif + +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + ble_ll_supported_features_init(); +#endif //CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + ret = ble_controller_init(cfg); if (ret != ESP_OK) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_controller_init failed %d", ret); goto modem_deint; } +#if CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE + r_ble_ll_customize_peer_sca_set(CONFIG_BT_LE_LL_PEER_SCA); +#endif // CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "ble controller commit:[%s]", ble_controller_get_compile_version()); ESP_LOGI(NIMBLE_PORT_LOG_TAG, "ble rom commit:[%s]", r_ble_controller_get_rom_compile_version()); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - interface_func_t bt_controller_log_interface; - bt_controller_log_interface = esp_bt_controller_log_interface; - uint8_t buffers = 0; -#if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED - buffers |= ESP_BLE_LOG_BUF_CONTROLLER; -#endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED -#if CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED - buffers |= ESP_BLE_LOG_BUF_HCI; -#endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED -#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY - ret = ble_log_init_async(bt_controller_log_interface, false, buffers, (uint32_t *)log_bufs_size); -#else - ret = ble_log_init_async(bt_controller_log_interface, true, buffers, (uint32_t *)log_bufs_size); -#endif // CONFIG_BT_CONTROLLER_LOG_DUMP + ret = esp_bt_controller_log_init(); if (ret != ESP_OK) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_controller_log_init failed %d", ret); goto controller_init_err; @@ -751,20 +934,32 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) uint8_t mac[6]; ESP_ERROR_CHECK(esp_read_mac((uint8_t *)mac, ESP_MAC_BT)); + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Bluetooth MAC: %02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + swap_in_place(mac, 6); esp_ble_ll_set_public_addr(mac); ble_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; - ble_hci_trans_cfg_hs((ble_hci_trans_rx_cmd_fn *)ble_hci_unregistered_hook,NULL, - (ble_hci_trans_rx_acl_fn *)ble_hci_unregistered_hook,NULL); +#if CONFIG_BT_LE_HCI_INTERFACE_USE_RAM + hci_transport_mode = HCI_TRANSPORT_VHCI; +#elif CONFIG_BT_LE_HCI_INTERFACE_USE_UART + hci_transport_mode = HCI_TRANSPORT_UART_NO_DMA; +#endif // CONFIG_BT_LE_HCI_INTERFACE_USE_RAM + ret = hci_transport_init(hci_transport_mode); + if (ret) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "hci transport init failed %d", ret); + goto free_controller; + } return ESP_OK; free_controller: + hci_transport_deinit(); controller_sleep_deinit(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED controller_init_err: - ble_log_deinit_async(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED ble_controller_deinit(); modem_deint: @@ -789,10 +984,11 @@ esp_err_t esp_bt_controller_deinit(void) return ESP_FAIL; } + hci_transport_deinit(); controller_sleep_deinit(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - ble_log_deinit_async(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED ble_controller_deinit(); @@ -846,6 +1042,12 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) #if CONFIG_SW_COEXIST_ENABLE coex_enable(); #endif + + if (ble_stack_enable() != 0) { + ret = ESP_FAIL; + goto error; + } + if (ble_controller_enable(mode) != 0) { ret = ESP_FAIL; goto error; @@ -855,6 +1057,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) return ESP_OK; error: + ble_stack_disable(); #if CONFIG_SW_COEXIST_ENABLE coex_disable(); #endif @@ -877,7 +1080,7 @@ esp_err_t esp_bt_controller_disable(void) if (ble_controller_disable() != 0) { return ESP_FAIL; } - + ble_stack_disable(); if (s_ble_active) { esp_phy_disable(PHY_MODEM_BT); #if CONFIG_PM_ENABLE @@ -1028,9 +1231,17 @@ esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_ switch (power_type) { case ESP_BLE_PWR_TYPE_DEFAULT: + if (ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_ADV: + if (ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0xFF, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_SCAN: - if (ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1060,9 +1271,13 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type esp_err_t stat = ESP_FAIL; switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + if (ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - if (ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1085,11 +1300,15 @@ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type) int tx_level = 0; switch (power_type) { - case ESP_BLE_PWR_TYPE_ADV: - case ESP_BLE_PWR_TYPE_SCAN: case ESP_BLE_PWR_TYPE_DEFAULT: tx_level = ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); break; + case ESP_BLE_PWR_TYPE_ADV: + tx_level = ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0); + break; + case ESP_BLE_PWR_TYPE_SCAN: + tx_level = ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); + break; case ESP_BLE_PWR_TYPE_CONN_HDL0: case ESP_BLE_PWR_TYPE_CONN_HDL1: case ESP_BLE_PWR_TYPE_CONN_HDL2: @@ -1118,9 +1337,11 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + tx_level = ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - tx_level = ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + tx_level = ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); break; case ESP_BLE_ENHANCED_PWR_TYPE_ADV: case ESP_BLE_ENHANCED_PWR_TYPE_CONN: @@ -1142,30 +1363,6 @@ uint8_t esp_ble_get_chip_rev_version(void) return efuse_ll_get_chip_wafer_version_minor(); } -#if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end) -{ - for (int i = 0; i < len; i++) { - esp_rom_printf("%02x ", addr[i]); - } - if (end) { - esp_rom_printf("\n"); - } -} - -void esp_ble_controller_log_dump_all(bool output) -{ - portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; - - portENTER_CRITICAL_SAFE(&spinlock); - esp_panic_handler_reconfigure_wdts(5000); - BT_ASSERT_PRINT("\r\n[DUMP_START:"); - ble_log_async_output_dump_all(output); - BT_ASSERT_PRINT(":DUMP_END]\r\n"); - portEXIT_CRITICAL_SAFE(&spinlock); -} -#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - #if (!CONFIG_BT_NIMBLE_ENABLED) && (CONFIG_BT_CONTROLLER_ENABLED) #if CONFIG_BT_LE_SM_LEGACY || CONFIG_BT_LE_SM_SC #define BLE_SM_KEY_ERR 0x17 diff --git a/lib/bt/controller/esp32c2/dummy.c b/lib/bt/controller/esp32c2/dummy.c new file mode 100644 index 00000000..0621f547 --- /dev/null +++ b/lib/bt/controller/esp32c2/dummy.c @@ -0,0 +1,320 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "esp_bt_cfg.h" + +#define BLE_ERR_UNKNOWN_HCI_CMD (0x01) +/* LL Features */ +#define BLE_LL_FEAT_LE_ENCRYPTION (0x0000000001) +#define BLE_LL_FEAT_CONN_PARM_REQ (0x0000000002) +#define BLE_LL_FEAT_EXTENDED_REJ (0x0000000004) +#define BLE_LL_FEAT_PERIPH_INIT (0x0000000008) +#define BLE_LL_FEAT_LE_PING (0x0000000010) +#define BLE_LL_FEAT_DATA_LEN_EXT (0x0000000020) +#define BLE_LL_FEAT_LL_PRIVACY (0x0000000040) +#define BLE_LL_FEAT_EXT_SCAN_FILT (0x0000000080) +#define BLE_LL_FEAT_LE_2M_PHY (0x0000000100) +#define BLE_LL_FEAT_STABLE_MOD_ID_TX (0x0000000200) +#define BLE_LL_FEAT_STABLE_MOD_ID_RX (0x0000000400) +#define BLE_LL_FEAT_LE_CODED_PHY (0x0000000800) +#define BLE_LL_FEAT_EXT_ADV (0x0000001000) +#define BLE_LL_FEAT_PERIODIC_ADV (0x0000002000) +#define BLE_LL_FEAT_CSA2 (0x0000004000) +#define BLE_LL_FEAT_LE_POWER_CLASS_1 (0x0000008000) +#define BLE_LL_FEAT_MIN_USED_CHAN (0x0000010000) +#define BLE_LL_FEAT_CTE_REQ (0x0000020000) +#define BLE_LL_FEAT_CTE_RSP (0x0000040000) +#define BLE_LL_FEAT_CTE_TX (0x0000080000) +#define BLE_LL_FEAT_CTE_RX (0x0000100000) +#define BLE_LL_FEAT_CTE_AOD (0x0000200000) +#define BLE_LL_FEAT_CTE_AOA (0x0000400000) +#define BLE_LL_FEAT_CTE_RECV (0x0000800000) +#define BLE_LL_FEAT_SYNC_TRANS_SEND (0x0001000000) +#define BLE_LL_FEAT_SYNC_TRANS_RECV (0x0002000000) +#define BLE_LL_FEAT_SCA_UPDATE (0x0004000000) +#define BLE_LL_FEAT_REM_PKEY (0x0008000000) +#define BLE_LL_FEAT_CIS_CENTRAL (0x0010000000) +#define BLE_LL_FEAT_CIS_PERIPH (0x0020000000) +#define BLE_LL_FEAT_ISO_BROADCASTER (0x0040000000) +#define BLE_LL_FEAT_SYNC_RECV (0x0080000000) +#define BLE_LL_FEAT_CIS_HOST (0x0100000000) +#define BLE_LL_FEAT_POWER_CTRL_REQ (0x0200000000) +#define BLE_LL_FEAT_POWER_CHANGE_IND (0x0400000000) +#define BLE_LL_FEAT_PATH_LOSS_MON (0x0800000000) +#define BLE_LL_FEAT_PERIODIC_ADV_ADI (0x1000000000) +#define BLE_LL_FEAT_CONN_SUBRATING (0x2000000000) +#define BLE_LL_FEAT_CONN_SUBRATING_HOST (0x4000000000) +#define BLE_LL_FEAT_CHANNEL_CLASS (0x8000000000) + +uint64_t ble_ll_supported_features; + +void +ble_ll_supported_features_init(void) +{ + ble_ll_supported_features = BLE_LL_FEAT_EXTENDED_REJ; + ble_ll_supported_features |= BLE_LL_FEAT_DATA_LEN_EXT; + +#if DEFAULT_BT_LE_ROLE_CENTROL || DEFAULT_BT_LE_ROLE_PERIPHERAL + ble_ll_supported_features |= BLE_LL_FEAT_PERIPH_INIT; + ble_ll_supported_features |= BLE_LL_FEAT_CONN_PARM_REQ; +#endif + +#if CONFIG_BT_LE_FEAT_LL_ENCRYPTION + ble_ll_supported_features |= BLE_LL_FEAT_LE_ENCRYPTION; +#endif + + ble_ll_supported_features |= (BLE_LL_FEAT_LL_PRIVACY | BLE_LL_FEAT_EXT_SCAN_FILT); + ble_ll_supported_features |= BLE_LL_FEAT_LE_PING; + +#if DEFAULT_BT_LE_EXT_ADV + ble_ll_supported_features |= BLE_LL_FEAT_EXT_ADV; +#endif + +#if DEFAULT_BT_LE_PERIODIC_ADV + ble_ll_supported_features |= BLE_LL_FEAT_PERIODIC_ADV; + ble_ll_supported_features |= BLE_LL_FEAT_PERIODIC_ADV_ADI; +#endif + +#if DEFAULT_BT_LE_PAST + ble_ll_supported_features |= BLE_LL_FEAT_SYNC_TRANS_RECV; + ble_ll_supported_features |= BLE_LL_FEAT_SYNC_TRANS_SEND; +#endif + +#if DEGAULT_BT_LE_2M_PHY + ble_ll_supported_features |= BLE_LL_FEAT_LE_2M_PHY; +#endif + +#if DEGAULT_BT_LE_CODED_PHY + ble_ll_supported_features |= BLE_LL_FEAT_LE_CODED_PHY; +#endif + +#if DEFAULT_BT_LE_50_FEATURE_SUPPORT + ble_ll_supported_features |= BLE_LL_FEAT_CSA2; + ble_ll_supported_features |= BLE_LL_FEAT_SCA_UPDATE; + ble_ll_supported_features |= BLE_LL_FEAT_REM_PKEY; + ble_ll_supported_features |= BLE_LL_FEAT_CHANNEL_CLASS; +#endif +} + +#if !DEFAULT_BT_LE_ROLE_BROADCASTER +void r_ble_ll_adv_rpa_timeout(void) { } +void r_ble_lll_adv_halt(void) { } +void r_ble_lll_adv_event_rmvd_from_sched(void) { } +void r_ble_lll_adv_ext_event_rmvd_from_sched(void) { } +int r_ble_ll_adv_enabled(void) { return 0; } +int r_ble_ll_adv_can_chg_whitelist(void) { return 1; } +int r_ble_ll_adv_set_random_addr(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +void r_ble_ll_adv_reset(void) { } +void r_ble_ll_adv_init(void) { } +void r_ble_ll_adv_deinit(void) { } +int r_ble_ll_adv_env_init(void) { return 0; } +void r_ble_ll_adv_env_deinit(void) { } +int r_ble_lll_adv_rx_pkt_isr(void) { return -1; } +void r_ble_ll_adv_rx_pkt_in(void) { } +int r_ble_ll_adv_set_adv_params(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_adv_read_txpwr(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_hci_set_adv_data(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_hci_set_scan_rsp_data(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_hci_adv_set_enable(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_adv_vendor_hci_legacy_adv_clear(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_adv_set_data_related_addr_change(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif // !DEFAULT_BT_LE_ROLE_BROADCASTER + +#if !DEFAULT_BT_LE_EXT_ADV +bool r_ble_ll_adv_ext_check_data_itvl(void) { return true; } +void r_ble_lll_adv_coex_dpc_update_on_aux_scheduled(void) { } +void r_ble_lll_adv_coex_dpc_calc_pti_update_itvl(void) { } +void r_ble_lll_adv_sec_done(void) { } +int r_ble_lll_adv_sec_schedule_next_aux(void) { return 0; } +void r_ble_lll_adv_sec_event_done(void) { } +int r_ble_lll_adv_secondary_tx_start_cb(void) { return 0; } +void r_ble_lll_adv_aux_schedule(void) { } +void r_ble_lll_adv_update_rsp_offset(void) { } +int r_ble_ll_adv_hci_set_random_addr(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_adv_ext_set_param(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_adv_ext_set_adv_data(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_adv_ext_set_scan_rsp(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_adv_ext_set_enable(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_adv_rd_max_adv_data_len(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_adv_rd_sup_adv_sets(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_adv_remove(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_adv_clear_all(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!DEFAULT_BT_LE_EXT_ADV + +#if !DEFAULT_BT_LE_PERIODIC_ADV +void r_ble_ll_adv_sm_stop_periodic(void) { } +void r_ble_lll_adv_periodic_event_done(void) { } +int r_ble_lll_adv_sync_tx_start_cb(void) { return 0; } +void r_ble_lll_adv_sync_tx_end(void) { } +int r_ble_lll_adv_periodic_start(void) { return 0; } +void r_ble_lll_adv_periodic_rmvd_from_sched(void) { } +int r_ble_ll_adv_periodic_set_param(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_adv_periodic_set_data(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_adv_periodic_enable(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!DEFAULT_BT_LE_PERIODIC_ADV + +#if !DEFAULT_BT_LE_ROLE_OBSERVER +void r_ble_lll_scan_halt(void) { } +void r_ble_ll_scan_end_adv_evt(void) { } +void r_ble_ll_scan_rx_pkt_in(void) { } +int r_ble_lll_scan_rx_pkt_isr(void) { return -1; } +int r_ble_ll_scan_env_init(void) { return 0; } +void r_ble_ll_scan_env_deinit(void) { } +void r_ble_ll_scan_init(void) { } +void r_ble_ll_scan_deinit(void) { } +void r_ble_ll_scan_reset(void) { } +int r_ble_ll_scan_can_chg_whitelist(void) { return 1; } +int r_ble_ll_scan_enabled(void) { return false; } +int r_ble_lll_scan_chk_resume(void) { return -1; } +int r_ble_ll_scan_set_scan_params(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_hci_scan_set_enable(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_scan_hci_update_adv_report_flow_ctrl(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_scan_hci_set_adv_report_flow_ctrl(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!DEFAULT_BT_LE_ROLE_OBSERVER + +#if !DEFAULT_BT_LE_EXT_SCAN +void r_ble_lll_scan_duration_period_timers_restart(void) { } +void r_ble_lll_scan_duration_period_timers_stop(void) { } +int r_ble_ll_hci_send_legacy_ext_adv_report(void) { return -1; } +void r_ble_lll_sched_rmv_elem_type(void) { } +void r_ble_ll_scan_send_truncated(void) { } +void r_ble_ll_scan_aux_data_unref(void) { } +void r_ble_lll_scan_sched_remove(void) { } +void r_ble_lll_scan_aux_data_free(void) { } +void r_ble_lll_aux_scan_drop(void) { } +int r_ble_lll_sched_aux_scan(void) { return -1; } +int r_ble_lll_scan_rx_isr_on_aux(void) { return -1; } +void r_ble_lll_scan_period_timer_cb(void) { } +void r_ble_lll_scan_duration_timer_cb(void) { } +void r_ble_ll_scan_rx_pkt_in_on_aux(void) { } +int r_ble_ll_set_ext_scan_params(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_hci_ext_scan_set_enable(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!DEFAULT_BT_LE_EXT_SCAN + +#if !DEFAULT_BT_LE_ROLE_CENTROL +void r_ble_ll_init_rx_pkt_in(void) { } +int r_ble_lll_init_rx_pkt_isr(void) { return -1; } +int r_ble_ll_conn_create(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_conn_create_cancel(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!DEFAULT_BT_LE_ROLE_CENTROL + +#if !DEFAULT_BT_LE_ROLE_CENTROL || !DEFAULT_BT_LE_EXT_SCAN +int r_ble_ll_ext_conn_create(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!DEFAULT_BT_LE_ROLE_CENTROL || !DEFAULT_BT_LE_EXT_SCAN + +#if !DEFAULT_BT_LE_ROLE_PERIPHERAL +int r_ble_ll_conn_slave_start(void) { return 0; } +#endif //!DEFAULT_BT_LE_ROLE_PERIPHERAL + +#if !DEFAULT_BT_LE_ROLE_CENTROL && !DEFAULT_BT_LE_ROLE_PERIPHERAL +void r_ble_ll_conn_rx_data_pdu(void) { } +int r_ble_lll_conn_rx_pkt_isr(void) { return -1; } +int r_ble_ll_hci_disconnect(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_conn_hci_rd_rem_ver_cmd(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_conn_hci_update(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_conn_hci_rd_chan_map(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_conn_hci_read_rem_features(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_conn_hci_param_rr(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_conn_hci_param_nrr(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!DEFAULT_BT_LE_ROLE_CENTROL && !DEFAULT_BT_LE_ROLE_PERIPHERAL + +#if !CONFIG_BT_LE_FEAT_LL_ENCRYPTION +int r_ble_ll_conn_chk_phy_upd_start(void) { return -1; } +void r_ble_ll_hci_ev_encrypt_chg(void) { } +int r_ble_ll_ctrl_enc_allowed_pdu_rx(void) { return 1; } +int r_ble_ll_ctrl_enc_allowed_pdu_tx(void) { return 1; } +uint8_t r_ble_ll_ctrl_rx_start_enc_rsp(void) { return 0x07; } +uint8_t r_ble_ll_ctrl_rx_pause_enc_rsp(void) { return 0x07; } +int r_ble_ll_hci_le_encrypt(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!CONFIG_BT_LE_FEAT_LL_ENCRYPTION + +#if !DEFAULT_BT_LE_ROLE_PERIPHERAL || !CONFIG_BT_LE_FEAT_LL_ENCRYPTION +uint8_t r_ble_ll_ctrl_rx_pause_enc_req(void) { return 0x07; } +uint8_t r_ble_ll_ctrl_rx_enc_req(void) { return 0x07; } +int r_ble_ll_conn_hci_le_ltk_reply(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_conn_hci_le_ltk_neg_reply(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!DEFAULT_BT_LE_ROLE_PERIPHERAL || !CONFIG_BT_LE_FEAT_LL_ENCRYPTION + +#if !DEFAULT_BT_LE_ROLE_CENTROL || !CONFIG_BT_LE_FEAT_LL_ENCRYPTION +uint8_t r_ble_ll_ctrl_rx_start_enc_req(void) { return 0x07; } +void r_ble_ll_ctrl_rx_enc_rsp(void) { } +void r_ble_ll_ctrl_enc_req_make(void) { } +int r_ble_ll_conn_hci_le_start_encrypt(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!DEFAULT_BT_LE_ROLE_CENTROL || !CONFIG_BT_LE_FEAT_LL_ENCRYPTION + +#if !DEGAULT_BT_LE_2M_PHY && !DEGAULT_BT_LE_CODED_PHY +void r_ble_ll_ctrl_phy_update_proc_complete(void) { } +void r_ble_ll_ctrl_phy_update_cancel(void) { } +uint8_t r_ble_ll_ctrl_rx_phy_update_ind(void) { return 0x07; } +uint8_t r_ble_ll_ctrl_rx_phy_rsp(void) { return 0x07; } +uint8_t r_ble_ll_ctrl_rx_phy_req(void) { return 0x07; } +void r_ble_ll_ctrl_phy_req_rsp_make(void) { } +#endif //DEGAULT_BT_LE_2M_PHY && DEGAULT_BT_LE_CODED_PHY + +#if !DEFAULT_BT_LE_PERIODIC_SYNC +void r_ble_lll_sync_halt(void) { } +void r_ble_lll_sync_rmvd_from_sched(void) { } +int r_ble_ll_sync_list_search(void) { return -1; } +uint8_t r_ble_ll_ctrl_rx_periodic_sync_ind(void) { return 0x07; } +void r_ble_ll_sync_rx_pkt_in(void) { } +int r_ble_lll_sync_rx_pkt_isr(void) { return -1; } +int r_ble_ll_sync_env_init(void) { return 0; } +void r_ble_ll_sync_env_deinit(void) { } +void r_ble_ll_sync_init(void) { } +void r_ble_ll_sync_deinit(void) { } +void r_ble_ll_sync_reset(void) { } +bool r_ble_ll_sync_enabled(void) { return false; } +int r_ble_ll_sync_create(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_sync_cancel(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_sync_terminate(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_sync_list_add(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_sync_list_remove(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_sync_list_clear(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_sync_list_size(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_sync_receive_enable(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!DEFAULT_BT_LE_PERIODIC_SYNC + +#if !DEFAULT_BT_LE_PAST || !DEFAULT_BT_LE_PERIODIC_ADV +int r_ble_ll_adv_periodic_set_info_transfer(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!DEFAULT_BT_LE_PAST || !DEFAULT_BT_LE_PERIODIC_ADV + +#if !DEFAULT_BT_LE_PAST || !DEFAULT_BT_LE_PERIODIC_SYNC +int r_ble_ll_sync_transfer(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_set_sync_transfer_params(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_set_default_sync_transfer_params(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!DEFAULT_BT_LE_PAST || !DEFAULT_BT_LE_PERIODIC_SYNC + +#if !DEFAULT_BT_LE_50_FEATURE_SUPPORT +uint8_t r_ble_ll_ctrl_rx_channel_reporting_ind(void) { return 0x07; } +uint8_t r_ble_ll_ctrl_rx_channel_status_ind(void) { return 0x07; } +uint8_t r_ble_ll_ctrl_rx_sca_req(void) { return 0x07; } +uint8_t r_ble_ll_ctrl_rx_sca_rsp(void) { return 0x07; } +void r_ble_ll_ctrl_channel_class_reporting_make(void) { } +void r_ble_ll_ctrl_channel_class_enable_make(void) { } +void r_ble_ll_ctrl_sca_req_rsp_make(void) { } +int r_ble_ll_modify_sca(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_conn_req_peer_sca(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!DEFAULT_BT_LE_50_FEATURE_SUPPORT + +#if !DEFAULT_BT_LE_50_FEATURE_SUPPORT +int r_ble_ll_conn_hci_le_rd_phy(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_hci_le_set_def_phy(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_ll_conn_hci_le_set_phy(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!DEFAULT_BT_LE_50_FEATURE_SUPPORT + +#if !CONFIG_BT_LE_DTM_ENABLED +void r_ble_lll_dtm_rx_pkt_in(void) { } +int r_ble_lll_dtm_rx_isr_end(void) { return -1; } +void r_ble_lll_dtm_reset(void) { } +void r_ble_lll_dtm_init(void) { } +void r_ble_lll_dtm_deinit(void) { } +int r_ble_lll_dtm_env_init(void) { return 0; } +void r_ble_lll_dtm_env_deinit(void) { } +int r_ble_lll_hci_dtm_tx_test(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_lll_hci_dtm_rx_test(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_lll_dtm_end_test(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_lll_hci_dtm_rx_test_v2(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +int r_ble_lll_hci_dtm_tx_test_v2(void) { return BLE_ERR_UNKNOWN_HCI_CMD; } +#endif //!CONFIG_BT_LE_DTM_ENABLED diff --git a/lib/bt/controller/esp32c2/esp_bt_cfg.h b/lib/bt/controller/esp32c2/esp_bt_cfg.h index 0cb4168e..95a3c6b2 100644 --- a/lib/bt/controller/esp32c2/esp_bt_cfg.h +++ b/lib/bt/controller/esp32c2/esp_bt_cfg.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -28,7 +28,6 @@ extern "C" { #else #define BLE_LL_SCAN_PHY_NUMBER_N (1) #endif - #define DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST MYNEWT_VAL(BLE_MAX_PERIODIC_ADVERTISER_LIST) #define DEFAULT_BT_LE_MAX_PERIODIC_SYNCS MYNEWT_VAL(BLE_MAX_PERIODIC_SYNCS) #define DEFAULT_BT_LE_MAX_CONNECTIONS MYNEWT_VAL(BLE_MAX_CONNECTIONS) @@ -46,6 +45,14 @@ extern "C" { #define DEFAULT_BT_LE_50_FEATURE_SUPPORT (0) #endif + #define DEGAULT_BT_LE_2M_PHY (CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_2M_PHY) + #define DEGAULT_BT_LE_CODED_PHY (CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY) + #define DEFAULT_BT_LE_EXT_ADV (CONFIG_BT_NIMBLE_EXT_ADV) + #define DEFAULT_BT_LE_PERIODIC_ADV (CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV) + #define DEFAULT_BT_LE_EXT_SCAN (CONFIG_BT_NIMBLE_EXT_SCAN) + #define DEFAULT_BT_LE_PERIODIC_SYNC (CONFIG_BT_NIMBLE_ENABLE_PERIODIC_SYNC) + #define DEFAULT_BT_LE_PAST (CONFIG_BT_NIMBLE_PERIODIC_ADV_SYNC_TRANSFER) + #define DEFAULT_BT_LE_ROLE_OBSERVER MYNEWT_VAL(BLE_ROLE_OBSERVER) #define DEFAULT_BT_LE_ROLE_CENTROL MYNEWT_VAL(BLE_ROLE_CENTRAL) #define DEFAULT_BT_LE_ROLE_PERIPHERAL MYNEWT_VAL(BLE_ROLE_PERIPHERAL) @@ -123,12 +130,55 @@ extern "C" { #else #define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT (8) #endif + #if defined(CONFIG_BT_LE_50_FEATURE_SUPPORT) #define DEFAULT_BT_LE_50_FEATURE_SUPPORT (1) #else #define DEFAULT_BT_LE_50_FEATURE_SUPPORT (0) #endif + #if defined(CONFIG_BT_LE_LL_CFG_FEAT_LE_2M_PHY) + #define DEGAULT_BT_LE_2M_PHY (CONFIG_BT_LE_LL_CFG_FEAT_LE_2M_PHY) + #else + #define DEGAULT_BT_LE_2M_PHY (0) + #endif + + #if defined(CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY) + #define DEGAULT_BT_LE_CODED_PHY (CONFIG_BT_LE_LL_CFG_FEAT_LE_CODED_PHY) + #else + #define DEGAULT_BT_LE_CODED_PHY (0) + #endif + + #if defined(CONFIG_BT_LE_EXT_ADV) + #define DEFAULT_BT_LE_EXT_ADV (CONFIG_BT_LE_EXT_ADV) + #else + #define DEFAULT_BT_LE_EXT_ADV (0) + #endif + + #if defined(CONFIG_BT_LE_ENABLE_PERIODIC_ADV) + #define DEFAULT_BT_LE_PERIODIC_ADV (CONFIG_BT_LE_ENABLE_PERIODIC_ADV) + #else + #define DEFAULT_BT_LE_PERIODIC_ADV (0) + #endif + + #if defined(CONFIG_BT_LE_EXT_SCAN) + #define DEFAULT_BT_LE_EXT_SCAN (CONFIG_BT_LE_EXT_SCAN) + #else + #define DEFAULT_BT_LE_EXT_SCAN (0) + #endif + + #if defined(CONFIG_BT_LE_ENABLE_PERIODIC_SYNC) + #define DEFAULT_BT_LE_PERIODIC_SYNC (CONFIG_BT_LE_ENABLE_PERIODIC_SYNC) + #else + #define DEFAULT_BT_LE_PERIODIC_SYNC (0) + #endif + + #if defined(BT_LE_PERIODIC_ADV_SYNC_TRANSFER) + #define DEFAULT_BT_LE_PAST (BT_LE_PERIODIC_ADV_SYNC_TRANSFER) + #else + #define DEFAULT_BT_LE_PAST (0) + #endif + #if defined(CONFIG_BT_LE_ROLE_CENTROL_ENABLE) #define DEFAULT_BT_LE_ROLE_CENTROL (1) #else @@ -152,16 +202,68 @@ extern "C" { #else #define DEFAULT_BT_LE_ROLE_OBSERVER (0) #endif + #if defined (CONFIG_BT_LE_HCI_UART_FLOWCTRL) + #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (CONFIG_BT_LE_HCI_UART_FLOWCTRL) + #if DEFAULT_BT_LE_HCI_UART_FLOW_CTRL + #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (CONFIG_BT_LE_HCI_UART_CTS_PIN) + #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (CONFIG_BT_LE_HCI_UART_RTS_PIN) + #else + #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (-1) + #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (-1) + #endif + #else + #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) + #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (-1) + #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (-1) + #endif #endif #define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF +#ifdef CONFIG_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS +#define DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS (CONFIG_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS) +#else +#define DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS (0) +#endif + +#ifdef CONFIG_BT_LE_CTRL_LLCP_CONN_UPDATE +#define BT_CTRL_BLE_LLCP_CONN_UPDATE (1<<0) +#else +#define BT_CTRL_BLE_LLCP_CONN_UPDATE (0<<0) +#endif + +#ifdef CONFIG_BT_LE_CTRL_LLCP_CHAN_MAP_UPDATE +#define BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE (1<<1) +#else +#define BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE (0<<1) +#endif + +#ifdef CONFIG_BT_LE_CTRL_LLCP_PHY_UPDATE +#define BT_CTRL_BLE_LLCP_PHY_UPDATE (1<<2) +#else +#define BT_CTRL_BLE_LLCP_PHY_UPDATE (0<<2) +#endif + +#define BT_LE_CTRL_LLCP_DISC_FLAG (BT_CTRL_BLE_LLCP_CONN_UPDATE | BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE | BT_CTRL_BLE_LLCP_PHY_UPDATE) + +#ifdef CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX +#define BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX (CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX) +#else +#define BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX (256) +#endif + #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART #define HCI_UART_EN CONFIG_BT_LE_HCI_INTERFACE_USE_UART #else #define HCI_UART_EN 0 // hci ram mode #endif +#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_RAM +#define DEFAULT_BT_LE_VHCI_ENABLED (CONFIG_BT_LE_HCI_INTERFACE_USE_RAM) +#else +#define DEFAULT_BT_LE_VHCI_ENABLED (0) +#endif + #ifdef CONFIG_BT_LE_SLEEP_ENABLE #define NIMBLE_SLEEP_ENABLE CONFIG_BT_LE_SLEEP_ENABLE #else @@ -192,8 +294,6 @@ extern "C" { #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (UART_DATA_8_BITS) #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (UART_STOP_BITS_1) #define DEFAULT_BT_LE_HCI_UART_PARITY (0) - #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (CONFIG_BT_LE_HCI_UART_TASK_STACK_SIZE) - #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) #else #define DEFAULT_BT_LE_HCI_UART_TX_PIN (0) #define DEFAULT_BT_LE_HCI_UART_RX_PIN (0) @@ -202,8 +302,6 @@ extern "C" { #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (0) #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (0) #define DEFAULT_BT_LE_HCI_UART_PARITY (0) - #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (0) - #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) #endif /* Unchanged configuration */ @@ -232,7 +330,7 @@ extern "C" { #define RTC_FREQ_N (32000) /* in Hz */ #endif // CONFIG_XTAL_FREQ_26 -#define BLE_LL_TX_PWR_DBM_N (9) +#define BLE_LL_TX_PWR_DBM_N (CONFIG_BT_LE_DFT_TX_POWER_LEVEL_DBM_EFF) #define RUN_BQB_TEST (0) diff --git a/lib/bt/controller/esp32c3/Kconfig.in b/lib/bt/controller/esp32c3/Kconfig.in index 059e71da..bc75b9bb 100644 --- a/lib/bt/controller/esp32c3/Kconfig.in +++ b/lib/bt/controller/esp32c3/Kconfig.in @@ -66,7 +66,7 @@ endchoice config BT_CTRL_HCI_TL int default 0 if BT_CTRL_HCI_MODE_UART_H4 - default 1 if BT_CTRL_HCI_M0DE_VHCI + default 1 if BT_CTRL_HCI_MODE_VHCI default 1 help HCI mode as VHCI or UART(H4) @@ -76,20 +76,23 @@ config BT_CTRL_ADV_DUP_FILT_MAX range 1 500 default 30 help - The maximum number of suplicate scan filter + The maximum number of 5.0 extend duplicate choice BT_BLE_CCA_MODE prompt "BLE CCA mode" default BT_BLE_CCA_MODE_NONE help Define BT BLE CCA mode + Note that if CCA feature is enabled, the hardware may not transmit packets due to channel busy. + Therefore, it may potentially lead to an increase in the time taken for scanning advertising packet + and establishing connections, or a decrease in the throughput rate of the connection. config BT_BLE_CCA_MODE_NONE bool "NONE" config BT_BLE_CCA_MODE_HW bool "Hardware" config BT_BLE_CCA_MODE_SW - bool "Software" + bool "Software (experimental)" endchoice config BT_BLE_CCA_MODE @@ -101,9 +104,11 @@ config BT_BLE_CCA_MODE config BT_CTRL_HW_CCA_VAL int "CCA threshold value" range 20 100 - default 20 + default 75 help It is the threshold value of HW CCA, if the value is 30, it means CCA threshold is -30 dBm. + If the channel assessment result exceeds the CCA threshold (e.g. -75 dBm), indicating the channel is busy, + the hardware will not transmit packets on that channel. config BT_CTRL_HW_CCA_EFF int @@ -200,8 +205,8 @@ choice BT_CTRL_DFT_TX_POWER_LEVEL bool "+15dBm" config BT_CTRL_DFT_TX_POWER_LEVEL_P18 bool "+18dBm" - config BT_CTRL_DFT_TX_POWER_LEVEL_P21 - bool "+21dBm" + config BT_CTRL_DFT_TX_POWER_LEVEL_P20 + bool "+20dBm" endchoice config BT_CTRL_DFT_TX_POWER_LEVEL_EFF @@ -221,11 +226,12 @@ config BT_CTRL_DFT_TX_POWER_LEVEL_EFF default 12 if BT_CTRL_DFT_TX_POWER_LEVEL_P12 default 13 if BT_CTRL_DFT_TX_POWER_LEVEL_P15 default 14 if BT_CTRL_DFT_TX_POWER_LEVEL_P18 - default 15 if BT_CTRL_DFT_TX_POWER_LEVEL_P21 + default 15 if BT_CTRL_DFT_TX_POWER_LEVEL_P20 default 0 config BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP bool "BLE adv report flow control supported" + depends on BT_CTRL_BLE_SCAN default y help The function is mainly used to enable flow control for advertising reports. When it is enabled, @@ -402,10 +408,10 @@ menu "MODEM SLEEP Options" bluetooth can work under light sleep enabled. Main crystal has a relatively better performance than other bluetooth low power clock sources. config BT_CTRL_LPCLK_SEL_EXT_32K_XTAL - bool "External 32kHz crystal" - depends on RTC_CLK_SRC_EXT_CRYS + bool "External 32kHz crystal/oscillator" + depends on RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC help - External 32kHz crystal has a nominal frequency of 32.768kHz and provides good frequency + External 32kHz crystal/oscillator has a nominal frequency of 32.768kHz and provides good frequency stability. If used as Bluetooth low power clock, External 32kHz can support Bluetooth modem sleep to be used with both DFS and light sleep. @@ -444,7 +450,7 @@ config BT_CTRL_SLEEP_CLOCK_EFF config BT_CTRL_HCI_TL_EFF int default 0 if BT_CTRL_HCI_MODE_UART_H4 - default 1 if BT_CTRL_HCI_M0DE_VHCI + default 1 if BT_CTRL_HCI_MODE_VHCI default 1 config BT_CTRL_AGC_RECORRECT_EN @@ -465,7 +471,7 @@ config BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX default n help Disable active scan backoff. The bluetooth spec requires that scanners should run a backoff procedure to - minimize collision of scan request PDUs from nultiple scanners. If scan backoff is disabled, in active + minimize collision of scan request PDUs from multiple scanners. If scan backoff is disabled, in active scanning, scan request PDU will be sent every time when HW receives scannable ADV PDU. config BT_BLE_ADV_DATA_LENGTH_ZERO_AUX @@ -489,3 +495,138 @@ config BT_CTRL_LE_PING_EN help If this option is disabled, The Controller will not start the LE authenticated payload timer. This option is used for some compatibility problems related to LE ping procedure. + +menu "BLE disconnects when Instant Passed (0x28) occurs" + config BT_CTRL_BLE_LLCP_CONN_UPDATE + bool "BLE ACL connection update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs during connection update procedure. + + config BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE + bool "BLE ACL channel map update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs in channel map update procedure. + + config BT_CTRL_BLE_LLCP_PHY_UPDATE + bool "BLE ACL PHY update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs in PHY update procedure. +endmenu +config BT_CTRL_RUN_IN_FLASH_ONLY + bool "Put all BLE Controller code in flash" + default n + help + If this option is enabled, all code for the Bluetooth controller will be moved from ROM and IRAM + to flash, saving over 20K bytes of memory. However, it will require more flash resources and the + performance of Bluetooth will decrease If this option is enabled, Bluetooth may not work properly + during erasing flash. It is recommended to turn on the auto suspend function of flash. After auto + suspend is turned on, Bluetooth interrupts can be executed normally during erasing flash, with less + impact on Bluetooth performance. + +config BT_CTRL_DTM_ENABLE + bool "Enable direct test mode feature" + default y + +config BT_CTRL_BLE_MASTER + bool "Enable BLE connection feature" + default y + help + If this option is disabled, it is not recommended to use connectable ADV. + +config BT_CTRL_BLE_TEST + bool "Enable BLE QA test feature (Not Used)" + default n + +config BT_CTRL_BLE_SCAN + bool "Enable BLE scan feature" + default y + +config BT_CTRL_BLE_SECURITY_ENABLE + bool "Enable BLE security feature" + default y + +config BT_CTRL_BLE_ADV + bool "Enable BLE ADV feature" + default y + +config BT_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS + bool "Enable enhanced Access Address check in CONNECT_IND" + default n + help + Enabling this option will add stricter verification of the Access Address in the CONNECT_IND PDU. + This improves security by ensuring that only connection requests with valid Access Addresses are accepted. + If disabled, only basic checks are applied, improving compatibility. + +menu "Controller debug log Options (Experimental)" + config BT_CTRL_LE_LOG_EN + depends on BT_CTRL_RUN_IN_FLASH_ONLY + bool "Enable BLE debug log" + default n + + config BT_CTRL_LE_HCI_LOG_EN + depends on BT_CTRL_LE_LOG_EN + bool "Enable BLE HCI log" + default n + + config BT_CTRL_LE_LOG_DUMP_ONLY + depends on BT_CTRL_LE_LOG_EN + bool "Enable BLE log dump only" + default n + + config BT_CTRL_LE_LOG_STORAGE_EN + depends on BT_CTRL_LE_LOG_EN + bool "Enable BLE log storage to flash" + default n + + config BT_CTRL_LE_LOG_PARTITION_SIZE + int "The size of ble controller log partition(Multiples of 4K)" + depends on BT_CTRL_LE_LOG_STORAGE_EN + default 65536 + help + The size of ble controller log partition shall be a multiples of 4K. + The name of log partition shall be "bt_ctrl_log". + The partition type shall be ESP_PARTITION_TYPE_DATA. + The partition sub_type shall be ESP_PARTITION_SUBTYPE_ANY. + + config BT_CTRL_LE_LOG_SPI_OUT_EN + bool "Output ble controller logs to SPI bus" + depends on BT_CTRL_LE_LOG_EN + depends on !BT_CTRL_LE_LOG_DUMP_ONLY + select BT_BLE_LOG_SPI_OUT_ENABLED + default n + help + Output ble controller logs to SPI bus + + config BT_CTRL_LE_LOG_MODE_EN + depends on BT_CTRL_LE_LOG_EN + int "Enable log for specified BLE mode" + range 0 4095 + default 4093 + + config BT_CTRL_LE_LOG_LEVEL + depends on BT_CTRL_LE_LOG_EN + int "The level of BLE log" + range 0 5 + default 2 + + config BT_CTRL_LE_LOG_BUF1_SIZE + depends on BT_CTRL_LE_LOG_EN + int "The size of BLE log buffer1" + default 1024 + + config BT_CTRL_LE_LOG_HCI_BUF_SIZE + depends on BT_CTRL_LE_LOG_EN + int "The size of BLE log HCI buffer" + default 1024 + + config BT_CTRL_LE_LOG_BUF2_SIZE + depends on BT_CTRL_LE_LOG_EN + int "The size of BLE log buffer2" + default 1024 +endmenu diff --git a/lib/bt/controller/esp32c3/bt.c b/lib/bt/controller/esp32c3/bt.c index e053cfdf..5a1ec437 100644 --- a/lib/bt/controller/esp32c3/bt.c +++ b/lib/bt/controller/esp32c3/bt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -49,6 +49,13 @@ #else //CONFIG_IDF_TARGET_ESP32S3 #include "esp32s3/rom/rom_layout.h" #endif +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED +#include "ble_log/ble_log_spi_out.h" +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_CTRL_LE_LOG_STORAGE_EN +#include "esp_partition.h" +#include "hal/wdt_hal.h" +#endif // CONFIG_BT_CTRL_LE_LOG_STORAGE_EN #if CONFIG_BT_ENABLED /* Macro definition @@ -115,9 +122,20 @@ do{\ } while(0) #define OSI_FUNCS_TIME_BLOCKING 0xffffffff -#define OSI_VERSION 0x00010008 +#define OSI_VERSION 0x0001000A #define OSI_MAGIC_VALUE 0xFADEBEAD +#define BLE_PWR_HDL_INVL 0xFFFF + +#define BLE_CONTROLLER_MALLOC_CAPS (MALLOC_CAP_INTERNAL|MALLOC_CAP_DMA) + +#if CONFIG_BT_CTRL_LE_LOG_STORAGE_EN +#define MAX_STORAGE_SIZE (CONFIG_BT_CTRL_LE_LOG_PARTITION_SIZE) +#define BLOCK_SIZE (4096) +#define THRESHOLD (3072) +#define PARTITION_NAME "bt_ctrl_log" +#endif + /* Types definition ************************************************************************ */ @@ -142,15 +160,24 @@ typedef struct { typedef void (* osi_intr_handler)(void); +typedef struct { + int source; /*!< ISR source */ + int flags; /*!< ISR alloc flag */ + void (*fn)(void *); /*!< ISR function */ + void *arg; /*!< ISR function args*/ + intr_handle_t *handle; /*!< ISR handle */ + esp_err_t ret; +} btdm_isr_alloc_t; + /* OSI function */ struct osi_funcs_t { uint32_t _magic; uint32_t _version; - void (*_interrupt_set)(int cpu_no, int intr_source, int interrupt_no, int interrpt_prio); - void (*_interrupt_clear)(int interrupt_source, int interrupt_no); - void (*_interrupt_handler_set)(int interrupt_no, intr_handler_t fn, void *arg); - void (*_interrupt_disable)(void); - void (*_interrupt_restore)(void); + int (* _interrupt_alloc)(int cpu_id, int source, intr_handler_t handler, void *arg, void **ret_handle); + int (* _interrupt_free)(void *handle); + void (*_interrupt_handler_set_rsv)(int interrupt_no, intr_handler_t fn, void *arg); + void (*_global_intr_disable)(void); + void (*_global_intr_restore)(void); void (*_task_yield)(void); void (*_task_yield_from_isr)(void); void *(*_semphr_create)(uint32_t max, uint32_t init); @@ -195,8 +222,8 @@ struct osi_funcs_t { uint32_t (* _coex_schm_interval_get)(void); uint8_t (* _coex_schm_curr_period_get)(void); void *(* _coex_schm_curr_phase_get)(void); - void (* _interrupt_on)(int intr_num); - void (* _interrupt_off)(int intr_num); + int (* _interrupt_enable)(void *handle); + int (* _interrupt_disable)(void *handle); void (* _esp_hw_power_down)(void); void (* _esp_hw_power_up)(void); void (* _ets_backup_dma_copy)(uint32_t reg, uint32_t mem_addr, uint32_t num, bool to_rem); @@ -204,8 +231,13 @@ struct osi_funcs_t { void (* _btdm_rom_table_ready)(void); bool (* _coex_bt_wakeup_request)(void); void (* _coex_bt_wakeup_request_end)(void); + int64_t (*_get_time_us)(void); + void (* _assert)(void); }; +#if CONFIG_BT_CTRL_LE_LOG_EN +typedef void (*interface_func_t) (uint32_t len, const uint8_t*addr, bool end); +#endif // CONFIG_BT_CTRL_LE_LOG_EN /* External functions or values ************************************************************************ @@ -245,10 +277,9 @@ extern bool API_vhci_host_check_send_available(void); extern void API_vhci_host_send_packet(uint8_t *data, uint16_t len); extern int API_vhci_host_register_callback(const vhci_host_callback_t *callback); /* TX power */ -extern int ble_txpwr_set(int power_type, int power_level); -extern int ble_txpwr_get(int power_type); +extern int ble_txpwr_set(int power_type, uint16_t handle, int power_level); +extern int ble_txpwr_get(int power_type, uint16_t handle); -extern uint16_t l2c_ble_link_get_tx_buf_num(void); extern void coex_pti_v2(void); extern bool btdm_deep_sleep_mem_init(void); @@ -264,6 +295,33 @@ extern void ets_backup_dma_copy(uint32_t reg, uint32_t mem_addr, uint32_t num, b #endif extern void btdm_cca_feature_enable(void); +extern void btdm_aa_check_enhance_enable(void); + +/* BLE Log module */ +#if CONFIG_BT_CTRL_LE_LOG_EN +extern int r_ble_log_init_async(interface_func_t bt_controller_log_interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); +extern int r_ble_log_deinit_async(void); +extern void r_ble_log_async_select_dump_buffers(uint8_t buffers); +extern void r_ble_log_async_output_dump_all(bool output); +extern void esp_panic_handler_feed_wdts(void); +#endif // CONFIG_BT_CTRL_LE_LOG_EN +#if (CONFIG_BT_BLUEDROID_ENABLED || CONFIG_BT_NIMBLE_ENABLED) +extern void scan_stack_enableAdvFlowCtrlVsCmd(bool en); +extern void adv_stack_enableClearLegacyAdvVsCmd(bool en); +extern void advFilter_stack_enableDupExcListVsCmd(bool en); +extern void chanSel_stack_enableSetCsaVsCmd(bool en); +#endif // (CONFIG_BT_BLUEDROID_ENABLED || CONFIG_BT_NIMBLE_ENABLED) + +extern void ble_dtm_funcs_reset(void); +extern void ble_scan_funcs_reset(void); +extern void ble_42_adv_funcs_reset(void); +extern void ble_init_funcs_reset(void); +extern void ble_con_funcs_reset(void); +extern void ble_cca_funcs_reset(void); +extern void ble_ext_adv_funcs_reset(void); +extern void ble_ext_scan_funcs_reset(void); +extern void ble_base_funcs_reset(void); +extern void ble_enc_funcs_reset(void); extern uint32_t _bt_bss_start; extern uint32_t _bt_bss_end; @@ -277,11 +335,10 @@ extern uint32_t _bt_controller_data_end; /* Local Function Declare ********************************************************************* */ -static void interrupt_set_wrapper(int cpu_no, int intr_source, int intr_num, int intr_prio); -static void interrupt_clear_wrapper(int intr_source, int intr_num); -static void interrupt_handler_set_wrapper(int n, intr_handler_t fn, void *arg); -static void interrupt_disable(void); -static void interrupt_restore(void); +static int interrupt_alloc_wrapper(int cpu_id, int source, intr_handler_t handler, void *arg, void **ret_handle); +static int interrupt_free_wrapper(void *handle); +static void global_interrupt_disable(void); +static void global_interrupt_restore(void); static void task_yield_from_isr(void); static void *semphr_create_wrapper(uint32_t max, uint32_t init); static void semphr_delete_wrapper(void *semphr); @@ -319,14 +376,16 @@ static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status); static uint32_t coex_schm_interval_get_wrapper(void); static uint8_t coex_schm_curr_period_get_wrapper(void); static void * coex_schm_curr_phase_get_wrapper(void); -static void interrupt_on_wrapper(int intr_num); -static void interrupt_off_wrapper(int intr_num); +static int interrupt_enable_wrapper(void *handle); +static int interrupt_disable_wrapper(void *handle); static void btdm_hw_mac_power_up_wrapper(void); static void btdm_hw_mac_power_down_wrapper(void); static void btdm_backup_dma_copy_wrapper(uint32_t reg, uint32_t mem_addr, uint32_t num, bool to_mem); static void btdm_funcs_table_ready_wrapper(void); static bool coex_bt_wakeup_request(void); static void coex_bt_wakeup_request_end(void); +static int64_t get_time_us_wrapper(void); +static void assert_wrapper(void); static void btdm_slp_tmr_callback(void *arg); @@ -334,6 +393,15 @@ static esp_err_t try_heap_caps_add_region(intptr_t start, intptr_t end); static void bt_controller_deinit_internal(void); +#if CONFIG_BT_CTRL_LE_LOG_EN +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end); +#if CONFIG_BT_CTRL_LE_LOG_STORAGE_EN +void esp_bt_read_ctrl_log_from_flash(bool output); +static int esp_bt_controller_log_storage(uint32_t len, const uint8_t *addr, bool end); +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); +#endif // #if CONFIG_BT_CTRL_LE_LOG_STORAGE_EN +#endif // CONFIG_BT_CTRL_LE_LOG_EN + /* Local variable definition *************************************************************************** */ @@ -341,11 +409,11 @@ static void bt_controller_deinit_internal(void); static const struct osi_funcs_t osi_funcs_ro = { ._magic = OSI_MAGIC_VALUE, ._version = OSI_VERSION, - ._interrupt_set = interrupt_set_wrapper, - ._interrupt_clear = interrupt_clear_wrapper, - ._interrupt_handler_set = interrupt_handler_set_wrapper, - ._interrupt_disable = interrupt_disable, - ._interrupt_restore = interrupt_restore, + ._interrupt_alloc = interrupt_alloc_wrapper, + ._interrupt_free = interrupt_free_wrapper, + ._interrupt_handler_set_rsv = NULL, + ._global_intr_disable = global_interrupt_disable, + ._global_intr_restore = global_interrupt_restore, ._task_yield = vPortYield, ._task_yield_from_isr = task_yield_from_isr, ._semphr_create = semphr_create_wrapper, @@ -390,8 +458,8 @@ static const struct osi_funcs_t osi_funcs_ro = { ._coex_schm_interval_get = coex_schm_interval_get_wrapper, ._coex_schm_curr_period_get = coex_schm_curr_period_get_wrapper, ._coex_schm_curr_phase_get = coex_schm_curr_phase_get_wrapper, - ._interrupt_on = interrupt_on_wrapper, - ._interrupt_off = interrupt_off_wrapper, + ._interrupt_enable = interrupt_enable_wrapper, + ._interrupt_disable = interrupt_disable_wrapper, ._esp_hw_power_down = btdm_hw_mac_power_down_wrapper, ._esp_hw_power_up = btdm_hw_mac_power_up_wrapper, ._ets_backup_dma_copy = btdm_backup_dma_copy_wrapper, @@ -399,6 +467,8 @@ static const struct osi_funcs_t osi_funcs_ro = { ._btdm_rom_table_ready = btdm_funcs_table_ready_wrapper, ._coex_bt_wakeup_request = coex_bt_wakeup_request, ._coex_bt_wakeup_request_end = coex_bt_wakeup_request_end, + ._get_time_us = get_time_us_wrapper, + ._assert = assert_wrapper, }; static DRAM_ATTR struct osi_funcs_t *osi_funcs_p; @@ -427,6 +497,255 @@ static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock; static DRAM_ATTR esp_pm_lock_handle_t s_light_sleep_pm_lock; #endif +#if CONFIG_BT_CTRL_LE_LOG_EN +enum log_out_mode { + LOG_DUMP_MEMORY, + LOG_ASYNC_OUT, + LOG_STORAGE_TO_FLASH, + LOG_SPI_OUT, +}; + +const static uint32_t log_bufs_size[] = {CONFIG_BT_CTRL_LE_LOG_BUF1_SIZE, CONFIG_BT_CTRL_LE_LOG_HCI_BUF_SIZE, CONFIG_BT_CTRL_LE_LOG_BUF2_SIZE}; +bool log_is_inited = false; +#if CONFIG_BT_CTRL_LE_LOG_DUMP_ONLY +uint8_t log_output_mode = LOG_DUMP_MEMORY; +#else +#if CONFIG_BT_CTRL_LE_LOG_STORAGE_EN +uint8_t log_output_mode = LOG_STORAGE_TO_FLASH; +#elif CONFIG_BT_CTRL_LE_LOG_SPI_OUT_EN +uint8_t log_output_mode = LOG_SPI_OUT; +#else +uint8_t log_output_mode = LOG_ASYNC_OUT; +#endif // CONFIG_BT_CTRL_LE_LOG_STORAGE_EN +#endif // CONFIG_BT_CTRL_LE_LOG_DUMP_ONLY +#if CONFIG_BT_CTRL_LE_LOG_STORAGE_EN +static const esp_partition_t *log_partition; +static uint32_t write_index = 0; +static uint32_t next_erase_index = BLOCK_SIZE; +static bool block_erased = false; +static bool stop_write = false; +static bool is_filled = false; +#endif // CONFIG_BT_CTRL_LE_LOG_STORAGE_EN + +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end) +{ + if (log_output_mode == LOG_STORAGE_TO_FLASH) { +#if CONFIG_BT_CTRL_LE_LOG_STORAGE_EN + esp_bt_controller_log_storage(len, addr, end); +#endif //CONFIG_BT_CTRL_LE_LOG_STORAGE_EN + } else { + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + for (int i = 0; i < len; i++) { + esp_rom_printf("%02x ", addr[i]); + } + + if (end) { + esp_rom_printf("\n"); + } + portEXIT_CRITICAL_SAFE(&spinlock); + } +} + +#if CONFIG_BT_CTRL_LE_LOG_SPI_OUT_EN +static IRAM_ATTR void esp_bt_controller_spi_log_interface(uint32_t len, const uint8_t *addr, bool end) +{ + ble_log_spi_out_write(BLE_LOG_SPI_OUT_SOURCE_ESP_LEGACY, addr, len); +} +#endif // CONFIG_BT_CTRL_LE_LOG_SPI_OUT_EN + +void esp_ble_controller_log_dump_all(bool output) +{ + if (log_output_mode == LOG_STORAGE_TO_FLASH) { +#if CONFIG_BT_CTRL_LE_LOG_STORAGE_EN + esp_bt_read_ctrl_log_from_flash(output); +#endif // CONFIG_BT_CTRL_LE_LOG_STORAGE_EN + } else { + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + esp_rom_printf("\r\n[DUMP_START:"); + r_ble_log_async_output_dump_all(output); + esp_rom_printf(":DUMP_END]\r\n"); + portEXIT_CRITICAL_SAFE(&spinlock); + } +} + +void esp_bt_log_output_mode_set(uint8_t output_mode) +{ + log_output_mode = output_mode; +} + +uint8_t esp_bt_log_output_mode_get(void) +{ + return log_output_mode; +} + +esp_err_t esp_bt_controller_log_init(uint8_t log_output_mode) +{ + esp_err_t ret = ESP_OK; + interface_func_t bt_controller_log_interface; + bt_controller_log_interface = esp_bt_controller_log_interface; + bool task_create; + uint8_t buffers = 0; + + if (log_is_inited) { + return ret; + } + +#if CONFIG_BT_CTRL_LE_LOG_EN + buffers |= ESP_BLE_LOG_BUF_CONTROLLER; +#endif // CONFIG_BT_CTRL_LE_LOG_EN +#if CONFIG_BT_CTRL_LE_HCI_LOG_EN + buffers |= ESP_BLE_LOG_BUF_HCI; +#endif // CONFIG_BT_CTRL_LE_HCI_LOG_EN + + switch (log_output_mode) { + case LOG_DUMP_MEMORY: + task_create = false; + break; + case LOG_ASYNC_OUT: + case LOG_STORAGE_TO_FLASH: + task_create = true; +#if CONFIG_BT_CTRL_LE_LOG_STORAGE_EN + if (log_output_mode == LOG_STORAGE_TO_FLASH) { + esp_bt_ctrl_log_partition_get_and_erase_first_block(); + } +#endif // CONFIG_BT_CTRL_LE_LOG_STORAGE_EN + break; + case LOG_SPI_OUT: + task_create = true; +#if CONFIG_BT_CTRL_LE_LOG_SPI_OUT_EN + bt_controller_log_interface = esp_bt_controller_spi_log_interface; +#endif // CONFIG_BT_CTRL_LE_LOG_SPI_OUT_EN + break; + default: + assert(0); + } + + ret = r_ble_log_init_async(bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size); + if (ret == ESP_OK) { + log_is_inited = true; + } + + return ret; +} + +void esp_bt_ontroller_log_deinit(void) +{ + r_ble_log_deinit_async(); + log_is_inited = false; +} + +#if CONFIG_BT_CTRL_LE_LOG_STORAGE_EN +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void) +{ + log_partition = NULL; + assert(MAX_STORAGE_SIZE % BLOCK_SIZE == 0); + // Find the partition map in the partition table + log_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, PARTITION_NAME); + assert(log_partition != NULL); + // Prepare data to be read later using the mapped address + ESP_ERROR_CHECK(esp_partition_erase_range(log_partition, 0, BLOCK_SIZE)); + write_index = 0; + next_erase_index = BLOCK_SIZE; + block_erased = false; + is_filled = false; + stop_write = false; +} + +static int esp_bt_controller_log_storage(uint32_t len, const uint8_t *addr, bool end) +{ + if (len > MAX_STORAGE_SIZE) { + return -1; + } + + if (stop_write) { + return 0; + } + + if (((write_index) % BLOCK_SIZE) >= THRESHOLD && !block_erased) { + // esp_rom_printf("Ers nxt: %d,%d\n", next_erase_index, write_index); + esp_partition_erase_range(log_partition, next_erase_index, BLOCK_SIZE); + next_erase_index = (next_erase_index + BLOCK_SIZE) % MAX_STORAGE_SIZE; + block_erased = true; + } + + if (((write_index + len) / BLOCK_SIZE) > (write_index / BLOCK_SIZE)) { + block_erased = false; + } + + if (write_index + len <= MAX_STORAGE_SIZE) { + esp_partition_write(log_partition, write_index, addr, len); + write_index = (write_index + len) % MAX_STORAGE_SIZE; + } else { + uint32_t first_part_len = MAX_STORAGE_SIZE - write_index; + esp_partition_write(log_partition, write_index, addr, first_part_len); + esp_partition_write(log_partition, 0, addr + first_part_len, len - first_part_len); + write_index = len - first_part_len; + is_filled = true; + // esp_rom_printf("old idx: %d,%d\n",next_erase_index, write_index); + } + + return 0; +} + +void esp_bt_read_ctrl_log_from_flash(bool output) +{ + esp_partition_mmap_handle_t mmap_handle; + uint32_t read_index; + const void *mapped_ptr; + const uint8_t *buffer; + uint32_t print_len; + uint32_t max_print_len; + esp_err_t err; + + print_len = 0; + max_print_len = 4096; + err = esp_partition_mmap(log_partition, 0, MAX_STORAGE_SIZE, ESP_PARTITION_MMAP_DATA, &mapped_ptr, &mmap_handle); + if (err != ESP_OK) { + ESP_LOGE("FLASH", "Mmap failed: %s", esp_err_to_name(err)); + return; + } + + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + r_ble_log_async_output_dump_all(true); + esp_bt_ontroller_log_deinit(); + stop_write = true; + + buffer = (const uint8_t *)mapped_ptr; + esp_panic_handler_feed_wdts(); + if (is_filled) { + read_index = next_erase_index; + } else { + read_index = 0; + } + + esp_rom_printf("\r\nREAD_CHECK:%ld,%ld,%d\r\n",read_index, write_index, is_filled); + esp_rom_printf("\r\n[DUMP_START:"); + while (read_index != write_index) { + esp_rom_printf("%02x ", buffer[read_index]); + if (print_len > max_print_len) { + esp_panic_handler_feed_wdts(); + print_len = 0; + } + + print_len++; + read_index = (read_index + 1) % MAX_STORAGE_SIZE; + } + + esp_rom_printf(":DUMP_END]\r\n"); + portEXIT_CRITICAL_SAFE(&spinlock); + esp_partition_munmap(mmap_handle); + err = esp_bt_controller_log_init(log_output_mode); + assert(err == ESP_OK); +} +#endif // CONFIG_BT_CTRL_LE_LOG_STORAGE_EN +#endif // CONFIG_BT_CTRL_LE_LOG_EN + void IRAM_ATTR btdm_hw_mac_power_down_wrapper(void) { #if CONFIG_MAC_BB_PD @@ -478,35 +797,48 @@ static inline void esp_bt_power_domain_off(void) esp_wifi_bt_power_domain_off(); } -static void interrupt_set_wrapper(int cpu_no, int intr_source, int intr_num, int intr_prio) +static void btdm_intr_alloc(void *arg) { - esp_rom_route_intr_matrix(cpu_no, intr_source, intr_num); -#if __riscv - esprv_int_set_priority(intr_num, intr_prio); - esprv_int_set_type(intr_num, 0); -#endif + btdm_isr_alloc_t *p = arg; + p->ret = esp_intr_alloc(p->source, p->flags, p->fn, p->arg, p->handle); } -static void interrupt_clear_wrapper(int intr_source, int intr_num) +static int interrupt_alloc_wrapper(int cpu_id, int source, intr_handler_t handler, void *arg, void **ret_handle) { + btdm_isr_alloc_t p; + p.source = source; +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + p.flags = ESP_INTR_FLAG_LEVEL3; +#else + p.flags = ESP_INTR_FLAG_LEVEL3 | ESP_INTR_FLAG_IRAM; +#endif + p.fn = handler; + p.arg = arg; + p.handle = (intr_handle_t *)ret_handle; +#if CONFIG_FREERTOS_UNICORE + btdm_intr_alloc(&p); +#else + esp_ipc_call_blocking(cpu_id, btdm_intr_alloc, &p); +#endif + return p.ret; } -static void interrupt_handler_set_wrapper(int n, intr_handler_t fn, void *arg) +static int interrupt_free_wrapper(void *handle) { - esp_cpu_intr_set_handler(n, fn, arg); + return esp_intr_free((intr_handle_t)handle); } -static void interrupt_on_wrapper(int intr_num) +static int interrupt_enable_wrapper(void *handle) { - esp_cpu_intr_enable(1 << intr_num); + return esp_intr_enable((intr_handle_t)handle); } -static void interrupt_off_wrapper(int intr_num) +static int interrupt_disable_wrapper(void *handle) { - esp_cpu_intr_disable(1<> 11); -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#if CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP + // recalculate clock drift when Bluetooth using main XTAL during light sleep if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) { uncertainty = us_to_sleep * BTDM_RTC_SLOW_CLK_RC_DRIFT_PERCENT / 100; } @@ -926,6 +1273,49 @@ static void btdm_funcs_table_ready_wrapper(void) #if BT_BLE_CCA_MODE == 2 btdm_cca_feature_enable(); #endif +#if BLE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS_ENABLED + btdm_aa_check_enhance_enable(); +#endif +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + // do nothing +#else + ESP_LOGI(BT_LOG_TAG, "Feature Config, ADV:%d, BLE_50:%d, DTM:%d, SCAN:%d, CCA:%d, SMP:%d, CONNECT:%d", + BT_CTRL_BLE_ADV, BT_CTRL_50_FEATURE_SUPPORT, BT_CTRL_DTM_ENABLE, BT_CTRL_BLE_SCAN, + BT_BLE_CCA_MODE, BLE_SECURITY_ENABLE, BT_CTRL_BLE_MASTER); + + ble_base_funcs_reset(); +#if CONFIG_BT_CTRL_BLE_ADV + ble_42_adv_funcs_reset(); +#if (BT_CTRL_50_FEATURE_SUPPORT == 1) + ble_ext_adv_funcs_reset(); +#endif // +#endif // CONFIG_BT_CTRL_BLE_ADV + +#if CONFIG_BT_CTRL_DTM_ENABLE + ble_dtm_funcs_reset(); +#endif // CONFIG_BT_CTRL_DTM_ENABLE + +#if CONFIG_BT_CTRL_BLE_SCAN + ble_scan_funcs_reset(); +#if (BT_CTRL_50_FEATURE_SUPPORT == 1) + ble_ext_scan_funcs_reset(); +#endif // (BT_CTRL_50_FEATURE_SUPPORT == 1) +#endif // CONFIG_BT_CTRL_BLE_SCAN + +#if (BT_BLE_CCA_MODE != 0) + ble_cca_funcs_reset(); +#endif // (BT_BLE_CCA_MODE != 0) + +#if CONFIG_BT_CTRL_BLE_SECURITY_ENABLE + ble_enc_funcs_reset(); +#endif // CONFIG_BT_CTRL_BLE_SECURITY_ENABLE + +#if CONFIG_BT_CTRL_BLE_MASTER + ble_init_funcs_reset(); + ble_con_funcs_reset(); +#endif // CONFIG_BT_CTRL_BLE_MASTER + +#endif // CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY } bool bt_async_wakeup_request(void) @@ -949,6 +1339,18 @@ static void coex_bt_wakeup_request_end(void) return; } +static IRAM_ATTR int64_t get_time_us_wrapper(void) +{ + return esp_timer_get_time(); +} + +static IRAM_ATTR void assert_wrapper(void) +{ +#if CONFIG_BT_CTRL_LE_LOG_EN + esp_ble_controller_log_dump_all(true); +#endif // CONFIG_BT_CTRL_LE_LOG_EN +} + bool esp_vhci_host_check_send_available(void) { if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { @@ -1391,6 +1793,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) ESP_LOGI(BT_LOG_TAG, "BT controller compile version [%s]", btdm_controller_get_compile_version()); +#if (CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) + ESP_LOGI(BT_LOG_TAG,"Put all controller code in flash"); +#endif + if ((err = btdm_low_power_mode_init(cfg)) != ESP_OK) { ESP_LOGE(BT_LOG_TAG, "Low power module initialization failed"); goto error; @@ -1400,20 +1806,49 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) coex_init(); #endif +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + if (ble_log_spi_out_init() != 0) { + ESP_LOGE(BT_LOG_TAG, "BLE Log SPI output init failed"); + goto error; + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + periph_module_enable(PERIPH_BT_MODULE); periph_module_reset(PERIPH_BT_MODULE); - if (btdm_controller_init(cfg) != 0) { +#if CONFIG_BT_CTRL_LE_LOG_EN + err = esp_bt_controller_log_init(log_output_mode); + if (err != ESP_OK) { + ESP_LOGW(BT_LOG_TAG, "ble_controller_log_init failed %d", err); + goto error; + } +#endif // CONFIG_BT_CTRL_LE_LOG_EN + + err = btdm_controller_init(cfg); + + if (err != 0) { + ESP_LOGE(BT_LOG_TAG, "%s %d\n",__func__,err); err = ESP_ERR_NO_MEM; goto error; } +#if (CONFIG_BT_BLUEDROID_ENABLED || CONFIG_BT_NIMBLE_ENABLED) + scan_stack_enableAdvFlowCtrlVsCmd(true); + adv_stack_enableClearLegacyAdvVsCmd(true); + advFilter_stack_enableDupExcListVsCmd(true); + chanSel_stack_enableSetCsaVsCmd(true); +#endif // (CONFIG_BT_BLUEDROID_ENABLED || CONFIG_BT_NIMBLE_ENABLED) + btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; return ESP_OK; error: +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + bt_controller_deinit_internal(); return err; @@ -1425,6 +1860,17 @@ esp_err_t esp_bt_controller_deinit(void) return ESP_ERR_INVALID_STATE; } +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if (CONFIG_BT_BLUEDROID_ENABLED || CONFIG_BT_NIMBLE_ENABLED) + scan_stack_enableAdvFlowCtrlVsCmd(false); + adv_stack_enableClearLegacyAdvVsCmd(false); + advFilter_stack_enableDupExcListVsCmd(false); + chanSel_stack_enableSetCsaVsCmd(false); +#endif // (CONFIG_BT_BLUEDROID_ENABLED || CONFIG_BT_NIMBLE_ENABLED) + btdm_controller_deinit(); bt_controller_deinit_internal(); @@ -1503,6 +1949,10 @@ static void bt_controller_deinit_internal(void) #endif esp_phy_modem_deinit(); +#if CONFIG_BT_CTRL_LE_LOG_EN + esp_bt_ontroller_log_deinit(); +#endif // CONFIG_BT_CTRL_LE_LOG_EN + if (osi_funcs_p != NULL) { free(osi_funcs_p); osi_funcs_p = NULL; @@ -1657,16 +2107,89 @@ esp_bt_controller_status_t esp_bt_controller_get_status(void) return btdm_controller_status; } +static int enh_power_type_get(esp_ble_power_type_t power_type) +{ + switch (power_type) { + case ESP_BLE_PWR_TYPE_ADV: + return ESP_BLE_ENHANCED_PWR_TYPE_ADV; + case ESP_BLE_PWR_TYPE_SCAN: + return ESP_BLE_ENHANCED_PWR_TYPE_SCAN; + case ESP_BLE_PWR_TYPE_CONN_HDL0: + case ESP_BLE_PWR_TYPE_CONN_HDL1: + case ESP_BLE_PWR_TYPE_CONN_HDL2: + case ESP_BLE_PWR_TYPE_CONN_HDL3: + case ESP_BLE_PWR_TYPE_CONN_HDL4: + case ESP_BLE_PWR_TYPE_CONN_HDL5: + case ESP_BLE_PWR_TYPE_CONN_HDL6: + case ESP_BLE_PWR_TYPE_CONN_HDL7: + case ESP_BLE_PWR_TYPE_CONN_HDL8: + return ESP_BLE_ENHANCED_PWR_TYPE_CONN; + case ESP_BLE_PWR_TYPE_DEFAULT: + return ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT; + default: + break; + } + + return power_type; +} + /* extra functions */ esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_t power_level) +{ + esp_err_t stat = ESP_FAIL; + uint16_t handle = BLE_PWR_HDL_INVL; + int enh_pwr_type = enh_power_type_get(power_type); + + if (power_type > ESP_BLE_PWR_TYPE_DEFAULT) { + return ESP_ERR_NOT_SUPPORTED; + } + + if (enh_pwr_type == ESP_BLE_ENHANCED_PWR_TYPE_CONN) { + handle = power_type; + } + + if (ble_txpwr_set(enh_pwr_type, handle, power_level) == 0) { + stat = ESP_OK; + } + + return stat; +} + +esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type) +{ + esp_power_level_t lvl; + uint16_t handle = BLE_PWR_HDL_INVL; + int enh_pwr_type = enh_power_type_get(power_type); + + if (power_type > ESP_BLE_PWR_TYPE_DEFAULT) { + return ESP_PWR_LVL_INVALID; + } + + if (enh_pwr_type == ESP_BLE_ENHANCED_PWR_TYPE_CONN) { + handle = power_type; + } + + lvl = (esp_power_level_t)ble_txpwr_get(enh_pwr_type, handle); + + return lvl; +} + +esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle, + esp_power_level_t power_level) { esp_err_t stat = ESP_FAIL; switch (power_type) { - case ESP_BLE_PWR_TYPE_ADV: - case ESP_BLE_PWR_TYPE_SCAN: - case ESP_BLE_PWR_TYPE_DEFAULT: - if (ble_txpwr_set(power_type, power_level) == 0) { + case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: + case ESP_BLE_ENHANCED_PWR_TYPE_INIT: + if (ble_txpwr_set(power_type, BLE_PWR_HDL_INVL, power_level) == 0) { + stat = ESP_OK; + } + break; + case ESP_BLE_ENHANCED_PWR_TYPE_ADV: + case ESP_BLE_ENHANCED_PWR_TYPE_CONN: + if (ble_txpwr_set(power_type, handle, power_level) == 0) { stat = ESP_OK; } break; @@ -1678,33 +2201,26 @@ esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_ return stat; } -esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type) +esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, + uint16_t handle) { - esp_power_level_t lvl; + int tx_level = 0; switch (power_type) { - case ESP_BLE_PWR_TYPE_ADV: - case ESP_BLE_PWR_TYPE_SCAN: - lvl = (esp_power_level_t)ble_txpwr_get(power_type); + case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: + case ESP_BLE_ENHANCED_PWR_TYPE_INIT: + tx_level = ble_txpwr_get(power_type, BLE_PWR_HDL_INVL); break; - case ESP_BLE_PWR_TYPE_CONN_HDL0: - case ESP_BLE_PWR_TYPE_CONN_HDL1: - case ESP_BLE_PWR_TYPE_CONN_HDL2: - case ESP_BLE_PWR_TYPE_CONN_HDL3: - case ESP_BLE_PWR_TYPE_CONN_HDL4: - case ESP_BLE_PWR_TYPE_CONN_HDL5: - case ESP_BLE_PWR_TYPE_CONN_HDL6: - case ESP_BLE_PWR_TYPE_CONN_HDL7: - case ESP_BLE_PWR_TYPE_CONN_HDL8: - case ESP_BLE_PWR_TYPE_DEFAULT: - lvl = (esp_power_level_t)ble_txpwr_get(ESP_BLE_PWR_TYPE_DEFAULT); + case ESP_BLE_ENHANCED_PWR_TYPE_ADV: + case ESP_BLE_ENHANCED_PWR_TYPE_CONN: + tx_level = ble_txpwr_get(power_type, handle); break; default: - lvl = ESP_PWR_LVL_INVALID; - break; + return ESP_PWR_LVL_INVALID; } - return lvl; + return (esp_power_level_t)tx_level; } esp_err_t esp_bt_sleep_enable (void) @@ -1765,11 +2281,6 @@ int IRAM_ATTR esp_bt_h4tl_eif_io_event_notify(int event) return btdm_hci_tl_io_event_post(event); } -uint16_t esp_bt_get_tx_buf_num(void) -{ - return l2c_ble_link_get_tx_buf_num(); -} - static void coex_wifi_sleep_set_hook(bool sleep) { diff --git a/lib/bt/controller/esp32c5/Kconfig.in b/lib/bt/controller/esp32c5/Kconfig.in index 02ac4995..2e6db9fd 100644 --- a/lib/bt/controller/esp32c5/Kconfig.in +++ b/lib/bt/controller/esp32c5/Kconfig.in @@ -2,15 +2,15 @@ menu "HCI Config" choice BT_LE_HCI_INTERFACE - prompt "Select HCI interface" + prompt "HCI mode" default BT_LE_HCI_INTERFACE_USE_RAM config BT_LE_HCI_INTERFACE_USE_RAM - bool "ram" + bool "VHCI" help Use RAM as HCI interface config BT_LE_HCI_INTERFACE_USE_UART - bool "uart" + bool "UART(H4)" help Use UART as HCI interface endchoice @@ -73,12 +73,26 @@ menu "HCI Config" UART_PARITY_ODD endchoice - config BT_LE_HCI_UART_TASK_STACK_SIZE - int "HCI uart task stack size" - depends on BT_LE_HCI_INTERFACE_USE_UART - default 1000 + config BT_LE_HCI_UART_RX_BUFFER_SIZE + int "The size of rx ring buffer memory" + depends on !BT_LE_HCI_INTERFACE_USE_RAM + default 512 + help + The size of rx ring buffer memory + + config BT_LE_HCI_UART_TX_BUFFER_SIZE + int "The size of tx ring buffer memory" + depends on !BT_LE_HCI_INTERFACE_USE_RAM + default 256 help - Set the size of uart task stack + The size of tx ring buffer memory + + config BT_LE_HCI_TRANS_TASK_STACK_SIZE + int "HCI transport task stack size" + depends on !BT_LE_HCI_INTERFACE_USE_RAM + default 2048 + help + This configures stack size of hci transport task endmenu config BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT @@ -269,54 +283,131 @@ config BT_LE_CONTROLLER_TASK_STACK_SIZE help This configures stack size of NimBLE controller task -menuconfig BT_LE_CONTROLLER_LOG_ENABLED - bool "Controller log enable" - default n - help - Enable controller log +menu "Controller debug features" + menuconfig BT_LE_CONTROLLER_LOG_ENABLED + bool "Controller log enable" + default n + help + Enable controller log -config BT_LE_CONTROLLER_LOG_CTRL_ENABLED - bool "enable controller log module" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default y - help + config BT_LE_CONTROLLER_LOG_CTRL_ENABLED + bool "enable controller log module" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default y + help Enable controller log module -config BT_LE_CONTROLLER_LOG_HCI_ENABLED - bool "enable HCI log module" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default y - help + config BT_LE_CONTROLLER_LOG_HCI_ENABLED + bool "enable HCI log module" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default y + help Enable hci log module -config BT_LE_CONTROLLER_LOG_DUMP_ONLY - bool "Controller log dump mode only" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default y - help + config BT_LE_CONTROLLER_LOG_DUMP_ONLY + bool "Controller log dump mode only" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default y + help Only operate in dump mode -config BT_LE_LOG_CTRL_BUF1_SIZE - int "size of the first BLE controller LOG buffer" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default 4096 - help + config BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + bool "Output ble controller logs to SPI bus (Experimental)" + depends on BT_LE_CONTROLLER_LOG_ENABLED + depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY + select BT_BLE_LOG_SPI_OUT_ENABLED + default n + help + Output ble controller logs to SPI bus + + config BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + bool "Store ble controller logs to flash(Experimental)" + depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Store ble controller logs to flash memory. + + config BT_LE_CONTROLLER_LOG_PARTITION_SIZE + int "size of ble controller log partition(Multiples of 4K)" + depends on BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + default 65536 + help + The size of ble controller log partition shall be a multiples of 4K. + The name of log partition shall be "bt_ctrl_log". + The partition type shall be ESP_PARTITION_TYPE_DATA. + The partition sub_type shall be ESP_PARTITION_SUBTYPE_ANY. + + config BT_LE_LOG_CTRL_BUF1_SIZE + int "size of the first BLE controller LOG buffer" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default 4096 + help Configure the size of the first BLE controller LOG buffer. -config BT_LE_LOG_CTRL_BUF2_SIZE - int "size of the second BLE controller LOG buffer" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default 1024 - help + config BT_LE_LOG_CTRL_BUF2_SIZE + int "size of the second BLE controller LOG buffer" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default 1024 + help Configure the size of the second BLE controller LOG buffer. -config BT_LE_LOG_HCI_BUF_SIZE - int "size of the BLE HCI LOG buffer" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default 4096 - help + config BT_LE_LOG_HCI_BUF_SIZE + int "size of the BLE HCI LOG buffer" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default 4096 + help Configure the size of the BLE HCI LOG buffer. + config BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE + bool "Enable wrap panic handler" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Wrap esp_panic_handler to get controller logs when PC pointer exception crashes. + + config BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE + bool "Enable esp_task_wdt_isr_user_handler implementation" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Implement esp_task_wdt_isr_user_handler to get controller logs when task wdt issue is triggered. + + config BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL + int "The output level of controller log" + depends on BT_LE_CONTROLLER_LOG_ENABLED + range 0 5 + default 1 + help + The output level of controller log. + + config BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH + hex "The switch of module log output" + depends on BT_LE_CONTROLLER_LOG_ENABLED + range 0 0xFFFFFFFF + default 0xFFFFFFFF + help + The switch of module log output, this is an unsigned 32-bit hexadecimal value. + + config BT_LE_ERROR_SIM_ENABLED + bool "Enable controller features for internal testing" + default n + + config BT_LE_ASSERT_WHEN_ABNORMAL_DISCONN_ENABLED + bool "When ACL disconnects abnormally, assertion processing is performed(Experimental)" + default n + + config BT_LE_DEBUG_REMAIN_SCENE_ENABLED + bool "Remain scene with GDB to capture relevant status info(Experimental)" + default n + help + Retain scene with GDB to capture info, requires disabling WDT (CONFIG_ESP_INT_WDT, CONFIG_ESP_TASK_WDT_EN). + + config BT_LE_PTR_CHECK_ENABLED + bool "Enable boundary check for internal memory" + default n +endmenu + config BT_LE_LL_RESOLV_LIST_SIZE int "BLE LL Resolving list size" range 1 5 @@ -372,7 +463,7 @@ config BT_LE_CRYPTO_STACK_MBEDTLS config BT_LE_WHITELIST_SIZE int "BLE white list size" - range 1 15 + range 1 31 default 12 depends on !BT_NIMBLE_ENABLED @@ -393,6 +484,23 @@ config BT_LE_LL_SCA help Sleep clock accuracy of our device (in ppm) +config BT_LE_LL_PEER_SCA_SET_ENABLE + bool "Enable to set constant peer SCA" + default n + help + Enable setting of constant peer SCA, use this if peer device has SCA larger than 500 PPM. + Enable this option, the controller will always use BT_LE_LL_PEER_SCA as the peer SCA value + to calculate the window widening instead of the value received from peer device. + + +config BT_LE_LL_PEER_SCA + int "Constant peer sleep clock accuracy value" + range 0 10000 + depends on BT_LE_LL_PEER_SCA_SET_ENABLE + default 0 + help + Set the sleep clock accuracy of peer device + config BT_LE_MAX_CONNECTIONS int "Maximum number of concurrent connections" depends on !BT_NIMBLE_ENABLED @@ -463,6 +571,7 @@ config BT_LE_USE_ESP_TIMER help Set this option to use Esp Timer which has higher priority timer instead of FreeRTOS timer + config BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP bool "BLE adv report flow control supported" default y @@ -561,3 +670,145 @@ config BT_LE_SCAN_DUPL_CACHE_REFRESH_PERIOD config BT_LE_MSYS_INIT_IN_CONTROLLER bool "Msys Mbuf Init in Controller" default y + +config BT_LE_TX_CCA_ENABLED + bool "Enable TX CCA feature" + default n + help + Enable CCA feature to cancel sending the packet if the signal power is stronger than CCA threshold. + +config BT_LE_CCA_RSSI_THRESH + int "CCA RSSI threshold value" + depends on BT_LE_TX_CCA_ENABLED + range 20 100 + default 65 + help + Power threshold of CCA in unit of -1 dBm. + +choice BT_LE_DFT_TX_POWER_LEVEL_DBM + prompt "BLE default Tx power level(dBm)" + default BT_LE_DFT_TX_POWER_LEVEL_P9 + help + Specify default Tx power level(dBm). + config BT_LE_DFT_TX_POWER_LEVEL_N24 + bool "-24dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N21 + bool "-21dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N18 + bool "-18dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N15 + bool "-15dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N12 + bool "-12dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N9 + bool "-9dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N6 + bool "-6dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N3 + bool "-3dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N0 + bool "0dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P3 + bool "+3dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P6 + bool "+6dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P9 + bool "+9dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P12 + bool "+12dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P15 + bool "+15dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P18 + bool "+18dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P20 + bool "+20dBm" +endchoice + +config BT_LE_DFT_TX_POWER_LEVEL_DBM_EFF + int + default -15 if BT_LE_DFT_TX_POWER_LEVEL_N15 + default -12 if BT_LE_DFT_TX_POWER_LEVEL_N12 + default -9 if BT_LE_DFT_TX_POWER_LEVEL_N9 + default -6 if BT_LE_DFT_TX_POWER_LEVEL_N6 + default -3 if BT_LE_DFT_TX_POWER_LEVEL_N3 + default 0 if BT_LE_DFT_TX_POWER_LEVEL_N0 + default 3 if BT_LE_DFT_TX_POWER_LEVEL_P3 + default 6 if BT_LE_DFT_TX_POWER_LEVEL_P6 + default 9 if BT_LE_DFT_TX_POWER_LEVEL_P9 + default 12 if BT_LE_DFT_TX_POWER_LEVEL_P12 + default 15 if BT_LE_DFT_TX_POWER_LEVEL_P15 + default 18 if BT_LE_DFT_TX_POWER_LEVEL_P18 + default 20 if BT_LE_DFT_TX_POWER_LEVEL_P20 + default 0 + +config BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS + bool "Enable enhanced Access Address check in CONNECT_IND" + default n + help + Enabling this option will add stricter verification of the Access Address in the CONNECT_IND PDU. + This improves security by ensuring that only connection requests with valid Access Addresses are accepted. + If disabled, only basic checks are applied, improving compatibility. + +config BT_CTRL_RUN_IN_FLASH_ONLY + bool "Reduce BLE IRAM usage (READ DOCS FIRST) (EXPERIMENTAL)" + default n + help + Move most IRAM into flash. This will increase the usage of flash and reduce ble performance. + Because the code is moved to the flash, the execution speed of the code is reduced. + To have a small impact on performance, you need to enable flash suspend (SPI_FLASH_AUTO_SUSPEND). + +menu "BLE disconnects when Instant Passed (0x28) occurs" + config BT_LE_CTRL_LLCP_CONN_UPDATE + bool "BLE ACL connection update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs during connection update procedure. + + config BT_LE_CTRL_LLCP_CHAN_MAP_UPDATE + bool "BLE ACL channel map update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs in channel map update procedure. + + config BT_LE_CTRL_LLCP_PHY_UPDATE + bool "BLE ACL PHY update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs in PHY update procedure. +endmenu + +config BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX + int "The value of upperlimitmax during scan backoff procedure" + range 1 256 + default 32 + help + The value of upperlimitmax needs to be a power of 2. + +config BT_LE_CTRL_CHAN_ASS_EN + bool "Enable channel assessment(Experimental)" + default n + help + If this option is enabled, The Controller will records the communication quality + for each channel and then start a timer to check and update the channel map every 4 seconds. + +config BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX + bool "Enable aux packet when ext adv data length is zero(Experimental)" + default y + help + When this option is enabled, auxiliary packets will be present in the events of + 'Non-Connectable and Non-Scannable' regardless of whether the advertising length is 0. + If this option is not enabled, auxiliary packets will only be present when the advertising length is not 0. + +config BT_LE_RXBUF_OPT_ENABLED + bool "Enable rxbuf optimization feature" + default y + +config BT_LE_CTRL_FAST_CONN_DATA_TX_EN + bool "Enable fast sending of connection data" + default y + help + If this option is enabled, The Controller will continue to + Send an empty PDU after sending valid connection data within an interval. diff --git a/lib/bt/controller/esp32c5/ble.c b/lib/bt/controller/esp32c5/ble.c new file mode 100644 index 00000000..8aef45a9 --- /dev/null +++ b/lib/bt/controller/esp32c5/ble.c @@ -0,0 +1,165 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include "sdkconfig.h" +#include "esp_bt_cfg.h" +#include "esp_bit_defs.h" + +/* External functions or variables + ************************************************************************ + */ +int base_stack_initEnv(void); +void base_stack_deinitEnv(void); +int base_stack_enable(void); +void base_stack_disable(void); + +int conn_stack_initEnv(void); +void conn_stack_deinitEnv(void); +int conn_stack_enable(void); +void conn_stack_disable(void); + +#if CONFIG_BT_LE_ERROR_SIM_ENABLED +int conn_errorSim_initEnv(void); +void conn_errorSim_deinitEnv(void); +int conn_errorSim_enable(void); +void conn_errorSim_disable(void); +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED + +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) +void adv_stack_enableClearLegacyAdvVsCmd(bool en); +void scan_stack_enableAdvFlowCtrlVsCmd(bool en); +void advFilter_stack_enableDupExcListVsCmd(bool en); +void arr_stack_enableMultiConnVsCmd(bool en); +void pcl_stack_enableSetRssiThreshVsCmd(bool en); +void chanSel_stack_enableSetCsaVsCmd(bool en); +void log_stack_enableLogsRelatedVsCmd(bool en); +void hci_stack_enableSetVsEvtMaskVsCmd(bool en); +void winWiden_stack_enableSetConstPeerScaVsCmd(bool en); + +void adv_stack_enableScanReqRxdVsEvent(bool en); +void conn_stack_enableChanMapUpdCompVsEvent(bool en); +void sleep_stack_enableWakeupVsEvent(bool en); +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) +#if CONFIG_BT_LE_RXBUF_OPT_ENABLED +extern void mmgmt_enableRxbufOptFeature(void); +#endif // CONFIG_BT_LE_RXBUF_OPT_ENABLED + +/* Local functions definition + *************************************************************************** + */ +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) +void ble_stack_enableVsCmds(bool en) +{ + adv_stack_enableClearLegacyAdvVsCmd(en); + advFilter_stack_enableDupExcListVsCmd(en); + scan_stack_enableAdvFlowCtrlVsCmd(en); + arr_stack_enableMultiConnVsCmd(en); + pcl_stack_enableSetRssiThreshVsCmd(en); + chanSel_stack_enableSetCsaVsCmd(en); + log_stack_enableLogsRelatedVsCmd(en); + hci_stack_enableSetVsEvtMaskVsCmd(en); + winWiden_stack_enableSetConstPeerScaVsCmd(en); +} + +void ble_stack_enableVsEvents(bool en) +{ + adv_stack_enableScanReqRxdVsEvent(en); + conn_stack_enableChanMapUpdCompVsEvent(en); + +#if CONFIG_BT_LE_SLEEP_ENABLE + sleep_stack_enableWakeupVsEvent(en); +#endif // CONFIG_BT_LE_SLEEP_ENABLE +} +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + +int ble_stack_initEnv(void) +{ + int rc; + + rc = base_stack_initEnv(); + if (rc) { + return rc; + } + +#if DEFAULT_BT_LE_MAX_CONNECTIONS + rc = conn_stack_initEnv(); + if (rc) { + return rc; + } +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + rc = conn_errorSim_initEnv(); + if (rc) { + return rc; + } +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + + return 0; +} + +void ble_stack_deinitEnv(void) +{ +#if DEFAULT_BT_LE_MAX_CONNECTIONS +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_errorSim_deinitEnv(); +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_stack_deinitEnv(); +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + + base_stack_deinitEnv(); +} + +int ble_stack_enable(void) +{ + int rc; + + rc = base_stack_enable(); + if (rc) { + return rc; + } + +#if DEFAULT_BT_LE_MAX_CONNECTIONS + rc = conn_stack_enable(); + if (rc) { + return rc; + } +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + rc = conn_errorSim_enable(); + if (rc) { + return rc; + } +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + ble_stack_enableVsCmds(true); + ble_stack_enableVsEvents(true); +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + +#if CONFIG_BT_LE_RXBUF_OPT_ENABLED + mmgmt_enableRxbufOptFeature(); +#endif // CONFIG_BT_LE_RXBUF_OPT_ENABLED + + return 0; +} + +void ble_stack_disable(void) +{ +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + ble_stack_enableVsEvents(false); + ble_stack_enableVsCmds(false); +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + +#if DEFAULT_BT_LE_MAX_CONNECTIONS +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_errorSim_disable(); +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_stack_disable(); +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + + base_stack_disable(); +} diff --git a/lib/bt/controller/esp32c5/ble_priv.h b/lib/bt/controller/esp32c5/ble_priv.h new file mode 100644 index 00000000..82dc4d16 --- /dev/null +++ b/lib/bt/controller/esp32c5/ble_priv.h @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +int ble_stack_initEnv(void); + +void ble_stack_deinitEnv(void); + +int ble_stack_enable(void); + +void ble_stack_disable(void); diff --git a/lib/bt/controller/esp32c5/bt.c b/lib/bt/controller/esp32c5/bt.c index 17794564..e6070f52 100644 --- a/lib/bt/controller/esp32c5/bt.c +++ b/lib/bt/controller/esp32c5/bt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,38 +30,36 @@ #endif // CONFIG_SW_COEXIST_ENABLE #include "nimble/nimble_npl_os.h" -#include "ble_hci_trans.h" +#include "esp_hci_transport.h" #include "os/endian.h" #include "esp_bt.h" +#include "ble_priv.h" #include "esp_intr_alloc.h" #include "esp_sleep.h" #include "esp_pm.h" #include "esp_phy_init.h" #include "esp_private/periph_ctrl.h" -#include "hci_uart.h" +#include "soc/retention_periph_defs.h" +#include "soc/regdma.h" #include "bt_osi_mem.h" -#if SOC_PM_RETENTION_HAS_CLOCK_BUG -#include "esp_private/sleep_retention.h" -#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG - #if CONFIG_FREERTOS_USE_TICKLESS_IDLE #include "esp_private/sleep_modem.h" +#include "esp_private/sleep_retention.h" #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE -#ifdef CONFIG_BT_BLUEDROID_ENABLED -#include "hci/hci_hal.h" -#endif // CONFIG_BT_BLUEDROID_ENABLED - #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "esp_private/periph_ctrl.h" -#include "esp_sleep.h" - +#include "esp_private/esp_clk_tree_common.h" #include "hal/efuse_hal.h" #include "soc/rtc.h" + +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED +#include "ble_log/ble_log_spi_out.h" +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + /* Macro definition ************************************************************************ */ @@ -69,16 +67,11 @@ #define OSI_COEX_VERSION 0x00010006 #define OSI_COEX_MAGIC_VALUE 0xFADEBEAD -#define EXT_FUNC_VERSION 0x20221122 +#define EXT_FUNC_VERSION 0x20250415 #define EXT_FUNC_MAGIC_VALUE 0xA5A5A5A5 #define BT_ASSERT_PRINT ets_printf -#ifdef CONFIG_BT_BLUEDROID_ENABLED -/* ACL_DATA_MBUF_LEADINGSPCAE: The leadingspace in user info header for ACL data */ -#define ACL_DATA_MBUF_LEADINGSPCAE 4 -#endif // CONFIG_BT_BLUEDROID_ENABLED - /* Types definition ************************************************************************ */ @@ -97,12 +90,6 @@ struct ext_funcs_t { int (*_esp_intr_free)(void **ret_handle); void *(* _malloc)(size_t size); void (*_free)(void *p); - void (*_hal_uart_start_tx)(int); - int (*_hal_uart_init_cbs)(int, hci_uart_tx_char, hci_uart_tx_done, hci_uart_rx_char, void *); - int (*_hal_uart_config)(int, int32_t, uint8_t, uint8_t, uart_parity_t, uart_hw_flowcontrol_t); - int (*_hal_uart_close)(int); - void (*_hal_uart_blocking_tx)(int, uint8_t); - int (*_hal_uart_init)(int, void *); int (* _task_create)(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id); void (* _task_delete)(void *task_handle); @@ -111,25 +98,33 @@ struct ext_funcs_t { int (* _ecc_gen_key_pair)(uint8_t *public, uint8_t *priv); int (* _ecc_gen_dh_key)(const uint8_t *remote_pub_key_x, const uint8_t *remote_pub_key_y, const uint8_t *local_priv_key, uint8_t *dhkey); - void (* _esp_reset_rpa_moudle)(void); uint32_t magic; }; #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -typedef void (*interface_func_t) (uint32_t len, const uint8_t*addr, bool end); -#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +typedef void (*interface_func_t) (uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); +enum { + BLE_LOG_INTERFACE_FLAG_CONTINUE = 0, + BLE_LOG_INTERFACE_FLAG_END, +}; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* External functions or variables ************************************************************************ */ extern int ble_osi_coex_funcs_register(struct osi_coex_funcs_t *coex_funcs); extern int r_ble_controller_init(esp_bt_controller_config_t *cfg); +extern void esp_ble_controller_info_capture(uint32_t cycle_times); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -extern int r_ble_log_init_async(interface_func_t bt_controller_log_interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); +extern int r_ble_log_init_async(interface_func_t interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); extern int r_ble_log_deinit_async(void); +extern int r_ble_log_init_simple(interface_func_t interface, void *handler); +extern void r_ble_log_deinit_simple(void); extern void r_ble_log_async_select_dump_buffers(uint8_t buffers); extern void r_ble_log_async_output_dump_all(bool output); -extern void esp_panic_handler_reconfigure_wdts(uint32_t timeout_ms); +extern void esp_panic_handler_feed_wdts(void); +extern int r_ble_log_ctrl_level_and_mod(uint8_t log_level, uint32_t mod_switch); +extern int r_ble_ctrl_mod_type(uint16_t mod, uint32_t mod_type_switch); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED extern int r_ble_controller_deinit(void); extern int r_ble_controller_enable(uint8_t mode); @@ -147,11 +142,17 @@ extern void r_ble_lll_rfmgmt_set_sleep_cb(void *s_cb, void *w_cb, void *s_arg, extern void r_ble_rtc_wake_up_state_clr(void); extern int os_msys_init(void); extern void os_msys_deinit(void); +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY +extern void r_ble_ll_scan_start_time_init_compensation(uint32_t init_compensation); +extern void r_priv_sdk_config_insert_proc_time_set(uint16_t insert_proc_time); +#endif // CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY #if CONFIG_FREERTOS_USE_TICKLESS_IDLE -extern const sleep_retention_entries_config_t *esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra); -extern void esp_ble_set_wakeup_overhead(uint32_t overhead); +extern sleep_retention_entries_config_t *r_esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra); +extern void r_esp_ble_set_wakeup_overhead(uint32_t overhead); #endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ -extern void r_esp_ble_change_rtc_freq(uint32_t freq); +#if CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE +extern void r_ble_ll_customize_peer_sca_set(uint16_t peer_sca); +#endif // CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE extern int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y, const uint8_t *our_priv_key, uint8_t *out_dhkey); @@ -179,27 +180,21 @@ static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status); static int task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id); static void task_delete_wrapper(void *task_handle); -#if CONFIG_BT_LE_HCI_INTERFACE_USE_UART -static void hci_uart_start_tx_wrapper(int uart_no); -static int hci_uart_init_cbs_wrapper(int uart_no, hci_uart_tx_char tx_func, - hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg); -static int hci_uart_config_wrapper(int uart_no, int32_t speed, uint8_t databits, uint8_t stopbits, - uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl); -static int hci_uart_close_wrapper(int uart_no); -static void hci_uart_blocking_tx_wrapper(int port, uint8_t data); -static int hci_uart_init_wrapper(int uart_no, void *cfg); -#endif // CONFIG_BT_LE_HCI_INTERFACE_USE_UART static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, void *arg, void **ret_handle_in); static int esp_intr_free_wrapper(void **ret_handle); static void osi_assert_wrapper(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2); static uint32_t osi_random_wrapper(void); -static void esp_reset_rpa_moudle(void); static int esp_ecc_gen_key_pair(uint8_t *pub, uint8_t *priv); static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y, const uint8_t *our_priv_key, uint8_t *out_dhkey); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end); +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* Local variable definition *************************************************************************** @@ -209,18 +204,242 @@ static DRAM_ATTR esp_bt_controller_status_t ble_controller_status = ESP_BT_CONTR #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED const static uint32_t log_bufs_size[] = {CONFIG_BT_LE_LOG_CTRL_BUF1_SIZE, CONFIG_BT_LE_LOG_HCI_BUF_SIZE, CONFIG_BT_LE_LOG_CTRL_BUF2_SIZE}; +static bool log_is_inited = false; + +esp_err_t esp_bt_controller_log_init(void) +{ + if (log_is_inited) { + return ESP_OK; + } + +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + if (ble_log_spi_out_init() != 0) { + goto spi_out_init_failed; + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + if (r_ble_log_init_simple(ble_log_spi_out_ll_write, ble_log_spi_out_ll_log_ev_proc) != 0) { + goto log_init_failed; + } +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + uint8_t buffers = 0; +#if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED + buffers |= ESP_BLE_LOG_BUF_CONTROLLER; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED + buffers |= ESP_BLE_LOG_BUF_HCI; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED + + bool task_create = true; +#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY + task_create = false; +#elif CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_ctrl_log_partition_get_and_erase_first_block(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + + if (r_ble_log_init_async(esp_bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size) != 0) { + goto log_init_failed; + } +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + + if (r_ble_log_ctrl_level_and_mod(CONFIG_BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL, CONFIG_BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH) != ESP_OK) { + goto ctrl_level_init_failed; + } + log_is_inited = true; + return ESP_OK; + +ctrl_level_init_failed: +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_simple(); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_async(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +log_init_failed: +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +spi_out_init_failed: +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + return ESP_FAIL; +} + +void esp_bt_controller_log_deinit(void) +{ +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_simple(); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_async(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + + log_is_inited = false; +} + +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +#include "esp_partition.h" +#include "hal/wdt_hal.h" + +#define MAX_STORAGE_SIZE (CONFIG_BT_LE_CONTROLLER_LOG_PARTITION_SIZE) +#define BLOCK_SIZE (4096) +#define THRESHOLD (3072) +#define PARTITION_NAME "bt_ctrl_log" + +static const esp_partition_t *log_partition; +static uint32_t write_index = 0; +static uint32_t next_erase_index = BLOCK_SIZE; +static bool block_erased = false; +static bool stop_write = false; +static bool is_filled = false; + +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void) +{ + log_partition = NULL; + assert(MAX_STORAGE_SIZE % BLOCK_SIZE == 0); + // Find the partition map in the partition table + log_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, PARTITION_NAME); + assert(log_partition != NULL); + // Prepare data to be read later using the mapped address + ESP_ERROR_CHECK(esp_partition_erase_range(log_partition, 0, BLOCK_SIZE)); + write_index = 0; + next_erase_index = BLOCK_SIZE; + block_erased = false; + is_filled = false; + stop_write = false; +} + +static int esp_bt_controller_log_storage(uint32_t len, const uint8_t *addr, bool end) +{ + if (len > MAX_STORAGE_SIZE) { + return -1; + } + + if (stop_write) { + return 0; + } + + if (((write_index) % BLOCK_SIZE) >= THRESHOLD && !block_erased) { + // esp_rom_printf("Ers nxt: %d,%d\n", next_erase_index, write_index); + esp_partition_erase_range(log_partition, next_erase_index, BLOCK_SIZE); + next_erase_index = (next_erase_index + BLOCK_SIZE) % MAX_STORAGE_SIZE; + block_erased = true; + } + + if (((write_index + len) / BLOCK_SIZE) > (write_index / BLOCK_SIZE)) { + block_erased = false; + } + + if (write_index + len <= MAX_STORAGE_SIZE) { + esp_partition_write(log_partition, write_index, addr, len); + write_index = (write_index + len) % MAX_STORAGE_SIZE; + } else { + uint32_t first_part_len = MAX_STORAGE_SIZE - write_index; + esp_partition_write(log_partition, write_index, addr, first_part_len); + esp_partition_write(log_partition, 0, addr + first_part_len, len - first_part_len); + write_index = len - first_part_len; + is_filled = true; + // esp_rom_printf("old idx: %d,%d\n",next_erase_index, write_index); + } + + return 0; +} + +void esp_bt_read_ctrl_log_from_flash(bool output) +{ + esp_partition_mmap_handle_t mmap_handle; + uint32_t read_index; + const void *mapped_ptr; + const uint8_t *buffer; + uint32_t print_len; + uint32_t max_print_len; + esp_err_t err; + + print_len = 0; + max_print_len = 4096; + err = esp_partition_mmap(log_partition, 0, MAX_STORAGE_SIZE, ESP_PARTITION_MMAP_DATA, &mapped_ptr, &mmap_handle); + if (err != ESP_OK) { + ESP_LOGE("FLASH", "Mmap failed: %s", esp_err_to_name(err)); + return; + } + + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + r_ble_log_async_output_dump_all(true); + esp_bt_controller_log_deinit(); + stop_write = true; + + buffer = (const uint8_t *)mapped_ptr; + esp_panic_handler_feed_wdts(); + if (is_filled) { + read_index = next_erase_index; + } else { + read_index = 0; + } + + esp_rom_printf("\r\nREAD_CHECK:%ld,%ld,%d\r\n",read_index, write_index, is_filled); + esp_rom_printf("\r\n[DUMP_START:"); + while (read_index != write_index) { + esp_rom_printf("%02x ", buffer[read_index]); + if (print_len > max_print_len) { + esp_panic_handler_feed_wdts(); + print_len = 0; + } + + print_len++; + read_index = (read_index + 1) % MAX_STORAGE_SIZE; + } + + esp_rom_printf(":DUMP_END]\r\n"); + portEXIT_CRITICAL_SAFE(&spinlock); + esp_partition_munmap(mmap_handle); + err = esp_bt_controller_log_init(); + assert(err == ESP_OK); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + +#if CONFIG_BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE +void esp_task_wdt_isr_user_handler(void) +{ + esp_ble_controller_log_dump_all(true); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE + +#if CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE +void __real_esp_panic_handler(void *info); +void __wrap_esp_panic_handler (void *info) +{ + esp_ble_controller_log_dump_all(true); + __real_esp_panic_handler(info); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* This variable tells if BLE is running */ static bool s_ble_active = false; #ifdef CONFIG_PM_ENABLE static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL; -#define BTDM_MIN_TIMER_UNCERTAINTY_US (200) #endif // CONFIG_PM_ENABLE +#define MAIN_XTAL_FREQ_HZ (48000000) +static DRAM_ATTR modem_clock_lpclk_src_t s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_INVALID; +static DRAM_ATTR uint32_t s_bt_lpclk_freq = 100000; #define BLE_RTC_DELAY_US_LIGHT_SLEEP (2500) #define BLE_RTC_DELAY_US_MODEM_SLEEP (500) +#define BLE_CONTROLLER_MALLOC_CAPS (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT|MALLOC_CAP_DMA) +void *malloc_ble_controller_mem(size_t size) +{ + return heap_caps_malloc(size, BLE_CONTROLLER_MALLOC_CAPS); +} + +uint32_t get_ble_controller_free_heap_size(void) +{ + return heap_caps_get_free_size(BLE_CONTROLLER_MALLOC_CAPS); +} + static const struct osi_coex_funcs_t s_osi_coex_funcs_ro = { ._magic = OSI_COEX_MAGIC_VALUE, ._version = OSI_COEX_VERSION, @@ -236,29 +455,15 @@ struct ext_funcs_t ext_funcs_ro = { ._esp_intr_free = esp_intr_free_wrapper, ._malloc = bt_osi_mem_malloc_internal, ._free = bt_osi_mem_free, -#if CONFIG_BT_LE_HCI_INTERFACE_USE_UART - ._hal_uart_start_tx = hci_uart_start_tx_wrapper, - ._hal_uart_init_cbs = hci_uart_init_cbs_wrapper, - ._hal_uart_config = hci_uart_config_wrapper, - ._hal_uart_close = hci_uart_close_wrapper, - ._hal_uart_blocking_tx = hci_uart_blocking_tx_wrapper, - ._hal_uart_init = hci_uart_init_wrapper, -#endif //CONFIG_BT_LE_HCI_INTERFACE_USE_UART ._task_create = task_create_wrapper, ._task_delete = task_delete_wrapper, ._osi_assert = osi_assert_wrapper, ._os_random = osi_random_wrapper, ._ecc_gen_key_pair = esp_ecc_gen_key_pair, ._ecc_gen_dh_key = esp_ecc_gen_dh_key, - ._esp_reset_rpa_moudle = esp_reset_rpa_moudle, .magic = EXT_FUNC_MAGIC_VALUE, }; -static void IRAM_ATTR esp_reset_rpa_moudle(void) -{ - -} - static void IRAM_ATTR osi_assert_wrapper(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2) { @@ -288,75 +493,6 @@ static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status) #endif // CONFIG_SW_COEXIST_ENABLE } -#ifdef CONFIG_BT_BLUEDROID_ENABLED -bool esp_vhci_host_check_send_available(void) -{ - if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { - return false; - } - return true; -} - -static struct os_mbuf *ble_hs_mbuf_gen_pkt(uint16_t leading_space) -{ - struct os_mbuf *om; - int rc; - - om = os_msys_get_pkthdr(0, 0); - if (om == NULL) { - return NULL; - } - - if (om->om_omp->omp_databuf_len < leading_space) { - rc = os_mbuf_free_chain(om); - assert(rc == 0); - return NULL; - } - - om->om_data += leading_space; - - return om; -} - -struct os_mbuf *ble_hs_mbuf_acl_pkt(void) -{ - return ble_hs_mbuf_gen_pkt(4 + 1); -} - -void esp_vhci_host_send_packet(uint8_t *data, uint16_t len) -{ - if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { - return; - } - - if (*(data) == DATA_TYPE_COMMAND) { - struct ble_hci_cmd *cmd = NULL; - cmd = (struct ble_hci_cmd *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD); - assert(cmd); - memcpy((uint8_t *)cmd, data + 1, len - 1); - ble_hci_trans_hs_cmd_tx((uint8_t *)cmd); - } - - if (*(data) == DATA_TYPE_ACL) { - struct os_mbuf *om = os_msys_get_pkthdr(len, ACL_DATA_MBUF_LEADINGSPCAE); - assert(om); - assert(os_mbuf_append(om, &data[1], len - 1) == 0); - ble_hci_trans_hs_acl_tx(om); - } -} - -esp_err_t esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback) -{ - if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { - return ESP_FAIL; - } - - ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL); - - return ESP_OK; -} -#endif // CONFIG_BT_BLUEDROID_ENABLED - static int task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id) { @@ -388,103 +524,91 @@ static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer return rc; } -#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART -static void hci_uart_start_tx_wrapper(int uart_no) -{ - hci_uart_start_tx(uart_no); -} - -static int hci_uart_init_cbs_wrapper(int uart_no, hci_uart_tx_char tx_func, - hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg) +static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, + void *arg, void **ret_handle_in) { - int rc = -1; - rc = hci_uart_init_cbs(uart_no, tx_func, tx_done, rx_func, arg); +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + int rc = esp_intr_alloc(source, flags, handler, arg, (intr_handle_t *)ret_handle_in); +#else + int rc = esp_intr_alloc(source, flags | ESP_INTR_FLAG_IRAM, handler, arg, (intr_handle_t *)ret_handle_in); +#endif return rc; } - -static int hci_uart_config_wrapper(int port_num, int32_t baud_rate, uint8_t data_bits, - uint8_t stop_bits, uart_parity_t parity, - uart_hw_flowcontrol_t flow_ctl) +static int esp_intr_free_wrapper(void **ret_handle) { - int rc = -1; - rc = hci_uart_config(port_num, baud_rate, data_bits, stop_bits, parity, flow_ctl); + int rc = 0; + rc = esp_intr_free((intr_handle_t) * ret_handle); + *ret_handle = NULL; return rc; } -static int hci_uart_close_wrapper(int uart_no) +void esp_bt_rtc_slow_clk_select(uint8_t slow_clk_src) { - int rc = -1; - rc = hci_uart_close(uart_no); - return rc; + /* Select slow clock source for BT momdule */ + switch (slow_clk_src) { + case MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL: + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (MAIN_XTAL_FREQ_HZ/s_bt_lpclk_freq - 1)); + break; + case MODEM_CLOCK_LPCLK_SRC_RC_SLOW: + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Using 136 kHz RC as clock source, use with caution as it may not maintain ACL or Sync process due to low clock accuracy!"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (5 - 1)); + break; + case MODEM_CLOCK_LPCLK_SRC_XTAL32K: + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using external 32.768 kHz XTAL as clock source"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (1 - 1)); + break; + case MODEM_CLOCK_LPCLK_SRC_RC32K: + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 32 kHz RC as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (1 - 1)); + break; + case MODEM_CLOCK_LPCLK_SRC_EXT32K: + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 32 kHz oscillator as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (1 - 1)); + break; + default: + } } -static void hci_uart_blocking_tx_wrapper(int port, uint8_t data) +modem_clock_lpclk_src_t esp_bt_get_lpclk_src(void) { - //This function is nowhere to use. + return s_bt_lpclk_src; } -static int hci_uart_init_wrapper(int uart_no, void *cfg) +void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src) { - //This function is nowhere to use. - return 0; -} + if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { + return; + } -#endif //CONFIG_BT_LE_HCI_INTERFACE_USE_UART + if (clk_src >= MODEM_CLOCK_LPCLK_SRC_MAX) { + return; + } -static int ble_hci_unregistered_hook(void*, void*) -{ - ESP_LOGD(NIMBLE_PORT_LOG_TAG,"%s ble hci rx_evt is not registered.",__func__); - return 0; + s_bt_lpclk_src = clk_src; } -static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, - void *arg, void **ret_handle_in) +uint32_t esp_bt_get_lpclk_freq(void) { - int rc = esp_intr_alloc(source, flags | ESP_INTR_FLAG_IRAM, handler, - arg, (intr_handle_t *)ret_handle_in); - return rc; + return s_bt_lpclk_freq; } -static int esp_intr_free_wrapper(void **ret_handle) +void esp_bt_set_lpclk_freq(uint32_t clk_freq) { - int rc = 0; - rc = esp_intr_free((intr_handle_t) * ret_handle); - *ret_handle = NULL; - return rc; -} + if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { + return; + } -void esp_bt_rtc_slow_clk_select(uint8_t slow_clk_src) -{ - /* Select slow clock source for BT momdule */ - // switch (slow_clk_src) { - // case MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL: - // ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source"); - // uint32_t chip_version = efuse_hal_chip_revision(); - // if (chip_version == 0) { - // modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (400 - 1)); - // } else{ - // modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (5 - 1)); - // } - // break; - // case MODEM_CLOCK_LPCLK_SRC_RC_SLOW: - // ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 136 kHz RC as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); - // modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (5 - 1)); - // break; - // case MODEM_CLOCK_LPCLK_SRC_XTAL32K: - // ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using external 32.768 kHz XTAL as clock source"); - // modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (1 - 1)); - // break; - // case MODEM_CLOCK_LPCLK_SRC_RC32K: - // ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 32 kHz RC as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); - // modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (1 - 1)); - // break; - // case MODEM_CLOCK_LPCLK_SRC_EXT32K: - // ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 32 kHz oscillator as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); - // modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (1 - 1)); - // break; - // default: - // } + if (!clk_freq) { + return; + } + + if (MAIN_XTAL_FREQ_HZ % clk_freq) { + return; + } + + s_bt_lpclk_freq = clk_freq; } IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) @@ -508,18 +632,26 @@ IRAM_ATTR void controller_wakeup_cb(void *arg) return; } #ifdef CONFIG_PM_ENABLE + esp_pm_config_t pm_config; esp_pm_lock_acquire(s_pm_lock); + esp_pm_get_configuration(&pm_config); + assert(esp_rom_get_cpu_ticks_per_us() == pm_config.max_freq_mhz); r_ble_rtc_wake_up_state_clr(); #endif //CONFIG_PM_ENABLE esp_phy_enable(PHY_MODEM_BT); + if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW) { + uint32_t *clk_freq = (uint32_t *)arg; + *clk_freq = esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED) / 5; + } s_ble_active = true; } #if CONFIG_FREERTOS_USE_TICKLESS_IDLE -static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra) +static esp_err_t sleep_modem_ble_mac_retention_init(void *arg) { uint8_t size; - const sleep_retention_entries_config_t *ble_mac_modem_config = esp_ble_mac_retention_link_get(&size, extra); + int extra = *(int *)arg; + sleep_retention_entries_config_t *ble_mac_modem_config = r_esp_ble_mac_retention_link_get(&size, extra); esp_err_t err = sleep_retention_entries_create(ble_mac_modem_config, size, REGDMA_LINK_PRI_BT_MAC_BB, SLEEP_RETENTION_MODULE_BLE_MAC); if (err == ESP_OK) { ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Modem BLE MAC retention initialization"); @@ -527,14 +659,32 @@ static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra) return err; } +static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra) +{ + int retention_args = extra; + sleep_retention_module_init_param_t init_param = { + .cbs = { .create = { .handle = sleep_modem_ble_mac_retention_init, .arg = &retention_args } }, + .depends = RETENTION_MODULE_BITMAP_INIT(BT_BB) + }; + esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BLE_MAC, &init_param); + if (err == ESP_OK) { + err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_BLE_MAC); + } + return err; +} + static void sleep_modem_ble_mac_modem_state_deinit(void) { - sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_BLE_MAC); + esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_BLE_MAC); + if (err == ESP_OK) { + err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_BLE_MAC); + assert(err == ESP_OK); + } } -void sleep_modem_light_sleep_overhead_set(uint32_t overhead) +void IRAM_ATTR sleep_modem_light_sleep_overhead_set(uint32_t overhead) { - esp_ble_set_wakeup_overhead(overhead); + r_esp_ble_set_wakeup_overhead(overhead); } #endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ @@ -559,10 +709,13 @@ esp_err_t controller_sleep_init(void) if (rc != ESP_OK) { goto error; } -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#endif // CONFIG_PM_ENABLE +#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE /* Create a new regdma link for BLE related register restoration */ - rc = sleep_modem_ble_mac_modem_state_init(1); - assert(rc == 0); + rc = sleep_modem_ble_mac_modem_state_init(0); + if (rc != ESP_OK) { + goto error; + } esp_sleep_enable_bt_wakeup(); ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer"); @@ -575,19 +728,21 @@ esp_err_t controller_sleep_init(void) sleep_modem_register_mac_bb_module_prepare_callback(sleep_modem_mac_bb_power_down_prepare, sleep_modem_mac_bb_power_up_prepare); #endif // SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD -#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ return rc; +#ifdef CONFIG_PM_ENABLE error: - -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#endif // CONFIG_PM_ENABLE +#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE #if SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD sleep_modem_unregister_mac_bb_module_prepare_callback(sleep_modem_mac_bb_power_down_prepare, sleep_modem_mac_bb_power_up_prepare); #endif // SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD esp_sleep_disable_bt_wakeup(); esp_pm_unregister_inform_out_light_sleep_overhead_callback(sleep_modem_light_sleep_overhead_set); -#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#ifdef CONFIG_PM_ENABLE /*lock should release first and then delete*/ if (s_pm_lock != NULL) { esp_pm_lock_delete(s_pm_lock); @@ -600,7 +755,7 @@ error: void controller_sleep_deinit(void) { -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE #if SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD sleep_modem_unregister_mac_bb_module_prepare_callback(sleep_modem_mac_bb_power_down_prepare, sleep_modem_mac_bb_power_up_prepare); @@ -688,15 +843,55 @@ void ble_controller_scan_duplicate_config(void) ble_vhci_disc_duplicate_set_max_cache_size(cache_size); } +static void ble_rtc_clk_init(esp_bt_controller_config_t *cfg) +{ + if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_INVALID) { +#if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL; +#else +#if CONFIG_RTC_CLK_SRC_INT_RC + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_RC_SLOW; +#elif CONFIG_RTC_CLK_SRC_EXT_CRYS + if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_XTAL32K; + } else { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock"); + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL; + } +#elif CONFIG_RTC_CLK_SRC_INT_RC32K + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_RC32K; +#elif CONFIG_RTC_CLK_SRC_EXT_OSC + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_EXT32K; +#else + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "Unsupported clock source"); + assert(0); +#endif +#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */ + } + + if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { + cfg->rtc_freq = s_bt_lpclk_freq; + } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) { + cfg->rtc_freq = 32768; + } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW) { + cfg->rtc_freq = esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED) / 5; + cfg->ble_ll_sca = 3000; + } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC32K) { + cfg->rtc_freq = 32000; + } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_EXT32K) { + cfg->rtc_freq = 32000; + } + esp_bt_rtc_slow_clk_select(s_bt_lpclk_src); +} + esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) { uint8_t mac[6]; esp_err_t ret = ESP_OK; ble_npl_count_info_t npl_info; - uint32_t slow_clk_freq = 0; + uint8_t hci_transport_mode; memset(&npl_info, 0, sizeof(ble_npl_count_info_t)); - if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "invalid controller state"); return ESP_ERR_INVALID_STATE; @@ -745,33 +940,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) modem_clock_module_enable(PERIPH_BT_MODULE); modem_clock_module_mac_reset(PERIPH_BT_MODULE); /* Select slow clock source for BT momdule */ -#if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL); - slow_clk_freq = 100000; -#else -#if CONFIG_RTC_CLK_SRC_INT_RC - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_RC_SLOW); - slow_clk_freq = 30000; -#elif CONFIG_RTC_CLK_SRC_EXT_CRYS - if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_XTAL32K); - slow_clk_freq = 32768; - } else { - ESP_LOGW(NIMBLE_PORT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock"); - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL); - slow_clk_freq = 100000; - } -#elif CONFIG_RTC_CLK_SRC_INT_RC32K - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_RC32K); - slow_clk_freq = 32000; -#elif CONFIG_RTC_CLK_SRC_EXT_OSC - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_EXT32K); - slow_clk_freq = 32000; -#else - ESP_LOGE(NIMBLE_PORT_LOG_TAG, "Unsupported clock source"); - assert(0); -#endif -#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */ + ble_rtc_clk_init(cfg); esp_phy_modem_init(); if (ble_osi_coex_funcs_register((struct osi_coex_funcs_t *)&s_osi_coex_funcs_ro) != 0) { @@ -785,20 +954,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) #endif // CONFIG_SW_COEXIST_ENABLE #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - interface_func_t bt_controller_log_interface; - bt_controller_log_interface = esp_bt_controller_log_interface; - uint8_t buffers = 0; -#if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED - buffers |= ESP_BLE_LOG_BUF_CONTROLLER; -#endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED -#if CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED - buffers |= ESP_BLE_LOG_BUF_HCI; -#endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED -#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY - ret = r_ble_log_init_async(bt_controller_log_interface, false, buffers, (uint32_t *)log_bufs_size); -#else - ret = r_ble_log_init_async(bt_controller_log_interface, true, buffers, (uint32_t *)log_bufs_size); -#endif // CONFIG_BT_CONTROLLER_LOG_DUMP + ret = esp_bt_controller_log_init(); if (ret != ESP_OK) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_controller_log_init failed %d", ret); goto modem_deint; @@ -810,14 +966,23 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) goto modem_deint; } + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "ble controller commit:[%s]", ble_controller_get_compile_version()); + ret = r_ble_controller_init(cfg); if (ret != ESP_OK) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "r_ble_controller_init failed %d", ret); goto modem_deint; } - ESP_LOGI(NIMBLE_PORT_LOG_TAG, "ble controller commit:[%s]", ble_controller_get_compile_version()); - r_esp_ble_change_rtc_freq(slow_clk_freq); +#if CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE + r_ble_ll_customize_peer_sca_set(CONFIG_BT_LE_LL_PEER_SCA); +#endif // CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE + + ret = ble_stack_initEnv(); + if (ret != ESP_OK) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_stack_initEnv failed %d", ret); + goto free_controller; + } ble_controller_scan_duplicate_config(); @@ -832,24 +997,37 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) ESP_LOGW(NIMBLE_PORT_LOG_TAG, "controller_sleep_init failed %d", ret); goto free_controller; } + ESP_ERROR_CHECK(esp_read_mac((uint8_t *)mac, ESP_MAC_BT)); + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Bluetooth MAC: %02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); swap_in_place(mac, 6); r_esp_ble_ll_set_public_addr(mac); ble_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; - ble_hci_trans_cfg_hs((ble_hci_trans_rx_cmd_fn *)ble_hci_unregistered_hook,NULL, - (ble_hci_trans_rx_acl_fn *)ble_hci_unregistered_hook,NULL); - return ESP_OK; +#if CONFIG_BT_LE_HCI_INTERFACE_USE_RAM + hci_transport_mode = HCI_TRANSPORT_VHCI; +#elif CONFIG_BT_LE_HCI_INTERFACE_USE_UART + hci_transport_mode = HCI_TRANSPORT_UART_NO_DMA; +#endif // CONFIG_BT_LE_HCI_INTERFACE_USE_RAM + ret = hci_transport_init(hci_transport_mode); + if (ret) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "hci transport init failed %d", ret); + goto free_controller; + } + return ESP_OK; free_controller: + hci_transport_deinit(); controller_sleep_deinit(); os_msys_deinit(); + ble_stack_deinitEnv(); r_ble_controller_deinit(); modem_deint: esp_ble_unregister_bb_funcs(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - r_ble_log_deinit_async(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED esp_phy_modem_deinit(); // modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); @@ -873,6 +1051,7 @@ esp_err_t esp_bt_controller_deinit(void) return ESP_FAIL; } + hci_transport_deinit(); controller_sleep_deinit(); os_msys_deinit(); @@ -881,10 +1060,11 @@ esp_err_t esp_bt_controller_deinit(void) // modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); modem_clock_module_disable(PERIPH_BT_MODULE); + ble_stack_deinitEnv(); r_ble_controller_deinit(); esp_ble_unregister_bb_funcs(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - r_ble_log_deinit_async(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED #if CONFIG_BT_NIMBLE_ENABLED @@ -930,6 +1110,16 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) coex_enable(); #endif // CONFIG_SW_COEXIST_ENABLE +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + r_ble_ll_scan_start_time_init_compensation(500); + r_priv_sdk_config_insert_proc_time_set(500); +#endif // CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + + if (ble_stack_enable() != 0) { + ret = ESP_FAIL; + goto error; + } + if (r_ble_controller_enable(mode) != 0) { ret = ESP_FAIL; goto error; @@ -938,6 +1128,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) return ESP_OK; error: + ble_stack_disable(); #if CONFIG_SW_COEXIST_ENABLE coex_disable(); #endif @@ -961,6 +1152,7 @@ esp_err_t esp_bt_controller_disable(void) if (r_ble_controller_disable() != 0) { return ESP_FAIL; } + ble_stack_disable(); #if CONFIG_SW_COEXIST_ENABLE coex_disable(); #endif @@ -1090,9 +1282,17 @@ esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_ switch (power_type) { case ESP_BLE_PWR_TYPE_DEFAULT: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_ADV: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0xFF, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_SCAN: - if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1123,9 +1323,13 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type esp_err_t stat = ESP_FAIL; switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1148,11 +1352,15 @@ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type) int tx_level = 0; switch (power_type) { - case ESP_BLE_PWR_TYPE_ADV: - case ESP_BLE_PWR_TYPE_SCAN: case ESP_BLE_PWR_TYPE_DEFAULT: tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); break; + case ESP_BLE_PWR_TYPE_ADV: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0); + break; + case ESP_BLE_PWR_TYPE_SCAN: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); + break; case ESP_BLE_PWR_TYPE_CONN_HDL0: case ESP_BLE_PWR_TYPE_CONN_HDL1: case ESP_BLE_PWR_TYPE_CONN_HDL2: @@ -1182,9 +1390,11 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); break; case ESP_BLE_ENHANCED_PWR_TYPE_ADV: case ESP_BLE_ENHANCED_PWR_TYPE_CONN: @@ -1202,26 +1412,47 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po } #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end) +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag) { - for (int i = 0; i < len; i++) { - esp_rom_printf("%02x ", addr[i]); + bool end = (flag & BIT(BLE_LOG_INTERFACE_FLAG_END)); +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_controller_log_storage(len, addr, end); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + + if (len && addr) { + for (int i = 0; i < len; i++) { esp_rom_printf("%02x ", addr[i]); } } - if (end) { - esp_rom_printf("\n"); + if (len_append && addr_append) { + for (int i = 0; i < len_append; i++) { esp_rom_printf("%02x ", addr_append[i]); } } + if (end) { esp_rom_printf("\n"); } + + portEXIT_CRITICAL_SAFE(&spinlock); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE } +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED void esp_ble_controller_log_dump_all(bool output) { - portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_dump_all(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_read_ctrl_log_from_flash(output); +#elif !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; portENTER_CRITICAL_SAFE(&spinlock); - esp_panic_handler_reconfigure_wdts(5000); + esp_panic_handler_feed_wdts(); BT_ASSERT_PRINT("\r\n[DUMP_START:"); r_ble_log_async_output_dump_all(output); BT_ASSERT_PRINT(":DUMP_END]\r\n"); portEXIT_CRITICAL_SAFE(&spinlock); +#endif } #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED @@ -1436,3 +1667,36 @@ int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) #endif // CONFIG_BT_LE_SM_LEGACY || CONFIG_BT_LE_SM_SC #endif // (!CONFIG_BT_NIMBLE_ENABLED) && (CONFIG_BT_CONTROLLER_ENABLED) + +#if CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED +#include "esp_gdbstub.h" +#endif // CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED + +int IRAM_ATTR +ble_capture_info_user_handler(uint8_t type, uint32_t reason, uint32_t param1, uint32_t param2) +{ + int i; + + switch(type) { + case 0: + for (i = 0; i < 2; i++) { + esp_ble_controller_info_capture(0x010101); + } +#if CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED + uintptr_t sp; + __asm__ volatile ("mv %0, sp" : "=r" (sp)); + esp_gdbstub_panic_handler(&sp); +#endif // CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED + break; +#if CONFIG_BT_LE_ASSERT_WHEN_ABNORMAL_DISCONN_ENABLED + case 1: + if ((reason == 0x08) || (reason == 0x3d) || (reason == 0x28)) { + osi_assert_wrapper(__LINE__,__func__, type, reason); + } + break; +#endif // CONFIG_BT_LE_ASSERT_WHEN_ABNORMAL_DISCONN_ENABLED + default: + break; + } + return 0; +} diff --git a/lib/bt/controller/esp32c5/esp_bt_cfg.h b/lib/bt/controller/esp32c5/esp_bt_cfg.h index b9597034..48a845a3 100644 --- a/lib/bt/controller/esp32c5/esp_bt_cfg.h +++ b/lib/bt/controller/esp32c5/esp_bt_cfg.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -129,16 +129,93 @@ extern "C" { #else #define DEFAULT_BT_LE_50_FEATURE_SUPPORT (0) #endif + + #if defined (CONFIG_BT_LE_HCI_UART_FLOWCTRL) + #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (CONFIG_BT_LE_HCI_UART_FLOWCTRL) + #if DEFAULT_BT_LE_HCI_UART_FLOW_CTRL + #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (CONFIG_BT_LE_HCI_UART_CTS_PIN) + #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (CONFIG_BT_LE_HCI_UART_RTS_PIN) + #else + #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (-1) + #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (-1) + #endif + #else + #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) + #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (-1) + #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (-1) + #endif #endif #define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF +#ifdef CONFIG_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS +#define DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS (CONFIG_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS) +#else +#define DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS (0) +#endif + +#ifdef CONFIG_BT_LE_CTRL_LLCP_CONN_UPDATE +#define BT_CTRL_BLE_LLCP_CONN_UPDATE (1<<0) +#else +#define BT_CTRL_BLE_LLCP_CONN_UPDATE (0<<0) +#endif + +#ifdef CONFIG_BT_LE_CTRL_LLCP_CHAN_MAP_UPDATE +#define BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE (1<<1) +#else +#define BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE (0<<1) +#endif + +#ifdef CONFIG_BT_LE_CTRL_LLCP_PHY_UPDATE +#define BT_CTRL_BLE_LLCP_PHY_UPDATE (1<<2) +#else +#define BT_CTRL_BLE_LLCP_PHY_UPDATE (0<<2) +#endif + +#define BT_LE_CTRL_LLCP_DISC_FLAG (BT_CTRL_BLE_LLCP_CONN_UPDATE | BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE | BT_CTRL_BLE_LLCP_PHY_UPDATE) + +#ifdef CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX +#define BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX (CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX) +#else +#define BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX (256) +#endif + +#if defined(CONFIG_BT_LE_CTRL_CHAN_ASS_EN) +#define DEFAULT_BT_LE_CTRL_CHAN_ASS_EN (CONFIG_BT_LE_CTRL_CHAN_ASS_EN) +#else +#define DEFAULT_BT_LE_CTRL_CHAN_ASS_EN (0) +#endif + +#if defined(CONFIG_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX) +#define DEFAULT_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX (CONFIG_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX) +#else +#define DEFAULT_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX (0) +#endif + +#if defined(CONFIG_BT_LE_CTRL_FAST_CONN_DATA_TX_EN) +#define DEFAULT_BT_LE_CTRL_FAST_CONN_DATA_TX_EN (CONFIG_BT_LE_CTRL_FAST_CONN_DATA_TX_EN) +#else +#define DEFAULT_BT_LE_CTRL_FAST_CONN_DATA_TX_EN (0) +#endif + #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART #define HCI_UART_EN CONFIG_BT_LE_HCI_INTERFACE_USE_UART #else #define HCI_UART_EN 0 // hci ram mode #endif +#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_RAM +#define DEFAULT_BT_LE_VHCI_ENABLED (CONFIG_BT_LE_HCI_INTERFACE_USE_RAM) +#else +#define DEFAULT_BT_LE_VHCI_ENABLED (0) +#endif + +#ifdef CONFIG_BT_LE_PTR_CHECK_ENABLED +#define DEFAULT_BT_LE_PTR_CHECK_ENABLED (CONFIG_BT_LE_PTR_CHECK_ENABLED) +#else +#define DEFAULT_BT_LE_PTR_CHECK_ENABLED (0) +#endif + #ifdef CONFIG_BT_LE_SLEEP_ENABLE #define NIMBLE_SLEEP_ENABLE CONFIG_BT_LE_SLEEP_ENABLE #else @@ -169,8 +246,6 @@ extern "C" { #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (UART_DATA_8_BITS) #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (UART_STOP_BITS_1) #define DEFAULT_BT_LE_HCI_UART_PARITY (0) - #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (CONFIG_BT_LE_HCI_UART_TASK_STACK_SIZE) - #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) #else #define DEFAULT_BT_LE_HCI_UART_TX_PIN (0) #define DEFAULT_BT_LE_HCI_UART_RX_PIN (0) @@ -179,8 +254,6 @@ extern "C" { #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (0) #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (0) #define DEFAULT_BT_LE_HCI_UART_PARITY (0) - #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (0) - #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) #endif /* Unchanged configuration */ @@ -205,8 +278,7 @@ extern "C" { #define RTC_FREQ_N (32768) /* in Hz */ -#define BLE_LL_TX_PWR_DBM_N (9) - +#define BLE_LL_TX_PWR_DBM_N (CONFIG_BT_LE_DFT_TX_POWER_LEVEL_DBM_EFF) #define RUN_BQB_TEST (0) #define RUN_QA_TEST (0) diff --git a/lib/bt/controller/esp32c6/Kconfig.in b/lib/bt/controller/esp32c6/Kconfig.in index 0dcc8996..949349aa 100644 --- a/lib/bt/controller/esp32c6/Kconfig.in +++ b/lib/bt/controller/esp32c6/Kconfig.in @@ -1,20 +1,37 @@ menu "HCI Config" - choice BT_LE_HCI_INTERFACE - prompt "Select HCI interface" + prompt "HCI mode" default BT_LE_HCI_INTERFACE_USE_RAM config BT_LE_HCI_INTERFACE_USE_RAM - bool "ram" + bool "VHCI" help Use RAM as HCI interface config BT_LE_HCI_INTERFACE_USE_UART - bool "uart" + bool "UART(H4)" help Use UART as HCI interface endchoice + choice BT_LE_UART_HCI_MODE_CHOICE + prompt "UART HCI mode" + depends on BT_LE_HCI_INTERFACE_USE_UART + default BT_LE_UART_HCI_NO_DMA_MODE + help + Specify UART HCI mode: DMA or No DMA + + config BT_LE_UART_HCI_DMA_MODE + bool "UHCI(UART with DMA)(EXPERIMENTAL)" + help + UART HCI Mode with DMA functionality. + + config BT_LE_UART_HCI_NO_DMA_MODE + bool "UART(NO DMA)" + help + UART HCI Mode without DMA functionality. + endchoice + config BT_LE_HCI_UART_PORT int "HCI UART port" depends on BT_LE_HCI_INTERFACE_USE_UART @@ -73,12 +90,40 @@ menu "HCI Config" UART_PARITY_ODD endchoice - config BT_LE_HCI_UART_TASK_STACK_SIZE - int "HCI uart task stack size" - depends on BT_LE_HCI_INTERFACE_USE_UART - default 1000 + config BT_LE_HCI_UART_RX_BUFFER_SIZE + int "The size of rx ring buffer memory" + depends on BT_LE_UART_HCI_NO_DMA_MODE + default 512 + help + The size of rx ring buffer memory + + config BT_LE_HCI_UART_TX_BUFFER_SIZE + int "The size of tx ring buffer memory" + depends on BT_LE_UART_HCI_NO_DMA_MODE + default 256 + help + The size of tx ring buffer memory + + config BT_LE_HCI_TRANS_TASK_STACK_SIZE + int "HCI transport task stack size" + depends on !BT_LE_HCI_INTERFACE_USE_RAM + default 2048 help - Set the size of uart task stack + This configures stack size of hci transport task + + config BT_LE_HCI_TRANS_RX_MEM_NUM + int "The amount of rx memory received at the same time" + depends on BT_LE_UART_HCI_DMA_MODE + default 3 + help + The amount of rx memory received at the same time + + config BT_LE_HCI_LLDESCS_POOL_NUM + int "The amount of lldecs memory for driver dma mode" + depends on BT_LE_UART_HCI_DMA_MODE + default 20 + help + The amount of lldecs memory for driver dma mode endmenu config BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT @@ -182,6 +227,16 @@ config BT_LE_POWER_CONTROL_ENABLED help Set this option to enable the Power Control feature on controller +config BT_LE_CTE_FEATURE_ENABLED + bool "Enable Bluetooth LE Direction Finding (AoA/AoD)" + depends on BT_LE_50_FEATURE_SUPPORT && SOC_BLE_CTE_SUPPORTED + default n + help + Enable this option to activate Bluetooth LE Direction Finding (AoA/AoD) feature. + Note: + This feature allows devices to determine the direction of a Bluetooth CTE signal, + enabling Angle of Arrival (AoA) and Angle of Departure (AoD) functionality. + menu "Memory Settings" depends on !BT_NIMBLE_ENABLED @@ -269,54 +324,131 @@ config BT_LE_CONTROLLER_TASK_STACK_SIZE help This configures stack size of NimBLE controller task -menuconfig BT_LE_CONTROLLER_LOG_ENABLED - bool "Controller log enable" - default n - help - Enable controller log +menu "Controller debug features" + menuconfig BT_LE_CONTROLLER_LOG_ENABLED + bool "Controller log enable" + default n + help + Enable controller log -config BT_LE_CONTROLLER_LOG_CTRL_ENABLED - bool "enable controller log module" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default y - help + config BT_LE_CONTROLLER_LOG_CTRL_ENABLED + bool "enable controller log module" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default y + help Enable controller log module -config BT_LE_CONTROLLER_LOG_HCI_ENABLED - bool "enable HCI log module" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default y - help + config BT_LE_CONTROLLER_LOG_HCI_ENABLED + bool "enable HCI log module" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default y + help Enable hci log module -config BT_LE_CONTROLLER_LOG_DUMP_ONLY - bool "Controller log dump mode only" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default y - help + config BT_LE_CONTROLLER_LOG_DUMP_ONLY + bool "Controller log dump mode only" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default y + help Only operate in dump mode -config BT_LE_LOG_CTRL_BUF1_SIZE - int "size of the first BLE controller LOG buffer" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default 4096 - help + config BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + bool "Output ble controller logs to SPI bus (Experimental)" + depends on BT_LE_CONTROLLER_LOG_ENABLED + depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY + select BT_BLE_LOG_SPI_OUT_ENABLED + default n + help + Output ble controller logs to SPI bus + + config BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + bool "Store ble controller logs to flash(Experimental)" + depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Store ble controller logs to flash memory. + + config BT_LE_CONTROLLER_LOG_PARTITION_SIZE + int "size of ble controller log partition(Multiples of 4K)" + depends on BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + default 65536 + help + The size of ble controller log partition shall be a multiples of 4K. + The name of log partition shall be "bt_ctrl_log". + The partition type shall be ESP_PARTITION_TYPE_DATA. + The partition sub_type shall be ESP_PARTITION_SUBTYPE_ANY. + + config BT_LE_LOG_CTRL_BUF1_SIZE + int "size of the first BLE controller LOG buffer" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default 4096 + help Configure the size of the first BLE controller LOG buffer. -config BT_LE_LOG_CTRL_BUF2_SIZE - int "size of the second BLE controller LOG buffer" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default 1024 - help + config BT_LE_LOG_CTRL_BUF2_SIZE + int "size of the second BLE controller LOG buffer" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default 1024 + help Configure the size of the second BLE controller LOG buffer. -config BT_LE_LOG_HCI_BUF_SIZE - int "size of the BLE HCI LOG buffer" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default 4096 - help + config BT_LE_LOG_HCI_BUF_SIZE + int "size of the BLE HCI LOG buffer" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default 4096 + help Configure the size of the BLE HCI LOG buffer. + config BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE + bool "Enable wrap panic handler" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Wrap esp_panic_handler to get controller logs when PC pointer exception crashes. + + config BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE + bool "Enable esp_task_wdt_isr_user_handler implementation" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Implement esp_task_wdt_isr_user_handler to get controller logs when task wdt issue is triggered. + + config BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL + int "The output level of controller log" + depends on BT_LE_CONTROLLER_LOG_ENABLED + range 0 5 + default 1 + help + The output level of controller log. + + config BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH + hex "The switch of module log output" + depends on BT_LE_CONTROLLER_LOG_ENABLED + range 0 0xFFFFFFFF + default 0xFFFFFFFF + help + The switch of module log output, this is an unsigned 32-bit hexadecimal value. + + config BT_LE_ERROR_SIM_ENABLED + bool "Enable controller features for internal testing" + default n + + config BT_LE_ASSERT_WHEN_ABNORMAL_DISCONN_ENABLED + bool "When ACL disconnects abnormally, assertion processing is performed(Experimental)" + default n + + config BT_LE_DEBUG_REMAIN_SCENE_ENABLED + bool "Remain scene with GDB to capture relevant status info(Experimental)" + default n + help + Retain scene with GDB to capture info, requires disabling WDT (CONFIG_ESP_INT_WDT, CONFIG_ESP_TASK_WDT_EN). + + config BT_LE_PTR_CHECK_ENABLED + bool "Enable boundary check for internal memory" + default n +endmenu + config BT_LE_LL_RESOLV_LIST_SIZE int "BLE LL Resolving list size" range 1 5 @@ -372,7 +504,7 @@ config BT_LE_CRYPTO_STACK_MBEDTLS config BT_LE_WHITELIST_SIZE int "BLE white list size" - range 1 15 + range 1 31 default 12 depends on !BT_NIMBLE_ENABLED @@ -393,6 +525,23 @@ config BT_LE_LL_SCA help Sleep clock accuracy of our device (in ppm) +config BT_LE_LL_PEER_SCA_SET_ENABLE + bool "Enable to set constant peer SCA" + default n + help + Enable setting of constant peer SCA, use this if peer device has SCA larger than 500 PPM. + Enable this option, the controller will always use BT_LE_LL_PEER_SCA as the peer SCA value + to calculate the window widening instead of the value received from peer device. + + +config BT_LE_LL_PEER_SCA + int "Constant peer sleep clock accuracy value" + range 0 10000 + depends on BT_LE_LL_PEER_SCA_SET_ENABLE + default 0 + help + Set the sleep clock accuracy of peer device + config BT_LE_MAX_CONNECTIONS int "Maximum number of concurrent connections" depends on !BT_NIMBLE_ENABLED @@ -572,6 +721,128 @@ config BT_LE_CCA_RSSI_THRESH int "CCA RSSI threshold value" depends on BT_LE_TX_CCA_ENABLED range 20 100 - default 20 + default 65 help Power threshold of CCA in unit of -1 dBm. + +choice BT_LE_DFT_TX_POWER_LEVEL_DBM + prompt "BLE default Tx power level(dBm)" + default BT_LE_DFT_TX_POWER_LEVEL_P9 + help + Specify default Tx power level(dBm). + config BT_LE_DFT_TX_POWER_LEVEL_N15 + bool "-15dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N12 + bool "-12dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N9 + bool "-9dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N6 + bool "-6dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N3 + bool "-3dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N0 + bool "0dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P3 + bool "+3dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P6 + bool "+6dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P9 + bool "+9dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P12 + bool "+12dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P15 + bool "+15dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P18 + bool "+18dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P20 + bool "+20dBm" +endchoice + +config BT_LE_DFT_TX_POWER_LEVEL_DBM_EFF + int + default -15 if BT_LE_DFT_TX_POWER_LEVEL_N15 + default -12 if BT_LE_DFT_TX_POWER_LEVEL_N12 + default -9 if BT_LE_DFT_TX_POWER_LEVEL_N9 + default -6 if BT_LE_DFT_TX_POWER_LEVEL_N6 + default -3 if BT_LE_DFT_TX_POWER_LEVEL_N3 + default 0 if BT_LE_DFT_TX_POWER_LEVEL_N0 + default 3 if BT_LE_DFT_TX_POWER_LEVEL_P3 + default 6 if BT_LE_DFT_TX_POWER_LEVEL_P6 + default 9 if BT_LE_DFT_TX_POWER_LEVEL_P9 + default 12 if BT_LE_DFT_TX_POWER_LEVEL_P12 + default 15 if BT_LE_DFT_TX_POWER_LEVEL_P15 + default 18 if BT_LE_DFT_TX_POWER_LEVEL_P18 + default 20 if BT_LE_DFT_TX_POWER_LEVEL_P20 + default 0 + +config BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS + bool "Enable enhanced Access Address check in CONNECT_IND" + default n + help + Enabling this option will add stricter verification of the Access Address in the CONNECT_IND PDU. + This improves security by ensuring that only connection requests with valid Access Addresses are accepted. + If disabled, only basic checks are applied, improving compatibility. + +config BT_CTRL_RUN_IN_FLASH_ONLY + bool "Reduce BLE IRAM usage (READ DOCS FIRST) (EXPERIMENTAL)" + default n + help + Move most IRAM into flash. This will increase the usage of flash and reduce ble performance. + Because the code is moved to the flash, the execution speed of the code is reduced. + To have a small impact on performance, you need to enable flash suspend (SPI_FLASH_AUTO_SUSPEND). + +menu "BLE disconnects when Instant Passed (0x28) occurs" + config BT_LE_CTRL_LLCP_CONN_UPDATE + bool "BLE ACL connection update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs during connection update procedure. + + config BT_LE_CTRL_LLCP_CHAN_MAP_UPDATE + bool "BLE ACL channel map update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs in channel map update procedure. + + config BT_LE_CTRL_LLCP_PHY_UPDATE + bool "BLE ACL PHY update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs in PHY update procedure. +endmenu + +config BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX + int "The value of upperlimitmax during scan backoff procedure" + range 1 256 + default 32 + help + The value of upperlimitmax needs to be a power of 2. + +config BT_LE_CTRL_CHAN_ASS_EN + bool "Enable channel assessment(Experimental)" + default n + help + If this option is enabled, The Controller will records the communication quality + for each channel and then start a timer to check and update the channel map every 4 seconds. + +config BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX + bool "Enable aux packet when ext adv data length is zero(Experimental)" + default y + help + When this option is enabled, auxiliary packets will be present in the events of + 'Non-Connectable and Non-Scannable' regardless of whether the advertising length is 0. + If this option is not enabled, auxiliary packets will only be present when the advertising length is not 0. + +config BT_LE_RXBUF_OPT_ENABLED + bool "Enable rxbuf optimization feature" + default y + +config BT_LE_CTRL_FAST_CONN_DATA_TX_EN + bool "Enable fast sending of connection data" + default y + help + If this option is enabled, The Controller will continue to + Send an empty PDU after sending valid connection data within an interval. diff --git a/lib/bt/controller/esp32c6/ble.c b/lib/bt/controller/esp32c6/ble.c new file mode 100644 index 00000000..a1eb1374 --- /dev/null +++ b/lib/bt/controller/esp32c6/ble.c @@ -0,0 +1,171 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include "sdkconfig.h" +#include "esp_bt_cfg.h" +#include "esp_bit_defs.h" + +/* External functions or variables + ************************************************************************ + */ +int base_stack_initEnv(void); +void base_stack_deinitEnv(void); +int base_stack_enable(void); +void base_stack_disable(void); + +int conn_stack_initEnv(void); +void conn_stack_deinitEnv(void); +int conn_stack_enable(void); +void conn_stack_disable(void); + +#if CONFIG_BT_LE_ERROR_SIM_ENABLED +int conn_errorSim_initEnv(void); +void conn_errorSim_deinitEnv(void); +int conn_errorSim_enable(void); +void conn_errorSim_disable(void); +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED + +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) +void adv_stack_enableClearLegacyAdvVsCmd(bool en); +void scan_stack_enableAdvFlowCtrlVsCmd(bool en); +void advFilter_stack_enableDupExcListVsCmd(bool en); +void arr_stack_enableMultiConnVsCmd(bool en); +void pcl_stack_enableSetRssiThreshVsCmd(bool en); +void chanSel_stack_enableSetCsaVsCmd(bool en); +void log_stack_enableLogsRelatedVsCmd(bool en); +void hci_stack_enableSetVsEvtMaskVsCmd(bool en); +void winWiden_stack_enableSetConstPeerScaVsCmd(bool en); +#if CONFIG_IDF_TARGET_ESP32C61_ECO3 +void conn_stack_enableSetPrefTxRxCntVsCmd(bool en); +#endif // CONFIG_IDF_TARGET_ESP32C61_ECO3 + +void adv_stack_enableScanReqRxdVsEvent(bool en); +void conn_stack_enableChanMapUpdCompVsEvent(bool en); +void sleep_stack_enableWakeupVsEvent(bool en); +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) +#if CONFIG_BT_LE_RXBUF_OPT_ENABLED +extern void mmgmt_enableRxbufOptFeature(void); +#endif // CONFIG_BT_LE_RXBUF_OPT_ENABLED + +/* Local functions definition + *************************************************************************** + */ +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) +void ble_stack_enableVsCmds(bool en) +{ + adv_stack_enableClearLegacyAdvVsCmd(en); + advFilter_stack_enableDupExcListVsCmd(en); + scan_stack_enableAdvFlowCtrlVsCmd(en); + arr_stack_enableMultiConnVsCmd(en); + pcl_stack_enableSetRssiThreshVsCmd(en); + chanSel_stack_enableSetCsaVsCmd(en); + log_stack_enableLogsRelatedVsCmd(en); + hci_stack_enableSetVsEvtMaskVsCmd(en); + winWiden_stack_enableSetConstPeerScaVsCmd(en); +#if CONFIG_IDF_TARGET_ESP32C61_ECO3 + conn_stack_enableSetPrefTxRxCntVsCmd(en); +#endif // CONFIG_IDF_TARGET_ESP32C61_ECO3 +} + +void ble_stack_enableVsEvents(bool en) +{ + adv_stack_enableScanReqRxdVsEvent(en); + conn_stack_enableChanMapUpdCompVsEvent(en); + +#if CONFIG_BT_LE_SLEEP_ENABLE + sleep_stack_enableWakeupVsEvent(en); +#endif // CONFIG_BT_LE_SLEEP_ENABLE +} +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + +int ble_stack_initEnv(void) +{ + int rc; + + rc = base_stack_initEnv(); + if (rc) { + return rc; + } + +#if DEFAULT_BT_LE_MAX_CONNECTIONS + rc = conn_stack_initEnv(); + if (rc) { + return rc; + } +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + rc = conn_errorSim_initEnv(); + if (rc) { + return rc; + } +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + + return 0; +} + +void ble_stack_deinitEnv(void) +{ +#if DEFAULT_BT_LE_MAX_CONNECTIONS +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_errorSim_deinitEnv(); +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_stack_deinitEnv(); +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + + base_stack_deinitEnv(); +} + +int ble_stack_enable(void) +{ + int rc; + + rc = base_stack_enable(); + if (rc) { + return rc; + } + +#if DEFAULT_BT_LE_MAX_CONNECTIONS + rc = conn_stack_enable(); + if (rc) { + return rc; + } +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + rc = conn_errorSim_enable(); + if (rc) { + return rc; + } +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + ble_stack_enableVsCmds(true); + ble_stack_enableVsEvents(true); +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + +#if CONFIG_BT_LE_RXBUF_OPT_ENABLED + mmgmt_enableRxbufOptFeature(); +#endif // CONFIG_BT_LE_RXBUF_OPT_ENABLED + + return 0; +} + +void ble_stack_disable(void) +{ +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + ble_stack_enableVsEvents(false); + ble_stack_enableVsCmds(false); +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + +#if DEFAULT_BT_LE_MAX_CONNECTIONS +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_errorSim_disable(); +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_stack_disable(); +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + + base_stack_disable(); +} diff --git a/lib/bt/controller/esp32c6/ble_priv.h b/lib/bt/controller/esp32c6/ble_priv.h new file mode 100644 index 00000000..82dc4d16 --- /dev/null +++ b/lib/bt/controller/esp32c6/ble_priv.h @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +int ble_stack_initEnv(void); + +void ble_stack_deinitEnv(void); + +int ble_stack_enable(void); + +void ble_stack_disable(void); diff --git a/lib/bt/controller/esp32c6/bt.c b/lib/bt/controller/esp32c6/bt.c index 489327f0..dd57e8b3 100644 --- a/lib/bt/controller/esp32c6/bt.c +++ b/lib/bt/controller/esp32c6/bt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,32 +30,26 @@ #endif // CONFIG_ESP_COEX_ENABLED #include "nimble/nimble_npl_os.h" -#include "ble_hci_trans.h" +#include "esp_hci_transport.h" #include "os/endian.h" #include "esp_bt.h" #include "esp_intr_alloc.h" +#include "ble_priv.h" #include "esp_sleep.h" #include "esp_pm.h" #ifdef CONFIG_ESP_PHY_ENABLED #include "esp_phy_init.h" #endif #include "esp_private/periph_ctrl.h" -#include "hci_uart.h" +#include "esp_private/esp_clk_tree_common.h" #include "bt_osi_mem.h" -#if SOC_PM_RETENTION_HAS_CLOCK_BUG -#include "esp_private/sleep_retention.h" -#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG - #if CONFIG_FREERTOS_USE_TICKLESS_IDLE #include "esp_private/sleep_modem.h" +#include "esp_private/sleep_retention.h" #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE -#ifdef CONFIG_BT_BLUEDROID_ENABLED -#include "hci/hci_hal.h" -#endif // CONFIG_BT_BLUEDROID_ENABLED - #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -64,6 +58,12 @@ #include "hal/efuse_hal.h" #include "soc/rtc.h" +#include "modem/modem_syscon_struct.h" + +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED +#include "ble_log/ble_log_spi_out.h" +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + /* Macro definition ************************************************************************ */ @@ -71,16 +71,11 @@ #define OSI_COEX_VERSION 0x00010006 #define OSI_COEX_MAGIC_VALUE 0xFADEBEAD -#define EXT_FUNC_VERSION 0x20221122 +#define EXT_FUNC_VERSION 0x20250415 #define EXT_FUNC_MAGIC_VALUE 0xA5A5A5A5 #define BT_ASSERT_PRINT ets_printf -#ifdef CONFIG_BT_BLUEDROID_ENABLED -/* ACL_DATA_MBUF_LEADINGSPCAE: The leadingspace in user info header for ACL data */ -#define ACL_DATA_MBUF_LEADINGSPCAE 4 -#endif // CONFIG_BT_BLUEDROID_ENABLED - /* Types definition ************************************************************************ */ @@ -99,12 +94,6 @@ struct ext_funcs_t { int (*_esp_intr_free)(void **ret_handle); void *(* _malloc)(size_t size); void (*_free)(void *p); - void (*_hal_uart_start_tx)(int); - int (*_hal_uart_init_cbs)(int, hci_uart_tx_char, hci_uart_tx_done, hci_uart_rx_char, void *); - int (*_hal_uart_config)(int, int32_t, uint8_t, uint8_t, uart_parity_t, uart_hw_flowcontrol_t); - int (*_hal_uart_close)(int); - void (*_hal_uart_blocking_tx)(int, uint8_t); - int (*_hal_uart_init)(int, void *); int (* _task_create)(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id); void (* _task_delete)(void *task_handle); @@ -113,25 +102,42 @@ struct ext_funcs_t { int (* _ecc_gen_key_pair)(uint8_t *public, uint8_t *priv); int (* _ecc_gen_dh_key)(const uint8_t *remote_pub_key_x, const uint8_t *remote_pub_key_y, const uint8_t *local_priv_key, uint8_t *dhkey); - void (* _esp_reset_rpa_moudle)(void); +#if CONFIG_IDF_TARGET_ESP32C6 + void (* _esp_reset_modem)(uint8_t mdl_opts, uint8_t start); +#endif // CONFIG_IDF_TARGET_ESP32C6 uint32_t magic; }; #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -typedef void (*interface_func_t) (uint32_t len, const uint8_t*addr, bool end); +typedef void (*interface_func_t) (uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); + +enum { + BLE_LOG_INTERFACE_FLAG_CONTINUE = 0, + BLE_LOG_INTERFACE_FLAG_END, +}; #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* External functions or variables ************************************************************************ */ +#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE +extern void coex_hw_timer_set(uint8_t idx,uint8_t src, uint8_t pti,uint32_t latency, uint32_t perioidc); +extern void coex_hw_timer_enable(uint8_t idx); +extern void coex_hw_timer_disable(uint8_t idx); +#endif // CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE extern int ble_osi_coex_funcs_register(struct osi_coex_funcs_t *coex_funcs); extern int r_ble_controller_init(esp_bt_controller_config_t *cfg); +extern void esp_ble_controller_info_capture(uint32_t cycle_times); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -extern int r_ble_log_init_async(interface_func_t bt_controller_log_interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); +extern int r_ble_log_init_async(interface_func_t interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); extern int r_ble_log_deinit_async(void); +extern int r_ble_log_init_simple(interface_func_t interface, void *handler); +extern void r_ble_log_deinit_simple(void); extern void r_ble_log_async_select_dump_buffers(uint8_t buffers); extern void r_ble_log_async_output_dump_all(bool output); -extern void esp_panic_handler_reconfigure_wdts(uint32_t timeout_ms); +extern void esp_panic_handler_feed_wdts(void); +extern int r_ble_log_ctrl_level_and_mod(uint8_t log_level, uint32_t mod_switch); +extern int r_ble_ctrl_mod_type(uint16_t mod, uint32_t mod_type_switch); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED extern int r_ble_controller_deinit(void); extern int r_ble_controller_enable(uint8_t mode); @@ -149,11 +155,17 @@ extern void r_ble_lll_rfmgmt_set_sleep_cb(void *s_cb, void *w_cb, void *s_arg, extern void r_ble_rtc_wake_up_state_clr(void); extern int os_msys_init(void); extern void os_msys_deinit(void); +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY +extern void r_ble_ll_scan_start_time_init_compensation(uint32_t init_compensation); +extern void r_priv_sdk_config_insert_proc_time_set(uint16_t insert_proc_time); +#endif // CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY #if CONFIG_FREERTOS_USE_TICKLESS_IDLE -extern const sleep_retention_entries_config_t *esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra); +extern sleep_retention_entries_config_t *r_esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra); extern void r_esp_ble_set_wakeup_overhead(uint32_t overhead); #endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ -extern void r_esp_ble_change_rtc_freq(uint32_t freq); +#if CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE +extern void r_ble_ll_customize_peer_sca_set(uint16_t peer_sca); +#endif // CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE extern int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y, const uint8_t *our_priv_key, uint8_t *out_dhkey); @@ -181,27 +193,24 @@ static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status); static int task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id); static void task_delete_wrapper(void *task_handle); -#if CONFIG_BT_LE_HCI_INTERFACE_USE_UART -static void hci_uart_start_tx_wrapper(int uart_no); -static int hci_uart_init_cbs_wrapper(int uart_no, hci_uart_tx_char tx_func, - hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg); -static int hci_uart_config_wrapper(int uart_no, int32_t speed, uint8_t databits, uint8_t stopbits, - uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl); -static int hci_uart_close_wrapper(int uart_no); -static void hci_uart_blocking_tx_wrapper(int port, uint8_t data); -static int hci_uart_init_wrapper(int uart_no, void *cfg); -#endif // CONFIG_BT_LE_HCI_INTERFACE_USE_UART static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, void *arg, void **ret_handle_in); static int esp_intr_free_wrapper(void **ret_handle); static void osi_assert_wrapper(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2); static uint32_t osi_random_wrapper(void); -static void esp_reset_rpa_moudle(void); +#if CONFIG_IDF_TARGET_ESP32C6 +static void esp_reset_modem(uint8_t mdl_opts,uint8_t start); +#endif // CONFIG_IDF_TARGET_ESP32C6 static int esp_ecc_gen_key_pair(uint8_t *pub, uint8_t *priv); static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y, const uint8_t *our_priv_key, uint8_t *out_dhkey); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end); +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* Local variable definition *************************************************************************** @@ -211,18 +220,243 @@ static DRAM_ATTR esp_bt_controller_status_t ble_controller_status = ESP_BT_CONTR #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED const static uint32_t log_bufs_size[] = {CONFIG_BT_LE_LOG_CTRL_BUF1_SIZE, CONFIG_BT_LE_LOG_HCI_BUF_SIZE, CONFIG_BT_LE_LOG_CTRL_BUF2_SIZE}; +static bool log_is_inited = false; + +esp_err_t esp_bt_controller_log_init(void) +{ + if (log_is_inited) { + return ESP_OK; + } + +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + if (ble_log_spi_out_init() != 0) { + goto spi_out_init_failed; + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + if (r_ble_log_init_simple(ble_log_spi_out_ll_write, ble_log_spi_out_ll_log_ev_proc) != 0) { + goto log_init_failed; + } +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + uint8_t buffers = 0; +#if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED + buffers |= ESP_BLE_LOG_BUF_CONTROLLER; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED + buffers |= ESP_BLE_LOG_BUF_HCI; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED + + bool task_create = true; +#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY + task_create = false; +#elif CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_ctrl_log_partition_get_and_erase_first_block(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + + if (r_ble_log_init_async(esp_bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size) != 0) { + goto log_init_failed; + } +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + + if (r_ble_log_ctrl_level_and_mod(CONFIG_BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL, CONFIG_BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH) != ESP_OK) { + goto ctrl_level_init_failed; + } + log_is_inited = true; + return ESP_OK; + +ctrl_level_init_failed: +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_simple(); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_async(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +log_init_failed: +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +spi_out_init_failed: +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + return ESP_FAIL; +} + +void esp_bt_controller_log_deinit(void) +{ +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_simple(); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_async(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + + log_is_inited = false; +} + +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +#include "esp_partition.h" +#include "hal/wdt_hal.h" + +#define MAX_STORAGE_SIZE (CONFIG_BT_LE_CONTROLLER_LOG_PARTITION_SIZE) +#define BLOCK_SIZE (4096) +#define THRESHOLD (3072) +#define PARTITION_NAME "bt_ctrl_log" + +static const esp_partition_t *log_partition; +static uint32_t write_index = 0; +static uint32_t next_erase_index = BLOCK_SIZE; +static bool block_erased = false; +static bool stop_write = false; +static bool is_filled = false; + +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void) +{ + log_partition = NULL; + assert(MAX_STORAGE_SIZE % BLOCK_SIZE == 0); + // Find the partition map in the partition table + log_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, PARTITION_NAME); + assert(log_partition != NULL); + // Prepare data to be read later using the mapped address + ESP_ERROR_CHECK(esp_partition_erase_range(log_partition, 0, BLOCK_SIZE)); + write_index = 0; + next_erase_index = BLOCK_SIZE; + block_erased = false; + is_filled = false; + stop_write = false; +} + +static int esp_bt_controller_log_storage(uint32_t len, const uint8_t *addr, bool end) +{ + if (len > MAX_STORAGE_SIZE) { + return -1; + } + + if (stop_write) { + return 0; + } + + if (((write_index) % BLOCK_SIZE) >= THRESHOLD && !block_erased) { + // esp_rom_printf("Ers nxt: %d,%d\n", next_erase_index, write_index); + esp_partition_erase_range(log_partition, next_erase_index, BLOCK_SIZE); + next_erase_index = (next_erase_index + BLOCK_SIZE) % MAX_STORAGE_SIZE; + block_erased = true; + } + + if (((write_index + len) / BLOCK_SIZE) > (write_index / BLOCK_SIZE)) { + block_erased = false; + } + + if (write_index + len <= MAX_STORAGE_SIZE) { + esp_partition_write(log_partition, write_index, addr, len); + write_index = (write_index + len) % MAX_STORAGE_SIZE; + } else { + uint32_t first_part_len = MAX_STORAGE_SIZE - write_index; + esp_partition_write(log_partition, write_index, addr, first_part_len); + esp_partition_write(log_partition, 0, addr + first_part_len, len - first_part_len); + write_index = len - first_part_len; + is_filled = true; + // esp_rom_printf("old idx: %d,%d\n",next_erase_index, write_index); + } + + return 0; +} + +void esp_bt_read_ctrl_log_from_flash(bool output) +{ + esp_partition_mmap_handle_t mmap_handle; + uint32_t read_index; + const void *mapped_ptr; + const uint8_t *buffer; + uint32_t print_len; + uint32_t max_print_len; + esp_err_t err; + + print_len = 0; + max_print_len = 4096; + err = esp_partition_mmap(log_partition, 0, MAX_STORAGE_SIZE, ESP_PARTITION_MMAP_DATA, &mapped_ptr, &mmap_handle); + if (err != ESP_OK) { + ESP_LOGE("FLASH", "Mmap failed: %s", esp_err_to_name(err)); + return; + } + + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + r_ble_log_async_output_dump_all(true); + esp_bt_controller_log_deinit(); + stop_write = true; + + buffer = (const uint8_t *)mapped_ptr; + esp_panic_handler_feed_wdts(); + if (is_filled) { + read_index = next_erase_index; + } else { + read_index = 0; + } + + esp_rom_printf("\r\nREAD_CHECK:%ld,%ld,%d\r\n",read_index, write_index, is_filled); + esp_rom_printf("\r\n[DUMP_START:"); + while (read_index != write_index) { + esp_rom_printf("%02x ", buffer[read_index]); + if (print_len > max_print_len) { + esp_panic_handler_feed_wdts(); + print_len = 0; + } + + print_len++; + read_index = (read_index + 1) % MAX_STORAGE_SIZE; + } + + esp_rom_printf(":DUMP_END]\r\n"); + portEXIT_CRITICAL_SAFE(&spinlock); + esp_partition_munmap(mmap_handle); + err = esp_bt_controller_log_init(log_output_mode); + assert(err == ESP_OK); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + +#if CONFIG_BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE +void esp_task_wdt_isr_user_handler(void) +{ + esp_ble_controller_log_dump_all(true); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE + +#if CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE +void __real_esp_panic_handler(void *info); +void __wrap_esp_panic_handler (void *info) +{ + esp_ble_controller_log_dump_all(true); + __real_esp_panic_handler(info); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* This variable tells if BLE is running */ static bool s_ble_active = false; #ifdef CONFIG_PM_ENABLE static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL; -#define BTDM_MIN_TIMER_UNCERTAINTY_US (200) #endif // CONFIG_PM_ENABLE +#define MAIN_XTAL_FREQ_HZ (40000000) +#define MAIN_XTAL_FREQ_HZ_WORKROUND (500000) +static DRAM_ATTR modem_clock_lpclk_src_t s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_INVALID; +static DRAM_ATTR uint32_t s_bt_lpclk_freq = 100000; -#define BLE_RTC_DELAY_US_LIGHT_SLEEP (2500) +#define BLE_RTC_DELAY_US_LIGHT_SLEEP (3200) #define BLE_RTC_DELAY_US_MODEM_SLEEP (500) +#define BLE_CONTROLLER_MALLOC_CAPS (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT|MALLOC_CAP_DMA) +void *malloc_ble_controller_mem(size_t size) +{ + return heap_caps_malloc(size, BLE_CONTROLLER_MALLOC_CAPS); +} + +uint32_t get_ble_controller_free_heap_size(void) +{ + return heap_caps_get_free_size(BLE_CONTROLLER_MALLOC_CAPS); +} + static const struct osi_coex_funcs_t s_osi_coex_funcs_ro = { ._magic = OSI_COEX_MAGIC_VALUE, ._version = OSI_COEX_VERSION, @@ -238,29 +472,40 @@ struct ext_funcs_t ext_funcs_ro = { ._esp_intr_free = esp_intr_free_wrapper, ._malloc = bt_osi_mem_malloc_internal, ._free = bt_osi_mem_free, -#if CONFIG_BT_LE_HCI_INTERFACE_USE_UART - ._hal_uart_start_tx = hci_uart_start_tx_wrapper, - ._hal_uart_init_cbs = hci_uart_init_cbs_wrapper, - ._hal_uart_config = hci_uart_config_wrapper, - ._hal_uart_close = hci_uart_close_wrapper, - ._hal_uart_blocking_tx = hci_uart_blocking_tx_wrapper, - ._hal_uart_init = hci_uart_init_wrapper, -#endif //CONFIG_BT_LE_HCI_INTERFACE_USE_UART ._task_create = task_create_wrapper, ._task_delete = task_delete_wrapper, ._osi_assert = osi_assert_wrapper, ._os_random = osi_random_wrapper, ._ecc_gen_key_pair = esp_ecc_gen_key_pair, ._ecc_gen_dh_key = esp_ecc_gen_dh_key, - ._esp_reset_rpa_moudle = esp_reset_rpa_moudle, +#if CONFIG_IDF_TARGET_ESP32C6 + ._esp_reset_modem = esp_reset_modem, +#endif // CONFIG_IDF_TARGET_ESP32C6 .magic = EXT_FUNC_MAGIC_VALUE, }; -static void IRAM_ATTR esp_reset_rpa_moudle(void) +#if CONFIG_IDF_TARGET_ESP32C6 +static void IRAM_ATTR esp_reset_modem(uint8_t mdl_opts,uint8_t start) { + if (mdl_opts == 0x05) { + if (start) { +#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE + coex_hw_timer_set(0x04, 0x02, 15, 0, 5000); + coex_hw_timer_enable(0x04); +#endif // CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE + MODEM_SYSCON.modem_rst_conf.val |= (BIT(16) | BIT(18)); + MODEM_SYSCON.modem_rst_conf.val &= ~(BIT(16) | BIT(18)); + } else { +#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE + coex_hw_timer_disable(0x04); +#endif // CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE + } + } } +#endif // CONFIG_IDF_TARGET_ESP32C6 + static void IRAM_ATTR osi_assert_wrapper(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2) { @@ -290,75 +535,6 @@ static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status) #endif // CONFIG_SW_COEXIST_ENABLE } -#ifdef CONFIG_BT_BLUEDROID_ENABLED -bool esp_vhci_host_check_send_available(void) -{ - if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { - return false; - } - return true; -} - -static struct os_mbuf *ble_hs_mbuf_gen_pkt(uint16_t leading_space) -{ - struct os_mbuf *om; - int rc; - - om = os_msys_get_pkthdr(0, 0); - if (om == NULL) { - return NULL; - } - - if (om->om_omp->omp_databuf_len < leading_space) { - rc = os_mbuf_free_chain(om); - assert(rc == 0); - return NULL; - } - - om->om_data += leading_space; - - return om; -} - -struct os_mbuf *ble_hs_mbuf_acl_pkt(void) -{ - return ble_hs_mbuf_gen_pkt(4 + 1); -} - -void esp_vhci_host_send_packet(uint8_t *data, uint16_t len) -{ - if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { - return; - } - - if (*(data) == DATA_TYPE_COMMAND) { - struct ble_hci_cmd *cmd = NULL; - cmd = (struct ble_hci_cmd *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD); - assert(cmd); - memcpy((uint8_t *)cmd, data + 1, len - 1); - ble_hci_trans_hs_cmd_tx((uint8_t *)cmd); - } - - if (*(data) == DATA_TYPE_ACL) { - struct os_mbuf *om = os_msys_get_pkthdr(len, ACL_DATA_MBUF_LEADINGSPCAE); - assert(om); - assert(os_mbuf_append(om, &data[1], len - 1) == 0); - ble_hci_trans_hs_acl_tx(om); - } -} - -esp_err_t esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback) -{ - if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { - return ESP_FAIL; - } - - ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL); - - return ESP_OK; -} -#endif // CONFIG_BT_BLUEDROID_ENABLED - static int task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id) { @@ -390,61 +566,13 @@ static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer return rc; } -#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART -static void hci_uart_start_tx_wrapper(int uart_no) +static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, void *arg, void **ret_handle_in) { - hci_uart_start_tx(uart_no); -} - -static int hci_uart_init_cbs_wrapper(int uart_no, hci_uart_tx_char tx_func, - hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg) -{ - int rc = -1; - rc = hci_uart_init_cbs(uart_no, tx_func, tx_done, rx_func, arg); - return rc; -} - - -static int hci_uart_config_wrapper(int port_num, int32_t baud_rate, uint8_t data_bits, - uint8_t stop_bits, uart_parity_t parity, - uart_hw_flowcontrol_t flow_ctl) -{ - int rc = -1; - rc = hci_uart_config(port_num, baud_rate, data_bits, stop_bits, parity, flow_ctl); - return rc; -} - -static int hci_uart_close_wrapper(int uart_no) -{ - int rc = -1; - rc = hci_uart_close(uart_no); - return rc; -} - -static void hci_uart_blocking_tx_wrapper(int port, uint8_t data) -{ - //This function is nowhere to use. -} - -static int hci_uart_init_wrapper(int uart_no, void *cfg) -{ - //This function is nowhere to use. - return 0; -} - -#endif //CONFIG_BT_LE_HCI_INTERFACE_USE_UART - -static int ble_hci_unregistered_hook(void*, void*) -{ - ESP_LOGD(NIMBLE_PORT_LOG_TAG,"%s ble hci rx_evt is not registered.",__func__); - return 0; -} - -static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, - void *arg, void **ret_handle_in) -{ - int rc = esp_intr_alloc(source, flags | ESP_INTR_FLAG_IRAM, handler, - arg, (intr_handle_t *)ret_handle_in); +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + int rc = esp_intr_alloc(source, flags, handler, arg, (intr_handle_t *)ret_handle_in); +#else + int rc = esp_intr_alloc(source, flags | ESP_INTR_FLAG_IRAM, handler, arg, (intr_handle_t *)ret_handle_in); +#endif return rc; } @@ -461,16 +589,21 @@ void esp_bt_rtc_slow_clk_select(uint8_t slow_clk_src) /* Select slow clock source for BT momdule */ switch (slow_clk_src) { case MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL: - ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source"); +#if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND uint32_t chip_version = efuse_hal_chip_revision(); + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source, chip ver: %d", chip_version); if (chip_version == 0) { - modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (400 - 1)); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (MAIN_XTAL_FREQ_HZ/s_bt_lpclk_freq - 1)); } else{ - modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (5 - 1)); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (MAIN_XTAL_FREQ_HZ_WORKROUND/s_bt_lpclk_freq - 1)); } +#else + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source"); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (MAIN_XTAL_FREQ_HZ/s_bt_lpclk_freq - 1)); +#endif // SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND break; case MODEM_CLOCK_LPCLK_SRC_RC_SLOW: - ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 136 kHz RC as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Using 136 kHz RC as clock source, use with caution as it may not maintain ACL or Sync process due to low clock accuracy!"); modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (5 - 1)); break; case MODEM_CLOCK_LPCLK_SRC_XTAL32K: @@ -489,6 +622,56 @@ void esp_bt_rtc_slow_clk_select(uint8_t slow_clk_src) } } +modem_clock_lpclk_src_t esp_bt_get_lpclk_src(void) +{ + return s_bt_lpclk_src; +} + +void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src) +{ + if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { + return; + } + + if (clk_src >= MODEM_CLOCK_LPCLK_SRC_MAX) { + return; + } + + s_bt_lpclk_src = clk_src; +} + +uint32_t esp_bt_get_lpclk_freq(void) +{ + return s_bt_lpclk_freq; +} + +void esp_bt_set_lpclk_freq(uint32_t clk_freq) +{ + uint32_t xtal_freq; + + if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { + return; + } + + if (!clk_freq) { + return; + } + + xtal_freq = MAIN_XTAL_FREQ_HZ; +#if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND + uint32_t chip_version = efuse_hal_chip_revision(); + if (chip_version == 1) { + xtal_freq = MAIN_XTAL_FREQ_HZ_WORKROUND; + } +#endif // SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND + + if (xtal_freq % clk_freq) { + return; + } + + s_bt_lpclk_freq = clk_freq; +} + IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) { if (!s_ble_active) { @@ -510,10 +693,17 @@ IRAM_ATTR void controller_wakeup_cb(void *arg) return; } #ifdef CONFIG_PM_ENABLE + esp_pm_config_t pm_config; esp_pm_lock_acquire(s_pm_lock); + esp_pm_get_configuration(&pm_config); + assert(esp_rom_get_cpu_ticks_per_us() == pm_config.max_freq_mhz); r_ble_rtc_wake_up_state_clr(); #endif //CONFIG_PM_ENABLE esp_phy_enable(PHY_MODEM_BT); + if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW) { + uint32_t *clk_freq = (uint32_t *)arg; + *clk_freq = esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED) / 5; + } s_ble_active = true; } @@ -522,7 +712,7 @@ static esp_err_t sleep_modem_ble_mac_retention_init(void *arg) { uint8_t size; int extra = *(int *)arg; - const sleep_retention_entries_config_t *ble_mac_modem_config = esp_ble_mac_retention_link_get(&size, extra); + sleep_retention_entries_config_t *ble_mac_modem_config = r_esp_ble_mac_retention_link_get(&size, extra); esp_err_t err = sleep_retention_entries_create(ble_mac_modem_config, size, REGDMA_LINK_PRI_BT_MAC_BB, SLEEP_RETENTION_MODULE_BLE_MAC); if (err == ESP_OK) { ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Modem BLE MAC retention initialization"); @@ -535,7 +725,7 @@ static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra) int retention_args = extra; sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_modem_ble_mac_retention_init, .arg = &retention_args } }, - .depends = BIT(SLEEP_RETENTION_MODULE_BT_BB) + .depends = RETENTION_MODULE_BITMAP_INIT(BT_BB) }; esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BLE_MAC, &init_param); if (err == ESP_OK) { @@ -553,7 +743,7 @@ static void sleep_modem_ble_mac_modem_state_deinit(void) } } -void sleep_modem_light_sleep_overhead_set(uint32_t overhead) +void IRAM_ATTR sleep_modem_light_sleep_overhead_set(uint32_t overhead) { r_esp_ble_set_wakeup_overhead(overhead); } @@ -580,13 +770,20 @@ esp_err_t controller_sleep_init(void) if (rc != ESP_OK) { goto error; } -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE -#if CONFIG_BT_LE_SLEEP_ENABLE && !CONFIG_MAC_BB_PD +#endif // CONFIG_PM_ENABLE +#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE +#if SOC_PM_RETENTION_HAS_CLOCK_BUG && !CONFIG_MAC_BB_PD #error "CONFIG_MAC_BB_PD required for BLE light sleep to run properly" -#endif // CONFIG_BT_LE_SLEEP_ENABLE && !CONFIG_MAC_BB_PD +#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG && !CONFIG_MAC_BB_PD /* Create a new regdma link for BLE related register restoration */ +#if SOC_PM_RETENTION_HAS_CLOCK_BUG rc = sleep_modem_ble_mac_modem_state_init(1); - assert(rc == 0); +#else + rc = sleep_modem_ble_mac_modem_state_init(0); +#endif // SOC_PM_RETENTION_HAS_CLOCK_BUG + if (rc != ESP_OK) { + goto error; + } esp_sleep_enable_bt_wakeup(); ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer"); @@ -599,19 +796,21 @@ esp_err_t controller_sleep_init(void) sleep_modem_register_mac_bb_module_prepare_callback(sleep_modem_mac_bb_power_down_prepare, sleep_modem_mac_bb_power_up_prepare); #endif // SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD -#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ return rc; +#ifdef CONFIG_PM_ENABLE error: - -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#endif // CONFIG_PM_ENABLE +#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE #if SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD sleep_modem_unregister_mac_bb_module_prepare_callback(sleep_modem_mac_bb_power_down_prepare, sleep_modem_mac_bb_power_up_prepare); #endif // SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD esp_sleep_disable_bt_wakeup(); esp_pm_unregister_inform_out_light_sleep_overhead_callback(sleep_modem_light_sleep_overhead_set); -#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#ifdef CONFIG_PM_ENABLE /*lock should release first and then delete*/ if (s_pm_lock != NULL) { esp_pm_lock_delete(s_pm_lock); @@ -624,7 +823,7 @@ error: void controller_sleep_deinit(void) { -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE #if SOC_PM_RETENTION_HAS_CLOCK_BUG && CONFIG_MAC_BB_PD sleep_modem_unregister_mac_bb_module_prepare_callback(sleep_modem_mac_bb_power_down_prepare, sleep_modem_mac_bb_power_up_prepare); @@ -633,7 +832,7 @@ void controller_sleep_deinit(void) esp_sleep_disable_bt_wakeup(); sleep_modem_ble_mac_modem_state_deinit(); esp_pm_unregister_inform_out_light_sleep_overhead_callback(sleep_modem_light_sleep_overhead_set); -#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ #ifdef CONFIG_PM_ENABLE /* lock should be released first */ esp_pm_lock_delete(s_pm_lock); @@ -712,15 +911,55 @@ void ble_controller_scan_duplicate_config(void) ble_vhci_disc_duplicate_set_max_cache_size(cache_size); } +static void ble_rtc_clk_init(esp_bt_controller_config_t *cfg) +{ + if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_INVALID) { +#if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL; +#else +#if CONFIG_RTC_CLK_SRC_INT_RC + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_RC_SLOW; +#elif CONFIG_RTC_CLK_SRC_EXT_CRYS + if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_XTAL32K; + } else { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock"); + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL; + } +#elif CONFIG_RTC_CLK_SRC_INT_RC32K + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_RC32K; +#elif CONFIG_RTC_CLK_SRC_EXT_OSC + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_EXT32K; +#else + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "Unsupported clock source"); + assert(0); +#endif +#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */ + } + + if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { + cfg->rtc_freq = s_bt_lpclk_freq; + } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) { + cfg->rtc_freq = 32768; + } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW) { + cfg->rtc_freq = esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED) / 5; + cfg->ble_ll_sca = 3000; + } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC32K) { + cfg->rtc_freq = 32000; + } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_EXT32K) { + cfg->rtc_freq = 32000; + } + esp_bt_rtc_slow_clk_select(s_bt_lpclk_src); +} + esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) { uint8_t mac[6]; esp_err_t ret = ESP_OK; ble_npl_count_info_t npl_info; - uint32_t slow_clk_freq = 0; + uint8_t hci_transport_mode; memset(&npl_info, 0, sizeof(ble_npl_count_info_t)); - if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "invalid controller state"); return ESP_ERR_INVALID_STATE; @@ -769,33 +1008,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) modem_clock_module_enable(PERIPH_BT_MODULE); modem_clock_module_mac_reset(PERIPH_BT_MODULE); /* Select slow clock source for BT momdule */ -#if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL); - slow_clk_freq = 100000; -#else -#if CONFIG_RTC_CLK_SRC_INT_RC - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_RC_SLOW); - slow_clk_freq = 30000; -#elif CONFIG_RTC_CLK_SRC_EXT_CRYS - if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_XTAL32K); - slow_clk_freq = 32768; - } else { - ESP_LOGW(NIMBLE_PORT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock"); - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL); - slow_clk_freq = 100000; - } -#elif CONFIG_RTC_CLK_SRC_INT_RC32K - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_RC32K); - slow_clk_freq = 32000; -#elif CONFIG_RTC_CLK_SRC_EXT_OSC - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_EXT32K); - slow_clk_freq = 32000; -#else - ESP_LOGE(NIMBLE_PORT_LOG_TAG, "Unsupported clock source"); - assert(0); -#endif -#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */ + ble_rtc_clk_init(cfg); esp_phy_modem_init(); if (ble_osi_coex_funcs_register((struct osi_coex_funcs_t *)&s_osi_coex_funcs_ro) != 0) { @@ -809,20 +1022,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) #endif // CONFIG_SW_COEXIST_ENABLE #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - interface_func_t bt_controller_log_interface; - bt_controller_log_interface = esp_bt_controller_log_interface; - uint8_t buffers = 0; -#if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED - buffers |= ESP_BLE_LOG_BUF_CONTROLLER; -#endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED -#if CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED - buffers |= ESP_BLE_LOG_BUF_HCI; -#endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED -#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY - ret = r_ble_log_init_async(bt_controller_log_interface, false, buffers, (uint32_t *)log_bufs_size); -#else - ret = r_ble_log_init_async(bt_controller_log_interface, true, buffers, (uint32_t *)log_bufs_size); -#endif // CONFIG_BT_CONTROLLER_LOG_DUMP + ret = esp_bt_controller_log_init(); if (ret != ESP_OK) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_controller_log_init failed %d", ret); goto modem_deint; @@ -834,14 +1034,23 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) goto modem_deint; } + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "ble controller commit:[%s]", ble_controller_get_compile_version()); + ret = r_ble_controller_init(cfg); if (ret != ESP_OK) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "r_ble_controller_init failed %d", ret); goto modem_deint; } - ESP_LOGI(NIMBLE_PORT_LOG_TAG, "ble controller commit:[%s]", ble_controller_get_compile_version()); - r_esp_ble_change_rtc_freq(slow_clk_freq); +#if CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE + r_ble_ll_customize_peer_sca_set(CONFIG_BT_LE_LL_PEER_SCA); +#endif // CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE + + ret = ble_stack_initEnv(); + if (ret != ESP_OK) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_stack_initEnv failed %d", ret); + goto free_controller; + } ble_controller_scan_duplicate_config(); @@ -856,24 +1065,40 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) ESP_LOGW(NIMBLE_PORT_LOG_TAG, "controller_sleep_init failed %d", ret); goto free_controller; } + ESP_ERROR_CHECK(esp_read_mac((uint8_t *)mac, ESP_MAC_BT)); + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Bluetooth MAC: %02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); swap_in_place(mac, 6); r_esp_ble_ll_set_public_addr(mac); ble_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; - ble_hci_trans_cfg_hs((ble_hci_trans_rx_cmd_fn *)ble_hci_unregistered_hook,NULL, - (ble_hci_trans_rx_acl_fn *)ble_hci_unregistered_hook,NULL); - return ESP_OK; +#if CONFIG_BT_LE_HCI_INTERFACE_USE_RAM + hci_transport_mode = HCI_TRANSPORT_VHCI; +#elif CONFIG_BT_LE_HCI_INTERFACE_USE_UART + hci_transport_mode = HCI_TRANSPORT_UART_NO_DMA; +#if CONFIG_BT_LE_UART_HCI_DMA_MODE + hci_transport_mode = HCI_TRANSPORT_UART_UHCI; +#endif // CONFIG_BT_LE_UART_HCI_DMA_MODE +#endif // CONFIG_BT_LE_HCI_INTERFACE_USE_RAM + ret = hci_transport_init(hci_transport_mode); + if (ret) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "hci transport init failed %d", ret); + goto free_controller; + } + return ESP_OK; free_controller: + hci_transport_deinit(); controller_sleep_deinit(); os_msys_deinit(); + ble_stack_deinitEnv(); r_ble_controller_deinit(); modem_deint: esp_ble_unregister_bb_funcs(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - r_ble_log_deinit_async(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED esp_phy_modem_deinit(); modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); @@ -897,6 +1122,7 @@ esp_err_t esp_bt_controller_deinit(void) return ESP_FAIL; } + hci_transport_deinit(); controller_sleep_deinit(); os_msys_deinit(); @@ -905,10 +1131,11 @@ esp_err_t esp_bt_controller_deinit(void) modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); modem_clock_module_disable(PERIPH_BT_MODULE); + ble_stack_deinitEnv(); r_ble_controller_deinit(); esp_ble_unregister_bb_funcs(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - r_ble_log_deinit_async(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED #if CONFIG_BT_NIMBLE_ENABLED @@ -954,6 +1181,16 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) coex_enable(); #endif // CONFIG_SW_COEXIST_ENABLE +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + r_ble_ll_scan_start_time_init_compensation(500); + r_priv_sdk_config_insert_proc_time_set(500); +#endif // CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + + if (ble_stack_enable() != 0) { + ret = ESP_FAIL; + goto error; + } + if (r_ble_controller_enable(mode) != 0) { ret = ESP_FAIL; goto error; @@ -962,6 +1199,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) return ESP_OK; error: + ble_stack_disable(); #if CONFIG_SW_COEXIST_ENABLE coex_disable(); #endif @@ -985,6 +1223,7 @@ esp_err_t esp_bt_controller_disable(void) if (r_ble_controller_disable() != 0) { return ESP_FAIL; } + ble_stack_disable(); #if CONFIG_SW_COEXIST_ENABLE coex_disable(); #endif @@ -1114,9 +1353,17 @@ esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_ switch (power_type) { case ESP_BLE_PWR_TYPE_DEFAULT: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_ADV: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0xFF, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_SCAN: - if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1147,9 +1394,13 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type esp_err_t stat = ESP_FAIL; switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1172,11 +1423,15 @@ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type) int tx_level = 0; switch (power_type) { - case ESP_BLE_PWR_TYPE_ADV: - case ESP_BLE_PWR_TYPE_SCAN: case ESP_BLE_PWR_TYPE_DEFAULT: tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); break; + case ESP_BLE_PWR_TYPE_ADV: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0); + break; + case ESP_BLE_PWR_TYPE_SCAN: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); + break; case ESP_BLE_PWR_TYPE_CONN_HDL0: case ESP_BLE_PWR_TYPE_CONN_HDL1: case ESP_BLE_PWR_TYPE_CONN_HDL2: @@ -1206,9 +1461,11 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); break; case ESP_BLE_ENHANCED_PWR_TYPE_ADV: case ESP_BLE_ENHANCED_PWR_TYPE_CONN: @@ -1226,26 +1483,47 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po } #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end) +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag) { - for (int i = 0; i < len; i++) { - esp_rom_printf("%02x ", addr[i]); + bool end = (flag & BIT(BLE_LOG_INTERFACE_FLAG_END)); +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_controller_log_storage(len, addr, end); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + + if (len && addr) { + for (int i = 0; i < len; i++) { esp_rom_printf("%02x ", addr[i]); } } - if (end) { - esp_rom_printf("\n"); + if (len_append && addr_append) { + for (int i = 0; i < len_append; i++) { esp_rom_printf("%02x ", addr_append[i]); } } + if (end) { esp_rom_printf("\n"); } + + portEXIT_CRITICAL_SAFE(&spinlock); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE } +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED void esp_ble_controller_log_dump_all(bool output) { - portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_dump_all(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_read_ctrl_log_from_flash(output); +#elif !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; portENTER_CRITICAL_SAFE(&spinlock); - esp_panic_handler_reconfigure_wdts(5000); + esp_panic_handler_feed_wdts(); BT_ASSERT_PRINT("\r\n[DUMP_START:"); r_ble_log_async_output_dump_all(output); BT_ASSERT_PRINT(":DUMP_END]\r\n"); portEXIT_CRITICAL_SAFE(&spinlock); +#endif } #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED @@ -1460,3 +1738,36 @@ int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) #endif // CONFIG_BT_LE_SM_LEGACY || CONFIG_BT_LE_SM_SC #endif // (!CONFIG_BT_NIMBLE_ENABLED) && (CONFIG_BT_CONTROLLER_ENABLED) + +#if CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED +#include "esp_gdbstub.h" +#endif // CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED + +int IRAM_ATTR +ble_capture_info_user_handler(uint8_t type, uint32_t reason, uint32_t param1, uint32_t param2) +{ + int i; + + switch(type) { + case 0: + for (i = 0; i < 2; i++) { + esp_ble_controller_info_capture(0x010101); + } +#if CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED + uintptr_t sp; + __asm__ volatile ("mv %0, sp" : "=r" (sp)); + esp_gdbstub_panic_handler(&sp); +#endif // CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED + break; +#if CONFIG_BT_LE_ASSERT_WHEN_ABNORMAL_DISCONN_ENABLED + case 1: + if ((reason == 0x08) || (reason == 0x3d) || (reason == 0x28)) { + osi_assert_wrapper(__LINE__,__func__, type, reason); + } + break; +#endif // CONFIG_BT_LE_ASSERT_WHEN_ABNORMAL_DISCONN_ENABLED + default: + break; + } + return 0; +} diff --git a/lib/bt/controller/esp32c6/esp_bt_cfg.h b/lib/bt/controller/esp32c6/esp_bt_cfg.h index 9e341e32..f22c4c75 100644 --- a/lib/bt/controller/esp32c6/esp_bt_cfg.h +++ b/lib/bt/controller/esp32c6/esp_bt_cfg.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -40,6 +40,7 @@ extern "C" { #define DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT MYNEWT_VAL(BLE_TRANSPORT_EVT_COUNT) #define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT MYNEWT_VAL(BLE_TRANSPORT_EVT_DISCARDABLE_COUNT) #define DEFAULT_BT_LE_POWER_CONTROL_ENABLED MYNEWT_VAL(BLE_POWER_CONTROL) + #define DEFAULT_BT_LE_SUBRATE_ENABLED MYNEWT_VAL(BLE_CONN_SUBRATING) #if defined(CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT) #define DEFAULT_BT_LE_50_FEATURE_SUPPORT (1) #else @@ -129,16 +130,95 @@ extern "C" { #else #define DEFAULT_BT_LE_50_FEATURE_SUPPORT (0) #endif + + #if defined (CONFIG_BT_LE_HCI_UART_FLOWCTRL) + #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (CONFIG_BT_LE_HCI_UART_FLOWCTRL) + #if DEFAULT_BT_LE_HCI_UART_FLOW_CTRL + #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (CONFIG_BT_LE_HCI_UART_CTS_PIN) + #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (CONFIG_BT_LE_HCI_UART_RTS_PIN) + #else + #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (-1) + #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (-1) + #endif + #else + #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) + #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (-1) + #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (-1) + #endif + + #define DEFAULT_BT_LE_SUBRATE_ENABLED 0 #endif #define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF +#ifdef CONFIG_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS +#define DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS (CONFIG_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS) +#else +#define DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS (0) +#endif + +#ifdef CONFIG_BT_LE_CTRL_LLCP_CONN_UPDATE +#define BT_CTRL_BLE_LLCP_CONN_UPDATE (1<<0) +#else +#define BT_CTRL_BLE_LLCP_CONN_UPDATE (0<<0) +#endif + +#ifdef CONFIG_BT_LE_CTRL_LLCP_CHAN_MAP_UPDATE +#define BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE (1<<1) +#else +#define BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE (0<<1) +#endif + +#ifdef CONFIG_BT_LE_CTRL_LLCP_PHY_UPDATE +#define BT_CTRL_BLE_LLCP_PHY_UPDATE (1<<2) +#else +#define BT_CTRL_BLE_LLCP_PHY_UPDATE (0<<2) +#endif + +#define BT_LE_CTRL_LLCP_DISC_FLAG (BT_CTRL_BLE_LLCP_CONN_UPDATE | BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE | BT_CTRL_BLE_LLCP_PHY_UPDATE) + +#ifdef CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX +#define BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX (CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX) +#else +#define BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX (256) +#endif + +#if defined(CONFIG_BT_LE_CTRL_CHAN_ASS_EN) +#define DEFAULT_BT_LE_CTRL_CHAN_ASS_EN (CONFIG_BT_LE_CTRL_CHAN_ASS_EN) +#else +#define DEFAULT_BT_LE_CTRL_CHAN_ASS_EN (0) +#endif + +#if defined(CONFIG_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX) +#define DEFAULT_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX (CONFIG_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX) +#else +#define DEFAULT_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX (0) +#endif + +#if defined(CONFIG_BT_LE_CTRL_FAST_CONN_DATA_TX_EN) +#define DEFAULT_BT_LE_CTRL_FAST_CONN_DATA_TX_EN (CONFIG_BT_LE_CTRL_FAST_CONN_DATA_TX_EN) +#else +#define DEFAULT_BT_LE_CTRL_FAST_CONN_DATA_TX_EN (0) +#endif + #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART #define HCI_UART_EN CONFIG_BT_LE_HCI_INTERFACE_USE_UART #else #define HCI_UART_EN 0 // hci ram mode #endif +#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_RAM +#define DEFAULT_BT_LE_VHCI_ENABLED (CONFIG_BT_LE_HCI_INTERFACE_USE_RAM) +#else +#define DEFAULT_BT_LE_VHCI_ENABLED (0) +#endif + +#ifdef CONFIG_BT_LE_PTR_CHECK_ENABLED +#define DEFAULT_BT_LE_PTR_CHECK_ENABLED (CONFIG_BT_LE_PTR_CHECK_ENABLED) +#else +#define DEFAULT_BT_LE_PTR_CHECK_ENABLED (0) +#endif + #ifdef CONFIG_BT_LE_SLEEP_ENABLE #define NIMBLE_SLEEP_ENABLE CONFIG_BT_LE_SLEEP_ENABLE #else @@ -169,8 +249,6 @@ extern "C" { #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (UART_DATA_8_BITS) #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (UART_STOP_BITS_1) #define DEFAULT_BT_LE_HCI_UART_PARITY (0) - #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (CONFIG_BT_LE_HCI_UART_TASK_STACK_SIZE) - #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) #else #define DEFAULT_BT_LE_HCI_UART_TX_PIN (0) #define DEFAULT_BT_LE_HCI_UART_RX_PIN (0) @@ -179,8 +257,6 @@ extern "C" { #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (0) #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (0) #define DEFAULT_BT_LE_HCI_UART_PARITY (0) - #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (0) - #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) #endif /* Unchanged configuration */ @@ -205,8 +281,7 @@ extern "C" { #define RTC_FREQ_N (32768) /* in Hz */ -#define BLE_LL_TX_PWR_DBM_N (9) - +#define BLE_LL_TX_PWR_DBM_N (CONFIG_BT_LE_DFT_TX_POWER_LEVEL_DBM_EFF) #define RUN_BQB_TEST (0) #define RUN_QA_TEST (0) diff --git a/lib/bt/controller/esp32c61/Kconfig.in b/lib/bt/controller/esp32c61/Kconfig.in index e69de29b..806ee5e8 100644 --- a/lib/bt/controller/esp32c61/Kconfig.in +++ b/lib/bt/controller/esp32c61/Kconfig.in @@ -0,0 +1 @@ +source "$IDF_PATH/components/bt/controller/esp32c6/Kconfig.in" diff --git a/lib/bt/controller/esp32h2/Kconfig.in b/lib/bt/controller/esp32h2/Kconfig.in index e0c49361..14330540 100644 --- a/lib/bt/controller/esp32h2/Kconfig.in +++ b/lib/bt/controller/esp32h2/Kconfig.in @@ -1,20 +1,37 @@ menu "HCI Config" - choice BT_LE_HCI_INTERFACE - prompt "Select HCI interface" + prompt "HCI mode" default BT_LE_HCI_INTERFACE_USE_RAM config BT_LE_HCI_INTERFACE_USE_RAM - bool "ram" + bool "VHCI" help Use RAM as HCI interface config BT_LE_HCI_INTERFACE_USE_UART - bool "uart" + bool "UART(H4)" help Use UART as HCI interface endchoice + choice BT_LE_UART_HCI_MODE_CHOICE + prompt "UART HCI mode" + depends on BT_LE_HCI_INTERFACE_USE_UART + default BT_LE_UART_HCI_NO_DMA_MODE + help + Specify UART HCI mode: DMA or No DMA + + config BT_LE_UART_HCI_DMA_MODE + bool "UHCI(UART with DMA)(EXPERIMENTAL)" + help + UART HCI Mode with DMA functionality. + + config BT_LE_UART_HCI_NO_DMA_MODE + bool "UART(NO DMA)" + help + UART HCI Mode without DMA functionality. + endchoice + config BT_LE_HCI_UART_PORT int "HCI UART port" depends on BT_LE_HCI_INTERFACE_USE_UART @@ -73,12 +90,40 @@ menu "HCI Config" UART_PARITY_ODD endchoice - config BT_LE_HCI_UART_TASK_STACK_SIZE - int "HCI uart task stack size" - depends on BT_LE_HCI_INTERFACE_USE_UART - default 1000 + config BT_LE_HCI_UART_RX_BUFFER_SIZE + int "The size of rx ring buffer memory" + depends on BT_LE_UART_HCI_NO_DMA_MODE + default 512 + help + The size of rx ring buffer memory + + config BT_LE_HCI_UART_TX_BUFFER_SIZE + int "The size of tx ring buffer memory" + depends on BT_LE_UART_HCI_NO_DMA_MODE + default 256 + help + The size of tx ring buffer memory + + config BT_LE_HCI_TRANS_TASK_STACK_SIZE + int "HCI transport task stack size" + depends on !BT_LE_HCI_INTERFACE_USE_RAM + default 2048 help - Set the size of uart task stack + This configures stack size of hci transport task + + config BT_LE_HCI_TRANS_RX_MEM_NUM + int "The amount of rx memory received at the same time" + depends on BT_LE_UART_HCI_DMA_MODE + default 3 + help + The amount of rx memory received at the same time + + config BT_LE_HCI_LLDESCS_POOL_NUM + int "The amount of lldecs memory for driver dma mode" + depends on BT_LE_UART_HCI_DMA_MODE + default 20 + help + The amount of lldecs memory for driver dma mode endmenu config BT_LE_CONTROLLER_NPL_OS_PORTING_SUPPORT @@ -182,6 +227,19 @@ config BT_LE_POWER_CONTROL_ENABLED help Set this option to enable the Power Control feature on controller +config BT_LE_CTE_FEATURE_ENABLED + bool "Enable Bluetooth LE Direction Finding (AoA/AoD)" + depends on BT_LE_50_FEATURE_SUPPORT && SOC_BLE_CTE_SUPPORTED && !(BT_LE_SECURITY_ENABLE) + default n + help + Enable this option to activate Bluetooth LE Direction Finding (AoA/AoD) feature. + Note: + This feature allows devices to determine the direction of a Bluetooth CTE signal, + enabling Angle of Arrival (AoA) and Angle of Departure (AoD) functionality. + In chip esp32h2, Direction Finding is not supported in encrypted + communication scenarios. If you are using chip esp32h2, ensure that encryption is + disabled when using this feature. + menu "Memory Settings" depends on !BT_NIMBLE_ENABLED @@ -260,54 +318,131 @@ config BT_LE_CONTROLLER_TASK_STACK_SIZE help This configures stack size of NimBLE controller task -menuconfig BT_LE_CONTROLLER_LOG_ENABLED - bool "Controller log enable" - default n - help - Enable controller log +menu "Controller debug features" + menuconfig BT_LE_CONTROLLER_LOG_ENABLED + bool "Controller log enable" + default n + help + Enable controller log -config BT_LE_CONTROLLER_LOG_CTRL_ENABLED - bool "enable controller log module" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default y - help + config BT_LE_CONTROLLER_LOG_CTRL_ENABLED + bool "enable controller log module" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default y + help Enable controller log module -config BT_LE_CONTROLLER_LOG_HCI_ENABLED - bool "enable HCI log module" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default y - help + config BT_LE_CONTROLLER_LOG_HCI_ENABLED + bool "enable HCI log module" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default y + help Enable hci log module -config BT_LE_CONTROLLER_LOG_DUMP_ONLY - bool "Controller log dump mode only" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default y - help + config BT_LE_CONTROLLER_LOG_DUMP_ONLY + bool "Controller log dump mode only" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default y + help Only operate in dump mode -config BT_LE_LOG_CTRL_BUF1_SIZE - int "size of the first BLE controller LOG buffer" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default 4096 - help + config BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + bool "Output ble controller logs to SPI bus (Experimental)" + depends on BT_LE_CONTROLLER_LOG_ENABLED + depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY + select BT_BLE_LOG_SPI_OUT_ENABLED + default n + help + Output ble controller logs to SPI bus + + config BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + bool "Store ble controller logs to flash(Experimental)" + depends on !BT_LE_CONTROLLER_LOG_DUMP_ONLY + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Store ble controller logs to flash memory. + + config BT_LE_CONTROLLER_LOG_PARTITION_SIZE + int "size of ble controller log partition(Multiples of 4K)" + depends on BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + default 65536 + help + The size of ble controller log partition shall be a multiples of 4K. + The name of log partition shall be "bt_ctrl_log". + The partition type shall be ESP_PARTITION_TYPE_DATA. + The partition sub_type shall be ESP_PARTITION_SUBTYPE_ANY. + + config BT_LE_LOG_CTRL_BUF1_SIZE + int "size of the first BLE controller LOG buffer" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default 4096 + help Configure the size of the first BLE controller LOG buffer. -config BT_LE_LOG_CTRL_BUF2_SIZE - int "size of the second BLE controller LOG buffer" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default 1024 - help + config BT_LE_LOG_CTRL_BUF2_SIZE + int "size of the second BLE controller LOG buffer" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default 1024 + help Configure the size of the second BLE controller LOG buffer. -config BT_LE_LOG_HCI_BUF_SIZE - int "size of the BLE HCI LOG buffer" - depends on BT_LE_CONTROLLER_LOG_ENABLED - default 4096 - help + config BT_LE_LOG_HCI_BUF_SIZE + int "size of the BLE HCI LOG buffer" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default 4096 + help Configure the size of the BLE HCI LOG buffer. + config BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE + bool "Enable wrap panic handler" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Wrap esp_panic_handler to get controller logs when PC pointer exception crashes. + + config BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE + bool "Enable esp_task_wdt_isr_user_handler implementation" + depends on BT_LE_CONTROLLER_LOG_ENABLED + default n + help + Implement esp_task_wdt_isr_user_handler to get controller logs when task wdt issue is triggered. + + config BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL + int "The output level of controller log" + depends on BT_LE_CONTROLLER_LOG_ENABLED + range 0 5 + default 1 + help + The output level of controller log. + + config BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH + hex "The switch of module log output" + depends on BT_LE_CONTROLLER_LOG_ENABLED + range 0 0xFFFFFFFF + default 0xFFFFFFFF + help + The switch of module log output, this is an unsigned 32-bit hexadecimal value. + + config BT_LE_ERROR_SIM_ENABLED + bool "Enable controller features for internal testing" + default n + + config BT_LE_ASSERT_WHEN_ABNORMAL_DISCONN_ENABLED + bool "When ACL disconnects abnormally, assertion processing is performed(Experimental)" + default n + + config BT_LE_DEBUG_REMAIN_SCENE_ENABLED + bool "Remain scene with GDB to capture relevant status info(Experimental)" + default n + help + Retain scene with GDB to capture info, requires disabling WDT (CONFIG_ESP_INT_WDT, CONFIG_ESP_TASK_WDT_EN). + + config BT_LE_PTR_CHECK_ENABLED + bool "Enable boundary check for internal memory" + default n +endmenu + config BT_LE_LL_RESOLV_LIST_SIZE int "BLE LL Resolving list size" range 1 5 @@ -363,7 +498,7 @@ config BT_LE_CRYPTO_STACK_MBEDTLS config BT_LE_WHITELIST_SIZE int "BLE white list size" - range 1 15 + range 1 31 default 12 depends on !BT_NIMBLE_ENABLED @@ -384,6 +519,23 @@ config BT_LE_LL_SCA help Sleep clock accuracy of our device (in ppm) +config BT_LE_LL_PEER_SCA_SET_ENABLE + bool "Enable to set constant peer SCA" + default n + help + Enable setting of constant peer SCA, use this if peer device has SCA larger than 500 PPM. + Enable this option, the controller will always use BT_LE_LL_PEER_SCA as the peer SCA value + to calculate the window widening instead of the value received from peer device. + + +config BT_LE_LL_PEER_SCA + int "Constant peer sleep clock accuracy value" + range 0 10000 + depends on BT_LE_LL_PEER_SCA_SET_ENABLE + default 0 + help + Set the sleep clock accuracy of peer device + config BT_LE_MAX_CONNECTIONS int "Maximum number of concurrent connections" depends on !BT_NIMBLE_ENABLED @@ -551,7 +703,7 @@ config BT_LE_SCAN_DUPL_CACHE_REFRESH_PERIOD again. config BT_LE_MSYS_INIT_IN_CONTROLLER - bool + bool "Msys Mbuf Init in Controller" default y config BT_LE_TX_CCA_ENABLED @@ -564,6 +716,137 @@ config BT_LE_CCA_RSSI_THRESH int "CCA RSSI threshold value" depends on BT_LE_TX_CCA_ENABLED range 20 100 - default 20 + default 65 help Power threshold of CCA in unit of -1 dBm. + +choice BT_LE_DFT_TX_POWER_LEVEL_DBM + prompt "BLE default Tx power level(dBm)" + default BT_LE_DFT_TX_POWER_LEVEL_P9 + help + Specify default Tx power level(dBm). + config BT_LE_DFT_TX_POWER_LEVEL_N24 + bool "-24dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N21 + bool "-21dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N18 + bool "-18dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N15 + bool "-15dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N12 + bool "-12dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N9 + bool "-9dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N6 + bool "-6dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N3 + bool "-3dBm" + config BT_LE_DFT_TX_POWER_LEVEL_N0 + bool "0dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P3 + bool "+3dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P6 + bool "+6dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P9 + bool "+9dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P12 + bool "+12dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P15 + bool "+15dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P18 + bool "+18dBm" + config BT_LE_DFT_TX_POWER_LEVEL_P20 + bool "+20dBm" +endchoice + +config BT_LE_DFT_TX_POWER_LEVEL_DBM_EFF + int + default -24 if BT_LE_DFT_TX_POWER_LEVEL_N24 + default -21 if BT_LE_DFT_TX_POWER_LEVEL_N21 + default -18 if BT_LE_DFT_TX_POWER_LEVEL_N18 + default -15 if BT_LE_DFT_TX_POWER_LEVEL_N15 + default -12 if BT_LE_DFT_TX_POWER_LEVEL_N12 + default -9 if BT_LE_DFT_TX_POWER_LEVEL_N9 + default -6 if BT_LE_DFT_TX_POWER_LEVEL_N6 + default -3 if BT_LE_DFT_TX_POWER_LEVEL_N3 + default 0 if BT_LE_DFT_TX_POWER_LEVEL_N0 + default 3 if BT_LE_DFT_TX_POWER_LEVEL_P3 + default 6 if BT_LE_DFT_TX_POWER_LEVEL_P6 + default 9 if BT_LE_DFT_TX_POWER_LEVEL_P9 + default 12 if BT_LE_DFT_TX_POWER_LEVEL_P12 + default 15 if BT_LE_DFT_TX_POWER_LEVEL_P15 + default 18 if BT_LE_DFT_TX_POWER_LEVEL_P18 + default 20 if BT_LE_DFT_TX_POWER_LEVEL_P20 + default 0 + +config BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS + bool "Enable enhanced Access Address check in CONNECT_IND" + default n + help + Enabling this option will add stricter verification of the Access Address in the CONNECT_IND PDU. + This improves security by ensuring that only connection requests with valid Access Addresses are accepted. + If disabled, only basic checks are applied, improving compatibility. + +config BT_CTRL_RUN_IN_FLASH_ONLY + bool "Reduce BLE IRAM usage (READ DOCS FIRST) (EXPERIMENTAL)" + default n + help + Move most IRAM into flash. This will increase the usage of flash and reduce ble performance. + Because the code is moved to the flash, the execution speed of the code is reduced. + To have a small impact on performance, you need to enable flash suspend (SPI_FLASH_AUTO_SUSPEND). + +menu "BLE disconnects when Instant Passed (0x28) occurs" + config BT_LE_CTRL_LLCP_CONN_UPDATE + bool "BLE ACL connection update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs during connection update procedure. + + config BT_LE_CTRL_LLCP_CHAN_MAP_UPDATE + bool "BLE ACL channel map update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs in channel map update procedure. + + config BT_LE_CTRL_LLCP_PHY_UPDATE + bool "BLE ACL PHY update procedure" + default n + help + If this option is enabled, Controller will terminate the connection + when Instant Passed (0x28) error occurs in PHY update procedure. +endmenu + +config BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX + int "The value of upperlimitmax during scan backoff procedure" + range 1 256 + default 32 + help + The value of upperlimitmax needs to be a power of 2. + +config BT_LE_CTRL_CHAN_ASS_EN + bool "Enable channel assessment(Experimental)" + default n + help + If this option is enabled, The Controller will records the communication quality + for each channel and then start a timer to check and update the channel map every 4 seconds. + +config BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX + bool "Enable aux packet when ext adv data length is zero(Experimental)" + default y + help + When this option is enabled, auxiliary packets will be present in the events of + 'Non-Connectable and Non-Scannable' regardless of whether the advertising length is 0. + If this option is not enabled, auxiliary packets will only be present when the advertising length is not 0. + +config BT_LE_RXBUF_OPT_ENABLED + bool "Enable rxbuf optimization feature" + default y + +config BT_LE_CTRL_FAST_CONN_DATA_TX_EN + bool "Enable fast sending of connection data" + default y + help + If this option is enabled, The Controller will continue to + Send an empty PDU after sending valid connection data within an interval. diff --git a/lib/bt/controller/esp32h2/ble.c b/lib/bt/controller/esp32h2/ble.c new file mode 100644 index 00000000..8aef45a9 --- /dev/null +++ b/lib/bt/controller/esp32h2/ble.c @@ -0,0 +1,165 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include "sdkconfig.h" +#include "esp_bt_cfg.h" +#include "esp_bit_defs.h" + +/* External functions or variables + ************************************************************************ + */ +int base_stack_initEnv(void); +void base_stack_deinitEnv(void); +int base_stack_enable(void); +void base_stack_disable(void); + +int conn_stack_initEnv(void); +void conn_stack_deinitEnv(void); +int conn_stack_enable(void); +void conn_stack_disable(void); + +#if CONFIG_BT_LE_ERROR_SIM_ENABLED +int conn_errorSim_initEnv(void); +void conn_errorSim_deinitEnv(void); +int conn_errorSim_enable(void); +void conn_errorSim_disable(void); +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED + +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) +void adv_stack_enableClearLegacyAdvVsCmd(bool en); +void scan_stack_enableAdvFlowCtrlVsCmd(bool en); +void advFilter_stack_enableDupExcListVsCmd(bool en); +void arr_stack_enableMultiConnVsCmd(bool en); +void pcl_stack_enableSetRssiThreshVsCmd(bool en); +void chanSel_stack_enableSetCsaVsCmd(bool en); +void log_stack_enableLogsRelatedVsCmd(bool en); +void hci_stack_enableSetVsEvtMaskVsCmd(bool en); +void winWiden_stack_enableSetConstPeerScaVsCmd(bool en); + +void adv_stack_enableScanReqRxdVsEvent(bool en); +void conn_stack_enableChanMapUpdCompVsEvent(bool en); +void sleep_stack_enableWakeupVsEvent(bool en); +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) +#if CONFIG_BT_LE_RXBUF_OPT_ENABLED +extern void mmgmt_enableRxbufOptFeature(void); +#endif // CONFIG_BT_LE_RXBUF_OPT_ENABLED + +/* Local functions definition + *************************************************************************** + */ +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) +void ble_stack_enableVsCmds(bool en) +{ + adv_stack_enableClearLegacyAdvVsCmd(en); + advFilter_stack_enableDupExcListVsCmd(en); + scan_stack_enableAdvFlowCtrlVsCmd(en); + arr_stack_enableMultiConnVsCmd(en); + pcl_stack_enableSetRssiThreshVsCmd(en); + chanSel_stack_enableSetCsaVsCmd(en); + log_stack_enableLogsRelatedVsCmd(en); + hci_stack_enableSetVsEvtMaskVsCmd(en); + winWiden_stack_enableSetConstPeerScaVsCmd(en); +} + +void ble_stack_enableVsEvents(bool en) +{ + adv_stack_enableScanReqRxdVsEvent(en); + conn_stack_enableChanMapUpdCompVsEvent(en); + +#if CONFIG_BT_LE_SLEEP_ENABLE + sleep_stack_enableWakeupVsEvent(en); +#endif // CONFIG_BT_LE_SLEEP_ENABLE +} +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + +int ble_stack_initEnv(void) +{ + int rc; + + rc = base_stack_initEnv(); + if (rc) { + return rc; + } + +#if DEFAULT_BT_LE_MAX_CONNECTIONS + rc = conn_stack_initEnv(); + if (rc) { + return rc; + } +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + rc = conn_errorSim_initEnv(); + if (rc) { + return rc; + } +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + + return 0; +} + +void ble_stack_deinitEnv(void) +{ +#if DEFAULT_BT_LE_MAX_CONNECTIONS +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_errorSim_deinitEnv(); +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_stack_deinitEnv(); +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + + base_stack_deinitEnv(); +} + +int ble_stack_enable(void) +{ + int rc; + + rc = base_stack_enable(); + if (rc) { + return rc; + } + +#if DEFAULT_BT_LE_MAX_CONNECTIONS + rc = conn_stack_enable(); + if (rc) { + return rc; + } +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + rc = conn_errorSim_enable(); + if (rc) { + return rc; + } +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + ble_stack_enableVsCmds(true); + ble_stack_enableVsEvents(true); +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + +#if CONFIG_BT_LE_RXBUF_OPT_ENABLED + mmgmt_enableRxbufOptFeature(); +#endif // CONFIG_BT_LE_RXBUF_OPT_ENABLED + + return 0; +} + +void ble_stack_disable(void) +{ +#if (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + ble_stack_enableVsEvents(false); + ble_stack_enableVsCmds(false); +#endif // (CONFIG_BT_NIMBLE_ENABLED || CONFIG_BT_BLUEDROID_ENABLED) + +#if DEFAULT_BT_LE_MAX_CONNECTIONS +#if CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_errorSim_disable(); +#endif // CONFIG_BT_LE_ERROR_SIM_ENABLED + conn_stack_disable(); +#endif // DEFAULT_BT_LE_MAX_CONNECTIONS + + base_stack_disable(); +} diff --git a/lib/bt/controller/esp32h2/ble_priv.h b/lib/bt/controller/esp32h2/ble_priv.h new file mode 100644 index 00000000..82dc4d16 --- /dev/null +++ b/lib/bt/controller/esp32h2/ble_priv.h @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +int ble_stack_initEnv(void); + +void ble_stack_deinitEnv(void); + +int ble_stack_enable(void); + +void ble_stack_disable(void); diff --git a/lib/bt/controller/esp32h2/bt.c b/lib/bt/controller/esp32h2/bt.c index adb10d49..2c564b91 100644 --- a/lib/bt/controller/esp32h2/bt.c +++ b/lib/bt/controller/esp32h2/bt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,16 +30,16 @@ #endif // CONFIG_ESP_COEX_ENABLED #include "nimble/nimble_npl_os.h" -#include "ble_hci_trans.h" +#include "esp_hci_transport.h" #include "os/endian.h" #include "esp_bt.h" +#include "ble_priv.h" #include "esp_intr_alloc.h" #include "esp_sleep.h" #include "esp_pm.h" #include "esp_phy_init.h" #include "esp_private/periph_ctrl.h" -#include "hci_uart.h" #include "bt_osi_mem.h" #if CONFIG_FREERTOS_USE_TICKLESS_IDLE @@ -47,16 +47,18 @@ #include "esp_private/sleep_retention.h" #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE -#ifdef CONFIG_BT_BLUEDROID_ENABLED -#include "hci/hci_hal.h" -#endif // CONFIG_BT_BLUEDROID_ENABLED - #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_private/periph_ctrl.h" +#include "esp_private/esp_clk_tree_common.h" #include "esp_sleep.h" #include "soc/rtc.h" + +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED +#include "ble_log/ble_log_spi_out.h" +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + /* Macro definition ************************************************************************ */ @@ -64,16 +66,11 @@ #define OSI_COEX_VERSION 0x00010006 #define OSI_COEX_MAGIC_VALUE 0xFADEBEAD -#define EXT_FUNC_VERSION 0x20221122 +#define EXT_FUNC_VERSION 0x20250415 #define EXT_FUNC_MAGIC_VALUE 0xA5A5A5A5 #define BT_ASSERT_PRINT ets_printf -#ifdef CONFIG_BT_BLUEDROID_ENABLED -/* ACL_DATA_MBUF_LEADINGSPCAE: The leadingspace in user info header for ACL data */ -#define ACL_DATA_MBUF_LEADINGSPCAE 4 -#endif // CONFIG_BT_BLUEDROID_ENABLED - /* Types definition ************************************************************************ */ @@ -92,12 +89,6 @@ struct ext_funcs_t { int (*_esp_intr_free)(void **ret_handle); void *(* _malloc)(size_t size); void (*_free)(void *p); - void (*_hal_uart_start_tx)(int); - int (*_hal_uart_init_cbs)(int, hci_uart_tx_char, hci_uart_tx_done, hci_uart_rx_char, void *); - int (*_hal_uart_config)(int, int32_t, uint8_t, uint8_t, uart_parity_t, uart_hw_flowcontrol_t); - int (*_hal_uart_close)(int); - void (*_hal_uart_blocking_tx)(int, uint8_t); - int (*_hal_uart_init)(int, void *); int (* _task_create)(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id); void (* _task_delete)(void *task_handle); @@ -106,24 +97,33 @@ struct ext_funcs_t { int (* _ecc_gen_key_pair)(uint8_t *public, uint8_t *priv); int (* _ecc_gen_dh_key)(const uint8_t *remote_pub_key_x, const uint8_t *remote_pub_key_y, const uint8_t *local_priv_key, uint8_t *dhkey); - void (* _esp_reset_rpa_moudle)(void); uint32_t magic; }; #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -typedef void (*interface_func_t) (uint32_t len, const uint8_t*addr, bool end); +typedef void (*interface_func_t) (uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); + +enum { + BLE_LOG_INTERFACE_FLAG_CONTINUE = 0, + BLE_LOG_INTERFACE_FLAG_END, +}; #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* External functions or variables ************************************************************************ */ extern int ble_osi_coex_funcs_register(struct osi_coex_funcs_t *coex_funcs); extern int r_ble_controller_init(esp_bt_controller_config_t *cfg); +extern void esp_ble_controller_info_capture(uint32_t cycle_times); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -extern int r_ble_log_init_async(interface_func_t bt_controller_log_interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); +extern int r_ble_log_init_async(interface_func_t interface, bool task_create, uint8_t buffers, uint32_t *bufs_size); extern int r_ble_log_deinit_async(void); +extern int r_ble_log_init_simple(interface_func_t interface, void *handler); +extern void r_ble_log_deinit_simple(void); extern void r_ble_log_async_select_dump_buffers(uint8_t buffers); extern void r_ble_log_async_output_dump_all(bool output); -extern void esp_panic_handler_reconfigure_wdts(uint32_t timeout_ms); +extern void esp_panic_handler_feed_wdts(void); +extern int r_ble_log_ctrl_level_and_mod(uint8_t log_level, uint32_t mod_switch); +extern int r_ble_ctrl_mod_type(uint16_t mod, uint32_t mod_type_switch); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED extern int r_ble_controller_deinit(void); extern int r_ble_controller_enable(uint8_t mode); @@ -141,11 +141,20 @@ extern void r_ble_lll_rfmgmt_set_sleep_cb(void *s_cb, void *w_cb, void *s_arg, extern void r_ble_rtc_wake_up_state_clr(void); extern int os_msys_init(void); extern void os_msys_deinit(void); +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY +extern void r_ble_ll_scan_start_time_init_compensation(uint32_t init_compensation); +extern void r_priv_sdk_config_insert_proc_time_set(uint16_t insert_proc_time); +#endif // CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY #if CONFIG_FREERTOS_USE_TICKLESS_IDLE -extern const sleep_retention_entries_config_t *esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra); +extern sleep_retention_entries_config_t *r_esp_ble_mac_retention_link_get(uint8_t *size, uint8_t extra); extern void r_esp_ble_set_wakeup_overhead(uint32_t overhead); #endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ -extern void r_esp_ble_change_rtc_freq(uint32_t freq); +#if CONFIG_PM_ENABLE +extern void r_esp_ble_stop_wakeup_timing(void); +#endif // CONFIG_PM_ENABLE +#if CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE +extern void r_ble_ll_customize_peer_sca_set(uint16_t peer_sca); +#endif // CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE extern int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y, const uint8_t *our_priv_key, uint8_t *out_dhkey); @@ -173,27 +182,21 @@ static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status); static int task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id); static void task_delete_wrapper(void *task_handle); -#if CONFIG_BT_LE_HCI_INTERFACE_USE_UART -static void hci_uart_start_tx_wrapper(int uart_no); -static int hci_uart_init_cbs_wrapper(int uart_no, hci_uart_tx_char tx_func, - hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg); -static int hci_uart_config_wrapper(int uart_no, int32_t speed, uint8_t databits, uint8_t stopbits, - uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl); -static int hci_uart_close_wrapper(int uart_no); -static void hci_uart_blocking_tx_wrapper(int port, uint8_t data); -static int hci_uart_init_wrapper(int uart_no, void *cfg); -#endif // CONFIG_BT_LE_HCI_INTERFACE_USE_UART static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, void *arg, void **ret_handle_in); static int esp_intr_free_wrapper(void **ret_handle); static void osi_assert_wrapper(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2); static uint32_t osi_random_wrapper(void); -static void esp_reset_rpa_moudle(void); static int esp_ecc_gen_key_pair(uint8_t *pub, uint8_t *priv); static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_y, const uint8_t *our_priv_key, uint8_t *out_dhkey); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end); +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag); +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* Local variable definition *************************************************************************** @@ -203,14 +206,238 @@ static DRAM_ATTR esp_bt_controller_status_t ble_controller_status = ESP_BT_CONTR #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED const static uint32_t log_bufs_size[] = {CONFIG_BT_LE_LOG_CTRL_BUF1_SIZE, CONFIG_BT_LE_LOG_HCI_BUF_SIZE, CONFIG_BT_LE_LOG_CTRL_BUF2_SIZE}; +static bool log_is_inited = false; + +esp_err_t esp_bt_controller_log_init(void) +{ + if (log_is_inited) { + return ESP_OK; + } + +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + if (ble_log_spi_out_init() != 0) { + goto spi_out_init_failed; + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + if (r_ble_log_init_simple(ble_log_spi_out_ll_write, ble_log_spi_out_ll_log_ev_proc) != 0) { + goto log_init_failed; + } +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + uint8_t buffers = 0; +#if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED + buffers |= ESP_BLE_LOG_BUF_CONTROLLER; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED + buffers |= ESP_BLE_LOG_BUF_HCI; +#endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED + + bool task_create = true; +#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY + task_create = false; +#elif CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_ctrl_log_partition_get_and_erase_first_block(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + + if (r_ble_log_init_async(esp_bt_controller_log_interface, task_create, buffers, (uint32_t *)log_bufs_size) != 0) { + goto log_init_failed; + } +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + + if (r_ble_log_ctrl_level_and_mod(CONFIG_BT_LE_CONTROLLER_LOG_OUTPUT_LEVEL, CONFIG_BT_LE_CONTROLLER_LOG_MOD_OUTPUT_SWITCH) != ESP_OK) { + goto ctrl_level_init_failed; + } + log_is_inited = true; + return ESP_OK; + +ctrl_level_init_failed: +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_simple(); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_async(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +log_init_failed: +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +spi_out_init_failed: +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + return ESP_FAIL; +} + +void esp_bt_controller_log_deinit(void) +{ +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + +#if CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_simple(); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + r_ble_log_deinit_async(); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + + log_is_inited = false; +} + +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE +#include "esp_partition.h" +#include "hal/wdt_hal.h" + +#define MAX_STORAGE_SIZE (CONFIG_BT_LE_CONTROLLER_LOG_PARTITION_SIZE) +#define BLOCK_SIZE (4096) +#define THRESHOLD (3072) +#define PARTITION_NAME "bt_ctrl_log" + +static const esp_partition_t *log_partition; +static uint32_t write_index = 0; +static uint32_t next_erase_index = BLOCK_SIZE; +static bool block_erased = false; +static bool stop_write = false; +static bool is_filled = false; + +static void esp_bt_ctrl_log_partition_get_and_erase_first_block(void) +{ + log_partition = NULL; + assert(MAX_STORAGE_SIZE % BLOCK_SIZE == 0); + // Find the partition map in the partition table + log_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, PARTITION_NAME); + assert(log_partition != NULL); + // Prepare data to be read later using the mapped address + ESP_ERROR_CHECK(esp_partition_erase_range(log_partition, 0, BLOCK_SIZE)); + write_index = 0; + next_erase_index = BLOCK_SIZE; + block_erased = false; + is_filled = false; + stop_write = false; +} + +static int esp_bt_controller_log_storage(uint32_t len, const uint8_t *addr, bool end) +{ + if (len > MAX_STORAGE_SIZE) { + return -1; + } + + if (stop_write) { + return 0; + } + + if (((write_index) % BLOCK_SIZE) >= THRESHOLD && !block_erased) { + // esp_rom_printf("Ers nxt: %d,%d\n", next_erase_index, write_index); + esp_partition_erase_range(log_partition, next_erase_index, BLOCK_SIZE); + next_erase_index = (next_erase_index + BLOCK_SIZE) % MAX_STORAGE_SIZE; + block_erased = true; + } + + if (((write_index + len) / BLOCK_SIZE) > (write_index / BLOCK_SIZE)) { + block_erased = false; + } + + if (write_index + len <= MAX_STORAGE_SIZE) { + esp_partition_write(log_partition, write_index, addr, len); + write_index = (write_index + len) % MAX_STORAGE_SIZE; + } else { + uint32_t first_part_len = MAX_STORAGE_SIZE - write_index; + esp_partition_write(log_partition, write_index, addr, first_part_len); + esp_partition_write(log_partition, 0, addr + first_part_len, len - first_part_len); + write_index = len - first_part_len; + is_filled = true; + // esp_rom_printf("old idx: %d,%d\n",next_erase_index, write_index); + } + + return 0; +} + +void esp_bt_read_ctrl_log_from_flash(bool output) +{ + esp_partition_mmap_handle_t mmap_handle; + uint32_t read_index; + const void *mapped_ptr; + const uint8_t *buffer; + uint32_t print_len; + uint32_t max_print_len; + esp_err_t err; + + print_len = 0; + max_print_len = 4096; + err = esp_partition_mmap(log_partition, 0, MAX_STORAGE_SIZE, ESP_PARTITION_MMAP_DATA, &mapped_ptr, &mmap_handle); + if (err != ESP_OK) { + ESP_LOGE("FLASH", "Mmap failed: %s", esp_err_to_name(err)); + return; + } + + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + r_ble_log_async_output_dump_all(true); + esp_bt_controller_log_deinit(); + stop_write = true; + + buffer = (const uint8_t *)mapped_ptr; + esp_panic_handler_feed_wdts(); + if (is_filled) { + read_index = next_erase_index; + } else { + read_index = 0; + } + + esp_rom_printf("\r\nREAD_CHECK:%ld,%ld,%d\r\n",read_index, write_index, is_filled); + esp_rom_printf("\r\n[DUMP_START:"); + while (read_index != write_index) { + esp_rom_printf("%02x ", buffer[read_index]); + if (print_len > max_print_len) { + esp_panic_handler_feed_wdts(); + print_len = 0; + } + + print_len++; + read_index = (read_index + 1) % MAX_STORAGE_SIZE; + } + + esp_rom_printf(":DUMP_END]\r\n"); + portEXIT_CRITICAL_SAFE(&spinlock); + esp_partition_munmap(mmap_handle); + err = esp_bt_controller_log_init(); + assert(err == ESP_OK); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + +#if CONFIG_BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE +void esp_task_wdt_isr_user_handler(void) +{ + esp_ble_controller_log_dump_all(true); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_TASK_WDT_USER_HANDLER_ENABLE + +#if CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE +void __real_esp_panic_handler(void *info); +void __wrap_esp_panic_handler (void *info) +{ + esp_ble_controller_log_dump_all(true); + __real_esp_panic_handler(info); +} +#endif // CONFIG_BT_LE_CONTROLLER_LOG_WRAP_PANIC_HANDLER_ENABLE #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED /* This variable tells if BLE is running */ static bool s_ble_active = false; #ifdef CONFIG_PM_ENABLE static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock = NULL; -#define BTDM_MIN_TIMER_UNCERTAINTY_US (200) #endif // CONFIG_PM_ENABLE +#define MAIN_XTAL_FREQ_HZ (32000000) +static DRAM_ATTR modem_clock_lpclk_src_t s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_INVALID; +static DRAM_ATTR uint32_t s_bt_lpclk_freq = 100000; + +#define BLE_CONTROLLER_MALLOC_CAPS (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT|MALLOC_CAP_DMA) +void *malloc_ble_controller_mem(size_t size) +{ + return heap_caps_malloc(size, BLE_CONTROLLER_MALLOC_CAPS); +} + +uint32_t get_ble_controller_free_heap_size(void) +{ + return heap_caps_get_free_size(BLE_CONTROLLER_MALLOC_CAPS); +} #define BLE_RTC_DELAY_US_LIGHT_SLEEP (5100) #define BLE_RTC_DELAY_US_MODEM_SLEEP (1500) @@ -230,29 +457,15 @@ struct ext_funcs_t ext_funcs_ro = { ._esp_intr_free = esp_intr_free_wrapper, ._malloc = bt_osi_mem_malloc_internal, ._free = bt_osi_mem_free, -#if CONFIG_BT_LE_HCI_INTERFACE_USE_UART - ._hal_uart_start_tx = hci_uart_start_tx_wrapper, - ._hal_uart_init_cbs = hci_uart_init_cbs_wrapper, - ._hal_uart_config = hci_uart_config_wrapper, - ._hal_uart_close = hci_uart_close_wrapper, - ._hal_uart_blocking_tx = hci_uart_blocking_tx_wrapper, - ._hal_uart_init = hci_uart_init_wrapper, -#endif //CONFIG_BT_LE_HCI_INTERFACE_USE_UART ._task_create = task_create_wrapper, ._task_delete = task_delete_wrapper, ._osi_assert = osi_assert_wrapper, ._os_random = osi_random_wrapper, ._ecc_gen_key_pair = esp_ecc_gen_key_pair, ._ecc_gen_dh_key = esp_ecc_gen_dh_key, - ._esp_reset_rpa_moudle = esp_reset_rpa_moudle, .magic = EXT_FUNC_MAGIC_VALUE, }; -static void IRAM_ATTR esp_reset_rpa_moudle(void) -{ - -} - static void IRAM_ATTR osi_assert_wrapper(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2) { @@ -282,75 +495,6 @@ static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status) #endif // CONFIG_SW_COEXIST_ENABLE } -#ifdef CONFIG_BT_BLUEDROID_ENABLED -bool esp_vhci_host_check_send_available(void) -{ - if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { - return false; - } - return true; -} - -static struct os_mbuf *ble_hs_mbuf_gen_pkt(uint16_t leading_space) -{ - struct os_mbuf *om; - int rc; - - om = os_msys_get_pkthdr(0, 0); - if (om == NULL) { - return NULL; - } - - if (om->om_omp->omp_databuf_len < leading_space) { - rc = os_mbuf_free_chain(om); - assert(rc == 0); - return NULL; - } - - om->om_data += leading_space; - - return om; -} - -struct os_mbuf *ble_hs_mbuf_acl_pkt(void) -{ - return ble_hs_mbuf_gen_pkt(4 + 1); -} - -void esp_vhci_host_send_packet(uint8_t *data, uint16_t len) -{ - if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { - return; - } - - if (*(data) == DATA_TYPE_COMMAND) { - struct ble_hci_cmd *cmd = NULL; - cmd = (struct ble_hci_cmd *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD); - assert(cmd); - memcpy((uint8_t *)cmd, data + 1, len - 1); - ble_hci_trans_hs_cmd_tx((uint8_t *)cmd); - } - - if (*(data) == DATA_TYPE_ACL) { - struct os_mbuf *om = os_msys_get_pkthdr(len, ACL_DATA_MBUF_LEADINGSPCAE); - assert(om); - assert(os_mbuf_append(om, &data[1], len - 1) == 0); - ble_hci_trans_hs_acl_tx(om); - } -} - -esp_err_t esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback) -{ - if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { - return ESP_FAIL; - } - - ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL); - - return ESP_OK; -} -#endif // CONFIG_BT_BLUEDROID_ENABLED - static int task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id) { @@ -382,61 +526,14 @@ static int esp_ecc_gen_dh_key(const uint8_t *peer_pub_key_x, const uint8_t *peer return rc; } -#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART -static void hci_uart_start_tx_wrapper(int uart_no) -{ - hci_uart_start_tx(uart_no); -} - -static int hci_uart_init_cbs_wrapper(int uart_no, hci_uart_tx_char tx_func, - hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg) -{ - int rc = -1; - rc = hci_uart_init_cbs(uart_no, tx_func, tx_done, rx_func, arg); - return rc; -} - - -static int hci_uart_config_wrapper(int port_num, int32_t baud_rate, uint8_t data_bits, - uint8_t stop_bits, uart_parity_t parity, - uart_hw_flowcontrol_t flow_ctl) -{ - int rc = -1; - rc = hci_uart_config(port_num, baud_rate, data_bits, stop_bits, parity, flow_ctl); - return rc; -} - -static int hci_uart_close_wrapper(int uart_no) -{ - int rc = -1; - rc = hci_uart_close(uart_no); - return rc; -} - -static void hci_uart_blocking_tx_wrapper(int port, uint8_t data) -{ - //This function is nowhere to use. -} - -static int hci_uart_init_wrapper(int uart_no, void *cfg) -{ - //This function is nowhere to use. - return 0; -} - -#endif //CONFIG_BT_LE_HCI_INTERFACE_USE_UART - -static int ble_hci_unregistered_hook(void*, void*) -{ - ESP_LOGD(NIMBLE_PORT_LOG_TAG,"%s ble hci rx_evt is not registered.",__func__); - return 0; -} - static int esp_intr_alloc_wrapper(int source, int flags, intr_handler_t handler, void *arg, void **ret_handle_in) { - int rc = esp_intr_alloc(source, flags | ESP_INTR_FLAG_IRAM, handler, - arg, (intr_handle_t *)ret_handle_in); +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + int rc = esp_intr_alloc(source, flags, handler, arg, (intr_handle_t *)ret_handle_in); +#else + int rc = esp_intr_alloc(source, flags | ESP_INTR_FLAG_IRAM, handler, arg, (intr_handle_t *)ret_handle_in); +#endif return rc; } @@ -454,10 +551,10 @@ void esp_bt_rtc_slow_clk_select(uint8_t slow_clk_src) switch (slow_clk_src) { case MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL: ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using main XTAL as clock source"); - modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (320 - 1)); + modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (MAIN_XTAL_FREQ_HZ/s_bt_lpclk_freq - 1)); break; case MODEM_CLOCK_LPCLK_SRC_RC_SLOW: - ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Using 136 kHz RC as clock source, can only run legacy ADV or SCAN due to low clock accuracy!"); + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Using 136 kHz RC as clock source, use with caution as it may not maintain ACL or Sync process due to low clock accuracy!"); modem_clock_select_lp_clock_source(PERIPH_BT_MODULE, slow_clk_src, (5 - 1)); break; case MODEM_CLOCK_LPCLK_SRC_XTAL32K: @@ -476,6 +573,46 @@ void esp_bt_rtc_slow_clk_select(uint8_t slow_clk_src) } } +modem_clock_lpclk_src_t esp_bt_get_lpclk_src(void) +{ + return s_bt_lpclk_src; +} + +void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src) +{ + if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { + return; + } + + if (clk_src >= MODEM_CLOCK_LPCLK_SRC_MAX) { + return; + } + + s_bt_lpclk_src = clk_src; +} + +uint32_t esp_bt_get_lpclk_freq(void) +{ + return s_bt_lpclk_freq; +} + +void esp_bt_set_lpclk_freq(uint32_t clk_freq) +{ + if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { + return; + } + + if (!clk_freq) { + return; + } + + if (MAIN_XTAL_FREQ_HZ % clk_freq) { + return; + } + + s_bt_lpclk_freq = clk_freq; +} + IRAM_ATTR void controller_sleep_cb(uint32_t enable_tick, void *arg) { if (!s_ble_active) { @@ -497,10 +634,17 @@ IRAM_ATTR void controller_wakeup_cb(void *arg) return; } #ifdef CONFIG_PM_ENABLE + esp_pm_config_t pm_config; esp_pm_lock_acquire(s_pm_lock); + esp_pm_get_configuration(&pm_config); + assert(esp_rom_get_cpu_ticks_per_us() == pm_config.max_freq_mhz); r_ble_rtc_wake_up_state_clr(); #endif //CONFIG_PM_ENABLE esp_phy_enable(PHY_MODEM_BT); + if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW) { + uint32_t *clk_freq = (uint32_t *)arg; + *clk_freq = esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED) / 5; + } s_ble_active = true; } @@ -509,7 +653,7 @@ static esp_err_t sleep_modem_ble_mac_retention_init(void *arg) { uint8_t size; int extra = *(int *)arg; - const sleep_retention_entries_config_t *ble_mac_modem_config = esp_ble_mac_retention_link_get(&size, extra); + sleep_retention_entries_config_t *ble_mac_modem_config = r_esp_ble_mac_retention_link_get(&size, extra); esp_err_t err = sleep_retention_entries_create(ble_mac_modem_config, size, REGDMA_LINK_PRI_BT_MAC_BB, SLEEP_RETENTION_MODULE_BLE_MAC); if (err == ESP_OK) { ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Modem BLE MAC retention initialization"); @@ -522,7 +666,7 @@ static esp_err_t sleep_modem_ble_mac_modem_state_init(uint8_t extra) int retention_args = extra; sleep_retention_module_init_param_t init_param = { .cbs = { .create = { .handle = sleep_modem_ble_mac_retention_init, .arg = &retention_args } }, - .depends = BIT(SLEEP_RETENTION_MODULE_BT_BB) + .depends = RETENTION_MODULE_BITMAP_INIT(BT_BB) }; esp_err_t err = sleep_retention_module_init(SLEEP_RETENTION_MODULE_BLE_MAC, &init_param); if (err == ESP_OK) { @@ -540,7 +684,7 @@ static void sleep_modem_ble_mac_modem_state_deinit(void) } } -void sleep_modem_light_sleep_overhead_set(uint32_t overhead) +void IRAM_ATTR sleep_modem_light_sleep_overhead_set(uint32_t overhead) { r_esp_ble_set_wakeup_overhead(overhead); } @@ -567,10 +711,17 @@ esp_err_t controller_sleep_init(void) if (rc != ESP_OK) { goto error; } -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE + rc = esp_deep_sleep_register_hook(&r_esp_ble_stop_wakeup_timing); + if (rc != ESP_OK) { + goto error; + } +#endif //CONFIG_PM_ENABLE +#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE /* Create a new regdma link for BLE related register restoration */ rc = sleep_modem_ble_mac_modem_state_init(0); - assert(rc == 0); + if (rc != ESP_OK) { + goto error; + } esp_sleep_enable_bt_wakeup(); ESP_LOGW(NIMBLE_PORT_LOG_TAG, "Enable light sleep, the wake up source is BLE timer"); @@ -578,15 +729,18 @@ esp_err_t controller_sleep_init(void) if (rc != ESP_OK) { goto error; } -#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ return rc; +#ifdef CONFIG_PM_ENABLE error: - -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#endif // CONFIG_PM_ENABLE +#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE esp_sleep_disable_bt_wakeup(); esp_pm_unregister_inform_out_light_sleep_overhead_callback(sleep_modem_light_sleep_overhead_set); -#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#ifdef CONFIG_PM_ENABLE + esp_deep_sleep_deregister_hook(&r_esp_ble_stop_wakeup_timing); /*lock should release first and then delete*/ if (s_pm_lock != NULL) { esp_pm_lock_delete(s_pm_lock); @@ -599,13 +753,14 @@ error: void controller_sleep_deinit(void) { -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE +#if CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE r_ble_rtc_wake_up_state_clr(); esp_sleep_disable_bt_wakeup(); sleep_modem_ble_mac_modem_state_deinit(); esp_pm_unregister_inform_out_light_sleep_overhead_callback(sleep_modem_light_sleep_overhead_set); -#endif /* CONFIG_FREERTOS_USE_TICKLESS_IDLE */ +#endif /* CONFIG_BT_LE_SLEEP_ENABLE && CONFIG_FREERTOS_USE_TICKLESS_IDLE */ #ifdef CONFIG_PM_ENABLE + esp_deep_sleep_deregister_hook(&r_esp_ble_stop_wakeup_timing); /* lock should be released first */ esp_pm_lock_delete(s_pm_lock); s_pm_lock = NULL; @@ -683,12 +838,53 @@ void ble_controller_scan_duplicate_config(void) ble_vhci_disc_duplicate_set_max_cache_size(cache_size); } +static void ble_rtc_clk_init(esp_bt_controller_config_t *cfg) +{ + if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_INVALID) { +#if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL; +#else +#if CONFIG_RTC_CLK_SRC_INT_RC + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_RC_SLOW; +#elif CONFIG_RTC_CLK_SRC_EXT_CRYS + if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_XTAL32K; + } else { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock"); + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL; + } +#elif CONFIG_RTC_CLK_SRC_INT_RC32K + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_RC32K; +#elif CONFIG_RTC_CLK_SRC_EXT_OSC + s_bt_lpclk_src = MODEM_CLOCK_LPCLK_SRC_EXT32K; +#else + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "Unsupported clock source"); + assert(0); +#endif +#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */ + } + + if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) { + cfg->rtc_freq = s_bt_lpclk_freq; + } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) { + cfg->rtc_freq = 32768; + } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW) { + cfg->rtc_freq = esp_clk_tree_lp_slow_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED) / 5; + cfg->ble_ll_sca = 3000; + } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_RC32K) { + cfg->rtc_freq = 32000; + } else if (s_bt_lpclk_src == MODEM_CLOCK_LPCLK_SRC_EXT32K) { + cfg->rtc_freq = 32000; + } + esp_bt_rtc_slow_clk_select(s_bt_lpclk_src); +} + esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) { uint8_t mac[6]; esp_err_t ret = ESP_OK; ble_npl_count_info_t npl_info; - uint32_t slow_clk_freq = 0; + uint8_t hci_transport_mode; memset(&npl_info, 0, sizeof(ble_npl_count_info_t)); if (ble_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { @@ -739,33 +935,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) modem_clock_module_enable(PERIPH_BT_MODULE); modem_clock_module_mac_reset(PERIPH_BT_MODULE); /* Select slow clock source for BT momdule */ -#if CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL); - slow_clk_freq = 100000; -#else -#if CONFIG_RTC_CLK_SRC_INT_RC - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_RC_SLOW); - slow_clk_freq = 30000; -#elif CONFIG_RTC_CLK_SRC_EXT_CRYS - if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_XTAL32K); - slow_clk_freq = 32768; - } else { - ESP_LOGW(NIMBLE_PORT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock"); - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL); - slow_clk_freq = 100000; - } -#elif CONFIG_RTC_CLK_SRC_INT_RC32K - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_RC32K); - slow_clk_freq = 32000; -#elif CONFIG_RTC_CLK_SRC_EXT_OSC - esp_bt_rtc_slow_clk_select(MODEM_CLOCK_LPCLK_SRC_EXT32K); - slow_clk_freq = 32000; -#else - ESP_LOGE(NIMBLE_PORT_LOG_TAG, "Unsupported clock source"); - assert(0); -#endif -#endif /* CONFIG_BT_LE_LP_CLK_SRC_MAIN_XTAL */ + ble_rtc_clk_init(cfg); if (ble_osi_coex_funcs_register((struct osi_coex_funcs_t *)&s_osi_coex_funcs_ro) != 0) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "osi coex funcs reg failed"); @@ -778,20 +948,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) #endif // CONFIG_SW_COEXIST_ENABLE #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - interface_func_t bt_controller_log_interface; - bt_controller_log_interface = esp_bt_controller_log_interface; - uint8_t buffers = 0; -#if CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED - buffers |= ESP_BLE_LOG_BUF_CONTROLLER; -#endif // CONFIG_BT_LE_CONTROLLER_LOG_CTRL_ENABLED -#if CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED - buffers |= ESP_BLE_LOG_BUF_HCI; -#endif // CONFIG_BT_LE_CONTROLLER_LOG_HCI_ENABLED -#if CONFIG_BT_LE_CONTROLLER_LOG_DUMP_ONLY - ret = r_ble_log_init_async(bt_controller_log_interface, false, buffers, (uint32_t *)log_bufs_size); -#else - ret = r_ble_log_init_async(bt_controller_log_interface, true, buffers, (uint32_t *)log_bufs_size); -#endif // CONFIG_BT_CONTROLLER_LOG_DUMP + ret = esp_bt_controller_log_init(); if (ret != ESP_OK) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_controller_log_init failed %d", ret); goto modem_deint; @@ -803,14 +960,23 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) goto modem_deint; } + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "ble controller commit:[%s]", ble_controller_get_compile_version()); + ret = r_ble_controller_init(cfg); if (ret != ESP_OK) { ESP_LOGW(NIMBLE_PORT_LOG_TAG, "r_ble_controller_init failed %d", ret); goto modem_deint; } - ESP_LOGI(NIMBLE_PORT_LOG_TAG, "ble controller commit:[%s]", ble_controller_get_compile_version()); - r_esp_ble_change_rtc_freq(slow_clk_freq); +#if CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE + r_ble_ll_customize_peer_sca_set(CONFIG_BT_LE_LL_PEER_SCA); +#endif // CONFIG_BT_LE_LL_PEER_SCA_SET_ENABLE + + ret = ble_stack_initEnv(); + if (ret != ESP_OK) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "ble_stack_initEnv failed %d", ret); + goto free_controller; + } ble_controller_scan_duplicate_config(); @@ -825,24 +991,40 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) ESP_LOGW(NIMBLE_PORT_LOG_TAG, "controller_sleep_init failed %d", ret); goto free_controller; } + ESP_ERROR_CHECK(esp_read_mac((uint8_t *)mac, ESP_MAC_BT)); + ESP_LOGI(NIMBLE_PORT_LOG_TAG, "Bluetooth MAC: %02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); swap_in_place(mac, 6); r_esp_ble_ll_set_public_addr(mac); ble_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; - ble_hci_trans_cfg_hs((ble_hci_trans_rx_cmd_fn *)ble_hci_unregistered_hook,NULL, - (ble_hci_trans_rx_acl_fn *)ble_hci_unregistered_hook,NULL); - return ESP_OK; +#if CONFIG_BT_LE_HCI_INTERFACE_USE_RAM + hci_transport_mode = HCI_TRANSPORT_VHCI; +#elif CONFIG_BT_LE_HCI_INTERFACE_USE_UART + hci_transport_mode = HCI_TRANSPORT_UART_NO_DMA; +#if CONFIG_BT_LE_UART_HCI_DMA_MODE + hci_transport_mode = HCI_TRANSPORT_UART_UHCI; +#endif // CONFIG_BT_LE_UART_HCI_DMA_MODE +#endif // CONFIG_BT_LE_HCI_INTERFACE_USE_RAM + ret = hci_transport_init(hci_transport_mode); + if (ret) { + ESP_LOGW(NIMBLE_PORT_LOG_TAG, "hci transport init failed %d", ret); + goto free_controller; + } + return ESP_OK; free_controller: + hci_transport_deinit(); controller_sleep_deinit(); os_msys_deinit(); + ble_stack_deinitEnv(); r_ble_controller_deinit(); modem_deint: esp_ble_unregister_bb_funcs(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - r_ble_log_deinit_async(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); modem_clock_module_disable(PERIPH_BT_MODULE); @@ -865,6 +1047,7 @@ esp_err_t esp_bt_controller_deinit(void) return ESP_FAIL; } + hci_transport_deinit(); controller_sleep_deinit(); os_msys_deinit(); @@ -872,10 +1055,11 @@ esp_err_t esp_bt_controller_deinit(void) modem_clock_deselect_lp_clock_source(PERIPH_BT_MODULE); modem_clock_module_disable(PERIPH_BT_MODULE); + ble_stack_deinitEnv(); r_ble_controller_deinit(); esp_ble_unregister_bb_funcs(); #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED - r_ble_log_deinit_async(); + esp_bt_controller_log_deinit(); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED #if CONFIG_BT_NIMBLE_ENABLED @@ -921,6 +1105,16 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) coex_enable(); #endif // CONFIG_SW_COEXIST_ENABLE +#if CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + r_ble_ll_scan_start_time_init_compensation(500); + r_priv_sdk_config_insert_proc_time_set(500); +#endif // CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY + + if (ble_stack_enable() != 0) { + ret = ESP_FAIL; + goto error; + } + if (r_ble_controller_enable(mode) != 0) { ret = ESP_FAIL; goto error; @@ -929,6 +1123,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) return ESP_OK; error: + ble_stack_disable(); #if CONFIG_SW_COEXIST_ENABLE coex_disable(); #endif @@ -952,6 +1147,7 @@ esp_err_t esp_bt_controller_disable(void) if (r_ble_controller_disable() != 0) { return ESP_FAIL; } + ble_stack_disable(); #if CONFIG_SW_COEXIST_ENABLE coex_disable(); #endif @@ -1069,7 +1265,6 @@ esp_err_t esp_bt_mem_release(esp_bt_mode_t mode) return ret; } - esp_bt_controller_status_t esp_bt_controller_get_status(void) { return ble_controller_status; @@ -1081,9 +1276,17 @@ esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_ switch (power_type) { case ESP_BLE_PWR_TYPE_DEFAULT: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_ADV: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0xFF, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_PWR_TYPE_SCAN: - if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1114,9 +1317,13 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type esp_err_t stat = ESP_FAIL; switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + stat = ESP_OK; + } + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0, power_level) == 0) { + if (r_ble_txpwr_set(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0, power_level) == 0) { stat = ESP_OK; } break; @@ -1139,11 +1346,15 @@ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type) int tx_level = 0; switch (power_type) { - case ESP_BLE_PWR_TYPE_ADV: - case ESP_BLE_PWR_TYPE_SCAN: case ESP_BLE_PWR_TYPE_DEFAULT: tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); break; + case ESP_BLE_PWR_TYPE_ADV: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_ADV, 0); + break; + case ESP_BLE_PWR_TYPE_SCAN: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); + break; case ESP_BLE_PWR_TYPE_CONN_HDL0: case ESP_BLE_PWR_TYPE_CONN_HDL1: case ESP_BLE_PWR_TYPE_CONN_HDL2: @@ -1173,9 +1384,11 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po switch (power_type) { case ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT: + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + break; case ESP_BLE_ENHANCED_PWR_TYPE_SCAN: case ESP_BLE_ENHANCED_PWR_TYPE_INIT: - tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT, 0); + tx_level = r_ble_txpwr_get(ESP_BLE_ENHANCED_PWR_TYPE_SCAN, 0); break; case ESP_BLE_ENHANCED_PWR_TYPE_ADV: case ESP_BLE_ENHANCED_PWR_TYPE_CONN: @@ -1193,26 +1406,47 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po } #if CONFIG_BT_LE_CONTROLLER_LOG_ENABLED -static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, bool end) +#if !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED +static void esp_bt_controller_log_interface(uint32_t len, const uint8_t *addr, uint32_t len_append, const uint8_t *addr_append, uint32_t flag) { - for (int i = 0; i < len; i++) { - esp_rom_printf("%02x ", addr[i]); + bool end = (flag & BIT(BLE_LOG_INTERFACE_FLAG_END)); +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_controller_log_storage(len, addr, end); +#else // !CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; + portENTER_CRITICAL_SAFE(&spinlock); + esp_panic_handler_feed_wdts(); + + if (len && addr) { + for (int i = 0; i < len; i++) { esp_rom_printf("%02x ", addr[i]); } } - if (end) { - esp_rom_printf("\n"); + if (len_append && addr_append) { + for (int i = 0; i < len_append; i++) { esp_rom_printf("%02x ", addr_append[i]); } } + if (end) { esp_rom_printf("\n"); } + + portEXIT_CRITICAL_SAFE(&spinlock); +#endif // CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE } +#endif // !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED void esp_ble_controller_log_dump_all(bool output) { - portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_dump_all(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED +#if CONFIG_BT_LE_CONTROLLER_LOG_STORAGE_ENABLE + esp_bt_read_ctrl_log_from_flash(output); +#elif !CONFIG_BT_LE_CONTROLLER_LOG_SPI_OUT_ENABLED + portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED; portENTER_CRITICAL_SAFE(&spinlock); - esp_panic_handler_reconfigure_wdts(5000); + esp_panic_handler_feed_wdts(); BT_ASSERT_PRINT("\r\n[DUMP_START:"); r_ble_log_async_output_dump_all(output); BT_ASSERT_PRINT(":DUMP_END]\r\n"); portEXIT_CRITICAL_SAFE(&spinlock); +#endif } #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED @@ -1427,3 +1661,35 @@ int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) #endif // CONFIG_BT_LE_SM_LEGACY || CONFIG_BT_LE_SM_SC #endif // (!CONFIG_BT_NIMBLE_ENABLED) && (CONFIG_BT_CONTROLLER_ENABLED) +#if CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED +#include "esp_gdbstub.h" +#endif // CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED + +int IRAM_ATTR +ble_capture_info_user_handler(uint8_t type, uint32_t reason, uint32_t param1, uint32_t param2) +{ + int i; + + switch(type) { + case 0: + for (i = 0; i < 2; i++) { + esp_ble_controller_info_capture(0x010101); + } +#if CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED + uintptr_t sp; + __asm__ volatile ("mv %0, sp" : "=r" (sp)); + esp_gdbstub_panic_handler(&sp); +#endif // CONFIG_BT_LE_DEBUG_REMAIN_SCENE_ENABLED + break; +#if CONFIG_BT_LE_ASSERT_WHEN_ABNORMAL_DISCONN_ENABLED + case 1: + if ((reason == 0x08) || (reason == 0x3d) || (reason == 0x28)) { + osi_assert_wrapper(__LINE__,__func__, type, reason); + } + break; +#endif // CONFIG_BT_LE_ASSERT_WHEN_ABNORMAL_DISCONN_ENABLED + default: + break; + } + return 0; +} diff --git a/lib/bt/controller/esp32h2/esp_bt_cfg.h b/lib/bt/controller/esp32h2/esp_bt_cfg.h index c0c5801a..48a845a3 100644 --- a/lib/bt/controller/esp32h2/esp_bt_cfg.h +++ b/lib/bt/controller/esp32h2/esp_bt_cfg.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -124,22 +124,98 @@ extern "C" { #else #define DEFAULT_BT_LE_POWER_CONTROL_ENABLED (0) #endif - #if defined(CONFIG_BT_LE_50_FEATURE_SUPPORT) #define DEFAULT_BT_LE_50_FEATURE_SUPPORT (1) #else #define DEFAULT_BT_LE_50_FEATURE_SUPPORT (0) #endif + + #if defined (CONFIG_BT_LE_HCI_UART_FLOWCTRL) + #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (CONFIG_BT_LE_HCI_UART_FLOWCTRL) + #if DEFAULT_BT_LE_HCI_UART_FLOW_CTRL + #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (CONFIG_BT_LE_HCI_UART_CTS_PIN) + #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (CONFIG_BT_LE_HCI_UART_RTS_PIN) + #else + #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (-1) + #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (-1) + #endif + #else + #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) + #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (-1) + #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (-1) + #endif #endif #define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF +#ifdef CONFIG_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS +#define DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS (CONFIG_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS) +#else +#define DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS (0) +#endif + +#ifdef CONFIG_BT_LE_CTRL_LLCP_CONN_UPDATE +#define BT_CTRL_BLE_LLCP_CONN_UPDATE (1<<0) +#else +#define BT_CTRL_BLE_LLCP_CONN_UPDATE (0<<0) +#endif + +#ifdef CONFIG_BT_LE_CTRL_LLCP_CHAN_MAP_UPDATE +#define BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE (1<<1) +#else +#define BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE (0<<1) +#endif + +#ifdef CONFIG_BT_LE_CTRL_LLCP_PHY_UPDATE +#define BT_CTRL_BLE_LLCP_PHY_UPDATE (1<<2) +#else +#define BT_CTRL_BLE_LLCP_PHY_UPDATE (0<<2) +#endif + +#define BT_LE_CTRL_LLCP_DISC_FLAG (BT_CTRL_BLE_LLCP_CONN_UPDATE | BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE | BT_CTRL_BLE_LLCP_PHY_UPDATE) + +#ifdef CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX +#define BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX (CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX) +#else +#define BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX (256) +#endif + +#if defined(CONFIG_BT_LE_CTRL_CHAN_ASS_EN) +#define DEFAULT_BT_LE_CTRL_CHAN_ASS_EN (CONFIG_BT_LE_CTRL_CHAN_ASS_EN) +#else +#define DEFAULT_BT_LE_CTRL_CHAN_ASS_EN (0) +#endif + +#if defined(CONFIG_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX) +#define DEFAULT_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX (CONFIG_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX) +#else +#define DEFAULT_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX (0) +#endif + +#if defined(CONFIG_BT_LE_CTRL_FAST_CONN_DATA_TX_EN) +#define DEFAULT_BT_LE_CTRL_FAST_CONN_DATA_TX_EN (CONFIG_BT_LE_CTRL_FAST_CONN_DATA_TX_EN) +#else +#define DEFAULT_BT_LE_CTRL_FAST_CONN_DATA_TX_EN (0) +#endif + #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART #define HCI_UART_EN CONFIG_BT_LE_HCI_INTERFACE_USE_UART #else #define HCI_UART_EN 0 // hci ram mode #endif +#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_RAM +#define DEFAULT_BT_LE_VHCI_ENABLED (CONFIG_BT_LE_HCI_INTERFACE_USE_RAM) +#else +#define DEFAULT_BT_LE_VHCI_ENABLED (0) +#endif + +#ifdef CONFIG_BT_LE_PTR_CHECK_ENABLED +#define DEFAULT_BT_LE_PTR_CHECK_ENABLED (CONFIG_BT_LE_PTR_CHECK_ENABLED) +#else +#define DEFAULT_BT_LE_PTR_CHECK_ENABLED (0) +#endif + #ifdef CONFIG_BT_LE_SLEEP_ENABLE #define NIMBLE_SLEEP_ENABLE CONFIG_BT_LE_SLEEP_ENABLE #else @@ -170,8 +246,6 @@ extern "C" { #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (UART_DATA_8_BITS) #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (UART_STOP_BITS_1) #define DEFAULT_BT_LE_HCI_UART_PARITY (0) - #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (CONFIG_BT_LE_HCI_UART_TASK_STACK_SIZE) - #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) #else #define DEFAULT_BT_LE_HCI_UART_TX_PIN (0) #define DEFAULT_BT_LE_HCI_UART_RX_PIN (0) @@ -180,8 +254,6 @@ extern "C" { #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (0) #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (0) #define DEFAULT_BT_LE_HCI_UART_PARITY (0) - #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (0) - #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) #endif /* Unchanged configuration */ @@ -206,8 +278,7 @@ extern "C" { #define RTC_FREQ_N (32768) /* in Hz */ -#define BLE_LL_TX_PWR_DBM_N (9) - +#define BLE_LL_TX_PWR_DBM_N (CONFIG_BT_LE_DFT_TX_POWER_LEVEL_DBM_EFF) #define RUN_BQB_TEST (0) #define RUN_QA_TEST (0) diff --git a/lib/bt/controller/esp32h21/Kconfig.in b/lib/bt/controller/esp32h21/Kconfig.in new file mode 100644 index 00000000..e69de29b diff --git a/lib/bt/controller/esp32h4/Kconfig.in b/lib/bt/controller/esp32h4/Kconfig.in new file mode 100644 index 00000000..e69de29b diff --git a/lib/bt/controller/lib_esp32/esp32/libbtdm_app.a b/lib/bt/controller/lib_esp32/esp32/libbtdm_app.a index 7e190d8a..558e9ec8 100644 Binary files a/lib/bt/controller/lib_esp32/esp32/libbtdm_app.a and b/lib/bt/controller/lib_esp32/esp32/libbtdm_app.a differ diff --git a/lib/bt/controller/lib_esp32c2/esp32c2-bt-lib/libble_app.a b/lib/bt/controller/lib_esp32c2/esp32c2-bt-lib/libble_app.a old mode 100644 new mode 100755 index 4df30d81..62e70fd3 Binary files a/lib/bt/controller/lib_esp32c2/esp32c2-bt-lib/libble_app.a and b/lib/bt/controller/lib_esp32c2/esp32c2-bt-lib/libble_app.a differ diff --git a/lib/bt/controller/lib_esp32c2/esp32c2-bt-lib/libble_app_flash.a b/lib/bt/controller/lib_esp32c2/esp32c2-bt-lib/libble_app_flash.a new file mode 100755 index 00000000..0156a515 Binary files /dev/null and b/lib/bt/controller/lib_esp32c2/esp32c2-bt-lib/libble_app_flash.a differ diff --git a/lib/bt/controller/lib_esp32c3_family/esp32c3/libbtdm_app.a b/lib/bt/controller/lib_esp32c3_family/esp32c3/libbtdm_app.a old mode 100644 new mode 100755 index 8d1cc4fe..2141b846 Binary files a/lib/bt/controller/lib_esp32c3_family/esp32c3/libbtdm_app.a and b/lib/bt/controller/lib_esp32c3_family/esp32c3/libbtdm_app.a differ diff --git a/lib/bt/controller/lib_esp32c3_family/esp32c3/libbtdm_app_flash.a b/lib/bt/controller/lib_esp32c3_family/esp32c3/libbtdm_app_flash.a new file mode 100755 index 00000000..674f6487 Binary files /dev/null and b/lib/bt/controller/lib_esp32c3_family/esp32c3/libbtdm_app_flash.a differ diff --git a/lib/bt/controller/lib_esp32c3_family/esp32s3/libbtdm_app.a b/lib/bt/controller/lib_esp32c3_family/esp32s3/libbtdm_app.a old mode 100644 new mode 100755 index 7d450357..08a8f5f1 Binary files a/lib/bt/controller/lib_esp32c3_family/esp32s3/libbtdm_app.a and b/lib/bt/controller/lib_esp32c3_family/esp32s3/libbtdm_app.a differ diff --git a/lib/bt/controller/lib_esp32c3_family/esp32s3/libbtdm_app_flash.a b/lib/bt/controller/lib_esp32c3_family/esp32s3/libbtdm_app_flash.a new file mode 100755 index 00000000..eb87092f Binary files /dev/null and b/lib/bt/controller/lib_esp32c3_family/esp32s3/libbtdm_app_flash.a differ diff --git a/lib/bt/controller/lib_esp32c5/esp32c5-bt-lib/NOTICE b/lib/bt/controller/lib_esp32c5/esp32c5-bt-lib/NOTICE new file mode 100644 index 00000000..f996f9a2 --- /dev/null +++ b/lib/bt/controller/lib_esp32c5/esp32c5-bt-lib/NOTICE @@ -0,0 +1,9 @@ +Apache Mynewt NimBLE +Copyright 2015-2021 The Apache Software Foundation +Modifications Copyright 2017-2024 Espressif Systems (Shanghai) CO., LTD. + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + +Portions of this software were developed at +Runtime Inc, copyright 2015. \ No newline at end of file diff --git a/lib/bt/controller/lib_esp32c5/esp32c5-bt-lib/README.md b/lib/bt/controller/lib_esp32c5/esp32c5-bt-lib/README.md new file mode 100644 index 00000000..7a64988a --- /dev/null +++ b/lib/bt/controller/lib_esp32c5/esp32c5-bt-lib/README.md @@ -0,0 +1 @@ +This software includes portions of code derived from mynewt-nimble project. See [NOTICE](NOTICE) file for details. diff --git a/lib/bt/controller/lib_esp32c5/esp32c5-bt-lib/libble_app.a b/lib/bt/controller/lib_esp32c5/esp32c5-bt-lib/libble_app.a new file mode 100755 index 00000000..1ec27254 Binary files /dev/null and b/lib/bt/controller/lib_esp32c5/esp32c5-bt-lib/libble_app.a differ diff --git a/lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/NOTICE b/lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/NOTICE index a0cb7d8b..f996f9a2 100644 --- a/lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/NOTICE +++ b/lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/NOTICE @@ -1,6 +1,6 @@ Apache Mynewt NimBLE Copyright 2015-2021 The Apache Software Foundation -Modifications Copyright 2017-2023 Espressif Systems (Shanghai) CO., LTD. +Modifications Copyright 2017-2024 Espressif Systems (Shanghai) CO., LTD. This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/esp32c6/libble_app.a b/lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/esp32c6/libble_app.a new file mode 100755 index 00000000..82dd0ff6 Binary files /dev/null and b/lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/esp32c6/libble_app.a differ diff --git a/lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/esp32c61/libble_app.a b/lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/esp32c61/libble_app.a new file mode 100755 index 00000000..10e59d9e Binary files /dev/null and b/lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/esp32c61/libble_app.a differ diff --git a/lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/libble_app.a b/lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/libble_app.a deleted file mode 100644 index d39ed65a..00000000 Binary files a/lib/bt/controller/lib_esp32c6/esp32c6-bt-lib/libble_app.a and /dev/null differ diff --git a/lib/bt/controller/lib_esp32h2/esp32h2-bt-lib/libble_app.a b/lib/bt/controller/lib_esp32h2/esp32h2-bt-lib/libble_app.a old mode 100644 new mode 100755 index 184b2def..69436b7f Binary files a/lib/bt/controller/lib_esp32h2/esp32h2-bt-lib/libble_app.a and b/lib/bt/controller/lib_esp32h2/esp32h2-bt-lib/libble_app.a differ diff --git a/lib/bt/esp_ble_mesh/Kconfig.in b/lib/bt/esp_ble_mesh/Kconfig.in index 216ab39a..eb761a5e 100644 --- a/lib/bt/esp_ble_mesh/Kconfig.in +++ b/lib/bt/esp_ble_mesh/Kconfig.in @@ -6,22 +6,97 @@ if BLE_MESH help It is a temporary solution and needs further modifications. + config BLE_MESH_V11_SUPPORT + bool "Support ESP BLE Mesh v1.1 features (Preview)" + default y + help + Support BLE Mesh v1.1 features + config BLE_MESH_RANDOM_ADV_INTERVAL bool "Support using random adv interval for mesh packets" select BT_BLE_HIGH_DUTY_ADV_INTERVAL if BT_BLUEDROID_ENABLED + select BT_NIMBLE_HIGH_DUTY_ADV_ITVL if BT_NIMBLE_ENABLED default n help Enable this option to allow using random advertising interval for mesh packets. And this could help avoid collision of advertising packets. + menuconfig BLE_MESH_USE_BLE_50 + bool "Support using BLE 5.0 APIs for BLE Mesh" + depends on BLE_MESH_EXPERIMENTAL + select BT_NIMBLE_50_FEATURE_SUPPORT if BT_NIMBLE_ENABLED + select BT_NIMBLE_EXT_ADV if BT_NIMBLE_ENABLED + select BT_BLE_50_FEATURES_SUPPORTED if BT_BLUEDROID_ENABLED + select BT_LE_50_FEATURE_SUPPORT if IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2 + default n + help + This option to enable BLE Mesh using some BLE 5.0 APIs. + + config BLE_MESH_ADV_INST_ID + depends on BLE_MESH_USE_BLE_50 + int "Extended adv instance for Mesh normal packets" + default 0 + range 0 3 + help + Extended ADV instance used by Mesh normal advertising packets. + + menuconfig BLE_MESH_SUPPORT_MULTI_ADV + bool "Support using multiple adv instance for BLE Mesh" + depends on BLE_MESH_USE_BLE_50 + default n + help + Enable this option to support using multiple adv instance while running BLE Mesh. + + config BLE_MESH_PROXY_ADV_INST_ID + int "Extended adv instance for Mesh proxy packets" + depends on BLE_MESH_PROXY + depends on (BLE_MESH_PB_GATT || BLE_MESH_GATT_PROXY_SERVER) + depends on BLE_MESH_SUPPORT_MULTI_ADV + default 1 + range 0 3 + help + Extended ADV instance used by Mesh proxy advertising packets. + + menuconfig BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + bool "Use separate extended adv instance for Mesh relay packets" + depends on BLE_MESH_SUPPORT_MULTI_ADV + depends on BLE_MESH_RELAY_ADV_BUF + default n + help + Enable this option to support using a separate extended ADV instance for Mesh relay packets. + + config BLE_MESH_RELAY_ADV_INST_ID + int "Extended adv instance for Mesh relay packets" + depends on BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + default 2 + range 0 3 + help + Extended ADV instance used by Mesh relay advertising packets. + + menuconfig BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + bool "Use separate extended adv instance for BLE normal packets" + depends on BLE_MESH_SUPPORT_MULTI_ADV + depends on BLE_MESH_SUPPORT_BLE_ADV + default n + help + Enable this option to support using a separate extended ADV instance for normal BLE advertising packets. + + config BLE_MESH_BLE_ADV_INST_ID + int "Extended adv instance for normal BLE packets" + depends on BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + default 3 + range 0 3 + help + Extended ADV instance used by normal BLE advertising packets. + config BLE_MESH_USE_DUPLICATE_SCAN bool "Support Duplicate Scan in BLE Mesh" select BTDM_BLE_SCAN_DUPL if IDF_TARGET_ESP32 select BTDM_BLE_MESH_SCAN_DUPL_EN if IDF_TARGET_ESP32 select BT_CTRL_BLE_SCAN_DUPL if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 select BT_CTRL_BLE_MESH_SCAN_DUPL_EN if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 - select BT_LE_SCAN_DUPL if IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2 + select BT_LE_SCAN_DUPL if IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2 || IDF_TARGET_ESP32C61 || IDF_TARGET_ESP32C5 select BT_NIMBLE_VS_SUPPORT if BT_NIMBLE_ENABLED default y help @@ -32,6 +107,7 @@ if BLE_MESH config BLE_MESH_ACTIVE_SCAN bool "Support Active Scan in BLE Mesh" + depends on BLE_MESH_V11_SUPPORT help Enable this option to allow using BLE Active Scan for BLE Mesh. @@ -281,6 +357,7 @@ if BLE_MESH config BLE_MESH_PROV_EPA bool "BLE Mesh enhanced provisioning authentication" depends on BLE_MESH_PROV + depends on BLE_MESH_V11_SUPPORT default y help Enable this option to support BLE Mesh enhanced provisioning authentication @@ -290,6 +367,7 @@ if BLE_MESH config BLE_MESH_CERT_BASED_PROV bool "Support Certificate-based provisioning" depends on BLE_MESH_PROV + depends on BLE_MESH_V11_SUPPORT default n help Enable this option to support BLE Mesh Certificate-Based Provisioning. @@ -390,6 +468,7 @@ if BLE_MESH config BLE_MESH_PROXY_SOLIC_PDU_RX bool "Support receiving Proxy Solicitation PDU" depends on BLE_MESH_GATT_PROXY_SERVER + depends on BLE_MESH_V11_SUPPORT help Enable this option to support receiving Proxy Solicitation PDU. @@ -397,7 +476,7 @@ if BLE_MESH int "Maximum capacity of solicitation replay protection list" depends on BLE_MESH_PROXY_SOLIC_PDU_RX default 2 - range 1 255 + range 1 65536 help This option specifies the maximum capacity of the solicitation replay protection list. The solicitation replay protection list is used to @@ -405,6 +484,13 @@ if BLE_MESH will store the solicitation src and solicitation sequence number of the received Solicitation PDU message. + config BLE_MESH_PROXY_CLI_SRV_COEXIST + bool "Support Proxy Client and Proxy Server coexistence" + depends on BLE_MESH_EXPERIMENTAL + default n + help + Enable this option to support the coexistence of proxy client and proxy server. + config BLE_MESH_GATT_PROXY_CLIENT bool "BLE Mesh GATT Proxy Client" select BLE_MESH_PROXY @@ -417,6 +503,7 @@ if BLE_MESH config BLE_MESH_PROXY_SOLIC_PDU_TX bool "Support sending Proxy Solicitation PDU" depends on BLE_MESH_GATT_PROXY_CLIENT + depends on BLE_MESH_V11_SUPPORT help Enable this option to support sending Proxy Solicitation PDU. @@ -703,6 +790,7 @@ if BLE_MESH to perform the IV index recovery procedure. config BLE_MESH_SAR_ENHANCEMENT + depends on BLE_MESH_V11_SUPPORT bool "Segmentation and reassembly enhancement" default n help @@ -1102,253 +1190,257 @@ if BLE_MESH help Enable support for Health Server model. - config BLE_MESH_BRC_CLI - bool "Bridge Configuration Client model" - help - Enable support for Bridge Configuration Client model. - - config BLE_MESH_BRC_SRV - bool "Bridge Configuration Server model" - default n - help - Enable support for Bridge Configuration Server model. - - if BLE_MESH_BRC_SRV + if BLE_MESH_V11_SUPPORT - config BLE_MESH_MAX_BRIDGING_TABLE_ENTRY_COUNT - int "Maximum number of Bridging Table entries" - range 16 65535 - default 16 + config BLE_MESH_BRC_CLI + bool "Bridge Configuration Client model" help - Maximum number of Bridging Table entries that the Bridge Configuration Server can support. + Enable support for Bridge Configuration Client model. - config BLE_MESH_BRIDGE_CRPL - int "Maximum capacity of bridge replay protection list" - default 5 - range 1 255 + config BLE_MESH_BRC_SRV + bool "Bridge Configuration Server model" + default n help - This option specifies the maximum capacity of the bridge replay - protection list. The bridge replay protection list is used to - prevent a bridged subnet from replay attack, which will store the - source address and sequence number of the received bridge messages. + Enable support for Bridge Configuration Server model. - endif #BLE_MESH_BRC_SRV + if BLE_MESH_BRC_SRV - config BLE_MESH_PRB_CLI - bool "Mesh Private Beacon Client model" - help - Enable support for Mesh Private Beacon Client model. + config BLE_MESH_MAX_BRIDGING_TABLE_ENTRY_COUNT + int "Maximum number of Bridging Table entries" + range 16 65535 + default 16 + help + Maximum number of Bridging Table entries that the Bridge Configuration Server can support. - config BLE_MESH_PRB_SRV - bool "Mesh Private Beacon Server model" - help - Enable support for Mesh Private Beacon Server model. + config BLE_MESH_BRIDGE_CRPL + int "Maximum capacity of bridge replay protection list" + default 5 + range 1 255 + help + This option specifies the maximum capacity of the bridge replay + protection list. The bridge replay protection list is used to + prevent a bridged subnet from replay attack, which will store the + source address and sequence number of the received bridge messages. - config BLE_MESH_ODP_CLI - bool "On-Demand Private Proxy Client model" - help - Enable support for On-Demand Private Proxy Client model. + endif #BLE_MESH_BRC_SRV - config BLE_MESH_ODP_SRV - bool "On-Demand Private Proxy Server model" - depends on BLE_MESH_PROXY_SOLIC_PDU_RX - select BLE_MESH_SRPL_SRV - help - Enable support for On-Demand Private Proxy Server model. + config BLE_MESH_PRB_CLI + bool "Mesh Private Beacon Client model" + help + Enable support for Mesh Private Beacon Client model. - config BLE_MESH_SRPL_CLI - bool "Solicitation PDU RPL Configuration Client model" - help - Enable support for Solicitation PDU RPL Configuration Client model. + config BLE_MESH_PRB_SRV + bool "Mesh Private Beacon Server model" + help + Enable support for Mesh Private Beacon Server model. - config BLE_MESH_SRPL_SRV - bool "Solicitation PDU RPL Configuration Server model" - depends on BLE_MESH_PROXY_SOLIC_PDU_RX - help - Enable support for Solicitation PDU RPL Configuration Server model. - Note: - This option depends on the functionality of receiving Solicitation - PDU. If the device doesn't support receiving Solicitation PDU, then - there is no need to enable this server model. + config BLE_MESH_ODP_CLI + bool "On-Demand Private Proxy Client model" + help + Enable support for On-Demand Private Proxy Client model. - config BLE_MESH_AGG_CLI - bool "Opcodes Aggregator Client model" - help - Enable support for Opcodes Aggregator Client model. + config BLE_MESH_ODP_SRV + bool "On-Demand Private Proxy Server model" + depends on BLE_MESH_PROXY_SOLIC_PDU_RX + select BLE_MESH_SRPL_SRV + help + Enable support for On-Demand Private Proxy Server model. - config BLE_MESH_AGG_SRV - bool "Opcodes Aggregator Server model" - help - Enable support for Opcodes Aggregator Server model. + config BLE_MESH_SRPL_CLI + bool "Solicitation PDU RPL Configuration Client model" + help + Enable support for Solicitation PDU RPL Configuration Client model. - config BLE_MESH_SAR_CLI - bool "SAR Configuration Client model" - help - Enable support for SAR Configuration Client model. + config BLE_MESH_SRPL_SRV + bool "Solicitation PDU RPL Configuration Server model" + depends on BLE_MESH_PROXY_SOLIC_PDU_RX + help + Enable support for Solicitation PDU RPL Configuration Server model. + Note: + This option depends on the functionality of receiving Solicitation + PDU. If the device doesn't support receiving Solicitation PDU, then + there is no need to enable this server model. + + config BLE_MESH_AGG_CLI + bool "Opcodes Aggregator Client model" + help + Enable support for Opcodes Aggregator Client model. - config BLE_MESH_SAR_SRV - bool "SAR Configuration Server model" - help - Enable support for SAR Configuration Server model. + config BLE_MESH_AGG_SRV + bool "Opcodes Aggregator Server model" + help + Enable support for Opcodes Aggregator Server model. - config BLE_MESH_COMP_DATA_1 - bool "Support Composition Data Page 1" - help - Composition Data Page 1 contains information about the relationships - among models. - Each model either can be a root model or can extend other models. + config BLE_MESH_SAR_CLI + bool "SAR Configuration Client model" + help + Enable support for SAR Configuration Client model. - config BLE_MESH_COMP_DATA_128 - bool "Support Composition Data Page 128" - help - Composition Data Page 128 is used to indicate the structure of - elements, features, and models of a node after the successful - execution of the Node Address Refresh procedure or the Node - Composition Refresh procedure, or after the execution of the - Node Removal procedure followed by the provisioning process. - Composition Data Page 128 shall be present if the node supports - the Remote Provisioning Server model; otherwise it is optional. + config BLE_MESH_SAR_SRV + bool "SAR Configuration Server model" + help + Enable support for SAR Configuration Server model. - config BLE_MESH_MODELS_METADATA_0 - bool "Support Models Metadata Page 0" - help - The Models Metadata state contains metadata of a node’s models. - The Models Metadata state is composed of a number of pages of - information. - Models Metadata Page 0 shall be present if the node supports - the Large Composition Data Server model. + config BLE_MESH_COMP_DATA_1 + bool "Support Composition Data Page 1" + help + Composition Data Page 1 contains information about the relationships + among models. + Each model either can be a root model or can extend other models. - config BLE_MESH_MODELS_METADATA_128 - bool "Support Models Metadata Page 128" - depends on BLE_MESH_MODELS_METADATA_0 - help - The Models Metadata state contains metadata of a node’s models. - The Models Metadata state is composed of a number of pages of - information. - Models Metadata Page 128 contains metadata for the node’s models - after the successful execution of the Node Address Refresh - procedure or the Node Composition Refresh procedure, or after - the execution of the Node Removal procedure followed by the - provisioning process. - Models Metadata Page 128 shall be present if the node supports - the Remote Provisioning Server model and the node supports the - Large Composition Data Server model. + config BLE_MESH_COMP_DATA_128 + bool "Support Composition Data Page 128" + help + Composition Data Page 128 is used to indicate the structure of + elements, features, and models of a node after the successful + execution of the Node Address Refresh procedure or the Node + Composition Refresh procedure, or after the execution of the + Node Removal procedure followed by the provisioning process. + Composition Data Page 128 shall be present if the node supports + the Remote Provisioning Server model; otherwise it is optional. + + config BLE_MESH_MODELS_METADATA_0 + bool "Support Models Metadata Page 0" + help + The Models Metadata state contains metadata of a node’s models. + The Models Metadata state is composed of a number of pages of + information. + Models Metadata Page 0 shall be present if the node supports + the Large Composition Data Server model. + + config BLE_MESH_MODELS_METADATA_128 + bool "Support Models Metadata Page 128" + depends on BLE_MESH_MODELS_METADATA_0 + help + The Models Metadata state contains metadata of a node’s models. + The Models Metadata state is composed of a number of pages of + information. + Models Metadata Page 128 contains metadata for the node’s models + after the successful execution of the Node Address Refresh + procedure or the Node Composition Refresh procedure, or after + the execution of the Node Removal procedure followed by the + provisioning process. + Models Metadata Page 128 shall be present if the node supports + the Remote Provisioning Server model and the node supports the + Large Composition Data Server model. + + config BLE_MESH_LCD_CLI + bool "Large Composition Data Client model" + help + Enable support for Large Composition Data Client model. - config BLE_MESH_LCD_CLI - bool "Large Composition Data Client model" - help - Enable support for Large Composition Data Client model. + config BLE_MESH_LCD_SRV + bool "Large Composition Data Server model" + select BLE_MESH_MODELS_METADATA_0 + help + Enable support for Large Composition Data Server model. - config BLE_MESH_LCD_SRV - bool "Large Composition Data Server model" - select BLE_MESH_MODELS_METADATA_0 - help - Enable support for Large Composition Data Server model. + config BLE_MESH_RPR_CLI + bool "Remote Provisioning Client model" + depends on BLE_MESH_PROVISIONER + select BLE_MESH_PROV + help + Enable support for Remote Provisioning Client model - config BLE_MESH_RPR_CLI - bool "Remote Provisioning Client model" - depends on BLE_MESH_PROVISIONER - select BLE_MESH_PROV - help - Enable support for Remote Provisioning Client model + if BLE_MESH_RPR_CLI - if BLE_MESH_RPR_CLI + config BLE_MESH_RPR_CLI_PROV_SAME_TIME + int "Maximum number of PB-Remote running at the same time by Provisioner" + range 1 5 + default 2 + help + This option specifies how many devices can be provisioned at the same time + using PB-REMOTE. For example, if the value is 2, it means a Provisioner can + provision two unprovisioned devices with PB-REMOTE at the same time. - config BLE_MESH_RPR_CLI_PROV_SAME_TIME - int "Maximum number of PB-Remote running at the same time by Provisioner" - range 1 5 - default 2 + endif # BLE_MESH_RPR_CLI + + config BLE_MESH_RPR_SRV + bool "Remote Provisioning Server model" + depends on BLE_MESH_NODE + select BLE_MESH_PB_ADV help - This option specifies how many devices can be provisioned at the same time - using PB-REMOTE. For example, if the value is 2, it means a Provisioner can - provision two unprovisioned devices with PB-REMOTE at the same time. + Enable support for Remote Provisioning Server model - endif # BLE_MESH_RPR_CLI + if BLE_MESH_RPR_SRV - config BLE_MESH_RPR_SRV - bool "Remote Provisioning Server model" - depends on BLE_MESH_NODE - select BLE_MESH_PB_ADV - help - Enable support for Remote Provisioning Server model + config BLE_MESH_RPR_SRV_MAX_SCANNED_ITEMS + int "Maximum number of device information can be scanned" + range 4 255 + default 10 + help + This option specifies how many device information can a Remote + Provisioning Server store each time while scanning. - if BLE_MESH_RPR_SRV + config BLE_MESH_RPR_SRV_ACTIVE_SCAN + bool "Support Active Scan for remote provisioning" + select BLE_MESH_ACTIVE_SCAN + help + Enable this option to support Active Scan for remote provisioning. - config BLE_MESH_RPR_SRV_MAX_SCANNED_ITEMS - int "Maximum number of device information can be scanned" - range 4 255 - default 10 - help - This option specifies how many device information can a Remote - Provisioning Server store each time while scanning. + config BLE_MESH_RPR_SRV_MAX_EXT_SCAN + int "Maximum number of extended scan procedures" + range 1 10 + default 1 + help + This option specifies how many extended scan procedures can be + started by the Remote Provisioning Server. - config BLE_MESH_RPR_SRV_ACTIVE_SCAN - bool "Support Active Scan for remote provisioning" - select BLE_MESH_ACTIVE_SCAN - help - Enable this option to support Active Scan for remote provisioning. + endif # BLE_MESH_RPR_SRV - config BLE_MESH_RPR_SRV_MAX_EXT_SCAN - int "Maximum number of extended scan procedures" - range 1 10 - default 1 + config BLE_MESH_DF_CLI + bool "Directed Forwarding Configuration Client model" help - This option specifies how many extended scan procedures can be - started by the Remote Provisioning Server. + Enable support for Directed Forwarding Configuration Client model. - endif # BLE_MESH_RPR_SRV + config BLE_MESH_DF_SRV + bool "Directed Forwarding Configuration Server model" + help + Enable support for Directed Forwarding Configuration Server model. - config BLE_MESH_DF_CLI - bool "Directed Forwarding Configuration Client model" - help - Enable support for Directed Forwarding Configuration Client model. + if BLE_MESH_DF_SRV - config BLE_MESH_DF_SRV - bool "Directed Forwarding Configuration Server model" - help - Enable support for Directed Forwarding Configuration Server model. + config BLE_MESH_MAX_DISC_TABLE_ENTRY_COUNT + int "Maximum number of discovery table entries in a given subnet" + range 2 255 + default 2 + help + Maximum number of Discovery Table entries supported by the node in a given subnet. - if BLE_MESH_DF_SRV + config BLE_MESH_MAX_FORWARD_TABLE_ENTRY_COUNT + int "Maximum number of forward table entries in a given subnet" + range 2 64 + default 2 + help + Maximum number of Forward Table entries supported by the node in a given subnet. - config BLE_MESH_MAX_DISC_TABLE_ENTRY_COUNT - int "Maximum number of discovery table entries in a given subnet" - range 2 255 - default 2 - help - Maximum number of Discovery Table entries supported by the node in a given subnet. + config BLE_MESH_MAX_DEPS_NODES_PER_PATH + int "Maximum number of dependent nodes per path" + range 2 64 + default 2 + help + Maximum size of dependent nodes list supported by each forward table entry. - config BLE_MESH_MAX_FORWARD_TABLE_ENTRY_COUNT - int "Maximum number of forward table entries in a given subnet" - range 2 64 - default 2 - help - Maximum number of Forward Table entries supported by the node in a given subnet. + config BLE_MESH_PATH_MONITOR_TEST + bool "Enable Path Monitoring test mode" + default n + help + The option only removes the Path Use timer; all other behavior of the + device is not changed. + If Path Monitoring test mode is going to be used, this option should + be enabled. - config BLE_MESH_MAX_DEPS_NODES_PER_PATH - int "Maximum number of dependent nodes per path" - range 2 64 - default 2 - help - Maximum size of dependent nodes list supported by each forward table entry. + if BLE_MESH_GATT_PROXY_SERVER + config BLE_MESH_SUPPORT_DIRECTED_PROXY + bool "Enable Directed Proxy functionality" + default y + help + Support Directed Proxy functionality. + endif - config BLE_MESH_PATH_MONITOR_TEST - bool "Enable Path Monitoring test mode" - default n - help - The option only removes the Path Use timer; all other behavior of the - device is not changed. - If Path Monitoring test mode is going to be used, this option should - be enabled. - - if BLE_MESH_GATT_PROXY_SERVER - config BLE_MESH_SUPPORT_DIRECTED_PROXY - bool "Enable Directed Proxy functionality" - default y - help - Support Directed Proxy functionality. - endif + endif # BLE_MESH_DF_SRV - endif # BLE_MESH_DF_SRV + endif # BLE_MESH_V11_SUPPORT endmenu #Support for BLE Mesh Foundation models @@ -1441,30 +1533,31 @@ if BLE_MESH config BLE_MESH_GENERIC_SERVER bool "Generic server models" - default y + default n help Enable support for Generic server models. config BLE_MESH_SENSOR_SERVER bool "Sensor server models" - default y + default n help Enable support for Sensor server models. config BLE_MESH_TIME_SCENE_SERVER bool "Time and Scenes server models" - default y + default n help Enable support for Time and Scenes server models. config BLE_MESH_LIGHTING_SERVER bool "Lighting server models" - default y + default n help Enable support for Lighting server models. config BLE_MESH_MBT_CLI bool "BLOB Transfer Client model" + depends on BLE_MESH_V11_SUPPORT default n help Enable support for BLOB Transfer Client model. @@ -1483,6 +1576,7 @@ if BLE_MESH config BLE_MESH_MBT_SRV bool "BLOB Transfer Server model" + depends on BLE_MESH_V11_SUPPORT default n help Enable support for BLOB Transfer Server model. @@ -1628,5 +1722,7 @@ if BLE_MESH Make BLE Mesh Experimental features visible. Experimental features list: - CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG + - CONFIG_BLE_MESH_USE_BLE_50 + - CONFIG_BLE_MESH_PROXY_CLI_SRV_COEXIST endif # BLE_MESH diff --git a/lib/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c b/lib/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c index 559528e8..fcba1f4b 100644 --- a/lib/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c +++ b/lib/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,14 +12,14 @@ #include "btc_ble_mesh_ble.h" #include "esp_ble_mesh_ble_api.h" -#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT +#if (CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50) esp_err_t esp_ble_mesh_register_ble_callback(esp_ble_mesh_ble_cb_t callback) { ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); return (btc_profile_cb_set(BTC_PID_BLE_MESH_BLE_COEX, callback) == 0 ? ESP_OK : ESP_FAIL); } -#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT */ +#endif /* (CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50) */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV esp_err_t esp_ble_mesh_start_ble_advertising(const esp_ble_mesh_ble_adv_param_t *param, @@ -100,3 +100,23 @@ esp_err_t esp_ble_mesh_stop_ble_scanning(void) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ + +esp_err_t esp_ble_mesh_scan_params_update(esp_ble_mesh_scan_param_t *scan_param) +{ + btc_ble_mesh_ble_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (!scan_param) { + return ESP_FAIL; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_BLE_MESH_BLE_COEX; + msg.act = BTC_BLE_MESH_ACT_UPDATE_SCAN_PARAMS; + + arg.scan_params.scan_interval = scan_param->scan_interval; + arg.scan_params.uncoded_scan_window = scan_param->uncoded_scan_window; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_ble_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} diff --git a/lib/bt/esp_ble_mesh/api/core/esp_ble_mesh_common_api.c b/lib/bt/esp_ble_mesh/api/core/esp_ble_mesh_common_api.c index 82128786..eaa18681 100644 --- a/lib/bt/esp_ble_mesh/api/core/esp_ble_mesh_common_api.c +++ b/lib/bt/esp_ble_mesh/api/core/esp_ble_mesh_common_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/lib/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h b/lib/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h index 6818ba18..83d7e627 100644 --- a/lib/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h +++ b/lib/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_ble_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,6 +9,10 @@ #include "esp_ble_mesh_defs.h" +#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BT_NIMBLE_ENABLED +#include "host/ble_gap.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -20,9 +24,38 @@ typedef enum { ESP_BLE_MESH_START_BLE_SCANNING_COMP_EVT, /*!< Start BLE scanning completion event */ ESP_BLE_MESH_STOP_BLE_SCANNING_COMP_EVT, /*!< Stop BLE scanning completion event */ ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT, /*!< Scanning BLE advertising packets event */ + ESP_BLE_MESH_SCAN_PARAMS_UPDATE_COMP_EVT, /*!< Scan parameters update completion event */ +#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BT_NIMBLE_ENABLED + ESP_BLE_MESH_NIMBLE_GAP_EVENT_EVT, /*!< NIMBLE GAP event */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BT_NIMBLE_ENABLED */ ESP_BLE_MESH_BLE_EVT_MAX, } esp_ble_mesh_ble_cb_event_t; +/** Context of BLE advertising report. */ +typedef struct { + uint8_t addr[6]; /*!< Device address */ + uint8_t addr_type; /*!< Device address type */ +#if CONFIG_BLE_MESH_USE_BLE_50 + uint8_t adv_type __attribute__((deprecated("`event_type` should be used to determine the advertising type"))); /*!< advertising type */ +#else + uint8_t adv_type; /*!< Advertising type */ +#endif + uint8_t *data; /*!< Advertising data */ + uint16_t length; /*!< Advertising data length */ + int8_t rssi; /*!< RSSI of the advertising packet */ +#if CONFIG_BLE_MESH_USE_BLE_50 + uint8_t event_type; /*!< Extended advertising event type */ + uint8_t primary_phy; /*!< Extended advertising primary PHY */ + uint8_t secondary_phy; /*!< Extended advertising secondary PHY */ + uint8_t sid; /*!< Extended advertising set ID */ + uint8_t tx_power; /*!< Extended advertising TX power */ + uint8_t dir_addr_type; /*!< Direct address type */ + uint8_t dir_addr[6]; /*!< Direct address */ + uint8_t data_status; /*!< Data type */ + uint16_t per_adv_interval; /*!< Periodic advertising interval */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +} esp_ble_mesh_ble_adv_rpt_t; + /** BLE operation callback parameters */ typedef union { /** @@ -52,16 +85,24 @@ typedef union { int err_code; /*!< Indicate the result of stopping BLE scanning */ } stop_ble_scan_comp; /*!< Event parameters of ESP_BLE_MESH_STOP_BLE_SCANNING_COMP_EVT */ /** - * @brief ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT + * @brief Event parameters of ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT */ - struct { - uint8_t addr[6]; /*!< Device address */ - uint8_t addr_type; /*!< Device address type */ - uint8_t adv_type; /*!< Advertising data type */ - uint8_t *data; /*!< Advertising data */ - uint16_t length; /*!< Advertising data length */ - int8_t rssi; /*!< RSSI of the advertising packet */ - } scan_ble_adv_pkt; /*!< Event parameters of ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT */ + esp_ble_mesh_ble_adv_rpt_t scan_ble_adv_pkt; + /** + * @brief Event parameter of ESP_BLE_MESH_SCAN_PARAMS_UPDATE_COMP_EVT + */ + struct ble_mesh_scan_params_update_comp_param { + int err_code; /*!< Indicates the result of updating scan parameters */ + } scan_params_update_comp; /*!< Event parameter of ESP_BLE_MESH_SCAN_PARAMS_UPDATE_COMP_EVT */ +#if CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BT_NIMBLE_ENABLED + /** + * @brief Event parameters of ESP_BLE_MESH_NIMBLE_GAP_EVENT_EVT + */ + struct ble_mesh_nimble_gap_event_evt_param { + struct ble_gap_event event; /*!< GAP event parameters for NimBLE Host */ + void *arg; /*!< User parameters */ + } nimble_gap_evt; /*!< Event parameters of ESP_BLE_MESH_NIMBLE_GAP_EVENT_EVT */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 && CONFIG_BT_NIMBLE_ENABLED */ } esp_ble_mesh_ble_cb_param_t; /** @@ -175,6 +216,33 @@ esp_err_t esp_ble_mesh_start_ble_scanning(esp_ble_mesh_ble_scan_param_t *param); */ esp_err_t esp_ble_mesh_stop_ble_scanning(void); +/** + * @brief Update BLE Mesh scan parameters. + * + * @note + * 1. This function shall be used after ESP BLE Mesh is initialized! + * Parameters `scan_interval` and `uncoded_scan_window` must both + * be multiples of 8. + * + * 2. If the config BLE_MESH_USE_BLE_50 is enabled, within the scan_interval: + * - If uncoded_scan_window is not zero, the scan_interval is divided into + * two parts: + * - uncoded_scan_window: Used for performing uncoded scanning. + * - (scan_interval - uncoded_scan_window): The remaining time is + * used for coded scanning (coded_scan). + * - If uncoded_scan_window is set to 0, it means the entire scan_interval + * is used for coded scanning. + * - If uncoded_scan_window is equal to scan_interval, it means the entire + * scan_interval is used for uncoded scanning. + * + * @param[in] scan_param: Scan parameters + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Invalid parameters or unable transfer this command to the stack +*/ +esp_err_t esp_ble_mesh_scan_params_update(esp_ble_mesh_scan_param_t *scan_param); + #ifdef __cplusplus } #endif diff --git a/lib/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h b/lib/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h index efbf2df5..188d6db2 100644 --- a/lib/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h +++ b/lib/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -415,6 +415,29 @@ typedef struct { bool erase_flash; /*!< Indicate if erasing flash when deinit mesh stack */ } esp_ble_mesh_deinit_param_t; +/** Scan parameters */ +typedef struct { + /** + * Scan interval. + * + * Range: 0x0004 to 0x4000. + * + * Time = N * 0.625 ms. Time Range: 2.5 ms to 10.24 s + */ + uint16_t scan_interval; + + /** + * Uncoded Scan window. + * + * Time scanned on uncoded PHY within a scan interval. + * + * Range: 0x0004 to 0x4000. + * + * Time = N * 0.625 ms. Time Range: 2.5 ms to 10.24 s + */ + uint16_t uncoded_scan_window; +} esp_ble_mesh_scan_param_t; + /** Format of Unicast Address Range */ typedef struct { uint16_t len_present:1, /*!< Indicate the presence or absence of the RangeLength field */ diff --git a/lib/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c b/lib/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c index ead6c2cc..27699600 100644 --- a/lib/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c +++ b/lib/bt/esp_ble_mesh/btc/btc_ble_mesh_ble.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,8 +13,7 @@ #include "mesh/adapter.h" #include "esp_ble_mesh_ble_api.h" -#if CONFIG_BLE_MESH_BLE_COEX_SUPPORT - +#if (CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50) static void btc_ble_mesh_ble_copy_req_data(btc_msg_t *msg, void *p_dst, void *p_src) { #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN @@ -29,6 +28,7 @@ static void btc_ble_mesh_ble_copy_req_data(btc_msg_t *msg, void *p_dst, void *p_ switch (msg->act) { case ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT: if (p_src_data->scan_ble_adv_pkt.data && p_src_data->scan_ble_adv_pkt.length) { + memcpy(&p_dst_data->scan_ble_adv_pkt, &p_src_data->scan_ble_adv_pkt, sizeof(p_src_data->scan_ble_adv_pkt)); p_dst_data->scan_ble_adv_pkt.length = p_src_data->scan_ble_adv_pkt.length; p_dst_data->scan_ble_adv_pkt.data = bt_mesh_calloc(p_src_data->scan_ble_adv_pkt.length); if (p_dst_data->scan_ble_adv_pkt.data) { @@ -86,26 +86,34 @@ static void btc_ble_mesh_ble_callback(esp_ble_mesh_ble_cb_param_t *cb_params, ui btc_ble_mesh_ble_copy_req_data, btc_ble_mesh_ble_free_req_data); } -#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN -void bt_mesh_ble_scan_cb_evt_to_btc(const bt_mesh_addr_t *addr, - uint8_t adv_type, uint8_t data[], - uint16_t length, int8_t rssi) +#if CONFIG_BT_NIMBLE_ENABLED && CONFIG_BLE_MESH_USE_BLE_50 +void bt_mesh_ble_nimble_evt_to_btc(struct ble_gap_event *event, void *arg) { esp_ble_mesh_ble_cb_param_t param = {0}; - if (addr == NULL) { + if (event == NULL) { BT_ERR("%s, Invalid parameter", __func__); return; } - memcpy(param.scan_ble_adv_pkt.addr, addr->val, sizeof(addr->val)); - param.scan_ble_adv_pkt.addr_type = addr->type; - if (data && length) { - param.scan_ble_adv_pkt.data = data; - param.scan_ble_adv_pkt.length = length; + memcpy(¶m.nimble_gap_evt.event, event, sizeof(struct ble_gap_event)); + param.nimble_gap_evt.arg = arg; + + btc_ble_mesh_ble_callback(¶m, ESP_BLE_MESH_NIMBLE_GAP_EVENT_EVT); +} +#endif /* CONFIG_BT_NIMBLE_ENABLED && CONFIG_BLE_MESH_USE_BLE_50 */ + +#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN +void bt_mesh_ble_scan_cb_evt_to_btc(bt_mesh_ble_adv_report_t *adv_report) +{ + esp_ble_mesh_ble_cb_param_t param = {0}; + + if (adv_report == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; } - param.scan_ble_adv_pkt.adv_type = adv_type; - param.scan_ble_adv_pkt.rssi = rssi; + + memcpy(¶m.scan_ble_adv_pkt, adv_report, sizeof(bt_mesh_ble_adv_report_t)); btc_ble_mesh_ble_callback(¶m, ESP_BLE_MESH_SCAN_BLE_ADVERTISING_PKT_EVT); } @@ -157,6 +165,14 @@ void btc_ble_mesh_ble_call_handler(btc_msg_t *msg) btc_ble_mesh_ble_callback(¶m, ESP_BLE_MESH_STOP_BLE_SCANNING_COMP_EVT); break; #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ + case BTC_BLE_MESH_ACT_UPDATE_SCAN_PARAMS: + struct bt_mesh_scan_param scan_param = { + .interval = arg->scan_params.scan_interval, + .window = arg->scan_params.uncoded_scan_window, + }; + param.scan_params_update_comp.err_code = bt_mesh_scan_param_update(&scan_param); + btc_ble_mesh_ble_callback(¶m, ESP_BLE_MESH_SCAN_PARAMS_UPDATE_COMP_EVT); + break; default: return; } @@ -191,5 +207,4 @@ void btc_ble_mesh_ble_cb_handler(btc_msg_t *msg) btc_ble_mesh_ble_free_req_data(msg); } - -#endif /* CONFIG_BLE_MESH_BLE_COEX_SUPPORT */ +#endif /* (CONFIG_BLE_MESH_BLE_COEX_SUPPORT || CONFIG_BLE_MESH_USE_BLE_50) */ diff --git a/lib/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c b/lib/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c index 67d5353b..e8782500 100644 --- a/lib/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c +++ b/lib/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c @@ -10,11 +10,13 @@ #include "btc_ble_mesh_prov.h" #include "btc_ble_mesh_config_model.h" #include "btc_ble_mesh_health_model.h" -#include "btc_ble_mesh_prb_model.h" #include "btc_ble_mesh_generic_model.h" #include "btc_ble_mesh_time_scene_model.h" #include "btc_ble_mesh_sensor_model.h" #include "btc_ble_mesh_lighting_model.h" + +#if CONFIG_BLE_MESH_V11_SUPPORT +#include "btc_ble_mesh_prb_model.h" #include "btc_ble_mesh_brc_model.h" #include "btc_ble_mesh_odp_model.h" #include "btc_ble_mesh_srpl_model.h" @@ -24,8 +26,11 @@ #include "btc_ble_mesh_rpr_model.h" #include "btc_ble_mesh_df_model.h" #include "btc_ble_mesh_mbt_model.h" +#include "mesh_v1.1/utils.h" +#endif /* CONFIG_BLE_MESH_V11_SUPPORT */ #include "adv.h" +#include "scan.h" #include "mesh/kernel.h" #include "mesh/proxy.h" #include "mesh.h" @@ -65,8 +70,6 @@ #include "mesh/state_binding.h" #include "local.h" -#include "mesh_v1.1/utils.h" - #include "esp_ble_mesh_common_api.h" #include "esp_ble_mesh_provisioning_api.h" #include "esp_ble_mesh_networking_api.h" @@ -2946,6 +2949,7 @@ void btc_ble_mesh_model_call_handler(btc_msg_t *msg) .ctx.send_tag = arg->model_send.ctx->send_tag, .msg_timeout = arg->model_send.msg_timeout, }; + err = bt_mesh_client_send_msg(¶m, buf, arg->model_send.need_rsp, btc_ble_mesh_client_model_timeout_cb); bt_mesh_free_buf(buf); diff --git a/lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h b/lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h index 8c63002a..e5d21df0 100644 --- a/lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h +++ b/lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_ble.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,6 +16,30 @@ extern "C" { #endif +typedef struct { + uint8_t addr[6]; /*!< Device address */ + uint8_t addr_type; /*!< Device address type */ +#if CONFIG_BLE_MESH_USE_BLE_50 + uint8_t adv_type __attribute__((deprecated("`event_type` should be used to determine the advertising type"))); /*!< advertising type */ +#else + uint8_t adv_type; /*!< Advertising type */ +#endif + uint8_t *data; /*!< Advertising data */ + uint16_t length; /*!< Advertising data length */ + int8_t rssi; /*!< RSSI of the advertising packet */ +#if CONFIG_BLE_MESH_USE_BLE_50 + uint8_t event_type; /*!< Extended advertising event type */ + uint8_t primary_phy; /*!< Extended advertising primary PHY */ + uint8_t secondary_phy; /*!< Extended advertising secondary PHY */ + uint8_t sid; /*!< Extended advertising set ID */ + uint8_t tx_power; /*!< Extended advertising TX power */ + uint8_t dir_addr_type; /*!< Direct address type */ + uint8_t dir_addr[6]; /*!< Direct address */ + uint8_t data_status; /*!< Data type */ + uint16_t per_adv_interval; /*!< Periodic advertising interval */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +} bt_mesh_ble_adv_report_t; + typedef union { struct { esp_ble_mesh_ble_adv_param_t param; @@ -30,6 +54,10 @@ typedef union { struct { /* RFU */ } stop_ble_scan; + struct ble_mesh_scan_params { + uint16_t scan_interval; + uint16_t uncoded_scan_window; + } scan_params; } btc_ble_mesh_ble_args_t; typedef enum { @@ -37,11 +65,14 @@ typedef enum { BTC_BLE_MESH_ACT_STOP_BLE_ADV, BTC_BLE_MESH_ACT_START_BLE_SCAN, BTC_BLE_MESH_ACT_STOP_BLE_SCAN, + BTC_BLE_MESH_ACT_UPDATE_SCAN_PARAMS, } btc_ble_mesh_ble_act_t; -void bt_mesh_ble_scan_cb_evt_to_btc(const bt_mesh_addr_t *addr, - uint8_t adv_type, uint8_t data[], - uint16_t length, int8_t rssi); +void bt_mesh_ble_scan_cb_evt_to_btc(bt_mesh_ble_adv_report_t *adv_report); + +#if CONFIG_BT_NIMBLE_ENABLED && CONFIG_BLE_MESH_USE_BLE_50 +void bt_mesh_ble_nimble_evt_to_btc(struct ble_gap_event *event, void *arg); +#endif /* CONFIG_BT_NIMBLE_ENABLED && CONFIG_BLE_MESH_USE_BLE_50 */ void btc_ble_mesh_ble_call_handler(btc_msg_t *msg); diff --git a/lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h b/lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h index f2777927..741a6b31 100644 --- a/lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h +++ b/lib/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/lib/bt/esp_ble_mesh/common/atomic.c b/lib/bt/esp_ble_mesh/common/atomic.c index 723ce7e3..9c856cc3 100644 --- a/lib/bt/esp_ble_mesh/common/atomic.c +++ b/lib/bt/esp_ble_mesh/common/atomic.c @@ -13,7 +13,7 @@ /* * SPDX-FileCopyrightText: 2016 Intel Corporation * SPDX-FileCopyrightText: 2011-2014 Wind River Systems, Inc. - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -170,4 +170,18 @@ bt_mesh_atomic_val_t bt_mesh_atomic_inc(bt_mesh_atomic_t *target) return ret; } +bool bt_mesh_atomic_cas(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t excepted, bt_mesh_atomic_val_t new_val) +{ + bt_mesh_atomic_lock(); + + if (*target == excepted) { + *target = new_val; + bt_mesh_atomic_unlock(); + return true; + } + + bt_mesh_atomic_unlock(); + return false; +} + #endif /* #ifndef CONFIG_ATOMIC_OPERATIONS_BUILTIN */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/atomic.h b/lib/bt/esp_ble_mesh/common/include/mesh/atomic.h index f7283436..b2849743 100644 --- a/lib/bt/esp_ble_mesh/common/include/mesh/atomic.h +++ b/lib/bt/esp_ble_mesh/common/include/mesh/atomic.h @@ -147,6 +147,33 @@ static inline bt_mesh_atomic_val_t bt_mesh_atomic_and(bt_mesh_atomic_t *target, extern bt_mesh_atomic_val_t bt_mesh_atomic_and(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t value); #endif +/** + * @brief Atomic CAS operation. + * + * This compares the contents of @a *target + * with the contents of @a excepted. If equal, + * the operation is a read-modify-write operation + * that writes @a new_val into @a *target and return true. + * If they are not equal, the operation is a read + * and return false. + * + * @param target Address of atomic variable. + * @param excepted Value of excepted. + * @param new_val Write if target value is equal to expected one. + * + * @return + * - true: Target value updated. + * - false: Target value not updated. + */ +#ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN +static inline bool bt_mesh_atomic_cas(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t excepted, bt_mesh_atomic_val_t new_val) +{ + return __atomic_compare_exchange_n(target, &excepted, &new_val, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); +} +#else +extern bool bt_mesh_atomic_cas(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t excepted, bt_mesh_atomic_val_t new_val); +#endif + /** * @cond INTERNAL_HIDDEN */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/mutex.h b/lib/bt/esp_ble_mesh/common/include/mesh/mutex.h index ee897500..0cc47eb0 100644 --- a/lib/bt/esp_ble_mesh/common/include/mesh/mutex.h +++ b/lib/bt/esp_ble_mesh/common/include/mesh/mutex.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -32,6 +32,11 @@ void bt_mesh_r_mutex_free(bt_mesh_mutex_t *mutex); void bt_mesh_r_mutex_lock(bt_mesh_mutex_t *mutex); void bt_mesh_r_mutex_unlock(bt_mesh_mutex_t *mutex); +void bt_mesh_c_semaphore_create(bt_mesh_mutex_t *mutex, int max, int init); +void bt_mesh_c_semaphore_free(bt_mesh_mutex_t *mutex); +void bt_mesh_c_semaphore_give(bt_mesh_mutex_t *mutex); +void bt_mesh_c_semaphore_take(bt_mesh_mutex_t *mutex, uint32_t timeout); + void bt_mesh_alarm_lock(void); void bt_mesh_alarm_unlock(void); diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/queue.h b/lib/bt/esp_ble_mesh/common/include/mesh/queue.h new file mode 100644 index 00000000..021c99ba --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/include/mesh/queue.h @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_MESH_QUEUE_H_ +#define _BLE_MESH_QUEUE_H_ + +#include "mesh/kernel.h" +#include "mesh/slist.h" +#include "mesh/atomic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + QueueHandle_t handle; +#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC + StaticQueue_t *buffer; + uint8_t *storage; +#endif +} bt_mesh_queue_t; + +int bt_mesh_queue_init(bt_mesh_queue_t *queue, uint16_t queue_size, uint8_t item_size); +int bt_mesh_queue_deinit(bt_mesh_queue_t *queue); + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_QUEUE_H_ */ diff --git a/lib/bt/esp_ble_mesh/common/include/mesh/utils.h b/lib/bt/esp_ble_mesh/common/include/mesh/utils.h index 98243483..967fed2e 100644 --- a/lib/bt/esp_ble_mesh/common/include/mesh/utils.h +++ b/lib/bt/esp_ble_mesh/common/include/mesh/utils.h @@ -200,7 +200,7 @@ extern "C" { * { MY_PWM0 , MY_PWM1 } * * @param LEN The length of the sequence. Must be an integer literal less - * than 255. + * than 255 (ref: utils_loops.h). * @param F A macro function that accepts at least two arguments: * F(i, ...). @p F is called repeatedly in the expansion. * Its first argument @p i is the index in the sequence, and diff --git a/lib/bt/esp_ble_mesh/common/mutex.c b/lib/bt/esp_ble_mesh/common/mutex.c index 6c3b2bf6..3a3dedb8 100644 --- a/lib/bt/esp_ble_mesh/common/mutex.c +++ b/lib/bt/esp_ble_mesh/common/mutex.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -125,6 +125,57 @@ void bt_mesh_r_mutex_unlock(bt_mesh_mutex_t *mutex) } } +void bt_mesh_c_semaphore_free(bt_mesh_mutex_t *mutex) +{ + bt_mesh_mutex_free(mutex); +} + +void bt_mesh_c_semaphore_create(bt_mesh_mutex_t *mutex, int max, int init) +{ + if (!mutex) { + BT_ERR("Create, invalid mutex"); + return; + } + +#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC +#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL + mutex->buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT + mutex->buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#endif + __ASSERT(mutex->buffer, "Failed to create counting semaphore buffer"); + mutex->mutex = xSemaphoreCreateCountingStatic(max, init, mutex->buffer); + __ASSERT(mutex->mutex, "Failed to create static counting semaphore"); +#else /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ + mutex->mutex = xSemaphoreCreateCounting(max, init); + __ASSERT(mutex->mutex, "Failed to create counting semaphore"); +#endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ +} + +void bt_mesh_c_semaphore_take(bt_mesh_mutex_t *mutex, uint32_t timeout) +{ + if (!mutex) { + BT_ERR("Lock, invalid counting semaphore"); + return; + } + + if (mutex->mutex) { + xSemaphoreTake(mutex->mutex, timeout / portTICK_PERIOD_MS); + } +} + +void bt_mesh_c_semaphore_give(bt_mesh_mutex_t *mutex) +{ + if (!mutex) { + BT_ERR("Unlock, invalid counting semaphore"); + return; + } + + if (mutex->mutex) { + xSemaphoreGive(mutex->mutex); + } +} + void bt_mesh_alarm_lock(void) { bt_mesh_mutex_lock(&alarm_lock); diff --git a/lib/bt/esp_ble_mesh/common/queue.c b/lib/bt/esp_ble_mesh/common/queue.c new file mode 100644 index 00000000..1fc3d66a --- /dev/null +++ b/lib/bt/esp_ble_mesh/common/queue.c @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mesh/common.h" +#include "mesh/queue.h" + +int bt_mesh_queue_init(bt_mesh_queue_t *queue, uint16_t queue_size, uint8_t item_size) +{ + __ASSERT(queue && queue_size && item_size, "Invalid queue init parameters"); + +#if !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC + queue->handle = xQueueCreate(queue_size, item_size); + __ASSERT(queue->handle, "Failed to create queue"); +#else /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ +#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL + queue->buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT + queue->buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#endif + __ASSERT(queue->buffer, "Failed to create queue buffer"); +#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL + queue->storage = heap_caps_calloc_prefer(1, (queue_size * item_size), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT + queue->storage = heap_caps_calloc_prefer(1, (queue_size * item_size), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#endif + __ASSERT(queue->storage, "Failed to create queue storage"); + queue->handle = xQueueCreateStatic(queue_size, item_size, (uint8_t*)queue->storage, queue->buffer); + __ASSERT(queue->handle, "Failed to create static queue"); +#endif /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ + return 0; +} + +int bt_mesh_queue_deinit(bt_mesh_queue_t *queue) +{ + __ASSERT(queue, "Invalid queue init parameters"); + vQueueDelete(queue->handle); + queue->handle = NULL; +#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC + heap_caps_free(queue->buffer); + queue->buffer = NULL; + heap_caps_free(queue->storage); + queue->storage = NULL; +#endif + return 0; +} diff --git a/lib/bt/esp_ble_mesh/core/access.c b/lib/bt/esp_ble_mesh/core/access.c index 9606581e..3791add9 100644 --- a/lib/bt/esp_ble_mesh/core/access.c +++ b/lib/bt/esp_ble_mesh/core/access.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,7 @@ #include #include "mesh.h" +#include "tag.h" #include "adv.h" #include "lpn.h" #include "friend.h" @@ -22,7 +23,9 @@ #include "fast_prov.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #define BLE_MESH_SDU_MAX_LEN 384 @@ -814,6 +817,135 @@ static bool ready_to_send(uint16_t dst) return false; } +#if !CONFIG_BLE_MESH_V11_SUPPORT +static bool use_friend_cred(uint16_t net_idx, uint16_t dst) +{ + /* Currently LPN only supports using NetKey in bt_mesh.sub[0] */ + if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER) && + net_idx == 0 && + bt_mesh_lpn_match(dst)) { + return true; + } + + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && + bt_mesh_friend_match(net_idx, dst)) { + return true; + } + + return false; +} + +bool bt_mesh_valid_security_cred(struct bt_mesh_net_tx *tx) +{ + /* If the message is tagged with immutable-credentials, + * then the security credentials shall not be changed + * in lower layers. + * If not, later a better security credentials could be + * chosen for the message. + */ + if (!bt_mesh_tag_immutable_cred(tx->ctx->send_tag)) { + return true; + } + + if (tx->ctx->send_cred > BLE_MESH_FRIENDSHIP_CRED) { + return false; + } + + if (tx->ctx->send_cred == BLE_MESH_FRIENDSHIP_CRED && + !use_friend_cred(tx->ctx->net_idx, tx->ctx->addr)) { + return false; + } + + return true; +} + +void bt_mesh_choose_better_security_cred(struct bt_mesh_net_tx *tx) +{ + uint8_t send_cred = 0U; + uint8_t send_tag = 0U; + uint16_t net_idx = 0U; + uint16_t addr = 0U; + + send_cred = tx->ctx->send_cred; + send_tag = tx->ctx->send_tag; + net_idx = tx->ctx->net_idx; + addr = tx->ctx->addr; + + /* If the message is tagged with immutable-credentials, + * then the security credentials shall not be changed. + */ + if (bt_mesh_tag_immutable_cred(send_tag)) { + return; + } + + if (send_cred > BLE_MESH_FRIENDSHIP_CRED) { + BT_INFO("Use managed flooding security credentials"); + tx->ctx->send_cred = BLE_MESH_FLOODING_CRED; + return; + } + + if (send_cred == BLE_MESH_FRIENDSHIP_CRED) { + if (!use_friend_cred(net_idx, addr)) { + BT_INFO("Use managed flooding security credentials"); + tx->ctx->send_cred = BLE_MESH_FLOODING_CRED; + tx->ctx->send_tag = send_tag | BLE_MESH_TAG_IMMUTABLE_CRED; + } else { + /* TODO: + * For LPN, do we need to change the friendship security + * credentials to managed flooding credentials? + * If changed, this could increase the possibility that + * the corresponding Friend node receives this message. + */ + } + return; + } + + /* If the message is destinated to a LPN, the following could be + * introduced to send the message with the friendship credentials. + * + * For LPN, this optimization should not be introduced, since it + * may cause the message failed to received by the Friend node, + * using friendship credentials will make the message can not be + * relayed by other mesh nodes. + */ + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && + BLE_MESH_ADDR_IS_UNICAST(addr) && + bt_mesh_friend_match(net_idx, addr)) { + BT_INFO("Use friendship security credentials"); + tx->ctx->send_cred = BLE_MESH_FRIENDSHIP_CRED; + tx->ctx->send_tag = send_tag | BLE_MESH_TAG_IMMUTABLE_CRED; + return; + } + + /** + * Spec 3.7.3.1 + * The Low power node in friendship should use friendship security + * material. + * + * But in Spec 3.6.6.2 + * Depending on the value of the Publish Friendship Credentials Flag + * (see Section 4.2.3.4), the Low Power node model publishes messages + * using either the friendship security credentials or the managed + * flooding security credentials (see Section 3.9.6.3.1). + * + * So use the BLE_MESH_TAG_IMMUTABLE_CRED to indicate that the + * credentials of the message should not be changed when the + * message is sent by model publishing, even though the spec + * didn't require this flag to be set when model publishing. + */ + +#if CONFIG_BLE_MESH_LOW_POWER + if (BLE_MESH_ADDR_IS_UNICAST(addr) && + bt_mesh.lpn.frnd == addr && + !bt_mesh_tag_immutable_cred(send_tag)) { + tx->ctx->send_cred = BLE_MESH_FRIENDSHIP_CRED; + tx->ctx->send_tag = send_tag | BLE_MESH_TAG_IMMUTABLE_CRED; + return; + } +#endif +} +#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ + static int model_send(struct bt_mesh_model *model, struct bt_mesh_net_tx *tx, bool implicit_bind, struct net_buf_simple *msg, @@ -1108,11 +1240,13 @@ size_t bt_mesh_rx_devkey_size(void) #if CONFIG_BLE_MESH_NODE && !CONFIG_BLE_MESH_PROVISIONER if (bt_mesh_is_provisioned()) { size = 1; +#if CONFIG_BLE_MESH_RPR_SRV if (bt_mesh_dev_key_ca_valid()) { size += 1; } +#endif /* CONFIG_BLE_MESH_RPR_SRV */ } -#endif +#endif /* CONFIG_BLE_MESH_NODE && !CONFIG_BLE_MESH_PROVISIONER */ #if !CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER if (bt_mesh_is_provisioner_en()) { @@ -1122,9 +1256,11 @@ size_t bt_mesh_rx_devkey_size(void) #if CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER size = 1; +#if CONFIG_BLE_MESH_RPR_SRV if (bt_mesh_dev_key_ca_valid()) { size += 1; } +#endif /* CONFIG_BLE_MESH_RPR_SRV */ if (bt_mesh_is_provisioner_en()) { size += 1; } @@ -1156,7 +1292,9 @@ const uint8_t *bt_mesh_rx_devkey_get(size_t index, uint16_t src) #if CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PROVISIONER if (index == 0) { key = bt_mesh.dev_key; - } else if (index == 1 && bt_mesh_dev_key_ca_valid()) { + } else +#if CONFIG_BLE_MESH_RPR_SRV + if (index == 1 && bt_mesh_dev_key_ca_valid()) { /* If index == 1, there are two cases. * 1. bt_mesh_dev_key_ca_valid() is true, it should be return bt_mesh.dev_key_ca. * 2. bt_mesh_is_provisioner_en() is true, it should be return bt_mesh_provisioner_dev_key_get(src). @@ -1166,7 +1304,9 @@ const uint8_t *bt_mesh_rx_devkey_get(size_t index, uint16_t src) * Then this round of function bt_mesh_rx_devkey_get(2, src) will return bt_mesh_provisioner_dev_key_get(src). */ key = bt_mesh.dev_key_ca; - } else { + } else +#endif + { key = bt_mesh_provisioner_dev_key_get(src); } #endif diff --git a/lib/bt/esp_ble_mesh/core/adv.c b/lib/bt/esp_ble_mesh/core/adv.c index dbbda0ab..54efa0d4 100644 --- a/lib/bt/esp_ble_mesh/core/adv.c +++ b/lib/bt/esp_ble_mesh/core/adv.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,110 +23,20 @@ #include "proxy_client.h" #include "prov_pvnr.h" #include "mesh/adapter.h" +#include "adv_common.h" +#include "ble_adv.h" -/* Convert from ms to 0.625ms units */ -#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) -/* Convert from 0.625ms units to interval(ms) */ -#define ADV_SCAN_INT(val) ((val) * 5 / 8) - -/* Pre-5.0 controllers enforce a minimum interval of 100ms - * whereas 5.0+ controllers can go down to 20ms. - */ -#if CONFIG_BLE_MESH_HCI_5_0 -#define ADV_ITVL_MIN 20 -#else -#define ADV_ITVL_MIN 100 -#endif - -static const uint8_t adv_type[] = { - [BLE_MESH_ADV_PROV] = BLE_MESH_DATA_MESH_PROV, - [BLE_MESH_ADV_DATA] = BLE_MESH_DATA_MESH_MESSAGE, - [BLE_MESH_ADV_BEACON] = BLE_MESH_DATA_MESH_BEACON, - [BLE_MESH_ADV_URI] = BLE_MESH_DATA_URI, -}; - -NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BLE_MESH_ADV_BUF_COUNT, - BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL); - -static struct bt_mesh_adv adv_pool[CONFIG_BLE_MESH_ADV_BUF_COUNT]; - -struct bt_mesh_queue { - QueueHandle_t handle; -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC - StaticQueue_t *buffer; - uint8_t *storage; -#endif -}; - -static struct bt_mesh_queue adv_queue; -/* We reserve one queue item for bt_mesh_adv_update() */ -#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV -#define BLE_MESH_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT + 1) -#else -#define BLE_MESH_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + 1) -#endif +static struct bt_mesh_adv_queue *adv_queue; #if CONFIG_BLE_MESH_RELAY_ADV_BUF -NET_BUF_POOL_DEFINE(relay_adv_buf_pool, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT, - BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL); -static struct bt_mesh_adv relay_adv_pool[CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT]; - -static struct bt_mesh_queue relay_queue; #define BLE_MESH_RELAY_QUEUE_SIZE CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT static QueueSetHandle_t mesh_queue_set; #define BLE_MESH_QUEUE_SET_SIZE (BLE_MESH_ADV_QUEUE_SIZE + BLE_MESH_RELAY_QUEUE_SIZE) -#define BLE_MESH_RELAY_TIME_INTERVAL K_SECONDS(6) -#define BLE_MESH_MAX_TIME_INTERVAL 0xFFFFFFFF - -static bool ignore_relay_packet(uint32_t timestamp); #endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ -#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV -/* length + advertising data + length + scan response data */ -NET_BUF_POOL_DEFINE(ble_adv_buf_pool, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT, - ((BLE_MESH_ADV_DATA_SIZE + 3) << 1), BLE_MESH_ADV_USER_DATA_SIZE, NULL); - -static struct bt_mesh_adv ble_adv_pool[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT]; - -enum { - TIMER_INIT, /* Resend timer is initialized */ - NUM_FLAGS, -}; - -static struct ble_adv_tx { - struct bt_mesh_ble_adv_param param; - struct net_buf *buf; - struct k_delayed_work resend; - BLE_MESH_ATOMIC_DEFINE(flags, NUM_FLAGS); -} ble_adv_tx[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT]; - -#define SEND_BLE_ADV_INFINITE 0xFFFF - -#if CONFIG_BLE_MESH_DEINIT -static void bt_mesh_ble_adv_deinit(void); -#endif /* CONFIG_BLE_MESH_DEINIT */ -#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ - -struct bt_mesh_adv_task { - TaskHandle_t handle; -#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ - (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ - CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) - StaticTask_t *task; - StackType_t *stack; -#endif -}; - -static struct bt_mesh_adv_task adv_task; - -static struct bt_mesh_adv *adv_alloc(int id) -{ - return &adv_pool[id]; -} - static inline void adv_send_start(uint16_t duration, int err, const struct bt_mesh_send_cb *cb, void *cb_data) @@ -144,17 +54,6 @@ static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb, } } -uint16_t bt_mesh_pdu_duration(uint8_t xmit) -{ - uint16_t duration = 0U; - uint16_t adv_int = 0U; - - adv_int = MAX(ADV_ITVL_MIN, BLE_MESH_TRANSMIT_INT(xmit)); - duration = (BLE_MESH_TRANSMIT_COUNT(xmit) + 1) * (adv_int + 10); - - return duration; -} - static inline int adv_send(struct net_buf *buf) { const struct bt_mesh_send_cb *cb = BLE_MESH_ADV(buf)->cb; @@ -187,25 +86,41 @@ static inline int adv_send(struct net_buf *buf) param.interval_min = ADV_SCAN_UNIT(adv_int); param.interval_max = param.interval_min; +#if CONFIG_BLE_MESH_USE_BLE_50 + param.adv_duration = duration; + param.adv_count = BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1; +#endif + #if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_PROXY_SOLIC) { bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); - struct bt_mesh_adv_data solic_ad[3] = { - BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_FLAGS, (BLE_MESH_AD_GENERAL | BLE_MESH_AD_NO_BREDR)), + struct bt_mesh_adv_data solic_ad[2] = { BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_UUID16_ALL, 0x59, 0x18), BLE_MESH_ADV_DATA(BLE_MESH_DATA_SVC_DATA16, buf->data, buf->len), }; - err = bt_le_adv_start(¶m, solic_ad, 3, NULL, 0); +#if CONFIG_BLE_MESH_USE_BLE_50 + param.primary_phy = BLE_MESH_ADV_PHY_1M; + param.secondary_phy = BLE_MESH_ADV_PHY_1M; + err = bt_le_ext_adv_start(CONFIG_BLE_MESH_ADV_INST_ID, ¶m, solic_ad, ARRAY_SIZE(solic_ad), NULL, 0); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ + err = bt_le_adv_start(¶m, solic_ad, ARRAY_SIZE(solic_ad), NULL, 0); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ } else #endif { bt_mesh_adv_buf_ref_debug(__func__, buf, 4U, BLE_MESH_BUF_REF_SMALL); +#if CONFIG_BLE_MESH_USE_BLE_50 + param.primary_phy = BLE_MESH_ADV_PHY_1M; + param.secondary_phy = BLE_MESH_ADV_PHY_1M; + err = bt_le_ext_adv_start(CONFIG_BLE_MESH_ADV_INST_ID, ¶m, &ad, 1, NULL, 0); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ err = bt_le_adv_start(¶m, &ad, 1, NULL, 0); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ } #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV } else { struct bt_mesh_ble_adv_data data = {0}; - struct ble_adv_tx *tx = cb_data; + struct bt_mesh_ble_adv_tx *tx = cb_data; if (tx == NULL) { BT_ERR("Invalid adv user data"); @@ -229,7 +144,11 @@ static inline int adv_send(struct net_buf *buf) bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); +#if CONFIG_BLE_MESH_USE_BLE_50 + err = bt_mesh_ble_ext_adv_start(CONFIG_BLE_MESH_ADV_INST_ID, &tx->param, &data); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ err = bt_mesh_ble_adv_start(&tx->param, &data); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ } #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ @@ -242,9 +161,19 @@ static inline int adv_send(struct net_buf *buf) BT_DBG("Advertising started. Sleeping %u ms", duration); - k_sleep(K_MSEC(duration)); +#if CONFIG_BLE_MESH_USE_BLE_50 + if (!ble_mesh_adv_task_wait(UINT32_MAX, K_FOREVER, NULL)) { + BT_WARN("Advertising didn't finish on time"); + bt_le_ext_adv_stop(CONFIG_BLE_MESH_ADV_INST_ID); + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ + ble_mesh_adv_task_wait(K_MSEC(duration)); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +#if !CONFIG_BLE_MESH_USE_BLE_50 err = bt_le_adv_stop(); +#endif + adv_send_end(err, cb, cb_data); if (err) { BT_ERR("Stop advertising failed: err %d", err); @@ -255,15 +184,12 @@ static inline int adv_send(struct net_buf *buf) return 0; } -static inline TickType_t K_WAIT(int32_t val) -{ - return (val == K_FOREVER) ? portMAX_DELAY : (val / portTICK_PERIOD_MS); -} - static void adv_thread(void *p) { #if CONFIG_BLE_MESH_RELAY_ADV_BUF QueueSetMemberHandle_t handle = NULL; + QueueHandle_t relay_adv_handle = + bt_mesh_adv_types_mgnt_get(BLE_MESH_ADV_RELAY_DATA)->adv_q->q.handle; #endif bt_mesh_msg_t msg = {0}; struct net_buf **buf = NULL; @@ -277,28 +203,28 @@ static void adv_thread(void *p) #if !CONFIG_BLE_MESH_RELAY_ADV_BUF #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER - xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT); + xQueueReceive(adv_queue->q.handle, &msg, K_NO_WAIT); while (!(*buf)) { int32_t timeout = 0; BT_DBG("Mesh Proxy Advertising start"); timeout = bt_mesh_proxy_server_adv_start(); BT_DBG("Mesh Proxy Advertising up to %d ms", timeout); - xQueueReceive(adv_queue.handle, &msg, K_WAIT(timeout)); + xQueueReceive(adv_queue->q.handle, &msg, K_WAIT(timeout)); BT_DBG("Mesh Proxy Advertising stop"); bt_mesh_proxy_server_adv_stop(); } #else - xQueueReceive(adv_queue.handle, &msg, portMAX_DELAY); + xQueueReceive(adv_queue->q.handle, &msg, portMAX_DELAY); #endif /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */ #else /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */ #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER handle = xQueueSelectFromSet(mesh_queue_set, K_NO_WAIT); if (handle) { - if (uxQueueMessagesWaiting(adv_queue.handle)) { - xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT); - } else if (uxQueueMessagesWaiting(relay_queue.handle)) { - xQueueReceive(relay_queue.handle, &msg, K_NO_WAIT); + if (uxQueueMessagesWaiting(adv_queue->q.handle)) { + xQueueReceive(adv_queue->q.handle, &msg, K_NO_WAIT); + } else if (uxQueueMessagesWaiting(relay_adv_handle)) { + xQueueReceive(relay_adv_handle, &msg, K_NO_WAIT); } } else { while (!(*buf)) { @@ -310,10 +236,10 @@ static void adv_thread(void *p) BT_DBG("Mesh Proxy Advertising stop"); bt_mesh_proxy_server_adv_stop(); if (handle) { - if (uxQueueMessagesWaiting(adv_queue.handle)) { - xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT); - } else if (uxQueueMessagesWaiting(relay_queue.handle)) { - xQueueReceive(relay_queue.handle, &msg, K_NO_WAIT); + if (uxQueueMessagesWaiting(adv_queue->q.handle)) { + xQueueReceive(adv_queue->q.handle, &msg, K_NO_WAIT); + } else if (uxQueueMessagesWaiting(relay_adv_handle)) { + xQueueReceive(relay_adv_handle, &msg, K_NO_WAIT); } } } @@ -321,10 +247,10 @@ static void adv_thread(void *p) #else handle = xQueueSelectFromSet(mesh_queue_set, portMAX_DELAY); if (handle) { - if (uxQueueMessagesWaiting(adv_queue.handle)) { - xQueueReceive(adv_queue.handle, &msg, K_NO_WAIT); - } else if (uxQueueMessagesWaiting(relay_queue.handle)) { - xQueueReceive(relay_queue.handle, &msg, K_NO_WAIT); + if (uxQueueMessagesWaiting(adv_queue->q.handle)) { + xQueueReceive(adv_queue->q.handle, &msg, K_NO_WAIT); + } else if (uxQueueMessagesWaiting(relay_adv_handle)) { + xQueueReceive(relay_adv_handle, &msg, K_NO_WAIT); } } #endif /* (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_SERVER */ @@ -335,14 +261,13 @@ static void adv_thread(void *p) } /* busy == 0 means this was canceled */ - if (BLE_MESH_ADV(*buf)->busy) { - BLE_MESH_ADV(*buf)->busy = 0U; + if (bt_mesh_atomic_cas(&BLE_MESH_ADV_BUSY(*buf), 1, 0)) { #if !CONFIG_BLE_MESH_RELAY_ADV_BUF if (adv_send(*buf)) { BT_WARN("Failed to send adv packet"); } #else /* !CONFIG_BLE_MESH_RELAY_ADV_BUF */ - if (msg.relay && ignore_relay_packet(msg.timestamp)) { + if (msg.relay && bt_mesh_ignore_relay_packet(msg.timestamp)) { /* If the interval between "current time - msg.timestamp" is bigger than * BLE_MESH_RELAY_TIME_INTERVAL, this relay packet will not be sent. */ @@ -364,119 +289,6 @@ static void adv_thread(void *p) } } -struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool, - bt_mesh_adv_alloc_t get_id, - enum bt_mesh_adv_type type, - int32_t timeout) -{ - struct bt_mesh_adv *adv = NULL; - struct net_buf *buf = NULL; - - if (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_SUSPENDED)) { - BT_WARN("Refusing to allocate buffer while suspended"); - return NULL; - } - - buf = net_buf_alloc(pool, timeout); - if (!buf) { - return NULL; - } - - BT_DBG("pool %p, buf_count %d, uinit_count %d", - buf->pool, pool->buf_count, pool->uninit_count); - - adv = get_id(net_buf_id(buf)); - BLE_MESH_ADV(buf) = adv; - - (void)memset(adv, 0, sizeof(*adv)); - - adv->type = type; - - return buf; -} - -void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool) -{ - int i; - - if (pool == NULL) { - BT_ERR("%s, Invalid parameter", __func__); - return; - } - - for (i = 0; i < pool->buf_count; i++) { - struct net_buf *buf = &pool->__bufs[i]; - if (buf->ref > 1U) { - buf->ref = 1U; - } - net_buf_unref(buf); - } -} - -struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, int32_t timeout) -{ - return bt_mesh_adv_create_from_pool(&adv_buf_pool, adv_alloc, - type, timeout); -} - -void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf, - uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag) -{ - if (buf == NULL || func == NULL || flag >= BLE_MESH_BUF_REF_MAX) { - BT_ERR("%s, Invalid parameter", __func__); - return; - } - - switch (flag) { - case BLE_MESH_BUF_REF_EQUAL: - if (buf->ref != ref_cmp) { - BT_ERR("Unexpected ref %d in %s, expect to equal to %d", buf->ref, func, ref_cmp); - } - break; - case BLE_MESH_BUF_REF_SMALL: - if (buf->ref >= ref_cmp) { - BT_ERR("Unexpected ref %d in %s, expect to smaller than %d", buf->ref, func, ref_cmp); - } - break; - default: - break; - } -} - -static void bt_mesh_unref_buf(bt_mesh_msg_t *msg) -{ - struct net_buf *buf = NULL; - - if (msg->arg) { - buf = (struct net_buf *)msg->arg; - BLE_MESH_ADV(buf)->busy = 0U; - if (buf->ref > 1U) { - buf->ref = 1U; - } - net_buf_unref(buf); - } -} - -static void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) -{ - if (adv_queue.handle == NULL) { - BT_ERR("Invalid adv queue"); - return; - } - - if (front) { - if (xQueueSendToFront(adv_queue.handle, msg, timeout) != pdTRUE) { - BT_ERR("Failed to send item to adv queue front"); - bt_mesh_unref_buf(msg); - } - } else { - if (xQueueSend(adv_queue.handle, msg, timeout) != pdTRUE) { - BT_ERR("Failed to send item to adv queue back"); - bt_mesh_unref_buf(msg); - } - } -} - void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, const struct bt_mesh_send_cb *cb, void *cb_data) @@ -490,7 +302,7 @@ void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, BLE_MESH_ADV(buf)->cb = cb; BLE_MESH_ADV(buf)->cb_data = cb_data; - BLE_MESH_ADV(buf)->busy = 1U; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 1); BLE_MESH_ADV(buf)->xmit = xmit; bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); @@ -509,476 +321,55 @@ void bt_mesh_adv_update(void) bt_mesh_task_post(&msg, K_NO_WAIT, false); } -#if CONFIG_BLE_MESH_RELAY_ADV_BUF -static bool ignore_relay_packet(uint32_t timestamp) -{ - uint32_t now = k_uptime_get_32(); - uint32_t interval = 0U; - - if (now >= timestamp) { - interval = now - timestamp; - } else { - interval = BLE_MESH_MAX_TIME_INTERVAL - (timestamp - now) + 1; - } - - return (interval >= BLE_MESH_RELAY_TIME_INTERVAL) ? true : false; -} - -static struct bt_mesh_adv *relay_adv_alloc(int id) -{ - return &relay_adv_pool[id]; -} - -struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, int32_t timeout) -{ - return bt_mesh_adv_create_from_pool(&relay_adv_buf_pool, relay_adv_alloc, - type, timeout); -} - -static void ble_mesh_relay_task_post(bt_mesh_msg_t *msg, uint32_t timeout) -{ - QueueSetMemberHandle_t handle = NULL; - bt_mesh_msg_t old_msg = {0}; - - if (relay_queue.handle == NULL) { - BT_ERR("Invalid relay queue"); - return; - } - - if (xQueueSend(relay_queue.handle, msg, timeout) == pdTRUE) { - return; - } - - /* If failed to send packet to the relay queue(queue is full), we will - * remove the oldest packet in the queue and put the new one into it. - */ - handle = xQueueSelectFromSet(mesh_queue_set, K_NO_WAIT); - if (handle && uxQueueMessagesWaiting(relay_queue.handle)) { - BT_INFO("Full queue, remove the oldest relay packet"); - /* Remove the oldest relay packet from queue */ - if (xQueueReceive(relay_queue.handle, &old_msg, K_NO_WAIT) != pdTRUE) { - BT_ERR("Failed to remove item from relay queue"); - bt_mesh_unref_buf(msg); - return; - } - /* Unref buf used for the oldest relay packet */ - bt_mesh_unref_buf(&old_msg); - /* Send the latest relay packet to queue */ - if (xQueueSend(relay_queue.handle, msg, K_NO_WAIT) != pdTRUE) { - BT_ERR("Failed to send item to relay queue"); - bt_mesh_unref_buf(msg); - return; - } - } else { - BT_WARN("Empty queue, but failed to send the relay packet"); - bt_mesh_unref_buf(msg); - } -} - -void bt_mesh_relay_adv_send(struct net_buf *buf, uint8_t xmit, - uint16_t src, uint16_t dst, - const struct bt_mesh_send_cb *cb, - void *cb_data) -{ - bt_mesh_msg_t msg = { - .relay = true, - }; - - BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len, - bt_hex(buf->data, buf->len)); - - BLE_MESH_ADV(buf)->cb = cb; - BLE_MESH_ADV(buf)->cb_data = cb_data; - BLE_MESH_ADV(buf)->busy = 1U; - BLE_MESH_ADV(buf)->xmit = xmit; - - msg.arg = (void *)net_buf_ref(buf); - msg.src = src; - msg.dst = dst; - msg.timestamp = k_uptime_get_32(); - /* Use K_NO_WAIT here, if relay_queue is full return immediately */ - ble_mesh_relay_task_post(&msg, K_NO_WAIT); -} - -uint16_t bt_mesh_get_stored_relay_count(void) -{ - return (uint16_t)uxQueueMessagesWaiting(relay_queue.handle); -} -#endif /* #if CONFIG_BLE_MESH_RELAY_ADV_BUF */ - void bt_mesh_adv_init(void) { -#if !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC - adv_queue.handle = xQueueCreate(BLE_MESH_ADV_QUEUE_SIZE, sizeof(bt_mesh_msg_t)); - __ASSERT(adv_queue.handle, "Failed to create queue"); -#else /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL - adv_queue.buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT - adv_queue.buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#endif - __ASSERT(adv_queue.buffer, "Failed to create queue buffer"); -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL - adv_queue.storage = heap_caps_calloc_prefer(1, (BLE_MESH_ADV_QUEUE_SIZE * sizeof(bt_mesh_msg_t)), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT - adv_queue.storage = heap_caps_calloc_prefer(1, (BLE_MESH_ADV_QUEUE_SIZE * sizeof(bt_mesh_msg_t)), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#endif - __ASSERT(adv_queue.storage, "Failed to create queue storage"); - adv_queue.handle = xQueueCreateStatic(BLE_MESH_ADV_QUEUE_SIZE, sizeof(bt_mesh_msg_t), (uint8_t*)adv_queue.storage, adv_queue.buffer); - __ASSERT(adv_queue.handle, "Failed to create static queue"); -#endif /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ #if CONFIG_BLE_MESH_RELAY_ADV_BUF -#if !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC - relay_queue.handle = xQueueCreate(BLE_MESH_RELAY_QUEUE_SIZE, sizeof(bt_mesh_msg_t)); - __ASSERT(relay_queue.handle, "Failed to create relay queue"); -#else /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL - relay_queue.buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT - relay_queue.buffer = heap_caps_calloc_prefer(1, sizeof(StaticQueue_t), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + bt_mesh_relay_adv_init(); #endif - __ASSERT(relay_queue.buffer, "Failed to create relay queue buffer"); -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL - relay_queue.storage = heap_caps_calloc_prefer(1, (BLE_MESH_RELAY_QUEUE_SIZE * sizeof(bt_mesh_msg_t)), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#elif CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT - relay_queue.storage = heap_caps_calloc_prefer(1, (BLE_MESH_RELAY_QUEUE_SIZE * sizeof(bt_mesh_msg_t)), 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + bt_mesh_ble_adv_init(); #endif - __ASSERT(relay_queue.storage, "Failed to create relay queue storage"); - relay_queue.handle = xQueueCreateStatic(BLE_MESH_RELAY_QUEUE_SIZE, sizeof(bt_mesh_msg_t), (uint8_t*)relay_queue.storage, relay_queue.buffer); - __ASSERT(relay_queue.handle, "Failed to create static relay queue"); -#endif /* !CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ + bt_mesh_adv_common_init(); + adv_queue = bt_mesh_adv_queue_get(); + + assert(adv_queue && adv_queue->q.handle && adv_queue->send); +#if CONFIG_BLE_MESH_RELAY_ADV_BUF && !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + QueueHandle_t relay_adv_handle = + bt_mesh_adv_types_mgnt_get(BLE_MESH_ADV_RELAY_DATA)->adv_q->q.handle; mesh_queue_set = xQueueCreateSet(BLE_MESH_QUEUE_SET_SIZE); __ASSERT(mesh_queue_set, "Failed to create queue set"); - xQueueAddToSet(adv_queue.handle, mesh_queue_set); - xQueueAddToSet(relay_queue.handle, mesh_queue_set); -#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ + xQueueAddToSet(adv_queue->q.handle, mesh_queue_set); + xQueueAddToSet(relay_adv_handle, mesh_queue_set); +#endif -#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ - (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ - CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) - adv_task.task = heap_caps_calloc(1, sizeof(StaticTask_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); - __ASSERT(adv_task.task, "Failed to create adv thread task"); - adv_task.stack = heap_caps_calloc_prefer(1, BLE_MESH_ADV_TASK_STACK_SIZE * sizeof(StackType_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); - __ASSERT(adv_task.stack, "Failed to create adv thread stack"); - adv_task.handle = xTaskCreateStaticPinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL, - BLE_MESH_ADV_TASK_PRIO, adv_task.stack, adv_task.task, BLE_MESH_ADV_TASK_CORE); - __ASSERT(adv_task.handle, "Failed to create static adv thread"); -#else /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */ - int ret = xTaskCreatePinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL, - BLE_MESH_ADV_TASK_PRIO, &adv_task.handle, BLE_MESH_ADV_TASK_CORE); - __ASSERT(ret == pdTRUE, "Failed to create adv thread"); - (void)ret; -#endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */ + bt_mesh_adv_task_init(adv_thread); } #if CONFIG_BLE_MESH_DEINIT void bt_mesh_adv_deinit(void) { - if (adv_queue.handle == NULL) { - return; - } - - vTaskDelete(adv_task.handle); - adv_task.handle = NULL; -#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ - (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ - CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) - heap_caps_free(adv_task.stack); - adv_task.stack = NULL; - heap_caps_free(adv_task.task); - adv_task.task = NULL; -#endif + /* Adv task must be deinit first */ + bt_mesh_adv_task_deinit(); #if CONFIG_BLE_MESH_RELAY_ADV_BUF - xQueueRemoveFromSet(adv_queue.handle, mesh_queue_set); - xQueueRemoveFromSet(relay_queue.handle, mesh_queue_set); - - vQueueDelete(relay_queue.handle); - relay_queue.handle = NULL; -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC - heap_caps_free(relay_queue.buffer); - relay_queue.buffer = NULL; - heap_caps_free(relay_queue.storage); - relay_queue.storage = NULL; -#endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ - - bt_mesh_unref_buf_from_pool(&relay_adv_buf_pool); - memset(relay_adv_pool, 0, sizeof(relay_adv_pool)); + QueueHandle_t relay_adv_handle = + bt_mesh_adv_types_mgnt_get(BLE_MESH_ADV_RELAY_DATA)->adv_q->q.handle; + xQueueRemoveFromSet(adv_queue->q.handle, mesh_queue_set); + xQueueRemoveFromSet(relay_adv_handle, mesh_queue_set); vQueueDelete(mesh_queue_set); mesh_queue_set = NULL; -#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ - vQueueDelete(adv_queue.handle); - adv_queue.handle = NULL; -#if CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC - heap_caps_free(adv_queue.buffer); - adv_queue.buffer = NULL; - heap_caps_free(adv_queue.storage); - adv_queue.storage = NULL; -#endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC */ - - bt_mesh_unref_buf_from_pool(&adv_buf_pool); - memset(adv_pool, 0, sizeof(adv_pool)); + bt_mesh_relay_adv_deinit(); +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV bt_mesh_ble_adv_deinit(); #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ -} -#endif /* CONFIG_BLE_MESH_DEINIT */ - -#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV -static struct bt_mesh_adv *ble_adv_alloc(int id) -{ - return &ble_adv_pool[id]; -} - -static struct net_buf *bt_mesh_ble_adv_create(enum bt_mesh_adv_type type, int32_t timeout) -{ - return bt_mesh_adv_create_from_pool(&ble_adv_buf_pool, ble_adv_alloc, - type, timeout); -} - -static void bt_mesh_ble_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, - void *cb_data, bool front) -{ - bt_mesh_msg_t msg = { - .relay = false, - }; - - BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len, - bt_hex(buf->data, buf->len)); - - BLE_MESH_ADV(buf)->cb = cb; - BLE_MESH_ADV(buf)->cb_data = cb_data; - BLE_MESH_ADV(buf)->busy = 1U; - - bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); - - msg.arg = (void *)net_buf_ref(buf); - bt_mesh_task_post(&msg, portMAX_DELAY, front); -} - -static void ble_adv_tx_reset(struct ble_adv_tx *tx, bool unref) -{ - if (tx->buf == NULL) { - return; - } - - if (bt_mesh_atomic_test_bit(tx->flags, TIMER_INIT)) { - k_delayed_work_free(&tx->resend); - } - bt_mesh_atomic_set(tx->flags, 0); - memset(&tx->param, 0, sizeof(tx->param)); - BLE_MESH_ADV(tx->buf)->busy = 0U; - if (unref) { - net_buf_unref(tx->buf); - } - tx->buf = NULL; -} - -static void ble_adv_send_start(uint16_t duration, int err, void *cb_data) -{ - struct ble_adv_tx *tx = cb_data; - - BT_DBG("%s, duration %d, err %d", __func__, duration, err); - - /* If failed to send BLE adv packet, and param->count is not 0 - * which means the timer has been initialized, here we need to - * free the timer. - */ - if (err) { - ble_adv_tx_reset(tx, true); - } -} - -static void ble_adv_send_end(int err, void *cb_data) -{ - struct ble_adv_tx *tx = cb_data; - - BT_DBG("%s, err %d", __func__, err); - - if (err) { - ble_adv_tx_reset(tx, true); - return; - } - - if (tx->param.count) { - k_delayed_work_submit(&tx->resend, tx->param.period); - } else { - ble_adv_tx_reset(tx, true); - } -} - -static struct bt_mesh_send_cb ble_adv_send_cb = { - .start = ble_adv_send_start, - .end = ble_adv_send_end, -}; - -static void ble_adv_resend(struct k_work *work) -{ - struct ble_adv_tx *tx = CONTAINER_OF(work, - struct ble_adv_tx, - resend.work); - bool front = false; - - if (tx->buf == NULL) { - /* The advertising has been cancelled */ - return; - } - - front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false; - bt_mesh_ble_adv_send(tx->buf, &ble_adv_send_cb, tx, front); - - if (tx->param.count == SEND_BLE_ADV_INFINITE) { - /* Send the BLE advertising packet infinitely */ - return; - } - - if (tx->param.count > 0U) { - tx->param.count--; - } -} - -int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, - const struct bt_mesh_ble_adv_data *data, uint8_t *index) -{ - struct ble_adv_tx *tx = NULL; - struct net_buf *buf = NULL; - bool front = false; - - if (param == NULL || index == NULL) { - BT_ERR("%s, Invalid parameter", __func__); - return -EINVAL; - } - - if (param->adv_type != BLE_MESH_ADV_DIRECT_IND && - (param->interval < 0x20 || param->interval > 0x4000)) { - BT_ERR("Invalid adv interval 0x%04x", param->interval); - return -EINVAL; - } - - if (param->adv_type > BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { - BT_ERR("Invalid adv type 0x%02x", param->adv_type); - return -EINVAL; - } - - if (param->own_addr_type > BLE_MESH_ADDR_RANDOM_ID) { - BT_ERR("Invalid own addr type 0x%02x", param->own_addr_type); - return -EINVAL; - } - - if ((param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID || - param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID || - param->adv_type == BLE_MESH_ADV_DIRECT_IND || - param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) && - param->peer_addr_type > BLE_MESH_ADDR_RANDOM) { - BT_ERR("Invalid peer addr type 0x%02x", param->peer_addr_type); - return -EINVAL; - } - - if (data && (data->adv_data_len > 31 || data->scan_rsp_data_len > 31)) { - BT_ERR("Invalid adv data length (adv %d, scan rsp %d)", - data->adv_data_len, data->scan_rsp_data_len); - return -EINVAL; - } - - if (param->priority > BLE_MESH_BLE_ADV_PRIO_HIGH) { - BT_ERR("Invalid adv priority %d", param->priority); - return -EINVAL; - } - - if (param->duration < ADV_SCAN_INT(param->interval)) { - BT_ERR("Too small duration %dms", param->duration); - return -EINVAL; - } - - buf = bt_mesh_ble_adv_create(BLE_MESH_ADV_BLE, K_NO_WAIT); - if (!buf) { - BT_ERR("No empty ble adv buffer"); - return -ENOBUFS; - } - - /* Set advertising data and scan response data */ - memset(buf->data, 0, buf->size); - if (data) { - net_buf_add_u8(buf, data->adv_data_len); - if (data->adv_data_len) { - net_buf_add_mem(buf, data->adv_data, data->adv_data_len); - } - net_buf_add_u8(buf, data->scan_rsp_data_len); - if (data->scan_rsp_data_len) { - net_buf_add_mem(buf, data->scan_rsp_data, data->scan_rsp_data_len); - } - } - - *index = net_buf_id(buf); - tx = &ble_adv_tx[*index]; - tx->buf = buf; - memcpy(&tx->param, param, sizeof(tx->param)); - - front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false; - bt_mesh_ble_adv_send(buf, &ble_adv_send_cb, tx, front); - if (param->count) { - if (k_delayed_work_init(&tx->resend, ble_adv_resend)) { - /* If failed to create a timer, the BLE adv packet will be - * sent only once. Just give a warning here, and since the - * BLE adv packet can be sent, return 0 here. - */ - BT_WARN("Send BLE adv packet only once"); - tx->param.count = 0; - net_buf_unref(buf); - return 0; - } - bt_mesh_atomic_set_bit(tx->flags, TIMER_INIT); - } else { - /* Send the BLE advertising packet only once */ - net_buf_unref(buf); - } - - return 0; -} - -int bt_mesh_stop_ble_advertising(uint8_t index) -{ - struct ble_adv_tx *tx = NULL; - bool unref = true; - - if (index >= ARRAY_SIZE(ble_adv_tx)) { - BT_ERR("Invalid adv index %d", index); - return -EINVAL; - } - - tx = &ble_adv_tx[index]; - - if (tx->buf == NULL) { - BT_WARN("Already stopped, index %d", index); - return 0; - } - - /* busy 1, ref 1; busy 1, ref 2; - * busy 0, ref 0; busy 0, ref 1; - */ - if (BLE_MESH_ADV(tx->buf)->busy == 1U && - tx->buf->ref == 1U) { - unref = false; - } - ble_adv_tx_reset(tx, unref); - - return 0; -} -#if CONFIG_BLE_MESH_DEINIT -static void bt_mesh_ble_adv_deinit(void) -{ - for (int i = 0; i < ARRAY_SIZE(ble_adv_tx); i++) { - struct ble_adv_tx *tx = &ble_adv_tx[i]; - ble_adv_tx_reset(tx, false); - } - bt_mesh_unref_buf_from_pool(&ble_adv_buf_pool); - memset(ble_adv_pool, 0, sizeof(ble_adv_pool)); + bt_mesh_adv_common_deinit(); } #endif /* CONFIG_BLE_MESH_DEINIT */ -#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ diff --git a/lib/bt/esp_ble_mesh/core/adv.h b/lib/bt/esp_ble_mesh/core/adv.h index ab37ec3c..5770364a 100644 --- a/lib/bt/esp_ble_mesh/core/adv.h +++ b/lib/bt/esp_ble_mesh/core/adv.h @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,96 +10,30 @@ #ifndef _ADV_H_ #define _ADV_H_ +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +#include "ext_adv.h" +#else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +#include "mesh/atomic.h" #include "mesh/access.h" #include "mesh/adapter.h" +#include "mesh/utils.h" +#include "adv_common.h" #ifdef __cplusplus extern "C" { #endif -/* Maximum advertising data payload for a single data type */ -#define BLE_MESH_ADV_DATA_SIZE 29 - -/* The user data is a pointer (4 bytes) to struct bt_mesh_adv */ -#define BLE_MESH_ADV_USER_DATA_SIZE 4 - -#define BLE_MESH_ADV(buf) (*(struct bt_mesh_adv **)net_buf_user_data(buf)) - -uint16_t bt_mesh_pdu_duration(uint8_t xmit); - -typedef struct bt_mesh_msg { - bool relay; /* Flag indicates if the packet is a relayed one */ - void *arg; /* Pointer to the struct net_buf */ - uint16_t src; /* Source address for relay packets */ - uint16_t dst; /* Destination address for relay packets */ - uint32_t timestamp; /* Timestamp recorded when the relay packet is posted to queue */ -} bt_mesh_msg_t; - -enum bt_mesh_adv_type { - BLE_MESH_ADV_PROV, - BLE_MESH_ADV_DATA, - BLE_MESH_ADV_BEACON, - BLE_MESH_ADV_URI, - BLE_MESH_ADV_BLE, - BLE_MESH_ADV_PROXY_SOLIC, -}; - -struct bt_mesh_adv { - const struct bt_mesh_send_cb *cb; - void *cb_data; - - uint8_t type:3, - busy:1; - uint8_t xmit; -}; - -typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id); - -struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, int32_t timeout); - -typedef enum { - BLE_MESH_BUF_REF_EQUAL, - BLE_MESH_BUF_REF_SMALL, - BLE_MESH_BUF_REF_MAX, -} bt_mesh_buf_ref_flag_t; - -void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf, - uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag); - -struct net_buf *bt_mesh_adv_create_from_pool(struct net_buf_pool *pool, - bt_mesh_adv_alloc_t get_id, - enum bt_mesh_adv_type type, - int32_t timeout); - -void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool); - void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, const struct bt_mesh_send_cb *cb, void *cb_data); -struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, int32_t timeout); - -void bt_mesh_relay_adv_send(struct net_buf *buf, uint8_t xmit, - uint16_t src, uint16_t dst, - const struct bt_mesh_send_cb *cb, - void *cb_data); - -uint16_t bt_mesh_get_stored_relay_count(void); - void bt_mesh_adv_update(void); void bt_mesh_adv_init(void); void bt_mesh_adv_deinit(void); -#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV -int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, - const struct bt_mesh_ble_adv_data *data, uint8_t *index); - -int bt_mesh_stop_ble_advertising(uint8_t index); -#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ - #ifdef __cplusplus } #endif - +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ #endif /* _ADV_H_ */ diff --git a/lib/bt/esp_ble_mesh/core/adv_common.c b/lib/bt/esp_ble_mesh/core/adv_common.c new file mode 100644 index 00000000..4a7078d7 --- /dev/null +++ b/lib/bt/esp_ble_mesh/core/adv_common.c @@ -0,0 +1,683 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "adv_common.h" +#include "net.h" +#include "ble_adv.h" + +NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BLE_MESH_ADV_BUF_COUNT, + BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL); + +static struct bt_mesh_adv adv_pool[CONFIG_BLE_MESH_ADV_BUF_COUNT]; + +static struct bt_mesh_adv_queue adv_queue; + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF +NET_BUF_POOL_DEFINE(relay_adv_buf_pool, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT, + BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL); + +static struct bt_mesh_adv relay_adv_pool[CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT]; +struct bt_mesh_adv_queue relay_adv_queue; + +#define BLE_MESH_RELAY_TIME_INTERVAL K_SECONDS(6) +#define BLE_MESH_MAX_TIME_INTERVAL 0xFFFFFFFF + +#endif + +#if CONFIG_BLE_MESH_FRIEND +/* We reserve one extra buffer for each friendship, since we need to be able + * to resend the last sent PDU, which sits separately outside of the queue. + */ +#define FRIEND_BUF_COUNT ((CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE + 1) * \ + CONFIG_BLE_MESH_FRIEND_LPN_COUNT) + +NET_BUF_POOL_FIXED_DEFINE(friend_buf_pool, FRIEND_BUF_COUNT, + BLE_MESH_ADV_DATA_SIZE, NULL); + +bt_mesh_friend_adv_t frnd_adv_pool[FRIEND_BUF_COUNT]; + +struct bt_mesh_adv *bt_mesh_frnd_adv_buf_get(int idx) +{ + frnd_adv_pool[idx].app_idx = BLE_MESH_KEY_UNUSED; + return &frnd_adv_pool[idx].adv; +} +#endif + +struct bt_mesh_adv_task { + TaskHandle_t handle; +#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ + (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ + CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) + StaticTask_t *task; + StackType_t *stack; +#endif +}; + +static struct bt_mesh_adv_task adv_task; +static struct bt_mesh_adv_type_manager adv_types[BLE_MESH_ADV_TYPES_NUM]; + +#if CONFIG_BLE_MESH_USE_BLE_50 +static struct bt_mesh_adv_inst adv_insts[] = { + [BLE_MESH_ADV_INS] = { + .id = CONFIG_BLE_MESH_ADV_INST_ID, +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + .busy = false, +#endif + }, +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + [BLE_MESH_ADV_PROXY_INS] = { + .id = CONFIG_BLE_MESH_PROXY_ADV_INST_ID, + .busy = false, + }, +#endif +#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + [BLE_MESH_RELAY_ADV_INS] = { + .id = CONFIG_BLE_MESH_RELAY_ADV_INST_ID, + .busy = false, + }, +#endif +#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + [BLE_MESH_BLE_ADV_INS] = { + .id = CONFIG_BLE_MESH_BLE_ADV_INST_ID, + .busy = false, + }, +#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +}; + +static struct bt_mesh_adv_inst *find_adv_inst_with_inst_id(uint8_t id) +{ + for (int i = 0; i < ARRAY_SIZE(adv_insts); i++) { + if (adv_insts[i].id == id) { + return &adv_insts[i]; + } + } + + return NULL; +} + +struct bt_mesh_adv_inst *bt_mesh_get_adv_insts_set(void) +{ + return adv_insts; +} + +bool bt_mesh_is_adv_inst_used(uint8_t adv_inst_id) +{ + return (find_adv_inst_with_inst_id(adv_inst_id) != NULL); +} + +int bt_mesh_adv_inst_init(enum bt_mesh_adv_inst_type inst_type, uint8_t inst_id) +{ + if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + BT_ERR("Invalid instance type %d", inst_type); + return -EINVAL; + } + + if (inst_id == BLE_MESH_ADV_INS_UNUSED) { + BT_ERR("Invalid instance id %d", inst_id); + return -EINVAL; + } + + adv_insts[inst_type].id = inst_id; + return 0; +} + +int bt_mesh_adv_inst_deinit(enum bt_mesh_adv_inst_type inst_type) +{ + if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + BT_ERR("Invalid instance type %d", inst_type); + return -EINVAL; + } + + bt_le_ext_adv_stop(adv_insts[inst_type].id); + + adv_insts[inst_type].id = BLE_MESH_ADV_INS_UNUSED; +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + adv_insts[inst_type].spt_mask = 0; +#endif + return 0; +} + +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + +struct bt_mesh_adv *adv_alloc(int id) +{ + return &adv_pool[id]; +} + +struct bt_mesh_adv_type_manager *bt_mesh_adv_types_mgnt_get(enum bt_mesh_adv_type adv_type) +{ + return &adv_types[adv_type]; +} + +void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf, + uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag) +{ + if (buf == NULL || func == NULL || flag >= BLE_MESH_BUF_REF_MAX) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + switch (flag) { + case BLE_MESH_BUF_REF_EQUAL: + if (buf->ref != ref_cmp) { + BT_ERR("Unexpected ref %d in %s, expect to equal to %d", buf->ref, func, ref_cmp); + } + break; + case BLE_MESH_BUF_REF_SMALL: + if (buf->ref >= ref_cmp) { + BT_ERR("Unexpected ref %d in %s, expect to smaller than %d", buf->ref, func, ref_cmp); + } + break; + default: + break; + } +} + +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +void bt_mesh_adv_inst_supported_adv_type_add(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type) +{ + if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + BT_ERR("Invalid instance type %d", inst_type); + return; + } + + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("Invalid adv type %d", adv_type); + return; + } + + adv_insts[inst_type].spt_mask |= BIT(adv_type); +} + +void bt_mesh_adv_inst_supported_adv_type_rm(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type) +{ + if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + BT_ERR("Invalid instance type %d", inst_type); + return; + } + + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("Invalid adv type %d", adv_type); + return; + } + + adv_insts[inst_type].spt_mask &= ~BIT(adv_type); +} + +void bt_mesh_adv_inst_supported_adv_type_clear(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type) +{ + if (inst_type >= BLE_MESH_ADV_INS_TYPES_NUM) { + BT_ERR("Invalid instance type %d", inst_type); + return; + } + + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("Invalid adv type %d", adv_type); + return; + } + + adv_insts[inst_type].spt_mask = 0; +} +#endif + +int bt_mesh_adv_queue_init(struct bt_mesh_adv_queue *adv_queue, uint16_t queue_size, + bt_mesh_adv_queue_send_cb_t cb) +{ + if (!adv_queue || !queue_size || !cb) { + BT_ERR("Invalid param %s", __func__); + return -EINVAL; + } + + bt_mesh_queue_init(&adv_queue->q, queue_size, sizeof(bt_mesh_msg_t)); + + adv_queue->send = cb; + + return 0; +} + +int bt_mesh_adv_queue_deinit(struct bt_mesh_adv_queue *adv_queue) +{ + if (!adv_queue) { + BT_ERR("Invalid param %s", __func__); + return -EINVAL; + } + + bt_mesh_queue_deinit(&adv_queue->q); + + adv_queue->send = NULL; + + return 0; +} + +void bt_mesh_adv_type_init(enum bt_mesh_adv_type adv_type, + struct bt_mesh_adv_queue *adv_queue, + struct net_buf_pool *buf_pool, + bt_mesh_pool_allocator_t adv_alloc) +{ + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("%s Invalid adv type %d",__func__, adv_type); + return; + } + + if (!adv_queue || !buf_pool || !adv_alloc) { + BT_ERR("Invalid parameters %s", __func__); + return; + } + + adv_types[adv_type].adv_q = adv_queue; + adv_types[adv_type].pool = buf_pool; + adv_types[adv_type].pool_allocator = adv_alloc; +} + +void bt_mesh_adv_type_deinit(enum bt_mesh_adv_type adv_type) +{ + if (adv_type >= BLE_MESH_ADV_TYPES_NUM) { + BT_ERR("%s Invalid adv type %d",__func__, adv_type); + return; + } + + adv_types[adv_type].adv_q = NULL; + adv_types[adv_type].pool = NULL; + adv_types[adv_type].pool_allocator = NULL; +} + +#if CONFIG_BLE_MESH_USE_BLE_50 +int ble_mesh_adv_task_wakeup(uint32_t evt) +{ + xTaskNotify(adv_task.handle, evt, eSetBits); + return 0; +} + +bool ble_mesh_adv_task_wait(uint32_t wait_bits, uint32_t timeout, uint32_t *notify) +{ + return (xTaskNotifyWait(wait_bits, UINT32_MAX, notify, K_WAIT(timeout)) == pdTRUE); +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ +bool ble_mesh_adv_task_wait(uint32_t timeout) +{ + vTaskDelay(K_WAIT(timeout)); + return true; +} +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + +uint16_t bt_mesh_pdu_duration(uint8_t xmit) +{ + uint16_t duration = 0U; + uint16_t adv_int = 0U; + + adv_int = MAX(ADV_ITVL_MIN, BLE_MESH_TRANSMIT_INT(xmit)); + duration = (BLE_MESH_TRANSMIT_COUNT(xmit) + 1) * (adv_int + 10); + + return duration; +} + +struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type, + int32_t timeout) +{ + struct bt_mesh_adv *adv = NULL; + struct net_buf *buf = NULL; + struct net_buf_pool *pool = adv_types[type].pool; + + if (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_SUSPENDED)) { + BT_WARN("Refusing to allocate buffer while suspended"); + return NULL; + } + + if (!pool || !adv_types[type].pool_allocator) { + BT_ERR("Uninitialized adv type %d", type); + return NULL; + } + + buf = net_buf_alloc(pool, timeout); + if (!buf) { + BT_WARN("Buf alloc failed"); + return NULL; + } + + BT_DBG("pool %p, buf_count %d, uinit_count %d, ref %d", + buf->pool, pool->buf_count, pool->uninit_count, buf->ref); + + adv = adv_types[type].pool_allocator(net_buf_id(buf)); + BLE_MESH_ADV(buf) = adv; + + (void)memset(adv, 0, sizeof(*adv)); + + adv->type = type; + + return buf; +} + +void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool) +{ + if (pool == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + for (int i = 0; i < pool->buf_count; i++) { + struct net_buf *buf = &pool->__bufs[i]; + if (buf->ref > 1U) { + buf->ref = 1U; + } + net_buf_unref(buf); + } +} + +void bt_mesh_unref_buf(bt_mesh_msg_t *msg) +{ + struct net_buf *buf = NULL; + + if (msg->arg) { + buf = (struct net_buf *)msg->arg; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 0); + if (buf->ref > 1U) { + buf->ref = 1U; + } + net_buf_unref(buf); + } +} + +void bt_mesh_generic_adv_send(struct net_buf *buf, uint8_t xmit, + const struct bt_mesh_send_cb *cb, + void *cb_data, uint16_t src, + uint16_t dst, bool front) +{ + bt_mesh_msg_t msg = { + .relay = false, /* useless flag in multi-instance mode */ + }; + + BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len, + bt_hex(buf->data, buf->len)); + + BLE_MESH_ADV(buf)->cb = cb; + BLE_MESH_ADV(buf)->cb_data = cb_data; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 1); + BLE_MESH_ADV(buf)->xmit = xmit; + + bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); + + msg.arg = (void *)net_buf_ref(buf); + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_RELAY_DATA) { + msg.relay = true; + msg.src = src; + msg.dst = dst; + msg.timestamp = k_uptime_get_32(); + } +#endif + + assert(adv_types[BLE_MESH_ADV(buf)->type].adv_q && adv_types[BLE_MESH_ADV(buf)->type].adv_q->send); + + adv_types[BLE_MESH_ADV(buf)->type].adv_q->send(&msg, portMAX_DELAY, front); + +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + ble_mesh_adv_task_wakeup(ADV_TASK_PKT_SEND_EVT); +#endif +} + +struct bt_mesh_adv_queue *bt_mesh_adv_queue_get(void) +{ + return &adv_queue; +} + +void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) +{ + if (adv_queue.q.handle == NULL) { + BT_ERR("Invalid adv queue"); + return; + } + + if (front) { + if (xQueueSendToFront(adv_queue.q.handle, msg, timeout) != pdTRUE) { + BT_ERR("Failed to send item to adv queue front"); + bt_mesh_unref_buf(msg); + } + } else { + if (xQueueSend(adv_queue.q.handle, msg, timeout) != pdTRUE) { + BT_ERR("Failed to send item to adv queue back"); + bt_mesh_unref_buf(msg); + } + } +} + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF +bool bt_mesh_ignore_relay_packet(uint32_t timestamp) +{ + uint32_t now = k_uptime_get_32(); + uint32_t interval = 0U; + + if (now >= timestamp) { + interval = now - timestamp; + } else { + interval = BLE_MESH_MAX_TIME_INTERVAL - (timestamp - now) + 1; + } + + return ((interval >= BLE_MESH_RELAY_TIME_INTERVAL) ? true : false); +} + +static struct bt_mesh_adv *relay_adv_alloc(int id) +{ + return &relay_adv_pool[id]; +} + +struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, int32_t timeout) +{ + return bt_mesh_adv_create_from_pool(type, timeout); +} + +static void ble_mesh_relay_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) +{ + bt_mesh_msg_t old_msg = {0}; + + ARG_UNUSED(front); + + if (relay_adv_queue.q.handle == NULL) { + BT_ERR("Invalid relay queue"); + return; + } + + if (xQueueSend(relay_adv_queue.q.handle, msg, timeout) == pdTRUE) { + return; + } + + /* If failed to send packet to the relay queue(queue is full), we will + * remove the oldest packet in the queue and put the new one into it. + */ + if (uxQueueMessagesWaiting(relay_adv_queue.q.handle)) { + BT_INFO("Full queue, remove the oldest relay packet"); + /* Remove the oldest relay packet from queue */ + if (xQueueReceive(relay_adv_queue.q.handle, &old_msg, K_NO_WAIT) != pdTRUE) { + BT_ERR("Failed to remove item from relay queue"); + bt_mesh_unref_buf(msg); + return; + } + /* Unref buf used for the oldest relay packet */ + bt_mesh_unref_buf(&old_msg); + /* Send the latest relay packet to queue */ + if (xQueueSend(relay_adv_queue.q.handle, msg, K_NO_WAIT) != pdTRUE) { + BT_ERR("Failed to send item to relay queue"); + bt_mesh_unref_buf(msg); + return; + } + } else { + BT_WARN("Empty queue, but failed to send the relay packet"); + bt_mesh_unref_buf(msg); + } +} + +uint16_t bt_mesh_get_stored_relay_count(void) +{ + return (uint16_t)uxQueueMessagesWaiting(relay_adv_queue.q.handle); +} + +void bt_mesh_relay_adv_init(void) +{ + bt_mesh_adv_queue_init(&relay_adv_queue, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT, + ble_mesh_relay_task_post); + bt_mesh_adv_type_init(BLE_MESH_ADV_RELAY_DATA, &relay_adv_queue, + &relay_adv_buf_pool, &relay_adv_alloc); +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + bt_mesh_adv_inst_init(BLE_MESH_RELAY_ADV_INS, + CONFIG_BLE_MESH_RELAY_ADV_INST_ID); + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_RELAY_DATA); +#else +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_RELAY_DATA); +#endif +#endif /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +} +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_relay_adv_deinit(void) +{ + bt_mesh_adv_queue_deinit(&relay_adv_queue); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_RELAY_DATA); +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_RELAY_ADV_INS, BLE_MESH_ADV_RELAY_DATA); + bt_mesh_adv_inst_deinit(BLE_MESH_RELAY_ADV_INS); +#else +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_RELAY_DATA); +#endif +#endif /* CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + bt_mesh_unref_buf_from_pool(&relay_adv_buf_pool); + memset(relay_adv_pool, 0, sizeof(relay_adv_pool)); +} +#endif /* CONFIG_BLE_MESH_DEINIT */ +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ + +#if CONFIG_BLE_MESH_FRIEND +struct net_buf_pool *bt_mesh_frnd_adv_pool_get(void) +{ + return &friend_buf_pool; +} + +void bt_mesh_frnd_adv_init(void) +{ + bt_mesh_adv_type_init(BLE_MESH_ADV_FRIEND, &adv_queue, &friend_buf_pool, bt_mesh_frnd_adv_buf_get); +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_FRIEND); +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +} + +void bt_mesh_frnd_adv_deinit(void) +{ + bt_mesh_adv_type_deinit(BLE_MESH_ADV_FRIEND); + +#if CONFIG_BLE_MESH_FRIEND && CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_FRIEND); +#endif /* CONFIG_BLE_MESH_FRIEND */ + + bt_mesh_unref_buf_from_pool(&friend_buf_pool); + memset(frnd_adv_pool, 0, sizeof(frnd_adv_pool)); +} +#endif /* CONFIG_BLE_MESH_FRIEND */ + +void bt_mesh_adv_task_init(void adv_thread(void *p)) +{ + if (!adv_thread) { + BT_ERR("Invalid param %s", __func__); + return; + } + +#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ + (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ + CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) + adv_task.task = heap_caps_calloc(1, sizeof(StaticTask_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + __ASSERT(adv_task.task, "Failed to create adv thread task"); + adv_task.stack = heap_caps_calloc_prefer(1, BLE_MESH_ADV_TASK_STACK_SIZE * sizeof(StackType_t), 2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + __ASSERT(adv_task.stack, "Failed to create adv thread stack"); + adv_task.handle = xTaskCreateStaticPinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL, + BLE_MESH_ADV_TASK_PRIO, adv_task.stack, adv_task.task, BLE_MESH_ADV_TASK_CORE); + __ASSERT(adv_task.handle, "Failed to create static adv thread"); +#else /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */ + int ret = xTaskCreatePinnedToCore(adv_thread, BLE_MESH_ADV_TASK_NAME, BLE_MESH_ADV_TASK_STACK_SIZE, NULL, + BLE_MESH_ADV_TASK_PRIO, &adv_task.handle, BLE_MESH_ADV_TASK_CORE); + __ASSERT(ret == pdTRUE, "Failed to create adv thread"); + (void)ret; +#endif /* CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */ +} + +void bt_mesh_adv_common_init(void) +{ + bt_mesh_adv_queue_init(&adv_queue, BLE_MESH_ADV_QUEUE_SIZE, bt_mesh_task_post); + bt_mesh_adv_type_init(BLE_MESH_ADV_PROV, &adv_queue, &adv_buf_pool, adv_alloc); + bt_mesh_adv_type_init(BLE_MESH_ADV_DATA, &adv_queue, &adv_buf_pool, adv_alloc); + bt_mesh_adv_type_init(BLE_MESH_ADV_BEACON, &adv_queue, &adv_buf_pool, adv_alloc); + bt_mesh_adv_type_init(BLE_MESH_ADV_URI, &adv_queue, &adv_buf_pool, adv_alloc); +#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX + bt_mesh_adv_type_init(BLE_MESH_ADV_PROXY_SOLIC, &adv_queue, &adv_buf_pool, adv_alloc); +#endif + +#if CONFIG_BLE_MESH_USE_BLE_50 + bt_mesh_adv_inst_init(BLE_MESH_ADV_INS, CONFIG_BLE_MESH_ADV_INST_ID); +#endif + +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + /** + * Due to the limitation of the sequence number in the network layer, + * it is not possible to use multiple advertising instances to process + * data from the same message queue when sending mesh packets. + * + * Therefore, shall to check whether there are + * duplicates in the queue buffer corresponding to each advertising instance. + */ + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_PROV); + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_DATA); + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_BEACON); + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_URI); +#endif +} + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_adv_task_deinit(void) +{ + vTaskDelete(adv_task.handle); + adv_task.handle = NULL; + +#if (CONFIG_BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL && \ + (CONFIG_SPIRAM_CACHE_WORKAROUND || !CONFIG_IDF_TARGET_ESP32) && \ + CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY) + heap_caps_free(adv_task.stack); + adv_task.stack = NULL; + heap_caps_free(adv_task.task); + adv_task.task = NULL; +#endif +} + +void bt_mesh_adv_common_deinit(void) +{ + bt_mesh_adv_type_deinit(BLE_MESH_ADV_PROV); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_DATA); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_BEACON); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_URI); + + bt_mesh_adv_queue_deinit(&adv_queue); +#if CONFIG_BLE_MESH_USE_BLE_50 + bt_mesh_adv_inst_deinit(BLE_MESH_ADV_INS); +#endif + + bt_mesh_unref_buf_from_pool(&adv_buf_pool); + memset(adv_pool, 0, sizeof(adv_pool)); +} +#endif /* CONFIG_BLE_MESH_DEINIT */ diff --git a/lib/bt/esp_ble_mesh/core/adv_common.h b/lib/bt/esp_ble_mesh/core/adv_common.h new file mode 100644 index 00000000..0477e889 --- /dev/null +++ b/lib/bt/esp_ble_mesh/core/adv_common.h @@ -0,0 +1,293 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _ADV_COMMON_H_ +#define _ADV_COMMON_H_ + +#include "mesh/common.h" +#include "mesh/atomic.h" +#include "mesh/access.h" +#include "mesh/adapter.h" +#include "mesh/queue.h" +#include "mesh/timer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Pre-5.0 controllers enforce a minimum interval of 100ms + * whereas 5.0+ controllers can go down to 20ms. + */ +#if CONFIG_BLE_MESH_HCI_5_0 +#define ADV_ITVL_MIN 20 +#else +#define ADV_ITVL_MIN 100 +#endif + +/* Convert from ms to 0.625ms units */ +#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5) +/* Convert from 0.625ms units to interval(ms) */ +#define ADV_SCAN_INT(val) ((val) * 5 / 8) + +/* Maximum advertising data payload for a single data type */ +#define BLE_MESH_ADV_DATA_SIZE 29 + +/* The user data is a pointer (4 bytes) to struct bt_mesh_adv */ +#define BLE_MESH_ADV_USER_DATA_SIZE 4 + +#define BLE_MESH_ADV(buf) (*(struct bt_mesh_adv **)net_buf_user_data(buf)) +#define BLE_MESH_ADV_BUSY(buf) (BLE_MESH_ADV(buf)->busy) + +#define BLE_MESH_MSG_NET_BUF(msg) ((struct net_buf *)(msg->arg)) + +#define BLE_MESH_ADV_INS_UNUSED 0xFF + +/* We reserve one queue item for bt_mesh_adv_update() */ +#define BLE_MESH_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + 1) + +struct bt_mesh_adv { + const struct bt_mesh_send_cb *cb; + void *cb_data; + + uint8_t type; + + bt_mesh_atomic_t busy; + + uint8_t xmit; +}; + +#if CONFIG_BLE_MESH_FRIEND + +#define FRIEND_ADV(buf) CONTAINER_OF(BLE_MESH_ADV(buf), bt_mesh_friend_adv_t, adv) + +typedef struct { + struct bt_mesh_adv adv; + uint16_t app_idx; +} bt_mesh_friend_adv_t; + +#endif + +enum { +#if CONFIG_BLE_MESH_USE_BLE_50 + ADV_TASK_MESH_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_ADV_INST_ID), + +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + ADV_TASK_PROX_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_PROXY_ADV_INST_ID), +#endif + +#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + ADV_TASK_RELAY_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_RELAY_ADV_INST_ID), +#endif + +#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + ADV_TASK_BLE_ADV_INST_EVT = BIT(CONFIG_BLE_MESH_BLE_ADV_INST_ID), +#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + ADV_TASK_PROXY_ADV_UPD_EVT = BIT(30), +#endif +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + ADV_TASK_PKT_SEND_EVT = BIT(31), + ADV_TASK_EVT_MAX, +}; + +uint16_t bt_mesh_pdu_duration(uint8_t xmit); + +typedef struct bt_mesh_msg { + bool relay; /* Flag indicates if the packet is a relayed one */ + void *arg; /* Pointer to the struct net_buf */ + uint16_t src; /* Source address for relay packets */ + uint16_t dst; /* Destination address for relay packets */ + uint32_t timestamp; /* Timestamp recorded when the relay packet is posted to queue */ +} bt_mesh_msg_t; + +typedef struct bt_mesh_adv *(*bt_mesh_pool_allocator_t)(int id); +typedef void (*bt_mesh_adv_queue_send_cb_t)(bt_mesh_msg_t *msg, uint32_t timeout, bool front); + +struct bt_mesh_adv_queue { + bt_mesh_queue_t q; + bt_mesh_adv_queue_send_cb_t send; +}; + +struct bt_mesh_adv_inst { + uint8_t id; +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bool busy; + struct net_buf *sending_buf; + + /* indicates that which adv_type is supported by this instance */ + uint32_t spt_mask; +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +}; + +enum bt_mesh_adv_type { + BLE_MESH_ADV_PROV, + BLE_MESH_ADV_DATA, +#if CONFIG_BLE_MESH_FRIEND + BLE_MESH_ADV_FRIEND, +#endif +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + BLE_MESH_ADV_RELAY_DATA, +#endif + BLE_MESH_ADV_BEACON, + BLE_MESH_ADV_URI, +#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX + BLE_MESH_ADV_PROXY_SOLIC, +#endif +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + BLE_MESH_ADV_BLE, +#endif + BLE_MESH_ADV_TYPES_NUM, +}; + +typedef enum { + BLE_MESH_BUF_REF_EQUAL, + BLE_MESH_BUF_REF_SMALL, + BLE_MESH_BUF_REF_MAX, +} bt_mesh_buf_ref_flag_t; + +struct bt_mesh_adv_type_manager { + struct bt_mesh_adv_queue *adv_q; + struct net_buf_pool *pool; + bt_mesh_pool_allocator_t pool_allocator; +}; + +static const uint8_t adv_type[] = { + [BLE_MESH_ADV_PROV] = BLE_MESH_DATA_MESH_PROV, + [BLE_MESH_ADV_DATA] = BLE_MESH_DATA_MESH_MESSAGE, +#if CONFIG_BLE_MESH_FRIEND + [BLE_MESH_ADV_FRIEND] = BLE_MESH_DATA_MESH_MESSAGE, +#endif +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + [BLE_MESH_ADV_RELAY_DATA] = BLE_MESH_DATA_MESH_MESSAGE, +#endif + [BLE_MESH_ADV_BEACON] = BLE_MESH_DATA_MESH_BEACON, + [BLE_MESH_ADV_URI] = BLE_MESH_DATA_URI, +}; + +static inline TickType_t K_WAIT(int32_t val) +{ + return (val == K_FOREVER) ? portMAX_DELAY : (val / portTICK_PERIOD_MS); +} + +struct bt_mesh_adv_queue *bt_mesh_adv_queue_get(void); + +struct net_buf *bt_mesh_adv_create_from_pool(enum bt_mesh_adv_type type, + int32_t timeout); + +static inline struct net_buf *bt_mesh_adv_create(enum bt_mesh_adv_type type, int32_t timeout) +{ + return bt_mesh_adv_create_from_pool(type, timeout); +} + +void bt_mesh_adv_buf_ref_debug(const char *func, struct net_buf *buf, + uint8_t ref_cmp, bt_mesh_buf_ref_flag_t flag); + +struct bt_mesh_adv_type_manager *bt_mesh_adv_types_mgnt_get(enum bt_mesh_adv_type adv_type); + +void bt_mesh_generic_adv_send(struct net_buf *buf, uint8_t xmit, + const struct bt_mesh_send_cb *cb, + void *cb_data, uint16_t src, + uint16_t dst, bool front); + +void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool); +void bt_mesh_unref_buf(bt_mesh_msg_t *msg); + +int bt_mesh_adv_queue_init(struct bt_mesh_adv_queue *adv_queue, + uint16_t queue_size, + bt_mesh_adv_queue_send_cb_t cb); + +int bt_mesh_adv_queue_deinit(struct bt_mesh_adv_queue *adv_queue); + +void bt_mesh_adv_type_init(enum bt_mesh_adv_type adv_type, + struct bt_mesh_adv_queue *adv_queue, + struct net_buf_pool *buf_pool, + bt_mesh_pool_allocator_t adv_alloc); + +void bt_mesh_adv_type_deinit(enum bt_mesh_adv_type adv_type); + +void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front); + +#if CONFIG_BLE_MESH_USE_BLE_50 +struct bt_mesh_adv_inst * bt_mesh_get_adv_insts_set(void); +int bt_mesh_adv_inst_init(enum bt_mesh_adv_inst_type inst_type, uint8_t inst_id); +int bt_mesh_adv_inst_deinit(enum bt_mesh_adv_inst_type inst_type); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +void bt_mesh_adv_inst_supported_adv_type_add(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type); + +void bt_mesh_adv_inst_supported_adv_type_rm(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type); + +void bt_mesh_adv_inst_supported_adv_type_clear(enum bt_mesh_adv_inst_type inst_type, + enum bt_mesh_adv_type adv_type); +#endif + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF +void bt_mesh_relay_adv_init(void); +bool bt_mesh_ignore_relay_packet(uint32_t timestamp); +struct net_buf *bt_mesh_relay_adv_create(enum bt_mesh_adv_type type, int32_t timeout); + +static inline void bt_mesh_relay_adv_send(struct net_buf *buf, uint8_t xmit, + uint16_t src, uint16_t dst, + const struct bt_mesh_send_cb *cb, + void *cb_data) +{ + bt_mesh_generic_adv_send(buf, xmit, cb, cb_data, src, dst, false); +}; + +uint16_t bt_mesh_get_stored_relay_count(void); + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_relay_adv_deinit(void); +#endif +#endif /* CONFIG_BLE_MESH_RELAY_ADV_BUF */ + +#if CONFIG_BLE_MESH_FRIEND +struct bt_mesh_adv *bt_mesh_frnd_adv_buf_get(int id); +struct net_buf_pool *bt_mesh_frnd_adv_pool_get(void); +void bt_mesh_frnd_adv_init(void); +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_frnd_adv_deinit(void); +#endif /* CONFIG_BLE_MESH_DEINIT */ +#endif /* CONFIG_BLE_MESH_FRIEND */ + +void bt_mesh_adv_task_init(void adv_thread(void *p)); +void bt_mesh_adv_common_init(void); + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_adv_task_deinit(void); +void bt_mesh_adv_common_deinit(void); +#endif + +#if CONFIG_BLE_MESH_USE_BLE_50 +bool bt_mesh_is_adv_inst_used(uint8_t adv_inst_id); +bool ble_mesh_adv_task_wait(uint32_t wait_bits, TickType_t timeout, uint32_t *notify); +int ble_mesh_adv_task_wakeup(uint32_t evt); +#else +bool ble_mesh_adv_task_wait(uint32_t timeout); +#endif + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV +int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, + const struct bt_mesh_ble_adv_data *data, uint8_t *index); + +int bt_mesh_stop_ble_advertising(uint8_t index); +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ + +#ifdef __cplusplus +} +#endif + +#endif /* _ADV_COMMON_H_ */ diff --git a/lib/bt/esp_ble_mesh/core/beacon.c b/lib/bt/esp_ble_mesh/core/beacon.c index 488a3c5f..97ec6ebd 100644 --- a/lib/bt/esp_ble_mesh/core/beacon.c +++ b/lib/bt/esp_ble_mesh/core/beacon.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,7 +25,9 @@ #include "pvnr_mgmt.h" #include "mesh/common.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if defined(CONFIG_BLE_MESH_UNPROVISIONED_BEACON_INTERVAL) #define UNPROV_BEACON_INTERVAL K_SECONDS(CONFIG_BLE_MESH_UNPROVISIONED_BEACON_INTERVAL) @@ -33,7 +35,11 @@ #define UNPROV_BEACON_INTERVAL K_SECONDS(5) #endif +#if CONFIG_BLE_MESH_BQB_TEST +#define SECURE_BEACON_INTERVAL K_SECONDS(3) +#else #define SECURE_BEACON_INTERVAL K_SECONDS(10) +#endif /* 3 transmissions, 20ms interval */ #define UNPROV_XMIT BLE_MESH_TRANSMIT(2, 20) @@ -472,12 +478,13 @@ void bt_mesh_beacon_recv(struct net_buf_simple *buf, int8_t rssi) bt_mesh_provisioner_unprov_beacon_recv(buf, rssi); } - if (IS_ENABLED(CONFIG_BLE_MESH_RPR_SRV) && - bt_mesh_is_provisioned()) { +#if CONFIG_BLE_MESH_RPR_SRV + if (bt_mesh_is_provisioned()) { const bt_mesh_addr_t *addr = bt_mesh_get_unprov_dev_addr(); bt_mesh_unprov_dev_fifo_enqueue(buf->data, addr->val, bt_mesh_get_adv_type()); bt_mesh_rpr_srv_unprov_beacon_recv(buf, bt_mesh_get_adv_type(), addr, rssi); } +#endif break; case BEACON_TYPE_SECURE: secure_beacon_recv(buf); diff --git a/lib/bt/esp_ble_mesh/core/ble_adv.c b/lib/bt/esp_ble_mesh/core/ble_adv.c new file mode 100644 index 00000000..ec99efa0 --- /dev/null +++ b/lib/bt/esp_ble_mesh/core/ble_adv.c @@ -0,0 +1,323 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "ble_adv.h" +#include "mesh/common.h" +#include "mesh/buf.h" + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + +static struct bt_mesh_adv_queue ble_adv_queue; +#define BLE_MESH_BLE_ADV_QUEUE_SIZE (CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT + 1) +/* length + advertising data + length + scan response data */ +NET_BUF_POOL_DEFINE(ble_adv_buf_pool, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT, + ((BLE_MESH_ADV_DATA_SIZE + 3) << 1), BLE_MESH_ADV_USER_DATA_SIZE, NULL); + +static struct bt_mesh_adv ble_adv_pool[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT]; + +static struct bt_mesh_ble_adv_tx ble_adv_tx[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT]; + +#define SEND_BLE_ADV_INFINITE 0xFFFF + +static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front); + +static struct bt_mesh_adv *ble_adv_alloc(int id) +{ + return &ble_adv_pool[id]; +} + +static void bt_mesh_ble_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front) +{ + BT_DBG("%s", __func__); + + if (ble_adv_queue.q.handle == NULL) { + BT_ERR("Invalid adv queue"); + return; + } + + if (front) { + if (xQueueSendToFront(ble_adv_queue.q.handle, msg, timeout) != pdTRUE) { + BT_ERR("Failed to send item to adv queue front"); + bt_mesh_unref_buf(msg); + } + } else { + if (xQueueSend(ble_adv_queue.q.handle, msg, timeout) != pdTRUE) { + BT_ERR("Failed to send item to adv queue back"); + bt_mesh_unref_buf(msg); + } + } +} + +static struct net_buf *bt_mesh_ble_adv_create(enum bt_mesh_adv_type type, int32_t timeout) +{ + return bt_mesh_adv_create_from_pool(type, timeout); +} + +inline void bt_mesh_ble_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb, + void *cb_data, bool front) +{ + bt_mesh_generic_adv_send(buf, 0, cb, cb_data, BLE_MESH_ADDR_UNASSIGNED, BLE_MESH_ADDR_UNASSIGNED, front); +} + +static void ble_adv_tx_reset(struct bt_mesh_ble_adv_tx *tx, bool unref) +{ + if (tx->buf == NULL) { + return; + } + + if (bt_mesh_atomic_test_bit(tx->flags, TIMER_INIT)) { + k_delayed_work_free(&tx->resend); + } + bt_mesh_atomic_set(tx->flags, 0); + memset(&tx->param, 0, sizeof(tx->param)); + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(tx->buf), 0); + if (unref) { + net_buf_unref(tx->buf); + } + tx->buf = NULL; +} + +static void ble_adv_send_start(uint16_t duration, int err, void *cb_data) +{ + struct bt_mesh_ble_adv_tx *tx = cb_data; + + BT_DBG("%s, duration %d, err %d", __func__, duration, err); + + /* If failed to send BLE adv packet, and param->count is not 0 + * which means the timer has been initialized, here we need to + * free the timer. + */ + if (err) { + ble_adv_tx_reset(tx, true); + } +} + +static void ble_adv_send_end(int err, void *cb_data) +{ + struct bt_mesh_ble_adv_tx *tx = cb_data; + + BT_DBG("%s, err %d", __func__, err); + + if (err) { + ble_adv_tx_reset(tx, true); + return; + } + + if (tx->param.count) { + if (tx->param.period) { + k_delayed_work_submit(&tx->resend, tx->param.period); + } else { + k_work_submit(&tx->resend.work); + } + } else { + ble_adv_tx_reset(tx, true); + } +} + +static struct bt_mesh_send_cb ble_adv_send_cb = { + .start = ble_adv_send_start, + .end = ble_adv_send_end, +}; + +static void ble_adv_resend(struct k_work *work) +{ + struct bt_mesh_ble_adv_tx *tx = CONTAINER_OF(work, struct bt_mesh_ble_adv_tx, resend.work); + bool front = false; + + if (tx->buf == NULL) { + /* The advertising has been cancelled */ + return; + } + + front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false; + bt_mesh_ble_adv_send(tx->buf, &ble_adv_send_cb, tx, front); + + if (tx->param.count == SEND_BLE_ADV_INFINITE) { + /* Send the BLE advertising packet infinitely */ + return; + } + + if (tx->param.count > 0U) { + tx->param.count--; + } +} + +int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, + const struct bt_mesh_ble_adv_data *data, uint8_t *index) +{ + struct bt_mesh_ble_adv_tx *tx = NULL; + struct net_buf *buf = NULL; + bool front = false; + + if (param == NULL || index == NULL) { + BT_ERR("%s, Invalid parameter", __func__); + return -EINVAL; + } + + if (param->adv_type != BLE_MESH_ADV_DIRECT_IND && + (param->interval < 0x20 || param->interval > 0x4000)) { + BT_ERR("Invalid adv interval 0x%04x", param->interval); + return -EINVAL; + } + + if (param->adv_type > BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { + BT_ERR("Invalid adv type 0x%02x", param->adv_type); + return -EINVAL; + } + + if (param->own_addr_type > BLE_MESH_ADDR_RANDOM_ID) { + BT_ERR("Invalid own addr type 0x%02x", param->own_addr_type); + return -EINVAL; + } + + if ((param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID || + param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID || + param->adv_type == BLE_MESH_ADV_DIRECT_IND || + param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) && + param->peer_addr_type > BLE_MESH_ADDR_RANDOM) { + BT_ERR("Invalid peer addr type 0x%02x", param->peer_addr_type); + return -EINVAL; + } + + if (data && (data->adv_data_len > 31 || data->scan_rsp_data_len > 31)) { + BT_ERR("Invalid adv data length (adv %d, scan rsp %d)", + data->adv_data_len, data->scan_rsp_data_len); + return -EINVAL; + } + + if (param->priority > BLE_MESH_BLE_ADV_PRIO_HIGH) { + BT_ERR("Invalid adv priority %d", param->priority); + return -EINVAL; + } + + if (param->duration < ADV_SCAN_INT(param->interval)) { + BT_ERR("Too small duration %dms", param->duration); + return -EINVAL; + } + + buf = bt_mesh_ble_adv_create(BLE_MESH_ADV_BLE, K_NO_WAIT); + if (!buf) { + BT_ERR("No empty ble adv buffer"); + return -ENOBUFS; + } + + /* Set advertising data and scan response data */ + memset(buf->data, 0, buf->size); + if (data) { + net_buf_add_u8(buf, data->adv_data_len); + if (data->adv_data_len) { + net_buf_add_mem(buf, data->adv_data, data->adv_data_len); + } + net_buf_add_u8(buf, data->scan_rsp_data_len); + if (data->scan_rsp_data_len) { + net_buf_add_mem(buf, data->scan_rsp_data, data->scan_rsp_data_len); + } + } + + *index = net_buf_id(buf); + tx = &ble_adv_tx[*index]; + tx->buf = buf; + memcpy(&tx->param, param, sizeof(tx->param)); + + front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false; + bt_mesh_ble_adv_send(buf, &ble_adv_send_cb, tx, front); + if (param->count) { + if (k_delayed_work_init(&tx->resend, ble_adv_resend)) { + /* If failed to create a timer, the BLE adv packet will be + * sent only once. Just give a warning here, and since the + * BLE adv packet can be sent, return 0 here. + */ + BT_WARN("Send BLE adv packet only once"); + tx->param.count = 0; + net_buf_unref(buf); + return 0; + } + bt_mesh_atomic_set_bit(tx->flags, TIMER_INIT); + } else { + /* Send the BLE advertising packet only once */ + net_buf_unref(buf); + } + + return 0; +} + +int bt_mesh_stop_ble_advertising(uint8_t index) +{ + struct bt_mesh_ble_adv_tx *tx = NULL; + bool unref = true; + + if (index >= ARRAY_SIZE(ble_adv_tx)) { + BT_ERR("Invalid adv index %d", index); + return -EINVAL; + } + + tx = &ble_adv_tx[index]; + + if (tx->buf == NULL) { + BT_WARN("Already stopped, index %d", index); + return 0; + } + + /* busy 1, ref 1; busy 1, ref 2; + * busy 0, ref 0; busy 0, ref 1; + */ + + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(tx->buf)) && + tx->buf->ref == 1U) { + unref = false; + } + ble_adv_tx_reset(tx, unref); + + return 0; +} + +void bt_mesh_ble_adv_init(void) +{ + bt_mesh_adv_queue_init(&ble_adv_queue, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT, bt_mesh_ble_task_post); + bt_mesh_adv_type_init(BLE_MESH_ADV_BLE, &ble_adv_queue, &ble_adv_buf_pool, ble_adv_alloc); +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + bt_mesh_adv_inst_init(BLE_MESH_BLE_ADV_INS, CONFIG_BLE_MESH_BLE_ADV_INST_ID); + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_BLE_ADV_INS, BLE_MESH_ADV_BLE); +#else +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_add(BLE_MESH_ADV_INS, BLE_MESH_ADV_BLE); +#endif +#endif /* CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +} + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_ble_adv_deinit(void) +{ + for (int i = 0; i < ARRAY_SIZE(ble_adv_tx); i++) { + struct bt_mesh_ble_adv_tx *tx = &ble_adv_tx[i]; + ble_adv_tx_reset(tx, false); + } + bt_mesh_unref_buf_from_pool(&ble_adv_buf_pool); + memset(ble_adv_pool, 0, sizeof(ble_adv_pool)); + + bt_mesh_adv_queue_deinit(&ble_adv_queue); + bt_mesh_adv_type_deinit(BLE_MESH_ADV_BLE); +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + bt_mesh_adv_inst_deinit(BLE_MESH_BLE_ADV_INS); + bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_BLE_ADV_INS, BLE_MESH_ADV_BLE); +#else +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_adv_inst_supported_adv_type_rm(BLE_MESH_ADV_INS, BLE_MESH_ADV_BLE); +#endif +#endif /* CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +} +#endif /* CONFIG_BLE_MESH_DEINIT */ +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ diff --git a/lib/bt/esp_ble_mesh/core/ble_adv.h b/lib/bt/esp_ble_mesh/core/ble_adv.h new file mode 100644 index 00000000..733320d6 --- /dev/null +++ b/lib/bt/esp_ble_mesh/core/ble_adv.h @@ -0,0 +1,54 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_ADV_H_ +#define _BLE_ADV_H_ + +#include "mesh/atomic.h" +#include "mesh/access.h" +#include "mesh/adapter.h" +#include "mesh/utils.h" +#include "adv_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + +enum { + TIMER_INIT, /* Resend timer is initialized */ + NUM_FLAGS, +}; + +struct bt_mesh_ble_adv_tx { + struct bt_mesh_ble_adv_param param; + struct net_buf *buf; + struct k_delayed_work resend; + BLE_MESH_ATOMIC_DEFINE(flags, NUM_FLAGS); +}; + +int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param, + const struct bt_mesh_ble_adv_data *data, uint8_t *index); + +int bt_mesh_stop_ble_advertising(uint8_t index); + +void bt_mesh_ble_adv_init(void); + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_ble_adv_deinit(void); +#endif + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_ADV_H_ */ diff --git a/lib/bt/esp_ble_mesh/core/bluedroid_host/adapter.c b/lib/bt/esp_ble_mesh/core/bluedroid_host/adapter.c index e0fc33b4..db962097 100644 --- a/lib/bt/esp_ble_mesh/core/bluedroid_host/adapter.c +++ b/lib/bt/esp_ble_mesh/core/bluedroid_host/adapter.c @@ -29,10 +29,14 @@ #include "mesh/adapter.h" #include "mesh/common.h" #include "prov_pvnr.h" +#include "scan.h" #include "net.h" #include "beacon.h" +#include "btc_ble_mesh_ble.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif struct bt_mesh_dev bt_mesh_dev; @@ -58,7 +62,10 @@ static uint8_t bt_mesh_private_key[32]; /* Scan related functions */ static bt_mesh_scan_cb_t *bt_mesh_scan_dev_found_cb; + +#if !CONFIG_BLE_MESH_USE_BLE_50 static void bt_mesh_scan_result_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data); +#endif #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER || \ @@ -102,6 +109,16 @@ static struct bt_mesh_prov_conn_cb *bt_mesh_gattc_conn_cb; static tBTA_GATTC_IF bt_mesh_gattc_if; #endif +#if CONFIG_BLE_MESH_USE_BLE_50 && \ + CONFIG_BLE_MESH_SUPPORT_BLE_ADV && \ + (!CONFIG_BLE_MESH_SUPPORT_MULTI_ADV) +static inline void bt_mesh_set_ble_adv_running(); + +static inline void bt_mesh_unset_ble_adv_running(); + +static inline bool bt_mesh_is_ble_adv_running(); +#endif + int bt_mesh_host_init(void) { return 0; @@ -136,11 +153,18 @@ void bt_mesh_hci_init(void) const uint8_t *p = controller_get_interface()->get_ble_supported_states(); uint64_t states_fh = 0, states_sh = 0; - STREAM_TO_UINT32(states_fh, p); - STREAM_TO_UINT32(states_sh, p); + + /* macro STREAM_TO_UINT32 expansion */ + states_fh = (((uint32_t)(*(p))) + ((((uint32_t)(*((p) + 1)))) << 8) + ((((uint32_t)(*((p) + 2)))) << 16) + ((((uint32_t)(*((p) + 3)))) << 24)); + (p) += 4; + + states_sh = (((uint32_t)(*(p))) + ((((uint32_t)(*((p) + 1)))) << 8) + ((((uint32_t)(*((p) + 2)))) << 16) + ((((uint32_t)(*((p) + 3)))) << 24)); + (p) += 4; + bt_mesh_dev.le.states = (states_sh << 32) | states_fh; } +#if !CONFIG_BLE_MESH_USE_BLE_50 static void bt_mesh_scan_results_change_2_bta(tBTM_INQ_RESULTS *p_inq, uint8_t *p_eir, tBTA_DM_SEARCH_CBACK *p_scan_cback) { @@ -183,6 +207,193 @@ static void bt_mesh_scan_results_cb(tBTM_INQ_RESULTS *p_inq, uint8_t *p_eir) { bt_mesh_scan_results_change_2_bta(p_inq, p_eir, bt_mesh_scan_result_callback); } +#endif + +#if CONFIG_BLE_MESH_USE_BLE_50 +extern void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, + tBTA_DM_BLE_5_GAP_CB_PARAMS *params); + +void bt_mesh_ble_ext_adv_report(tBTM_BLE_EXT_ADV_REPORT *ext_adv_report) +{ +#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN + bt_mesh_ble_adv_report_t adv_rpt = {0}; + + if (bt_mesh_ble_scan_state_get()) { + memcpy(adv_rpt.addr, ext_adv_report->addr, BLE_MESH_ADDR_LEN); + memcpy(adv_rpt.dir_addr, ext_adv_report->dir_addr, BLE_MESH_ADDR_LEN); + + adv_rpt.addr_type = ext_adv_report->addr_type; + adv_rpt.data = ext_adv_report->adv_data; + adv_rpt.length = ext_adv_report->adv_data_len; + adv_rpt.rssi = ext_adv_report->rssi; + adv_rpt.event_type = ext_adv_report->event_type; + adv_rpt.primary_phy = ext_adv_report->primary_phy; + adv_rpt.secondary_phy = ext_adv_report->secondry_phy; + adv_rpt.sid = ext_adv_report->sid; + adv_rpt.tx_power = ext_adv_report->tx_power; + adv_rpt.dir_addr_type = ext_adv_report->dir_addr_type; + adv_rpt.data_status = ext_adv_report->data_status; + adv_rpt.per_adv_interval = ext_adv_report->per_adv_interval; + + bt_mesh_ble_scan_cb_evt_to_btc(&adv_rpt); + } +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ +} + +static bool bt_mesh_scan_result_process(tBTM_BLE_EXT_ADV_REPORT *ext_adv_report) +{ + struct bt_mesh_adv_report adv_rpt = {0}; + + assert(ext_adv_report); + + adv_rpt.addr.type = ext_adv_report->addr_type; + memcpy(adv_rpt.addr.val, ext_adv_report->addr, BLE_MESH_ADDR_LEN); + adv_rpt.primary_phy = ext_adv_report->primary_phy; + adv_rpt.secondary_phy = ext_adv_report->secondry_phy; + adv_rpt.rssi = ext_adv_report->rssi; + + if (!(ext_adv_report->event_type & BTM_BLE_ADV_LEGACY_MASK)) { + return false; + } + + if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING)) { + return false; + } + + BT_DBG("Recv adv report type %04x", ext_adv_report->event_type); + + switch (ext_adv_report->event_type) { + case BLE_MESH_ADV_IND: + case BLE_MESH_ADV_DIRECT_IND: + case BLE_MESH_ADV_SCAN_IND: + case BLE_MESH_ADV_NONCONN_IND: + case BLE_MESH_ADV_SCAN_RSP: + adv_rpt.adv_type = ext_adv_report->event_type; + break; + default: + return false; + break; + } + + if (bt_mesh_scan_dev_found_cb) { + net_buf_simple_init_with_data(&adv_rpt.adv_data, ext_adv_report->adv_data, ext_adv_report->adv_data_len); + bt_mesh_scan_dev_found_cb(&adv_rpt); + if (adv_rpt.adv_data.len != ext_adv_report->adv_data_len) { + /* The advertising data has been processed by Mesh Protocol */ + return true; + } + } + return false; +} + +void ble_mesh_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, + tBTA_DM_BLE_5_GAP_CB_PARAMS *params) +{ + BT_DBG("recv event %d", event); + + switch (event) { + case BTA_DM_BLE_5_GAP_EXT_ADV_SET_PARAMS_COMPLETE_EVT: + if (!bt_mesh_is_adv_inst_used(params->set_params.instance)) { + goto transfer_to_user; + } + if (params->set_params.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_ADV_SET_PARAMS_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_EXT_ADV_DATA_SET_COMPLETE_EVT: + if (!bt_mesh_is_adv_inst_used(params->adv_data_set.instance)) { + goto transfer_to_user; + } + if (params->adv_data_set.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_ADV_DATA_SET_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT: + if (!bt_mesh_is_adv_inst_used(params->scan_rsp_data_set.instance)) { + goto transfer_to_user; + } + if (params->scan_rsp_data_set.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_EXT_ADV_START_COMPLETE_EVT: + if (!bt_mesh_is_adv_inst_used(params->adv_start.instance[0])) { + goto transfer_to_user; + } + if (params->adv_start.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_ADV_START_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_EXT_ADV_STOP_COMPLETE_EVT: + if (!bt_mesh_is_adv_inst_used(params->adv_start.instance[0])) { + goto transfer_to_user; + } + if (params->adv_start.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_ADV_STOP_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_ADV_TERMINATED_EVT: + if (!bt_mesh_is_adv_inst_used(params->adv_term.adv_handle)) { + goto transfer_to_user; + } +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(params->adv_term.adv_handle)); +#else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + if (params->adv_term.status == 0x43 || /* Limit reached */ + params->adv_term.status == 0x3C) { /* Advertising timeout */ + ble_mesh_adv_task_wakeup(ADV_TASK_MESH_ADV_INST_EVT); + } +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + /** + * This judgment is to distinguish between the termination + * events of BLE connectable broadcasting and proxy connectable + * adv under the same instance ID, that is, when the status is 0. + * + * Since the host task and adv task are currently operated in + * series, there is no need to consider competition issues between + * tasks. + * + * @attention: once multiple adv instances are used, the adv task + * and host will be asynchronous, and it is necessary to consider + * the issue of resource competition. + */ + if (bt_mesh_is_ble_adv_running() && + params->adv_term.status == 0x00) { + /* The unset operation must be performed before waking up the + * adv task; performing the unset after waking up the adv task + * could lead to resource contention issues. + */ + bt_mesh_unset_ble_adv_running(); + ble_mesh_adv_task_wakeup(ADV_TASK_MESH_ADV_INST_EVT); + } +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + break; + case BTA_DM_BLE_5_GAP_EXT_ADV_REPORT_EVT: + if (!bt_mesh_scan_result_process(¶ms->ext_adv_report)) { + bt_mesh_ble_ext_adv_report(¶ms->ext_adv_report); + } + break; + case BTA_DM_BLE_5_GAP_EXT_SCAN_START_COMPLETE_EVT: + if (params->scan_start.status != BTM_SUCCESS) { + BT_ERR("BTA_DM_BLE_5_GAP_EXT_SCAN_START_COMPLETE_EVT Failed"); + } + break; + case BTA_DM_BLE_5_GAP_EXT_SCAN_STOP_COMPLETE_EVT: + if (params->scan_stop.status != BTM_SUCCESS) { + BT_ERR("BTM_BLE_5_GAP_EXT_SCAN_START_COMPLETE_EVT Failed"); + } + break; + default: + goto transfer_to_user; + } + + return; + +transfer_to_user: + btc_ble_5_gap_callback(event, params); +} +#endif static bool valid_adv_param(const struct bt_mesh_adv_param *param) { @@ -203,7 +414,12 @@ static bool valid_adv_param(const struct bt_mesh_adv_param *param) return true; } +#if CONFIG_BLE_MESH_USE_BLE_50 +static int set_adv_data(uint16_t hci_op, const uint8_t inst_id, + const struct bt_mesh_adv_data *ad, size_t ad_len) +#else static int set_adv_data(uint16_t hci_op, const struct bt_mesh_adv_data *ad, size_t ad_len) +#endif { struct bt_mesh_hci_cp_set_adv_data param = {0}; int i; @@ -225,16 +441,22 @@ static int set_adv_data(uint16_t hci_op, const struct bt_mesh_adv_data *ad, size param.len += ad[i].data_len; } +#if CONFIG_BLE_MESH_USE_BLE_50 + BTA_DmBleGapConfigExtAdvDataRaw(hci_op == BLE_MESH_HCI_OP_SET_SCAN_RSP_DATA, + inst_id, param.len, param.data); +#else /* Set adv data and scan rsp data. */ if (hci_op == BLE_MESH_HCI_OP_SET_ADV_DATA) { BLE_MESH_BTM_CHECK_STATUS(BTM_BleWriteAdvDataRaw(param.data, param.len)); } else if (hci_op == BLE_MESH_HCI_OP_SET_SCAN_RSP_DATA) { BLE_MESH_BTM_CHECK_STATUS(BTM_BleWriteScanRspRaw(param.data, param.len)); } +#endif return 0; } +#if !CONFIG_BLE_MESH_USE_BLE_50 static void start_adv_completed_cb(uint8_t status) { #if BLE_MESH_DEV @@ -243,6 +465,7 @@ static void start_adv_completed_cb(uint8_t status) } #endif } +#endif static bool valid_scan_param(const struct bt_mesh_scan_param *param) { @@ -274,15 +497,54 @@ static bool valid_scan_param(const struct bt_mesh_scan_param *param) static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, uint8_t filter_dup, uint8_t scan_fil_policy) { +#if !CONFIG_BLE_MESH_USE_BLE_50 uint8_t addr_type_own = BLE_MESH_ADDR_PUBLIC; /* Currently only support Public Address */ tGATT_IF client_if = 0xFF; /* Default GATT interface id */ +#endif + +#if CONFIG_BLE_MESH_USE_BLE_50 + tBTA_DM_BLE_EXT_SCAN_PARAMS ext_scan_params = {0}; + + if (interval == 0 || + interval < window) { + BT_ERR("invalid scan param itvl %d win %d", interval, window); + return EINVAL; + } + + ext_scan_params.own_addr_type = BLE_MESH_ADDR_PUBLIC; + ext_scan_params.filter_policy = scan_fil_policy; + ext_scan_params.scan_duplicate = filter_dup; + if (window == 0) { + ext_scan_params.cfg_mask = BTM_BLE_GAP_EXT_SCAN_CODE_MASK; + } else if (interval > window) { + ext_scan_params.cfg_mask = BTM_BLE_GAP_EXT_SCAN_UNCODE_MASK | BTM_BLE_GAP_EXT_SCAN_CODE_MASK; + } else { + // interval == window + ext_scan_params.cfg_mask = BTM_BLE_GAP_EXT_SCAN_UNCODE_MASK; + } + + ext_scan_params.uncoded_cfg.scan_type = scan_type; + ext_scan_params.uncoded_cfg.scan_interval = interval; + ext_scan_params.uncoded_cfg.scan_window = window; + + ext_scan_params.coded_cfg.scan_type = scan_type; + ext_scan_params.coded_cfg.scan_interval = interval; + ext_scan_params.coded_cfg.scan_window = interval - window; + + BTA_DmBleGapSetExtScanParams(&ext_scan_params); + + BTM_BleGapRegisterCallback(ble_mesh_5_gap_callback); + + BTA_DmBleGapExtScan(true, 0, 0); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ BLE_MESH_BTM_CHECK_STATUS( BTM_BleSetScanFilterParams(client_if, interval, window, scan_type, addr_type_own, filter_dup, scan_fil_policy, NULL)); /* BLE Mesh scan permanently, so no duration of scan here */ BLE_MESH_BTM_CHECK_STATUS(BTM_BleScan(true, 0, bt_mesh_scan_results_cb, NULL, NULL)); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if BLE_MESH_DEV if (scan_type == BLE_MESH_SCAN_ACTIVE) { @@ -295,22 +557,32 @@ static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, return 0; } +#if !CONFIG_BLE_MESH_USE_BLE_50 static void bt_mesh_scan_result_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data) { - struct net_buf_simple buf = {0}; - bt_mesh_addr_t addr = {0}; + struct bt_mesh_adv_report adv_rpt = {0}; BT_DBG("%s, event %d", __func__, event); if (event == BTA_DM_INQ_RES_EVT) { /* TODO: How to process scan response here? PS: p_data->inq_res.scan_rsp_len */ - addr.type = p_data->inq_res.ble_addr_type; - memcpy(addr.val, p_data->inq_res.bd_addr, BLE_MESH_ADDR_LEN); - net_buf_simple_init_with_data(&buf, p_data->inq_res.p_eir, p_data->inq_res.adv_data_len); + adv_rpt.addr.type = p_data->inq_res.ble_addr_type; + adv_rpt.rssi = p_data->inq_res.rssi; + adv_rpt.adv_type = p_data->inq_res.ble_evt_type; + + memcpy(adv_rpt.addr.val, p_data->inq_res.bd_addr, BLE_MESH_ADDR_LEN); + + net_buf_simple_init_with_data(&adv_rpt.adv_data, p_data->inq_res.p_eir, p_data->inq_res.adv_data_len); if (bt_mesh_scan_dev_found_cb) { - bt_mesh_scan_dev_found_cb(&addr, p_data->inq_res.rssi, p_data->inq_res.ble_evt_type, &buf, p_data->inq_res.scan_rsp_len); + bt_mesh_scan_dev_found_cb(&adv_rpt); + + if (p_data->inq_res.scan_rsp_len) { + adv_rpt.adv_type = BLE_MESH_ADV_SCAN_RSP; + net_buf_simple_init_with_data(&adv_rpt.adv_data, p_data->inq_res.p_eir + p_data->inq_res.adv_data_len, p_data->inq_res.scan_rsp_len); + bt_mesh_scan_dev_found_cb(&adv_rpt); + } } } else if (event == BTA_DM_INQ_CMPL_EVT) { BT_INFO("Scan completed, number of scan response %d", p_data->inq_cmpl.num_resps); @@ -318,7 +590,133 @@ static void bt_mesh_scan_result_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARC BT_WARN("Unexpected scan result event %d", event); } } +#endif + +#if CONFIG_BLE_MESH_USE_BLE_50 +int bt_le_ext_adv_start(const uint8_t inst_id, + const struct bt_mesh_adv_param *param, + const struct bt_mesh_adv_data *ad, size_t ad_len, + const struct bt_mesh_adv_data *sd, size_t sd_len) +{ + tBTA_DM_BLE_GAP_EXT_ADV_PARAMS ext_adv_params = {0}; + tBTA_DM_BLE_EXT_ADV ext_adv = {0}; + uint16_t interval = 0U; + int err = 0; + + assert(param); + +#if BLE_MESH_DEV + if (bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING)) { + return -EALREADY; + } +#endif + + if (!valid_adv_param(param)) { + BT_ERR("Invalid adv parameters"); + return -EINVAL; + } + + memset(&ext_adv_params, 0, sizeof(tBTA_DM_BLE_GAP_EXT_ADV_PARAMS)); + + if (param->options & BLE_MESH_ADV_OPT_CONNECTABLE) { + ext_adv_params.type = BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_IND; + } else if (sd != NULL) { + ext_adv_params.type = BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_SCAN; + } else { + if (param->primary_phy == BLE_MESH_ADV_PHY_1M && + param->secondary_phy == BLE_MESH_ADV_PHY_1M) { + ext_adv_params.type = BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_NONCONN; + } else { + BT_ERR("Unsupported PHY: pri %d sec %d",param->primary_phy, param->secondary_phy); + return -EINVAL; + } + } + +#if CONFIG_BLE_MESH_PRB_SRV + /* NOTE: When a Mesh Private beacon is advertised, the Mesh Private beacon shall + * use a resolvable private address or a non-resolvable private address in the + * AdvA field of the advertising PDU. + */ + if (ad->type == BLE_MESH_DATA_MESH_BEACON && ad->data[0] == BEACON_TYPE_PRIVATE) { + ext_adv_params.own_addr_type = BLE_MESH_ADDR_RANDOM; + } else { + ext_adv_params.own_addr_type = BLE_MESH_ADDR_PUBLIC; + } +#else + ext_adv_params.own_addr_type = BLE_MESH_ADDR_PUBLIC; +#endif + ext_adv_params.sid = inst_id; + ext_adv_params.max_skip = 0; + ext_adv_params.tx_power = 0x7F; + ext_adv_params.scan_req_notif = false; + ext_adv_params.primary_phy = param->primary_phy; + ext_adv_params.secondary_phy = param->secondary_phy; + ext_adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL; + ext_adv_params.channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39; + + interval = param->interval_min; + +#if CONFIG_BLE_MESH_RANDOM_ADV_INTERVAL + /* If non-connectable mesh packets are transmitted with an adv interval + * not smaller than 10ms, then we will use a random adv interval between + * [interval / 2, interval] for them. + */ + if (ext_adv_params.type == BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_NONCONN + && interval >= 16) { + interval >>= 1; + interval += (bt_mesh_get_rand() % (interval + 1)); + + BT_DBG("%u->%u", param->interval_min, interval); + } +#endif + + ext_adv_params.interval_min = interval; + ext_adv_params.interval_max = interval; + + /* Check if we can start adv using BTM_BleSetAdvParamsStartAdvCheck */ + BTA_DmBleGapExtAdvSetParams(inst_id, &ext_adv_params); + + err = set_adv_data(BLE_MESH_HCI_OP_SET_ADV_DATA, inst_id, ad, ad_len); + if (err) { + BT_ERR("Failed to set adv data, err %d", err); + return err; + } + + /* + * We need to set SCAN_RSP when enabling advertising type that allows + * for Scan Requests. + * + * If sd was not provided but we enable connectable undirected + * advertising sd needs to be cleared from values set by previous calls. + * Clearing sd is done by calling set_adv_data() with NULL data and zero len. + * So following condition check is unusual but correct. + */ + if (sd && (param->options & BLE_MESH_ADV_OPT_CONNECTABLE)) { + err = set_adv_data(BLE_MESH_HCI_OP_SET_SCAN_RSP_DATA, inst_id, sd, sd_len); + if (err) { + BT_ERR("Failed to set scan rsp data err %d", err); + return err; + } + } + + ext_adv.instance = inst_id; + ext_adv.duration = param->adv_duration / 10; + ext_adv.max_events = param->adv_count; + + BTA_DmBleGapExtAdvEnable(true, 1, &ext_adv); + +#if BLE_MESH_DEV + bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); + + if (!(param->options & BLE_MESH_ADV_OPT_ONE_TIME)) { + bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_KEEP_ADVERTISING); + } +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ /* APIs functions */ int bt_le_adv_start(const struct bt_mesh_adv_param *param, const struct bt_mesh_adv_data *ad, size_t ad_len, @@ -346,7 +744,7 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, err = set_adv_data(BLE_MESH_HCI_OP_SET_ADV_DATA, ad, ad_len); if (err) { - BT_ERR("Failed to set adv data"); + BT_ERR("Failed to set adv data, err %d", err); return err; } @@ -362,7 +760,7 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, if (sd && (param->options & BLE_MESH_ADV_OPT_CONNECTABLE)) { err = set_adv_data(BLE_MESH_HCI_OP_SET_SCAN_RSP_DATA, sd, sd_len); if (err) { - BT_ERR("Failed to set scan rsp data"); + BT_ERR("Failed to set scan rsp data, err %d", err); return err; } } @@ -425,8 +823,100 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV +#if CONFIG_BLE_MESH_USE_BLE_50 +#if !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +static bool _ble_adv_running_flag; + +static inline void bt_mesh_set_ble_adv_running() +{ + _ble_adv_running_flag = true; +} + +static inline void bt_mesh_unset_ble_adv_running() +{ + _ble_adv_running_flag = false; +} + +static inline bool bt_mesh_is_ble_adv_running() +{ + return _ble_adv_running_flag == true; +} +#endif /* !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + +int bt_mesh_ble_ext_adv_start(const uint8_t inst_id, + const struct bt_mesh_ble_adv_param *param, + const struct bt_mesh_ble_adv_data *data) +{ + tBTA_DM_BLE_GAP_EXT_ADV_PARAMS ext_adv_params = {0}; + tBTA_DM_BLE_EXT_ADV ext_adv = {0}; + struct bt_mesh_hci_cp_set_adv_data set = {0}; + + if (data && param->adv_type != BLE_MESH_ADV_DIRECT_IND && + param->adv_type != BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { + if (data->adv_data_len) { + set.len = data->adv_data_len; + memcpy(set.data, data->adv_data, data->adv_data_len); + BTA_DmBleGapConfigExtAdvDataRaw(false, inst_id, set.len, set.data); + } + if (data->scan_rsp_data_len && param->adv_type != BLE_MESH_ADV_NONCONN_IND) { + set.len = data->scan_rsp_data_len; + memcpy(set.data, data->scan_rsp_data, data->scan_rsp_data_len); + BTA_DmBleGapConfigExtAdvDataRaw(true, inst_id, set.len, set.data); + } + } + + switch (param->adv_type) { + case BLE_MESH_ADV_IND: + case BLE_MESH_ADV_DIRECT_IND: + case BLE_MESH_ADV_SCAN_IND: + case BLE_MESH_ADV_NONCONN_IND: + case BLE_MESH_ADV_SCAN_RSP: + ext_adv_params.type = param->adv_type; + break; + default: + BT_ERR("Unsupported adv type %d", param->adv_type); + return -EINVAL; + } + + ext_adv_params.max_skip = 0; + ext_adv_params.tx_power = 0x7F; + ext_adv_params.sid = inst_id; + ext_adv_params.scan_req_notif = false; + ext_adv_params.own_addr_type = param->own_addr_type; + ext_adv_params.interval_min = param->interval; + ext_adv_params.interval_max = param->interval; + ext_adv_params.primary_phy = BLE_MESH_ADV_PHY_1M; + ext_adv_params.secondary_phy = BLE_MESH_ADV_PHY_1M; + ext_adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL; + ext_adv_params.channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39; + + if (param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID || + param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID || + param->adv_type == BLE_MESH_ADV_DIRECT_IND || + param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { + ext_adv_params.peer_addr_type = param->peer_addr_type; + memcpy(ext_adv_params.peer_addr, param->peer_addr, BLE_MESH_ADDR_LEN); + } + + ext_adv.instance = inst_id; + ext_adv.duration = param->duration; + ext_adv.max_events = param->count; + + /* Check if we can start adv using BTM_BleSetAdvParamsStartAdvCheck */ + BTA_DmBleGapExtAdvSetParams(inst_id, &ext_adv_params); + + BTA_DmBleGapExtAdvEnable(true, 1, &ext_adv); + +#if !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_set_ble_adv_running(); +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, const struct bt_mesh_ble_adv_data *data) { @@ -468,8 +958,32 @@ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#if CONFIG_BLE_MESH_USE_BLE_50 +int bt_le_ext_adv_stop(uint8_t inst_id) +{ + tBTA_DM_BLE_EXT_ADV ext_adv = {0}; + +#if BLE_MESH_DEV + bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_KEEP_ADVERTISING); + if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING)) { + return 0; + } +#endif + + ext_adv.instance = inst_id; + + BTA_DmBleGapExtAdvEnable(false, 1, &ext_adv); + +#if BLE_MESH_DEV + bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_le_adv_stop(void) { #if BLE_MESH_DEV @@ -487,6 +1001,7 @@ int bt_le_adv_stop(void) return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_le_scan_start(const struct bt_mesh_scan_param *param, bt_mesh_scan_cb_t cb) { @@ -528,7 +1043,11 @@ int bt_le_scan_stop(void) return -EALREADY; } +#if CONFIG_BLE_MESH_USE_BLE_50 + BTA_DmBleGapExtScan(false, 0 ,0); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ BLE_MESH_BTM_CHECK_STATUS(BTM_BleScan(false, 0, NULL, NULL, NULL)); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING); bt_mesh_scan_dev_found_cb = NULL; @@ -655,6 +1174,19 @@ static void bt_mesh_bta_gatts_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) /* When connection is created, advertising will be stopped automatically. */ bt_mesh_atomic_test_and_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); #endif + +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) + /* Check if this connection is created by Proxy client */ + for (size_t i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { + if (!memcmp(bt_mesh_gattc_info[i].addr.val, p_data->conn.remote_bda, BLE_MESH_ADDR_LEN)) { + BT_WARN("Already create connection with %s by proxy client", + bt_hex(p_data->conn.remote_bda, BLE_MESH_ADDR_LEN)); + return; + } + } +#endif if (bt_mesh_gatts_conn_cb != NULL && bt_mesh_gatts_conn_cb->connected != NULL) { uint8_t index = BLE_MESH_GATT_GET_CONN_ID(p_data->conn.conn_id); if (index < BLE_MESH_MAX_CONN) { @@ -1196,6 +1728,7 @@ uint16_t bt_mesh_gattc_get_service_uuid(struct bt_mesh_conn *conn) int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, uint16_t service_uuid) { + tBTA_BLE_CONN_PARAMS conn_1m_param = {0}; uint8_t zero[6] = {0}; int i; @@ -1238,21 +1771,49 @@ int bt_mesh_gattc_conn_create(const bt_mesh_addr_t *addr, uint16_t service_uuid) } if (bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING)) { +#if CONFIG_BLE_MESH_USE_BLE_50 + BTA_DmBleGapExtScan(false, 0 ,0); +#else BLE_MESH_BTM_CHECK_STATUS(BTM_BleScan(false, 0, NULL, NULL, NULL)); +#endif bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING); } BT_DBG("Create conn with %s", bt_hex(addr->val, BLE_MESH_ADDR_LEN)); +#if CONFIG_BLE_MESH_USE_BLE_50 /* Min_interval: 15ms * Max_interval: 15ms * Slave_latency: 0x0 * Supervision_timeout: 1s */ - BTA_DmSetBlePrefConnParams(bt_mesh_gattc_info[i].addr.val, 0x18, 0x18, 0x00, 0x64); - - BTA_GATTC_Open(bt_mesh_gattc_if, bt_mesh_gattc_info[i].addr.val, - bt_mesh_gattc_info[i].addr.type, true, BTA_GATT_TRANSPORT_LE, FALSE); + conn_1m_param.scan_interval = 0x0020; + conn_1m_param.scan_window = 0x0020; + conn_1m_param.interval_min = 0x18; + conn_1m_param.interval_max = 0x18; + conn_1m_param.latency = 0; + conn_1m_param.supervision_timeout = 0x64; + conn_1m_param.min_ce_len = 0; + conn_1m_param.max_ce_len = 0; + + BTA_GATTC_Enh_Open(bt_mesh_gattc_if, bt_mesh_gattc_info[i].addr.val, + bt_mesh_gattc_info[i].addr.type, true, BTA_GATT_TRANSPORT_LE, TRUE, BLE_ADDR_UNKNOWN_TYPE, + BTA_BLE_PHY_1M_MASK, &conn_1m_param, NULL, NULL); +#else + /* Min_interval: 15ms + * Max_interval: 15ms + * Slave_latency: 0x0 + * Supervision_timeout: 1s + */ + conn_1m_param.interval_min = 0x18; + conn_1m_param.interval_max = 0x18; + conn_1m_param.latency = 0; + conn_1m_param.supervision_timeout = 0x64; + + BTA_GATTC_Enh_Open(bt_mesh_gattc_if, bt_mesh_gattc_info[i].addr.val, + bt_mesh_gattc_info[i].addr.type, true, BTA_GATT_TRANSPORT_LE, FALSE, BLE_ADDR_UNKNOWN_TYPE, + BTA_BLE_PHY_1M_MASK, &conn_1m_param, NULL, NULL); +#endif return 0; } @@ -1592,8 +2153,10 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { if (bt_mesh_gattc_info[i].conn.handle == handle) { if (bt_mesh_gattc_info[i].wr_desc_done == false) { - BT_DBG("Receive notification before finishing to write ccc"); + BT_WARN("Receive notification before finishing to write ccc"); +#if !CONFIG_BLE_MESH_BQB_TEST return; +#endif } conn = &bt_mesh_gattc_info[i].conn; @@ -1653,11 +2216,15 @@ static void bt_mesh_bta_gattc_cb(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) * use BTM_BleScan() to re-enable scan. */ if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING)) { +#if CONFIG_BLE_MESH_USE_BLE_50 + BTA_DmBleGapExtScan(true, 0 ,0); +#else tBTM_STATUS status = BTM_BleScan(true, 0, bt_mesh_scan_results_cb, NULL, NULL); if (status != BTM_SUCCESS && status != BTM_CMD_STARTED) { BT_ERR("Invalid scan status %d", status); break; } +#endif bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING); } break; diff --git a/lib/bt/esp_ble_mesh/core/cfg_srv.c b/lib/bt/esp_ble_mesh/core/cfg_srv.c index 9d91cb21..fe605939 100644 --- a/lib/bt/esp_ble_mesh/core/cfg_srv.c +++ b/lib/bt/esp_ble_mesh/core/cfg_srv.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,7 +30,9 @@ #include "mesh/common.h" #include "heartbeat.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #define DEFAULT_TTL 7 @@ -38,6 +40,158 @@ static struct bt_mesh_cfg_srv *conf; static struct label labels[CONFIG_BLE_MESH_LABEL_COUNT]; +#if !CONFIG_BLE_MESH_V11_SUPPORT +const void *comp_0; + +static uint8_t bt_mesh_comp_page_check(uint8_t page, bool largest) +{ + /* If the page doesn't exist, TWO situations currently: + * 1. For Composition Data Get: + * With the Page field set to the largest page number of + * the Composition Data that the node supports and that is + * less than the Page field value of the received Config + * Composition Data Get message; + * 2. For Large Composition Data Get: + * The Page field shall be set to the largest page number + * of the Composition Data that the node supports. + */ + ARG_UNUSED(largest); + + if (page != 0) { + BT_WARN("Composition Data Page %d not exists", page); + } + + return 0; +} + +static inline uint16_t get_comp_elem_size(struct bt_mesh_elem *elem) +{ + return (4 + elem->model_count * 2 + elem->vnd_model_count * 4); +} + +static uint16_t get_comp_data_size(const struct bt_mesh_comp *comp) +{ + uint16_t size = 10; /* CID + PID + VID + CRPL + Features */ + + for (int i = 0; i < comp->elem_count; i++) { + size += get_comp_elem_size(&(comp->elem[i])); + } + + return size; +} + +static void get_comp_data(struct net_buf_simple *buf, + const struct bt_mesh_comp *comp, + bool full_element) +{ + struct bt_mesh_model *model = NULL; + struct bt_mesh_elem *elem = NULL; + uint16_t feat = 0; + + if (IS_ENABLED(CONFIG_BLE_MESH_RELAY)) { + feat |= BLE_MESH_FEAT_RELAY; + } + + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER)) { + feat |= BLE_MESH_FEAT_PROXY; + } + + if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND)) { + feat |= BLE_MESH_FEAT_FRIEND; + } + + if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER)) { + feat |= BLE_MESH_FEAT_LOW_POWER; + } + + net_buf_simple_add_le16(buf, comp->cid); + net_buf_simple_add_le16(buf, comp->pid); + net_buf_simple_add_le16(buf, comp->vid); + net_buf_simple_add_le16(buf, CONFIG_BLE_MESH_CRPL); + net_buf_simple_add_le16(buf, feat); + + for (size_t i = 0; i < comp->elem_count; i++) { + elem = &(comp->elem[i]); + + /* If "full_element" is true, which means the complete list + * of models within the element needs to fit in the data, + * otherwise the element shall not be reported. + */ + if (full_element && + net_buf_simple_tailroom(buf) < get_comp_elem_size(elem)) { + return; + } + + net_buf_simple_add_le16(buf, elem->loc); + net_buf_simple_add_u8(buf, elem->model_count); + net_buf_simple_add_u8(buf, elem->vnd_model_count); + + for (size_t j = 0; j < elem->model_count; j++) { + model = &(elem->models[j]); + net_buf_simple_add_le16(buf, model->id); + } + + for (size_t j = 0; j < elem->vnd_model_count; j++) { + model = &(elem->vnd_models[j]); + net_buf_simple_add_le16(buf, model->vnd.company); + net_buf_simple_add_le16(buf, model->vnd.id); + } + } +} + +static int fetch_comp_data(struct net_buf_simple *buf, + const struct bt_mesh_comp *comp, + uint8_t page, uint16_t offset, + bool full_element) +{ + uint16_t size = get_comp_data_size(comp); + + if (offset >= size) { + BT_WARN("Too large offset %d for comp data %d, size %d", + page, offset, size); + return 0; + } + + if (net_buf_simple_tailroom(buf) < 10 || + size - offset > net_buf_simple_tailroom(buf)) { + BT_ERR("Too small buffer for comp data %d, %d, expected %d", + page, buf->size, size - offset); + return -EINVAL; + } + + if (offset) { + struct net_buf_simple *pdu = bt_mesh_alloc_buf(size); + if (pdu == NULL) { + BT_ERR("%s, Out of memory", __func__); + return -ENOMEM; + } + + get_comp_data(pdu, comp, false); + + /* Get part of Composition Data Page 0/128 */ + net_buf_simple_add_mem(buf, pdu->data + offset, pdu->len - offset); + + bt_mesh_free_buf(pdu); + } else { + get_comp_data(buf, comp, full_element); + } + + return 0; +} + +static int bt_mesh_get_comp_data(struct net_buf_simple *buf, + uint8_t page, uint16_t offset, + bool full_element) +{ + if (page == 0) { + return fetch_comp_data(buf, comp_0, page, offset, full_element); + } + + BT_ERR("Invalid Composition Data Page %d", page); + return -EINVAL; +} +#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ + static void comp_data_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct net_buf_simple *buf) @@ -1133,7 +1287,7 @@ static struct label *va_find(const uint8_t *label_uuid, return match; } -static uint8_t va_add(uint8_t *label_uuid, uint16_t *addr) +uint8_t va_add(uint8_t *label_uuid, uint16_t *addr) { struct label *update = NULL, *free_slot = NULL; @@ -1141,6 +1295,9 @@ static uint8_t va_add(uint8_t *label_uuid, uint16_t *addr) if (update) { update->ref++; va_store(update); + if (addr) { + *addr = update->addr; + } return STATUS_SUCCESS; } @@ -1160,7 +1317,7 @@ static uint8_t va_add(uint8_t *label_uuid, uint16_t *addr) return STATUS_SUCCESS; } -static uint8_t va_del(uint8_t *label_uuid, uint16_t *addr) +uint8_t va_del(uint8_t *label_uuid, uint16_t *addr) { struct label *update = NULL; @@ -2758,7 +2915,7 @@ static void node_reset(struct bt_mesh_model *model, bt_mesh_model_msg_init(&msg, OP_NODE_RESET_STATUS); - /* Send the response first since we wont have any keys left to + /* Send the response first since we won't have any keys left to * send it later. */ if (bt_mesh_model_send(model, ctx, &msg, NULL, NULL)) { diff --git a/lib/bt/esp_ble_mesh/core/crypto.c b/lib/bt/esp_ble_mesh/core/crypto.c index 9b762fb5..2577c65e 100644 --- a/lib/bt/esp_ble_mesh/core/crypto.c +++ b/lib/bt/esp_ble_mesh/core/crypto.c @@ -22,7 +22,9 @@ #include "mesh/common.h" #include "mesh/adapter.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #define NET_MIC_LEN(pdu) (((pdu)[1] & 0x80) ? 8 : 4) #define APP_MIC_LEN(aszmic) ((aszmic) ? 8 : 4) diff --git a/lib/bt/esp_ble_mesh/core/ext_adv.c b/lib/bt/esp_ble_mesh/core/ext_adv.c new file mode 100644 index 00000000..b8b4d231 --- /dev/null +++ b/lib/bt/esp_ble_mesh/core/ext_adv.c @@ -0,0 +1,427 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "mesh/kernel.h" +#include "mesh.h" +#include "mesh/hci.h" +#include "mesh/common.h" +#include "mesh/ffs.h" +#include "ext_adv.h" +#include "beacon.h" +#include "prov_common.h" +#include "foundation.h" +#include "proxy_server.h" +#include "proxy_client.h" +#include "prov_pvnr.h" +#include "mesh/adapter.h" + +#include "adv_common.h" +#include "ble_adv.h" + +static struct bt_mesh_adv_queue *adv_queue; + +static struct bt_mesh_adv_inst *adv_insts; + +static inline void adv_send_start(uint16_t duration, int err, + const struct bt_mesh_send_cb *cb, + void *cb_data) +{ + if (cb && cb->start) { + cb->start(duration, err, cb_data); + } +} + +static inline void adv_send_end(int err, const struct bt_mesh_send_cb *cb, + void *cb_data) +{ + if (cb && cb->end) { + cb->end(err, cb_data); + } +} + +static inline int adv_send(struct bt_mesh_adv_inst *inst, uint16_t *adv_duration) +{ + struct net_buf *buf = inst->sending_buf; + const struct bt_mesh_send_cb *cb = BLE_MESH_ADV(buf)->cb; + void *cb_data = BLE_MESH_ADV(buf)->cb_data; + struct bt_mesh_adv_param param = {0}; + uint16_t duration = 0U, adv_int = 0U; + struct bt_mesh_adv_data ad = {0}; + int err = 0; + + BT_DBG("type %u len %u: %s", BLE_MESH_ADV(buf)->type, + buf->len, bt_hex(buf->data, buf->len)); + + switch (BLE_MESH_ADV(buf)->type) { + case BLE_MESH_ADV_PROV: + case BLE_MESH_ADV_DATA: +#if CONFIG_BLE_MESH_FRIEND + case BLE_MESH_ADV_FRIEND: +#endif +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + case BLE_MESH_ADV_RELAY_DATA: +#endif +#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX + case BLE_MESH_ADV_PROXY_SOLIC: +#endif + case BLE_MESH_ADV_BEACON: + case BLE_MESH_ADV_URI: { + adv_int = MAX(ADV_ITVL_MIN, + BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit)); + duration = (BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1) * + (adv_int + 10); + + BT_DBG("count %u interval %ums duration %ums", + BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1, adv_int, + duration); + + ad.type = adv_type[BLE_MESH_ADV(buf)->type]; + ad.data_len = buf->len; + ad.data = buf->data; + + param.options = 0U; + param.interval_min = ADV_SCAN_UNIT(adv_int); + param.interval_max = param.interval_min; + + param.adv_duration = duration; + param.adv_count = BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1; + + param.primary_phy = BLE_MESH_ADV_PHY_1M; + param.secondary_phy = BLE_MESH_ADV_PHY_1M; + +#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX + if (BLE_MESH_ADV(buf)->type == BLE_MESH_ADV_PROXY_SOLIC) { + bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); + struct bt_mesh_adv_data solic_ad[2] = { + BLE_MESH_ADV_DATA_BYTES(BLE_MESH_DATA_UUID16_ALL, 0x59, 0x18), + BLE_MESH_ADV_DATA(BLE_MESH_DATA_SVC_DATA16, buf->data, buf->len), + }; + err = bt_le_ext_adv_start(CONFIG_BLE_MESH_ADV_INST_ID, ¶m, solic_ad, ARRAY_SIZE(solic_ad), NULL, 0); + } else +#endif + { + bt_mesh_adv_buf_ref_debug(__func__, buf, 4U, BLE_MESH_BUF_REF_SMALL); + err = bt_le_ext_adv_start(inst->id, ¶m, &ad, 1, NULL, 0); + } + } + break; +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + case BLE_MESH_ADV_BLE: + struct bt_mesh_ble_adv_data data = {0}; + struct bt_mesh_ble_adv_tx *tx = cb_data; + + if (tx == NULL) { + BT_ERR("Invalid adv user data"); + net_buf_unref(buf); + return -EINVAL; + } + + BT_DBG("interval %dms, duration %dms, period %dms, count %d", + ADV_SCAN_INT(tx->param.interval), tx->param.duration, + tx->param.period, tx->param.count); + + data.adv_data_len = tx->buf->data[0]; + if (data.adv_data_len) { + memcpy(data.adv_data, tx->buf->data + 1, data.adv_data_len); + } + data.scan_rsp_data_len = tx->buf->data[data.adv_data_len + 1]; + if (data.scan_rsp_data_len) { + memcpy(data.scan_rsp_data, tx->buf->data + data.adv_data_len + 2, data.scan_rsp_data_len); + } + duration = tx->param.duration; + + bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); + + err = bt_mesh_ble_ext_adv_start(inst->id, &tx->param, &data); + break; +#endif + default: + BT_ERR("Error Type"); + break; + } + + adv_send_start(duration, err, cb, cb_data); + if (err) { + BT_ERR("Start advertising failed: err %d", err); + return err; + } + + *adv_duration = duration; + BT_DBG("Advertising started. %u ms", duration); + return 0; +} + +static inline int find_valid_msg_from_queue(bt_mesh_queue_t *msg_queue, bt_mesh_msg_t *msg) +{ + while(uxQueueMessagesWaiting(msg_queue->handle)) { + xQueueReceive(msg_queue->handle, msg, K_WAIT(K_FOREVER)); + + /* In the previous adv task design, only + * the *buf of messages pushed to the queue + * by adv_update would be empty, but in the + * new design, there is a new processing method + * for adv_update's messages, + * so *buf here cannot be empty. */ + assert(msg->arg); + + /* If the message is canceled for advertising, + * then continue to retrieve the next message + * from that queue. */ + if (!bt_mesh_atomic_cas(&BLE_MESH_ADV_BUSY(BLE_MESH_MSG_NET_BUF(msg)), 1, 0)) { + bt_mesh_adv_buf_ref_debug(__func__, BLE_MESH_MSG_NET_BUF(msg), 1U, BLE_MESH_BUF_REF_EQUAL); + /* Cancel the adv task's reference to this data packet. + * tips: The reference of buffer by adv_task occurs + * when the buffer is pushed into the queue. + */ + net_buf_unref(BLE_MESH_MSG_NET_BUF(msg)); + /* Avoid reading the last message in the queue, which could lead + * to pointing to an invalid buffer due to the absence of other + * messages in the queue. */ + msg->arg = NULL; + continue; + } + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + /* If the relay message should be ignored, + * then continue to retrieve the next message + * from that queue. */ + if (msg->relay && bt_mesh_ignore_relay_packet(msg->timestamp)) { + /* If the interval between "current time - msg.timestamp" is bigger than + * BLE_MESH_RELAY_TIME_INTERVAL, this relay packet will not be sent. + */ + BT_DBG("Ignore relay packet"); + net_buf_unref(BLE_MESH_MSG_NET_BUF(msg)); + msg->arg = NULL; + continue; + } +#endif + break; + } + + if (msg->arg == NULL) { + return -EINVAL; + } + + return 0; +} + +static inline int active_idle_adv_instance(uint32_t *update_evts, uint16_t *min_duration) +{ + uint32_t evts = 0; + uint16_t duration = K_FOREVER; + uint16_t cur_min_duration = K_FOREVER; + enum bt_mesh_adv_type adv_type = 0; + struct bt_mesh_adv_inst *instance = NULL; + bt_mesh_queue_t *msg_queue = NULL; + bt_mesh_msg_t msg = {0}; + uint32_t spt_mask = 0; + +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + if (!adv_insts[BLE_MESH_ADV_PROXY_INS].busy) { + BT_DBG("Mesh Proxy Advertising start"); + duration = bt_mesh_proxy_server_adv_start(); + if (duration < cur_min_duration) { + cur_min_duration = duration; + } + adv_insts[BLE_MESH_ADV_PROXY_INS].busy = true; + evts |= ADV_TASK_ADV_INST_EVT(adv_insts[BLE_MESH_ADV_PROXY_INS].id); + } +#endif + + for (int i = BLE_MESH_ADV_INS; i < BLE_MESH_ADV_INS_TYPES_NUM; i++) { + instance = &adv_insts[i]; + if (instance->busy +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + || unlikely(instance->id == CONFIG_BLE_MESH_PROXY_ADV_INST_ID) +#endif + ) { + continue; + } + + spt_mask = instance->spt_mask; + adv_type = 0; + + while(spt_mask) { + adv_type = find_lsb_set(spt_mask) - 1; + spt_mask &= ~BIT(adv_type); + msg_queue = &(bt_mesh_adv_types_mgnt_get(adv_type)->adv_q->q); + + /* When there is no new message in the queue, *buf (aka: msg.arg) + * will be empty. */ + if (find_valid_msg_from_queue(msg_queue, &msg)) { + BT_DBG("no valid message for instance %d", instance->id); + continue; + } + + instance->sending_buf = (struct net_buf *)msg.arg; + if (adv_send(instance, &duration)) { + BT_ERR("adv start failed"); + net_buf_unref(instance->sending_buf); + instance->sending_buf = NULL; + /* When this adv instance fails to broadcast, it could be + * due to some persistent issues, such as incorrect adv + * parameter settings, or it could be due to some temporary + * issues, such as memory allocation failure. Therefore, it + * is advisable to skip subsequent queue reads for this instance + * and attempt to broadcast subsequent data again next time, + * rather than disabling the adv instance. */ + break; + } + + if (duration < cur_min_duration) { + cur_min_duration = duration; + } + + instance->busy = true; + evts |= ADV_TASK_ADV_INST_EVT(adv_insts[i].id); + + /* Must be nullified to avoid affecting the next adv + * instance's judgment on whether the message queue + * is empty. */ + msg.arg = NULL; + break; + } + } + + *min_duration = cur_min_duration; + *update_evts |= evts; + + return 0; +} + +static uint32_t received_adv_evts_handle(uint32_t recv_evts) +{ + uint32_t evt = 0; + + if (!recv_evts) { + return 0; + } + + for (int i = 0; recv_evts && i < BLE_MESH_ADV_INS_TYPES_NUM; i++) { + evt = ADV_TASK_ADV_INST_EVT(adv_insts[i].id); + if (recv_evts & evt) { + recv_evts &= ~evt; +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ +CONFIG_BLE_MESH_GATT_PROXY_SERVER + if (unlikely(i == BLE_MESH_ADV_PROXY_INS)) { + BT_DBG("Mesh Proxy Advertising auto stop"); + bt_mesh_proxy_server_adv_flag_set(false); + } else +#endif + { + /* adv_send_end maybe*/ + adv_send_end(0, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb, BLE_MESH_ADV(adv_insts[i].sending_buf)->cb_data); + bt_mesh_adv_buf_ref_debug(__func__, adv_insts[i].sending_buf, 4U, BLE_MESH_BUF_REF_SMALL); + net_buf_unref(adv_insts[i].sending_buf); + adv_insts[i].sending_buf = NULL; + } + adv_insts[i].busy = false; + } + } + + return recv_evts; +} + +static void adv_thread(void *p) +{ + uint16_t adv_duration = K_FOREVER; + uint32_t recv_evts = 0; + uint32_t wait_evts = 0; + + BT_DBG("%s, starts", __func__); + + while (1) { + adv_duration = K_FOREVER; + wait_evts |= ADV_TASK_PKT_SEND_EVT; + + active_idle_adv_instance(&wait_evts, &adv_duration); + + ble_mesh_adv_task_wait(wait_evts, adv_duration, &recv_evts); + + wait_evts &= ~recv_evts; + +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + if (recv_evts & ADV_TASK_PROXY_ADV_UPD_EVT) { + adv_insts[BLE_MESH_ADV_PROXY_INS].busy = false; + recv_evts &= ~ADV_TASK_PROXY_ADV_UPD_EVT; + } +#endif + + /** + * `recv_evts == ADV_TASK_PKT_SEND_EVT` indicates that new packets + * have been placed into the queue, and the advertising instances started + * previous have not yet stopped. + */ + if (recv_evts == ADV_TASK_PKT_SEND_EVT) { + continue; + } + + recv_evts = received_adv_evts_handle(recv_evts); + + if (recv_evts) { + BT_ERR("Remain evts %08x to handle", recv_evts); + } + } +} + +void bt_mesh_adv_update(void) +{ +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + BT_DBG("Mesh Proxy Advertising stopped manually"); + bt_mesh_proxy_server_adv_stop(); + if (adv_insts[BLE_MESH_ADV_PROXY_INS].busy) { + ble_mesh_adv_task_wakeup(ADV_TASK_PROXY_ADV_UPD_EVT); + } +#endif +} + +void bt_mesh_adv_init(void) +{ + bt_mesh_adv_common_init(); + + adv_insts = bt_mesh_get_adv_insts_set(); + adv_queue = bt_mesh_adv_queue_get(); + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + bt_mesh_relay_adv_init(); +#endif + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + bt_mesh_ble_adv_init(); +#endif + + bt_mesh_adv_task_init(adv_thread); +} + +#if CONFIG_BLE_MESH_DEINIT +void bt_mesh_adv_deinit(void) +{ + bt_mesh_adv_task_deinit(); + + bt_mesh_adv_common_deinit(); + + adv_insts = NULL; + +#if CONFIG_BLE_MESH_RELAY_ADV_BUF + bt_mesh_relay_adv_deinit(); +#endif + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + bt_mesh_ble_adv_deinit(); +#endif +} +#endif /* CONFIG_BLE_MESH_DEINIT */ diff --git a/lib/bt/esp_ble_mesh/core/ext_adv.h b/lib/bt/esp_ble_mesh/core/ext_adv.h new file mode 100644 index 00000000..3004db27 --- /dev/null +++ b/lib/bt/esp_ble_mesh/core/ext_adv.h @@ -0,0 +1,39 @@ +/* Bluetooth Mesh */ + +/* + * SPDX-FileCopyrightText: 2017 Intel Corporation + * SPDX-FileContributor: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _EXT_ADV_H_ +#define _EXT_ADV_H_ + +#include "mesh/atomic.h" +#include "mesh/access.h" +#include "mesh/adapter.h" +#include "mesh/queue.h" +#include "adv_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, + const struct bt_mesh_send_cb *cb, + void *cb_data) +{ + bt_mesh_generic_adv_send(buf, xmit, cb, cb_data, BLE_MESH_ADDR_UNASSIGNED, BLE_MESH_ADDR_UNASSIGNED, false); +} + +void bt_mesh_adv_update(void); + +void bt_mesh_adv_init(void); +void bt_mesh_adv_deinit(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _EXT_ADV_H_ */ diff --git a/lib/bt/esp_ble_mesh/core/friend.c b/lib/bt/esp_ble_mesh/core/friend.c index fca3cf13..99e41cd0 100644 --- a/lib/bt/esp_ble_mesh/core/friend.c +++ b/lib/bt/esp_ble_mesh/core/friend.c @@ -21,18 +21,12 @@ #include "mesh/common.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #ifdef CONFIG_BLE_MESH_FRIEND -/* We reserve one extra buffer for each friendship, since we need to be able - * to resend the last sent PDU, which sits separately outside of the queue. - */ -#define FRIEND_BUF_COUNT ((CONFIG_BLE_MESH_FRIEND_QUEUE_SIZE + 1) * \ - CONFIG_BLE_MESH_FRIEND_LPN_COUNT) - -#define FRIEND_ADV(buf) CONTAINER_OF(BLE_MESH_ADV(buf), struct friend_adv, adv) - /* PDUs from Friend to the LPN should only be transmitted once with the * smallest possible interval (20ms). * @@ -55,14 +49,6 @@ struct friend_pdu_info { uint32_t iv_index; }; -NET_BUF_POOL_FIXED_DEFINE(friend_buf_pool, FRIEND_BUF_COUNT, - BLE_MESH_ADV_DATA_SIZE, NULL); - -static struct friend_adv { - struct bt_mesh_adv adv; - uint16_t app_idx; -} adv_pool[FRIEND_BUF_COUNT]; - enum { BLE_MESH_FRIENDSHIP_TERMINATE_ESTABLISH_FAIL, BLE_MESH_FRIENDSHIP_TERMINATE_POLL_TIMEOUT, @@ -81,12 +67,6 @@ static struct bt_mesh_subnet *friend_subnet_get(uint16_t net_idx) return bt_mesh_subnet_get(net_idx); } -static struct bt_mesh_adv *adv_alloc(int id) -{ - adv_pool[id].app_idx = BLE_MESH_KEY_UNUSED; - return &adv_pool[id].adv; -} - static bool is_lpn_unicast(struct bt_mesh_friend *frnd, uint16_t addr) { if (frnd->lpn == BLE_MESH_ADDR_UNASSIGNED) { @@ -183,7 +163,7 @@ static void friend_clear(struct bt_mesh_friend *frnd, uint8_t reason) /* Cancel the sending if necessary */ if (frnd->pending_buf) { bt_mesh_adv_buf_ref_debug(__func__, frnd->last, 2U, BLE_MESH_BUF_REF_EQUAL); - BLE_MESH_ADV(frnd->last)->busy = 0U; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(frnd->last), 0); } else { bt_mesh_adv_buf_ref_debug(__func__, frnd->last, 1U, BLE_MESH_BUF_REF_EQUAL); } @@ -366,8 +346,7 @@ static struct net_buf *create_friend_pdu(struct bt_mesh_friend *frnd, { struct net_buf *buf = NULL; - buf = bt_mesh_adv_create_from_pool(&friend_buf_pool, adv_alloc, - BLE_MESH_ADV_DATA, K_NO_WAIT); + buf = bt_mesh_adv_create_from_pool(BLE_MESH_ADV_FRIEND, K_NO_WAIT); if (!buf) { return NULL; } @@ -1321,6 +1300,8 @@ int bt_mesh_friend_init(void) } } + bt_mesh_frnd_adv_init(); + friend_init = true; return 0; @@ -1347,8 +1328,7 @@ int bt_mesh_friend_deinit(void) k_delayed_work_free(&frnd->clear.timer); } - bt_mesh_unref_buf_from_pool(&friend_buf_pool); - memset(adv_pool, 0, sizeof(adv_pool)); + bt_mesh_frnd_adv_deinit(); friend_init = false; diff --git a/lib/bt/esp_ble_mesh/core/include/mesh/access.h b/lib/bt/esp_ble_mesh/core/include/mesh/access.h index 86731036..fac49976 100644 --- a/lib/bt/esp_ble_mesh/core/include/mesh/access.h +++ b/lib/bt/esp_ble_mesh/core/include/mesh/access.h @@ -4,7 +4,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -348,7 +348,7 @@ struct bt_mesh_model_op { * @return Mesh transmit value that can be used e.g. for the default * values of the configuration model data. */ -#define BLE_MESH_TRANSMIT(count, int_ms) ((count) | ((((int_ms) / 10) - 1) << 3)) +#define BLE_MESH_TRANSMIT(count, int_ms) ((uint8_t)(count) | ((((int_ms) / 10) - 1) << 3)) /** @def BLE_MESH_TRANSMIT_COUNT * diff --git a/lib/bt/esp_ble_mesh/core/include/mesh/adapter.h b/lib/bt/esp_ble_mesh/core/include/mesh/adapter.h index 1cb239a3..f02c9f5b 100644 --- a/lib/bt/esp_ble_mesh/core/include/mesh/adapter.h +++ b/lib/bt/esp_ble_mesh/core/include/mesh/adapter.h @@ -1,7 +1,7 @@ /* * SPDX-FileCopyrightText: 2017 Nordic Semiconductor ASA * SPDX-FileCopyrightText: 2015-2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,18 +21,78 @@ extern "C" { #endif /* BLE Mesh Max Connection Count */ +/** + * The maximum number of connection count is limited by + * the resources allocated by both the host and the controller + * components, so the actual number of available connections + * is the minimum of the resources from both. + * + * On the C3/S3 platform, the controller uses the macro `CONFIG_BT_CTRL_BLE_MAX_ACT`, + * but adv and scan also occupy this resource, so the actual number of available + * connections is (CONFIG_BT_CTRL_BLE_MAX_ACT - adv instance count - scan). + * However, the macro allocation on the host is entirely for connections, + * so on the C3/S3 platform, the maximum number of connectable devices should + * be determined by the configuration at the host minus the number of + * advertising instances and scan from the controller's configuration. +*/ #ifdef CONFIG_BT_BLUEDROID_ENABLED +#if CONFIG_IDF_TARGET_ESP32 +#define BLE_MESH_MAX_CONN 1 +#elif (CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3) +/* @todo: must ensure CONFIG_BT_CTRL_BLE_MAX_ACT is greater than 2 */ +#if CONFIG_BT_ACL_CONNECTIONS > (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) +/* decrease the adv,scan */ +#define BLE_MESH_MAX_CONN (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) +#else #define BLE_MESH_MAX_CONN CONFIG_BT_ACL_CONNECTIONS +#endif /* CONFIG_BT_ACL_CONNECTIONS > (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) */ +#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 +#if CONFIG_BT_ACL_CONNECTIONS > CONFIG_BT_LE_MAX_CONNECTIONS +#define BLE_MESH_MAX_CONN CONFIG_BT_LE_MAX_CONNECTIONS +#else +#define BLE_MESH_MAX_CONN CONFIG_BT_ACL_CONNECTIONS +#endif /* CONFIG_BT_ACL_CONNECTIONS > CONFIG_BT_LE_MAX_CONNECTIONS */ +#else +/* default setting */ +#define BLE_MESH_MAX_CONN 1 #endif +#endif /* CONFIG_BT_BLUEDROID_ENABLED */ #ifdef CONFIG_BT_NIMBLE_ENABLED +#if CONFIG_IDF_TARGET_ESP32 +#define BLE_MESH_MAX_CONN 1 +#elif (CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3) +/* @todo: must ensure CONFIG_BT_CTRL_BLE_MAX_ACT is greater than 2 */ +#if CONFIG_BT_NIMBLE_MAX_CONNECTIONS > (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) +/* decrease the adv,scan */ +#define BLE_MESH_MAX_CONN (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) +#else +#define BLE_MESH_MAX_CONN CONFIG_BT_NIMBLE_MAX_CONNECTIONS +#endif /* CONFIG_BT_NIMBLE_MAX_CONNECTIONS > (CONFIG_BT_CTRL_BLE_MAX_ACT - 2) */ +#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 #define BLE_MESH_MAX_CONN CONFIG_BT_NIMBLE_MAX_CONNECTIONS +#else +/* default setting */ +#define BLE_MESH_MAX_CONN 1 #endif +#endif /* CONFIG_BT_NIMBLE_ENABLED */ #define BLE_MESH_GAP_ADV_MAX_LEN 31 #define BLE_MESH_GATT_DEF_MTU_SIZE 23 +#if CONFIG_BLE_MESH_USE_BLE_50 +#define BLE_MESH_ADV_PHY_UNASSIGNED 0 +#define BLE_MESH_ADV_PHY_1M 1 +#define BLE_MESH_ADV_PHY_2M 2 +#define BLE_MESH_ADV_PHY_CODED 3 +#define BLE_MESH_ADV_PHY_OPTION_NO_PREFER 0 +#define BLE_MESH_ADV_PHY_OPTION_PREFER_S2 1 +#define BLE_MESH_ADV_PHY_OPTION_PREFER_S8 2 +#define BLE_MESH_ADV_PHY_OPTION_REQUIRE_S2 3 +#define BLE_MESH_ADV_PHY_OPTION_REQUIRE_S8 4 +#endif + /* BD ADDR types */ #define BLE_MESH_ADDR_PUBLIC 0x00 #define BLE_MESH_ADDR_RANDOM 0x01 @@ -43,11 +103,22 @@ extern "C" { #define BLE_MESH_ADDR_LEN 0x06 /* Advertising types */ +#if !CONFIG_BLE_MESH_USE_BLE_50 #define BLE_MESH_ADV_IND 0x00 #define BLE_MESH_ADV_DIRECT_IND 0x01 #define BLE_MESH_ADV_SCAN_IND 0x02 #define BLE_MESH_ADV_NONCONN_IND 0x03 #define BLE_MESH_ADV_DIRECT_IND_LOW_DUTY 0x04 +#define BLE_MESH_ADV_SCAN_RSP 0x04 +#else +/* Bluetooth Core Spec 6.0, Vol 4, Part E, 7.7.65.13 */ +#define BLE_MESH_ADV_IND (0x13) +#define BLE_MESH_ADV_DIRECT_IND (0x15) +#define BLE_MESH_ADV_SCAN_IND (0x12) +#define BLE_MESH_ADV_NONCONN_IND (0x10) +#define BLE_MESH_ADV_DIRECT_IND_LOW_DUTY (0x1b) +#define BLE_MESH_ADV_SCAN_RSP (0x1b) +#endif /* advertising channel map */ #define BLE_MESH_ADV_CHNL_37 BIT(0) @@ -400,6 +471,39 @@ struct bt_mesh_adv_param { /** Maximum Advertising Interval (N * 0.625) */ uint16_t interval_max; + +#if CONFIG_BLE_MESH_USE_BLE_50 + /** Maximum Advertising Duration (N * 0.625) */ + uint16_t adv_duration; + + /** Advertising Packages Number */ + uint16_t adv_count; + + /** Advertising Primary PHY */ + uint8_t primary_phy; + + /** Advertising Secondary PHY */ + uint8_t secondary_phy; +#endif +}; + +#define ADV_TASK_ADV_INST_EVT(inst_id) BIT(inst_id) + +enum bt_mesh_adv_inst_type { + BLE_MESH_ADV_INS, +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +#if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_SERVER + BLE_MESH_ADV_PROXY_INS, +#endif +#if CONFIG_BLE_MESH_SEPARATE_RELAY_ADV_INSTANCE + BLE_MESH_RELAY_ADV_INS, +#endif +#if CONFIG_BLE_MESH_SEPARATE_BLE_ADV_INSTANCE + BLE_MESH_BLE_ADV_INS, +#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + BLE_MESH_ADV_INS_TYPES_NUM, }; #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV @@ -441,7 +545,7 @@ struct bt_mesh_scan_param { /** Scan interval (N * 0.625 ms) */ uint16_t interval; - /** Scan window (N * 0.625 ms) */ + /** Uncoded phy Scan window (N * 0.625 ms) */ uint16_t window; /** BLE scan filter policy */ @@ -453,21 +557,38 @@ struct bt_mesh_conn { bt_mesh_atomic_t ref; }; +/* BLE Mesh advertising report */ +struct bt_mesh_adv_report { + /* Advertiser LE address and type. */ + bt_mesh_addr_t addr; + + /* Strength of advertiser signal. */ + int8_t rssi; + + /* Type of advertising response from advertiser. */ + uint8_t adv_type; + + /* Buffer containing advertiser data. */ + struct net_buf_simple adv_data; + +#if CONFIG_BLE_MESH_USE_BLE_50 + /* Primary advertising PHY */ + uint8_t primary_phy; + + /* Secondary advertising PHY */ + uint8_t secondary_phy; +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ +}; + /** @typedef bt_mesh_scan_cb_t * @brief Callback type for reporting LE scan results. * * A function of this type is given to the bt_le_scan_start() function * and will be called for any discovered LE device. * - * @param addr Advertiser LE address and type. - * @param rssi Strength of advertiser signal. - * @param adv_type Type of advertising response from advertiser. - * @param data Buffer containing advertiser data. - * @param scan_rsp_len Scan Response data length. + * @param adv_rpt: BLE Mesh advertising report. */ -typedef void bt_mesh_scan_cb_t(const bt_mesh_addr_t *addr, int8_t rssi, - uint8_t adv_type, struct net_buf_simple *buf, - uint8_t scan_rsp_len); +typedef void bt_mesh_scan_cb_t(struct bt_mesh_adv_report *adv_rpt); /* @typedef bt_mesh_dh_key_cb_t * @brief Callback type for DH Key calculation. @@ -553,7 +674,7 @@ struct bt_mesh_gatt_attr { * @param len Length of data to read * @param offset Offset to start reading from * - * @return Number fo bytes read, or in case of an error + * @return Number of bytes read, or in case of an error * BLE_MESH_GATT_ERR() with a specific ATT error code. */ ssize_t (*read)(struct bt_mesh_conn *conn, @@ -684,6 +805,21 @@ struct bt_mesh_gatt_attr { int bt_mesh_host_init(void); int bt_mesh_host_deinit(void); +#if CONFIG_BLE_MESH_USE_BLE_50 +int bt_le_ext_adv_start(const uint8_t inst_id, + const struct bt_mesh_adv_param *param, + const struct bt_mesh_adv_data *ad, size_t ad_len, + const struct bt_mesh_adv_data *sd, size_t sd_len); + +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV +int bt_mesh_ble_ext_adv_start(const uint8_t inst_id, + const struct bt_mesh_ble_adv_param *param, + const struct bt_mesh_ble_adv_data *adv_data); +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ + +int bt_le_ext_adv_stop(uint8_t inst_id); + +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_le_adv_start(const struct bt_mesh_adv_param *param, const struct bt_mesh_adv_data *ad, size_t ad_len, const struct bt_mesh_adv_data *sd, size_t sd_len); @@ -691,9 +827,10 @@ int bt_le_adv_start(const struct bt_mesh_adv_param *param, #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, const struct bt_mesh_ble_adv_data *data); -#endif +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ int bt_le_adv_stop(void); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_le_scan_start(const struct bt_mesh_scan_param *param, bt_mesh_scan_cb_t cb); diff --git a/lib/bt/esp_ble_mesh/core/lpn.c b/lib/bt/esp_ble_mesh/core/lpn.c index f445be56..80f5b432 100644 --- a/lib/bt/esp_ble_mesh/core/lpn.c +++ b/lib/bt/esp_ble_mesh/core/lpn.c @@ -10,6 +10,7 @@ #include #include "crypto.h" +#include "tag.h" #include "adv.h" #include "scan.h" #include "mesh.h" @@ -23,7 +24,9 @@ #include "mesh/cfg_srv.h" #include "heartbeat.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #ifdef CONFIG_BLE_MESH_LOW_POWER diff --git a/lib/bt/esp_ble_mesh/core/main.c b/lib/bt/esp_ble_mesh/core/main.c index ad94e2c8..957234e3 100644 --- a/lib/bt/esp_ble_mesh/core/main.c +++ b/lib/bt/esp_ble_mesh/core/main.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,7 +30,9 @@ #include "prov_pvnr.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif static bool mesh_init = false; @@ -161,9 +163,9 @@ void bt_mesh_node_reset(void) bt_mesh_clear_seq(); bt_mesh_clear_dkca(); bt_mesh_clear_role(); - if (IS_ENABLED(CONFIG_BLE_MESH_DF_SRV)) { - bt_mesh_clear_all_directed_forwarding_table_data(); - } +#if CONFIG_BLE_MESH_DF_SRV + bt_mesh_clear_all_directed_forwarding_table_data(); +#endif } memset(bt_mesh.flags, 0, sizeof(bt_mesh.flags)); @@ -405,12 +407,14 @@ int bt_mesh_init(const struct bt_mesh_prov *prov, return -EALREADY; } +#if CONFIG_BLE_MESH_V11_SUPPORT extern int bt_mesh_v11_ext_init(void); err = bt_mesh_v11_ext_init(); if (err) { BT_ERR("Bluetooth Mesh v1.1 init failed"); return err; } +#endif bt_mesh_mutex_init(); @@ -437,7 +441,9 @@ int bt_mesh_init(const struct bt_mesh_prov *prov, if ((IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) || - IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)) { + IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT) || + (IS_ENABLED(CONFIG_BLE_MESH_RPR_SRV) && + IS_ENABLED(CONFIG_BLE_MESH_PB_GATT))) { bt_mesh_proxy_client_init(); } @@ -587,7 +593,9 @@ int bt_mesh_deinit(struct bt_mesh_deinit_param *param) if ((IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && IS_ENABLED(CONFIG_BLE_MESH_PB_GATT)) || - IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)) { + IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT) || + (IS_ENABLED(CONFIG_BLE_MESH_RPR_SRV) && + IS_ENABLED(CONFIG_BLE_MESH_PB_GATT))) { bt_mesh_proxy_client_deinit(); } diff --git a/lib/bt/esp_ble_mesh/core/mesh.h b/lib/bt/esp_ble_mesh/core/mesh.h index c9392240..12784479 100644 --- a/lib/bt/esp_ble_mesh/core/mesh.h +++ b/lib/bt/esp_ble_mesh/core/mesh.h @@ -11,6 +11,7 @@ #define _MESH_H_ #include "net.h" +#include "tag.h" #ifdef __cplusplus extern "C" { diff --git a/lib/bt/esp_ble_mesh/core/net.c b/lib/bt/esp_ble_mesh/core/net.c index 2f988966..4f54c854 100644 --- a/lib/bt/esp_ble_mesh/core/net.c +++ b/lib/bt/esp_ble_mesh/core/net.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,7 @@ #include "crypto.h" #include "adv.h" +#include "net.h" #include "scan.h" #include "mesh.h" #include "lpn.h" @@ -31,7 +32,9 @@ #include "proxy_server.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif /* Minimum valid Mesh Network PDU length. The Network headers * themselves take up 9 bytes. After that there is a minimum of 1 byte @@ -834,6 +837,9 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf, uint16_t dst = 0U; int err = 0; + /* The variable is not used when proxy server or proxy client is disabled. */ + ARG_UNUSED(dst); + BT_DBG("net_idx 0x%04x new_key %u len %u", sub->net_idx, new_key, buf->len); @@ -911,18 +917,22 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf, return err; } - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && - bt_mesh_proxy_server_relay(&buf->b, dst) && - BLE_MESH_ADDR_IS_UNICAST(dst)) { + /** + * TODO: Find a way to determine how the message was sent previously + * during a retransmission, to avoid ineffective advertising. + */ +#if CONFIG_BLE_MESH_GATT_PROXY_SERVER + if (bt_mesh_proxy_server_relay(&buf->b, dst) && + BLE_MESH_ADDR_IS_UNICAST(dst) && + bt_mesh_proxy_server_find_client_by_addr(dst)) { send_cb_finalize(cb, cb_data); return 0; } +#endif - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT) && - bt_mesh_proxy_client_relay(&buf->b, dst)) { - send_cb_finalize(cb, cb_data); - return 0; - } +#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT + bt_mesh_proxy_client_relay(&buf->b, dst); +#endif bt_mesh_adv_send(buf, BLE_MESH_ADV(buf)->xmit, cb, cb_data); return 0; @@ -1019,9 +1029,37 @@ int bt_mesh_net_encode(struct bt_mesh_net_tx *tx, struct net_buf_simple *buf, return bt_mesh_net_obfuscate(buf->data, BLE_MESH_NET_IVI_TX, priv); } +#if !CONFIG_BLE_MESH_V11_SUPPORT +static void bt_mesh_net_adv_xmit_update(struct bt_mesh_net_tx *tx) +{ + /* When transmitting a Network PDU that is tagged as friendship, + * the Advertising Bearer Network Interface shall transmit the + * Network PDU over the advertising bearer only once. + * + * Note: Currently when transmitting a packet with the friendship + * credentials used, the message flow will not reach here. It + * will be enqueued into the friend queue in transport.c, and + * waited to be sent. + */ + if (bt_mesh_tag_friendship(tx->ctx->send_tag)) { + tx->xmit = BLE_MESH_TRANSMIT(0, BLE_MESH_TRANSMIT_INT(bt_mesh_net_transmit_get())); + return; + } + + if (bt_mesh_tag_relay(tx->ctx->send_tag)) { + tx->xmit = bt_mesh_relay_retransmit_get(); + } else { + tx->xmit = bt_mesh_net_transmit_get(); + } + + return; +} +#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ + int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, const struct bt_mesh_send_cb *cb, void *cb_data) { + const struct bt_mesh_send_cb *send_cb = cb; uint8_t bearer = BLE_MESH_ALL_BEARERS; int err = 0; @@ -1086,31 +1124,48 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, * shall drop all messages secured using the friendship security * credentials." */ - - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && - (bearer & BLE_MESH_GATT_BEARER) && - (tx->ctx->send_ttl != 1U || - bt_mesh_tag_relay(tx->ctx->send_tag)) && +#if CONFIG_BLE_MESH_GATT_PROXY_SERVER + if ((bearer & BLE_MESH_GATT_BEARER) && + (tx->ctx->send_ttl != 1U || bt_mesh_tag_relay(tx->ctx->send_tag)) && tx->ctx->send_cred != BLE_MESH_FRIENDSHIP_CRED) { if (bt_mesh_proxy_server_relay(&buf->b, tx->ctx->addr) && BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { - /* Notify completion if this only went - * through the Mesh Proxy. + /* When the destination address is identified as a proxy client + * address, the message will be sent only to the proxy client. + * This action will enhance the efficiency of the proxy server + * in sending data packets. + * + * It should be noted that this approach does not significantly + * reduce the number of advertising packets in the air, as other + * proxy clients may receive the message and resend it through + * a advertising method. */ - if ((bearer & (~BLE_MESH_GATT_BEARER)) == 0) { - send_cb_finalize(cb, cb_data); + if (bt_mesh_proxy_server_find_client_by_addr(tx->ctx->addr)) { + send_cb_finalize(send_cb, cb_data); + send_cb = NULL; - err = 0; goto done; } + /* Finalize transmission if this only went through GATT bearer */ + if ((bearer & (~BLE_MESH_GATT_BEARER)) == 0) { + send_cb_finalize(send_cb, cb_data); + send_cb = NULL; + +#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT + /* This message will not be transmitted by proxy client */ + if (!bt_mesh_proxy_client_get_conn_count()) { + goto done; + } +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ + } } } +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT) && - (bearer & BLE_MESH_GATT_BEARER) && - (tx->ctx->send_ttl != 1U || - bt_mesh_tag_relay(tx->ctx->send_tag)) && +#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT + if ((bearer & BLE_MESH_GATT_BEARER) && + (tx->ctx->send_ttl != 1U || bt_mesh_tag_relay(tx->ctx->send_tag)) && tx->ctx->send_cred != BLE_MESH_FRIENDSHIP_CRED) { if (bt_mesh_proxy_client_relay(&buf->b, tx->ctx->addr)) { /* If Proxy Client succeeds to send messages with GATT bearer, @@ -1118,34 +1173,43 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, * connection has been created with Proxy Client, here we will * use advertising bearer for the messages. */ - send_cb_finalize(cb, cb_data); + if ((bearer & (~BLE_MESH_GATT_BEARER)) == 0) { + send_cb_finalize(send_cb, cb_data); + send_cb = NULL; - err = 0; - goto done; + goto done; + } } } +#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ /* Deliver to local network interface if necessary */ if (((IS_ENABLED(CONFIG_BLE_MESH_NODE) && bt_mesh_is_provisioned()) || (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en())) && (bt_mesh_fixed_group_match(tx->ctx->addr) || bt_mesh_elem_find(tx->ctx->addr))) { - if (cb && cb->start) { - cb->start(0, 0, cb_data); - } + /* If the target address isn't a unicast address, then the callback + * function will be called by mesh adv task instead of called here + * to avoid the callback function being called twice. + * See BLEMESH24-76 for more details. + */ + if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { + if (send_cb && send_cb->start) { + send_cb->start(0, 0, cb_data); + } - net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf)); + net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf)); - if (cb && cb->end) { - cb->end(0, cb_data); - } + if (send_cb && send_cb->end) { + send_cb->end(0, cb_data); + } - bt_mesh_net_local(); + bt_mesh_net_local(); - err = 0; - /* If it is a group address, it still needs to be relayed */ - if (BLE_MESH_ADDR_IS_UNICAST(tx->ctx->addr)) { goto done; } + + net_buf_slist_put(&bt_mesh.local_queue, net_buf_ref(buf)); + bt_mesh_net_local(); } if ((bearer & BLE_MESH_ADV_BEARER) && @@ -1167,7 +1231,6 @@ int bt_mesh_net_send(struct bt_mesh_net_tx *tx, struct net_buf *buf, BLE_MESH_TRANSMIT_COUNT(tx->xmit), BLE_MESH_TRANSMIT_INT(tx->xmit)); bt_mesh_adv_send(buf, tx->xmit, cb, cb_data); - err = 0; goto done; } @@ -1407,13 +1470,94 @@ static bool relay_to_adv(enum bt_mesh_net_if net_if) case BLE_MESH_NET_IF_ADV: return (bt_mesh_relay_get() == BLE_MESH_RELAY_ENABLED); case BLE_MESH_NET_IF_PROXY: - return (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED || - bt_mesh_private_gatt_proxy_state_get() == BLE_MESH_PRIVATE_GATT_PROXY_ENABLED); + return (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED +#if CONFIG_BLE_MESH_PRB_SRV + || bt_mesh_private_gatt_proxy_state_get() == BLE_MESH_PRIVATE_GATT_PROXY_ENABLED +#endif + ); default: return false; } } +#if !CONFIG_BLE_MESH_V11_SUPPORT +static uint8_t net_retransmission_adv(struct bt_mesh_net_rx *rx, + uint8_t *cred, uint8_t *tag) +{ + if (rx->ctx.recv_cred == BLE_MESH_FLOODING_CRED) { + uint8_t bearer = BLE_MESH_NONE_BEARER; + + /* Inbound bearer: ADV; + * Inbound Security Material: managed flooding; + */ + + /* Condition: Relay is enabled. */ + if (IS_ENABLED(CONFIG_BLE_MESH_RELAY) && + bt_mesh_relay_get() == BLE_MESH_RELAY_ENABLED) { + bearer |= BLE_MESH_ADV_BEARER; + *cred = BLE_MESH_FLOODING_CRED; + /* Additional action: Tag as relay */ + *tag |= BLE_MESH_TAG_RELAY; + } + + /* Condition: Proxy is enabled. */ + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && + bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) { + bearer |= BLE_MESH_GATT_BEARER; + *cred = BLE_MESH_FLOODING_CRED; + } + + return bearer; + } + + if (rx->ctx.recv_cred == BLE_MESH_FRIENDSHIP_CRED && + IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && + bt_mesh_friend_get() == BLE_MESH_FRIEND_ENABLED) { + + /* Condition: Directed friend is disabled. */ + *cred = BLE_MESH_FLOODING_CRED; + return BLE_MESH_ALL_BEARERS; + } + + return BLE_MESH_NONE_BEARER; +} + +static uint8_t net_retransmission_gatt(struct bt_mesh_net_rx *rx, + uint8_t *cred, uint8_t *tag) +{ + if (rx->ctx.recv_cred == BLE_MESH_FLOODING_CRED) { + /* Inbound bearer: GATT; + * Inbound Security Material: managed flooding; + * Condition: Proxy is enabled; + */ + if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && + bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) { + /* Condition: Directed proxy is disabled. */ + *cred = BLE_MESH_FLOODING_CRED; + return BLE_MESH_ALL_BEARERS; + } + + return BLE_MESH_NONE_BEARER; + } + + return BLE_MESH_NONE_BEARER; +} + +static uint8_t bt_mesh_net_retrans_match(struct bt_mesh_net_rx *rx, + uint8_t *cred, uint8_t *tag) +{ + if (rx->net_if == BLE_MESH_NET_IF_ADV) { + return net_retransmission_adv(rx, cred, tag); + } + + if (rx->net_if == BLE_MESH_NET_IF_PROXY) { + return net_retransmission_gatt(rx, cred, tag); + } + + return BLE_MESH_NONE_BEARER; +} +#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ + static void bt_mesh_net_relay(struct net_buf_simple *sbuf, struct bt_mesh_net_rx *rx) { @@ -1538,7 +1682,7 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, if (bt_mesh_get_stored_relay_count() >= BLE_MESH_MAX_STORED_RELAY_COUNT) { xmit = BLE_MESH_TRANSMIT(0, 20); } - buf = bt_mesh_relay_adv_create(BLE_MESH_ADV_DATA, K_NO_WAIT); + buf = bt_mesh_relay_adv_create(BLE_MESH_ADV_RELAY_DATA, K_NO_WAIT); #endif if (!buf) { @@ -1606,20 +1750,25 @@ static void bt_mesh_net_relay(struct net_buf_simple *sbuf, * shall drop all messages secured using the friendship security * credentials. */ - if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && - (bearer & BLE_MESH_GATT_BEARER) && +#if CONFIG_BLE_MESH_GATT_PROXY_SERVER + if ((bearer & BLE_MESH_GATT_BEARER) && ((bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED && cred != BLE_MESH_FRIENDSHIP_CRED) || +#if CONFIG_BLE_MESH_PRB_SRV bt_mesh_private_gatt_proxy_state_get() == BLE_MESH_PRIVATE_GATT_PROXY_ENABLED || +#endif rx->net_if == BLE_MESH_NET_IF_LOCAL || rx->ctx.recv_cred == BLE_MESH_FRIENDSHIP_CRED)) { if (bt_mesh_proxy_server_relay(&buf->b, rx->ctx.recv_dst) && BLE_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst)) { - if ((bearer & (~BLE_MESH_GATT_BEARER)) == 0) { + + if (((bearer & (~BLE_MESH_GATT_BEARER)) == 0) || + bt_mesh_proxy_server_find_client_by_addr(rx->ctx.recv_dst)) { goto done; } } } +#endif /* CONFIG_BLE_MESH_GATT_PROXY_SERVER */ if (((bearer & BLE_MESH_ADV_BEARER) && relay_to_adv(rx->net_if)) || netkey_changed || @@ -1769,24 +1918,26 @@ static bool ignore_net_msg(uint16_t src, uint16_t dst) return false; } -void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, - enum bt_mesh_net_if net_if) +void bt_mesh_generic_net_recv(struct net_buf_simple *data, + struct bt_mesh_net_rx *rx, + enum bt_mesh_net_if net_if) { NET_BUF_SIMPLE_DEFINE(buf, 29); - struct bt_mesh_net_rx rx = { .ctx.recv_rssi = rssi }; struct net_buf_simple_state state = {0}; - BT_DBG("rssi %d net_if %u", rssi, net_if); + assert(rx); + + BT_DBG("rssi %d net_if %u", rx->ctx.recv_rssi, net_if); if (!ready_to_recv()) { return; } - if (bt_mesh_net_decode(data, net_if, &rx, &buf)) { + if (bt_mesh_net_decode(data, net_if, rx, &buf)) { return; } - if (ignore_net_msg(rx.ctx.addr, rx.ctx.recv_dst)) { + if (ignore_net_msg(rx->ctx.addr, rx->ctx.recv_dst)) { return; } @@ -1796,24 +1947,26 @@ void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, BT_BQB(BLE_MESH_BQB_TEST_LOG_LEVEL_PRIMARY_ID_NODE | \ BLE_MESH_BQB_TEST_LOG_LEVEL_SUB_ID_NET, "\nNetRecv: ctl: %d, src: %d, dst: %d, ttl: %d, data: 0x%s", - rx.ctl, rx.ctx.addr, rx.ctx.recv_dst, rx.ctx.recv_ttl, + rx->ctl, rx->ctx.addr, rx->ctx.recv_dst, rx->ctx.recv_ttl, bt_hex(buf.data + BLE_MESH_NET_HDR_LEN, buf.len - BLE_MESH_NET_HDR_LEN)); /* If trying to handle a message with DST set to all-directed-forwarding-nodes, * we need to make sure the directed forwarding functionality is enabled in the * corresponding subnet. */ - rx.local_match = (bt_mesh_fixed_group_match(rx.ctx.recv_dst) || - bt_mesh_fixed_direct_match(rx.sub, rx.ctx.recv_dst) || - bt_mesh_elem_find(rx.ctx.recv_dst)); + rx->local_match = (bt_mesh_fixed_group_match(rx->ctx.recv_dst) || + bt_mesh_fixed_direct_match(rx->sub, rx->ctx.recv_dst) || + bt_mesh_elem_find(rx->ctx.recv_dst)); if (IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && +#if CONFIG_BLE_MESH_PRB_SRV bt_mesh_private_gatt_proxy_state_get() != BLE_MESH_PRIVATE_GATT_PROXY_ENABLED && +#endif net_if == BLE_MESH_NET_IF_PROXY) { - bt_mesh_proxy_server_addr_add(data, rx.ctx.addr); + bt_mesh_proxy_server_addr_add(data, rx->ctx.addr); if (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_DISABLED && - !rx.local_match) { + !rx->local_match) { BT_INFO("Proxy is disabled; ignoring message"); return; } @@ -1826,11 +1979,11 @@ void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, * tag the Network PDU with the immutable-credentials tag. */ #if CONFIG_BLE_MESH_DF_SRV - if (rx.sub->directed_proxy == BLE_MESH_DIRECTED_PROXY_ENABLED && - rx.sub->use_directed == BLE_MESH_PROXY_USE_DIRECTED_ENABLED && - !bt_mesh_addr_in_uar(&rx.sub->proxy_client_uar, rx.ctx.addr) && - !bt_mesh_proxy_server_find_client_by_addr(rx.ctx.addr)) { - rx.ctx.recv_tag |= BLE_MESH_TAG_IMMUTABLE_CRED; + if (rx->sub->directed_proxy == BLE_MESH_DIRECTED_PROXY_ENABLED && + rx->sub->use_directed == BLE_MESH_PROXY_USE_DIRECTED_ENABLED && + !bt_mesh_addr_in_uar(&rx->sub->proxy_client_uar, rx->ctx.addr) && + !bt_mesh_proxy_server_find_client_by_addr(rx->ctx.addr)) { + rx->ctx.recv_tag |= BLE_MESH_TAG_IMMUTABLE_CRED; } #endif /* CONFIG_BLE_MESH_DF_SRV */ } @@ -1842,24 +1995,24 @@ void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, * credentials. Remove it from the message cache so that we accept * it again in the future. */ - if (bt_mesh_trans_recv(&buf, &rx) == -EAGAIN) { + if (bt_mesh_trans_recv(&buf, rx) == -EAGAIN) { BT_WARN("Removing rejected message from Network Message Cache"); - msg_cache[rx.msg_cache_idx].src = BLE_MESH_ADDR_UNASSIGNED; + msg_cache[rx->msg_cache_idx].src = BLE_MESH_ADDR_UNASSIGNED; /* Rewind the next index now that we're not using this entry */ - msg_cache_next = rx.msg_cache_idx; + msg_cache_next = rx->msg_cache_idx; } /* Relay if this was a group/virtual address, or if the destination * was neither a local element nor an LPN we're Friends for. */ - if (!BLE_MESH_ADDR_IS_UNICAST(rx.ctx.recv_dst) || - (!rx.local_match && !rx.friend_match + if (!BLE_MESH_ADDR_IS_UNICAST(rx->ctx.recv_dst) || + (!rx->local_match && !rx->friend_match #if CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG - && !rx.replay_msg + && !rx->replay_msg #endif )) { net_buf_simple_restore(&buf, &state); - bt_mesh_net_relay(&buf, &rx); + bt_mesh_net_relay(&buf, rx); } } diff --git a/lib/bt/esp_ble_mesh/core/net.h b/lib/bt/esp_ble_mesh/core/net.h index 7da8c4a0..94e07819 100644 --- a/lib/bt/esp_ble_mesh/core/net.h +++ b/lib/bt/esp_ble_mesh/core/net.h @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -465,8 +465,16 @@ int bt_mesh_net_resend(struct bt_mesh_subnet *sub, struct net_buf *buf, int bt_mesh_net_decode(struct net_buf_simple *data, enum bt_mesh_net_if net_if, struct bt_mesh_net_rx *rx, struct net_buf_simple *buf); -void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, - enum bt_mesh_net_if net_if); +void bt_mesh_generic_net_recv(struct net_buf_simple *data, + struct bt_mesh_net_rx *rx, + enum bt_mesh_net_if net_if); + +static inline void bt_mesh_net_recv(struct net_buf_simple *data, int8_t rssi, + enum bt_mesh_net_if net_if) +{ + struct bt_mesh_net_rx rx = { .ctx.recv_rssi = rssi }; + bt_mesh_generic_net_recv(data, &rx, net_if); +} bool bt_mesh_primary_subnet_exist(void); diff --git a/lib/bt/esp_ble_mesh/core/nimble_host/adapter.c b/lib/bt/esp_ble_mesh/core/nimble_host/adapter.c index 0418b76c..b2477345 100644 --- a/lib/bt/esp_ble_mesh/core/nimble_host/adapter.c +++ b/lib/bt/esp_ble_mesh/core/nimble_host/adapter.c @@ -1,7 +1,7 @@ /* * SPDX-FileCopyrightText: 2017 Nordic Semiconductor ASA * SPDX-FileCopyrightText: 2015-2016 Intel Corporation - * SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,6 +27,8 @@ #include "mesh/hci.h" #include "mesh/common.h" #include "prov_pvnr.h" +#include "scan.h" +#include "btc_ble_mesh_ble.h" /** @def BT_UUID_MESH_PROV * @brief Mesh Provisioning Service @@ -69,7 +71,6 @@ static uint8_t bt_mesh_private_key[32]; /* Scan related functions */ static bt_mesh_scan_cb_t *bt_mesh_scan_dev_found_cb; - #if CONFIG_BLE_MESH_NODE /* the gatt database list to save the attribute table */ static sys_slist_t bt_mesh_gatts_db; @@ -79,10 +80,59 @@ static struct bt_mesh_conn bt_mesh_gatts_conn[BLE_MESH_MAX_CONN]; static struct bt_mesh_conn_cb *bt_mesh_gatts_conn_cb; static uint8_t bt_mesh_gatts_addr[6]; + +#if CONFIG_BLE_MESH_USE_BLE_50 +static bool g_gatts_svcs_add = false; +#endif #endif /* CONFIG_BLE_MESH_NODE */ +#if CONFIG_BLE_MESH_USE_BLE_50 && \ + CONFIG_BLE_MESH_SUPPORT_BLE_ADV && \ + (!CONFIG_BLE_MESH_SUPPORT_MULTI_ADV) +static inline void bt_mesh_set_ble_adv_running(); + +static inline void bt_mesh_unset_ble_adv_running(); + +static inline bool bt_mesh_is_ble_adv_running(); +#endif + static bool g_host_init = false; +#if CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_USE_BLE_50 + +#define BT_MESH_GATTS_CONN_UNUSED 0xFF + +static void bt_mesh_gatts_conn_init(void) +{ + int i; + for (i = 0; i < BLE_MESH_MAX_CONN; i++) { + bt_mesh_gatts_conn[i].handle = BT_MESH_GATTS_CONN_UNUSED; + } +} + +static int bt_mesh_find_free_conn_idx(void) +{ + int i; + for (i = 0; i < BLE_MESH_MAX_CONN; i++) { + if (bt_mesh_gatts_conn[i].handle == BT_MESH_GATTS_CONN_UNUSED) { + return i; + } + } + return -ENOMEM; +} + +static int bt_mesh_find_conn_idx(uint16_t conn_handle) +{ + int i; + for (i = 0; i < BLE_MESH_MAX_CONN; i++) { + if (bt_mesh_gatts_conn[i].handle == conn_handle) { + return i; + } + } + return -ENODEV; +} +#endif /* CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_USE_BLE_50 */ + int bt_mesh_host_init(void) { int rc; @@ -145,9 +195,16 @@ void bt_mesh_hci_init(void) #endif } +#if CONFIG_BLE_MESH_USE_BLE_50 +static struct ble_gap_ext_disc_params uncoded_disc_params; +static struct ble_gap_ext_disc_params coded_disc_params; +#else static struct ble_gap_disc_params scan_param; +#endif + #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) static struct gattc_prov_info { /* Service to be found depends on the type of adv pkt received */ struct bt_mesh_conn conn; @@ -350,13 +407,19 @@ static int svc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, } uuid = &service->uuid; - uuid_length = (uint8_t) (uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16); + uuid_length = (uint8_t)(uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16); if (uuid_length != 2) { return 0; } for (i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { - if (bt_mesh_gattc_info[i].service_uuid == (uint16_t)BLE_UUID16(uuid)->value) { + /** + * In scenarios with multiple connections, to prevent + * subsequent connections from affecting the first one, + * a check for the connection handle is needed here. + */ + if (bt_mesh_gattc_info[i].conn.handle == conn_handle && + bt_mesh_gattc_info[i].service_uuid == (uint16_t)BLE_UUID16(uuid)->value) { bt_mesh_gattc_info[i].start_handle = service->start_handle; bt_mesh_gattc_info[i].end_handle = service->end_handle; break; @@ -396,13 +459,52 @@ static int svc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, return rc; } -#endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ +#endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) */ -static int disc_cb(struct ble_gap_event *event, void *arg) +#if CONFIG_BLE_MESH_USE_BLE_50 +void bt_mesh_ble_ext_adv_report(struct ble_gap_ext_disc_desc *desc) { +#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN + bt_mesh_ble_adv_report_t adv_rpt = {0}; + if (bt_mesh_ble_scan_state_get()) { + memcpy(adv_rpt.addr, desc->addr.val, BLE_MESH_ADDR_LEN); + memcpy(adv_rpt.dir_addr, desc->direct_addr.val, BLE_MESH_ADDR_LEN); + + /* Here, only a shallow copy needs to be implemented; + * deep copying behavior occurs in btc_ble_mesh_ble_copy_req_data. */ + adv_rpt.data = desc->data; + + adv_rpt.event_type = desc->props; + adv_rpt.addr_type = desc->addr.type; + adv_rpt.length = desc->length_data; + adv_rpt.rssi = desc->rssi; + adv_rpt.primary_phy = desc->prim_phy; + adv_rpt.secondary_phy = desc->sec_phy; + adv_rpt.sid = desc->sid; + adv_rpt.tx_power = desc->tx_power; + adv_rpt.dir_addr_type = desc->direct_addr.type; + adv_rpt.data_status = desc->data_status; + adv_rpt.per_adv_interval = desc->periodic_adv_itvl; + + bt_mesh_ble_scan_cb_evt_to_btc(&adv_rpt); + } +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ +} +#endif + +int disc_cb(struct ble_gap_event *event, void *arg) +{ +#if CONFIG_BLE_MESH_USE_BLE_50 + struct ble_gap_ext_disc_desc *desc; +#else struct ble_gap_disc_desc *desc; +#endif + #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) int rc, i; uint8_t notif_data[100]; uint16_t notif_len; @@ -412,21 +514,59 @@ static int disc_cb(struct ble_gap_event *event, void *arg) #endif switch (event->type) { +#if CONFIG_BLE_MESH_USE_BLE_50 + case BLE_GAP_EVENT_EXT_DISC: { + struct bt_mesh_adv_report adv_rpt = {0}; + + desc = &event->ext_disc; + + memcpy(&adv_rpt.addr, &desc->addr, sizeof(bt_mesh_addr_t)); + adv_rpt.rssi = desc->rssi; + adv_rpt.adv_type = desc->props; + adv_rpt.primary_phy = desc->prim_phy; + adv_rpt.secondary_phy = desc->sec_phy; + + net_buf_simple_init_with_data(&adv_rpt.adv_data, (void *)desc->data, desc->length_data); + + if (bt_mesh_scan_dev_found_cb) { + /* TODO: Support Scan Response data length for NimBLE host */ + if (desc->props & BLE_HCI_ADV_LEGACY_MASK) { + bt_mesh_scan_dev_found_cb(&adv_rpt); + } + } + + /* Mesh didn't process that data */ + if (adv_rpt.adv_data.len == desc->length_data) { + bt_mesh_ble_ext_adv_report(desc); + } + + break; + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ case BLE_GAP_EVENT_DISC: { - struct net_buf_simple buf = {0}; + struct bt_mesh_adv_report adv_rpt = {0}; desc = &event->disc; - net_buf_simple_init_with_data(&buf, (void *)desc->data, desc->length_data); + + adv_rpt.rssi = desc->rssi; + adv_rpt.adv_type = desc->event_type; + + memcpy(&adv_rpt.addr, &desc->addr, sizeof(bt_mesh_addr_t)); + + net_buf_simple_init_with_data(&adv_rpt.adv_data, (void *)desc->data, desc->length_data); if (bt_mesh_scan_dev_found_cb) { /* TODO: Support Scan Response data length for NimBLE host */ - bt_mesh_scan_dev_found_cb((bt_mesh_addr_t *)&desc->addr, desc->rssi, desc->event_type, &buf, 0); + bt_mesh_scan_dev_found_cb(&adv_rpt); } break; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) case BLE_GAP_EVENT_CONNECT: + /* @todo: process connect failed event */ if (event->connect.status == 0) { /* Connection successfully established. */ MODLOG_DFLT(INFO, "Connection established "); @@ -442,10 +582,21 @@ static int disc_cb(struct ble_gap_event *event, void *arg) break; } } + if (i == ARRAY_SIZE(bt_mesh_gattc_info)) { + goto transfer_to_user; + } + } else { + goto transfer_to_user; } } if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_SCANNING)) { +#if CONFIG_BLE_MESH_USE_BLE_50 + rc = ble_gap_ext_disc(BLE_OWN_ADDR_PUBLIC, 0, 0, 0, 0, 0, + uncoded_disc_params.itvl ? &uncoded_disc_params : NULL, + coded_disc_params.itvl ? &coded_disc_params : NULL, disc_cb, NULL); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ rc = ble_gap_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER, &scan_param, disc_cb, NULL); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ if (rc != 0) { BT_ERR("Invalid scan status %d", rc); break; @@ -494,7 +645,13 @@ static int disc_cb(struct ble_gap_event *event, void *arg) bt_mesh_gattc_info[i].wr_desc_done = false; break; } + + if (i == ARRAY_SIZE(bt_mesh_gattc_info)) { + goto transfer_to_user; + } } + } else { + goto transfer_to_user; } break; case BLE_GAP_EVENT_MTU: @@ -521,6 +678,8 @@ static int disc_cb(struct ble_gap_event *event, void *arg) } /* Search Mesh Provisioning Service or Mesh Proxy Service */ ble_gattc_disc_all_svcs(bt_mesh_gattc_info[i].conn.handle, svc_disced, NULL); + } else { + goto transfer_to_user; } break; case BLE_GAP_EVENT_NOTIFY_RX: @@ -531,8 +690,8 @@ static int disc_cb(struct ble_gap_event *event, void *arg) } if (i == ARRAY_SIZE(bt_mesh_gattc_info)) { - BT_ERR("Conn handle 0x%04x not found", event->notify_rx.conn_handle); - return 0; + BT_DBG("Conn handle 0x%04x not blonges to Mesh", event->notify_rx.conn_handle); + goto transfer_to_user; } conn = &bt_mesh_gattc_info[i].conn; @@ -557,7 +716,7 @@ static int disc_cb(struct ble_gap_event *event, void *arg) if (bt_mesh_gattc_info[i].service_uuid == BLE_MESH_UUID_MESH_PROV_VAL) { if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->prov_notify != NULL) { len = bt_mesh_gattc_conn_cb->prov_notify(&bt_mesh_gattc_info[i].conn, - notif_data, notif_len); + notif_data, notif_len); if (len < 0) { BT_ERR("prov_notify failed"); bt_mesh_gattc_disconnect(conn); @@ -568,7 +727,7 @@ static int disc_cb(struct ble_gap_event *event, void *arg) if (bt_mesh_gattc_conn_cb != NULL && bt_mesh_gattc_conn_cb->proxy_notify != NULL && bt_mesh_gattc_info[i].wr_desc_done) { len = bt_mesh_gattc_conn_cb->proxy_notify(&bt_mesh_gattc_info[i].conn, - notif_data, notif_len); + notif_data, notif_len); if (len < 0) { BT_ERR("proxy_notify failed"); bt_mesh_gattc_disconnect(conn); @@ -579,14 +738,53 @@ static int disc_cb(struct ble_gap_event *event, void *arg) break; #endif default: + goto transfer_to_user; break; } return 0; + +transfer_to_user: +#if CONFIG_BLE_MESH_USE_BLE_50 + bt_mesh_ble_nimble_evt_to_btc(event, arg); +#endif + return 0; } +#if CONFIG_BLE_MESH_USE_BLE_50 +/** + * @brief Get the gap callback function used by BLE Mesh + * + * @note The user must get the mesh gap event handler function + * through the bt_mesh_nimble_gap_cb_get function and pass + * it in as a callback function when using the api: + * ble_gap_ext_connect, ble_gap_ext_disc, ble_gap_connect, + * and ble_gap_disc. + * + * @return void* + */ +void *bt_mesh_nimble_gap_cb_get(void) +{ + return (void*)disc_cb; +} +#endif + static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, uint8_t filter_dup) { +#if CONFIG_BLE_MESH_USE_BLE_50 + uncoded_disc_params.itvl = (window ? interval : 0); + uncoded_disc_params.window = window; + + coded_disc_params.itvl = ((interval > window) ? interval : 0); + coded_disc_params.window = ((interval > window) ? interval - window : 0); + + coded_disc_params.passive = (scan_type == BLE_MESH_SCAN_PASSIVE); + uncoded_disc_params.passive = (scan_type == BLE_MESH_SCAN_PASSIVE); + + ble_gap_ext_disc(BLE_OWN_ADDR_PUBLIC, 0, 0, filter_dup, 0, 0, + uncoded_disc_params.itvl ? &uncoded_disc_params : NULL, + coded_disc_params.itvl ? &coded_disc_params : NULL, disc_cb, NULL); +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ scan_param.filter_duplicates = filter_dup; scan_param.itvl = interval; scan_param.window = window; @@ -597,6 +795,7 @@ static int start_le_scan(uint8_t scan_type, uint16_t interval, uint16_t window, scan_param.passive = 0; } ble_gap_disc(BLE_OWN_ADDR_PUBLIC, BLE_HS_FOREVER, &scan_param, disc_cb, NULL); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if BLE_MESH_DEV if (scan_type == BLE_MESH_SCAN_ACTIVE) { @@ -648,12 +847,38 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) /* When connection is created, advertising will be stopped automatically. */ bt_mesh_atomic_test_and_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); #endif + +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) + /* Check if this connection is created by Proxy client */ + for (size_t i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { + if (!memcmp(bt_mesh_gattc_info[i].addr.val, desc.peer_id_addr.val, BLE_MESH_ADDR_LEN)) { + BT_WARN("Already create connection with %s by proxy client", + bt_hex(desc.peer_id_addr.val, BLE_MESH_ADDR_LEN)); + return 0; + } + } +#endif + if (bt_mesh_gatts_conn_cb != NULL && bt_mesh_gatts_conn_cb->connected != NULL) { - uint8_t index = BLE_MESH_GATT_GET_CONN_ID(event->connect.conn_handle); + int index = 0; +#if CONFIG_BLE_MESH_USE_BLE_50 + index = bt_mesh_find_free_conn_idx(); + if (index != -ENOMEM) { + bt_mesh_gatts_conn[index].handle = BLE_MESH_GATT_GET_CONN_ID(event->connect.conn_handle); + (bt_mesh_gatts_conn_cb->connected)(&bt_mesh_gatts_conn[index], 0); + } else { + BT_ERR("No space for new connection"); + ble_gap_terminate(event->connect.conn_handle, BLE_ERR_CONN_LIMIT); + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ + index = BLE_MESH_GATT_GET_CONN_ID(event->connect.conn_handle); if (index < BLE_MESH_MAX_CONN) { bt_mesh_gatts_conn[index].handle = BLE_MESH_GATT_GET_CONN_ID(event->connect.conn_handle); (bt_mesh_gatts_conn_cb->connected)(&bt_mesh_gatts_conn[index], 0); } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ memcpy(bt_mesh_gatts_addr, desc.peer_id_addr.val, BLE_MESH_ADDR_LEN); /* This is for EspBleMesh Android app. When it tries to connect with the * device at the first time and it fails due to some reason. And after @@ -673,11 +898,23 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) bt_mesh_atomic_test_and_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); #endif if (bt_mesh_gatts_conn_cb != NULL && bt_mesh_gatts_conn_cb->disconnected != NULL) { - uint8_t index = BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle); + int index = 0; +#if CONFIG_BLE_MESH_USE_BLE_50 + index = bt_mesh_find_conn_idx(BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle)); + if (index != -ENODEV) { + bt_mesh_gatts_conn[index].handle = BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle); + (bt_mesh_gatts_conn_cb->disconnected)(&bt_mesh_gatts_conn[index], event->disconnect.reason); + } else { + BT_ERR("No device"); + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ + index = BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle); if (index < BLE_MESH_MAX_CONN) { bt_mesh_gatts_conn[index].handle = BLE_MESH_GATT_GET_CONN_ID(event->disconnect.conn.conn_handle); (bt_mesh_gatts_conn_cb->disconnected)(&bt_mesh_gatts_conn[index], event->disconnect.reason); } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + bt_mesh_gatts_conn[index].handle = 0; memset(bt_mesh_gatts_addr, 0x0, BLE_MESH_ADDR_LEN); } @@ -693,8 +930,43 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) return 0; case BLE_GAP_EVENT_ADV_COMPLETE: - MODLOG_DFLT(INFO, "advertise complete; reason=%d", - event->adv_complete.reason); + BT_DBG("advertise complete; reason=%d", + event->adv_complete.reason); +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); +#else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + assert(CONFIG_BLE_MESH_ADV_INST_ID == event->adv_complete.instance); + /* Limit Reached (0x43) and Advertising Timeout (0x3C) will cause BLE_HS_ETIMEOUT to be set. */ + if (event->adv_complete.reason == BLE_HS_ETIMEOUT) { + ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); + } +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + /** + * This judgment is to distinguish between the termination + * events of BLE connectable broadcasting and proxy connectable + * adv under the same instance ID, that is, when the status is 0. + * + * Since the host task and adv task are currently operated in + * series, there is no need to consider competition issues between + * tasks. + * + * @attention: once multiple adv instances are used, the adv task + * and host will be asynchronous, and it is necessary to consider + * the issue of resource competition. + */ + if (bt_mesh_is_ble_adv_running() && + event->adv_complete.reason == 0) { + /* The unset operation must be performed before waking up the + * adv task; performing the unset after waking up the adv task + * could lead to resource contention issues. + */ + bt_mesh_unset_ble_adv_running(); + ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); + } +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ return 0; case BLE_GAP_EVENT_ENC_CHANGE: @@ -717,10 +989,20 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) event->subscribe.prev_indicate, event->subscribe.cur_indicate); struct bt_mesh_gatt_attr *attr = bt_mesh_gatts_find_attr_by_handle(event->subscribe.attr_handle + 1); - uint8_t index = BLE_MESH_GATT_GET_CONN_ID(event->subscribe.conn_handle); + int index = 0; uint16_t len = 0; uint16_t ccc_val = 0; +#if CONFIG_BLE_MESH_USE_BLE_50 + index = bt_mesh_find_conn_idx(BLE_MESH_GATT_GET_CONN_ID(event->subscribe.conn_handle)); + if (index == -ENODEV) { + BT_ERR("Couldn't find conn %d", event->subscribe.conn_handle); + return 0; + } +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ + index = BLE_MESH_GATT_GET_CONN_ID(event->subscribe.conn_handle); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + if (event->subscribe.prev_notify != event->subscribe.cur_notify) { ccc_val = event->subscribe.cur_notify; } else if (event->subscribe.prev_indicate != event->subscribe.cur_indicate) { @@ -773,10 +1055,233 @@ static int gap_event_cb(struct ble_gap_event *event, void *arg) #else static int gap_event_cb(struct ble_gap_event *event, void *arg) { +#if CONFIG_BLE_MESH_USE_BLE_50 + switch (event->type) { + case BLE_GAP_EVENT_ADV_COMPLETE: + BT_DBG("Provisioner advertise complete; reason=%d", + event->adv_complete.reason); +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(event->adv_complete.instance)); +#else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + assert(CONFIG_BLE_MESH_ADV_INST_ID == event->adv_complete.instance); + /* Limit Reached (0x43) and Advertising Timeout (0x3C) will cause BLE_HS_ETIMEOUT to be set. */ + if (event->adv_complete.reason == BLE_HS_ETIMEOUT) { + ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(CONFIG_BLE_MESH_ADV_INST_ID)); + } +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV + /** + * This judgment is to distinguish between the termination + * events of BLE connectable broadcasting and proxy connectable + * adv under the same instance ID, that is, when the status is 0. + * + * Since the host task and adv task are currently operated in + * series, there is no need to consider competition issues between + * tasks. + * + * @attention: once multiple adv instances are used, the adv task + * and host will be asynchronous, and it is necessary to consider + * the issue of resource competition. + */ + if (bt_mesh_is_ble_adv_running() && + event->adv_complete.reason == 0) { + /* The unset operation must be performed before waking up the + * adv task; performing the unset after waking up the adv task + * could lead to resource contention issues. + */ + bt_mesh_unset_ble_adv_running(); + ble_mesh_adv_task_wakeup(ADV_TASK_ADV_INST_EVT(CONFIG_BLE_MESH_ADV_INST_ID)); + } +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#endif /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + break; + } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ return 0; } #endif /* CONFIG_BLE_MESH_NODE */ +#if CONFIG_BLE_MESH_USE_BLE_50 +int bt_le_ext_adv_start(const uint8_t inst_id, + const struct bt_mesh_adv_param *param, + const struct bt_mesh_adv_data *ad, size_t ad_len, + const struct bt_mesh_adv_data *sd, size_t sd_len) +{ + struct ble_gap_ext_adv_params adv_params = {0}; + struct os_mbuf *data = NULL; + struct os_mbuf *scan_rsp = NULL; + uint8_t *buf = NULL; + uint16_t interval = 0; + uint8_t buf_len = 0; + int err = 0; + + err = ble_gap_ext_adv_active(inst_id); + if (err) { + BT_ERR("adv inst(%d) is running %d", inst_id, err); + return -EINVAL; + } + +#if BLE_MESH_DEV + if (bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING)) { + return -EALREADY; + } +#endif + buf = bt_mesh_calloc(ad_len * BLE_HS_ADV_MAX_SZ); + if (!buf) { + BT_ERR("ad buffer alloc failed"); + return -ENOMEM; + } + + err = set_ad(ad, ad_len, buf, &buf_len); + if (err) { + bt_mesh_free(buf); + BT_ERR("set_ad failed: err %d", err); + return err; + } + + data = os_msys_get_pkthdr(buf_len, 0); + if (!data) { + bt_mesh_free(buf); + BT_ERR("os buf get failed"); + return -ENOBUFS; + } + + err = os_mbuf_append(data, buf, buf_len); + if (err) { + bt_mesh_free(buf); + BT_ERR("Append ad data to os buf failed %d", err); + return -EINVAL; + } + + bt_mesh_free(buf); + + if (sd && (param->options & BLE_MESH_ADV_OPT_CONNECTABLE)) { + buf_len = 0; + + buf = bt_mesh_calloc(sd_len * BLE_HS_ADV_MAX_SZ); + if (!buf) { + BT_ERR("ad buffer alloc failed"); + return -ENOMEM; + } + + err = set_ad(sd, sd_len, buf, &buf_len); + if (err) { + bt_mesh_free(buf); + BT_ERR("set_ad failed: err %d", err); + return err; + } + + scan_rsp = os_msys_get_pkthdr(buf_len, 0); + if (!data) { + bt_mesh_free(buf); + BT_ERR("os buf get failed"); + return -ENOBUFS; + } + + err = os_mbuf_append(scan_rsp, buf, buf_len); + if (err) { + bt_mesh_free(buf); + BT_ERR("Append ad data to os buf failed %d", err); + return -EINVAL; + } + + bt_mesh_free(buf); + } + + memset(&adv_params, 0, sizeof adv_params); + + assert(param); + + if (param->options & BLE_MESH_ADV_OPT_CONNECTABLE) { + adv_params.connectable = true; + adv_params.scannable = true; + adv_params.legacy_pdu = true; + } else if (sd != NULL) { + adv_params.connectable = false; + adv_params.scannable = true; + adv_params.legacy_pdu = true; + } else { + if (param->primary_phy == BLE_MESH_ADV_PHY_1M && + param->secondary_phy == BLE_MESH_ADV_PHY_1M) { + adv_params.legacy_pdu = true; + } + } + + adv_params.sid = inst_id; + adv_params.primary_phy = param->primary_phy; + adv_params.secondary_phy = param->secondary_phy; + adv_params.tx_power = 0x7F; // tx power will be selected by controller + adv_params.own_addr_type = BLE_OWN_ADDR_PUBLIC; + + interval = param->interval_min; + +#if CONFIG_BLE_MESH_RANDOM_ADV_INTERVAL + /* If non-connectable mesh packets are transmitted with an adv interval + * not smaller than 10ms, then we will use a random adv interval between + * [interval / 2, interval] for them. + */ + if (adv_params.legacy_pdu && interval >= 16) { + interval >>= 1; + interval += (bt_mesh_get_rand() % (interval + 1)); + + BT_DBG("%u->%u", param->interval_min, interval); + } +#endif + + adv_params.itvl_min = interval; + adv_params.itvl_max = interval; + + err = ble_gap_ext_adv_configure(inst_id, &adv_params, NULL, gap_event_cb, NULL); + if (err != 0) { + BT_ERR("Advertising config failed: err %d", err); + return err; + } + + err = ble_gap_ext_adv_set_data(inst_id, data); + if (err != 0) { + BT_ERR("Advertising set failed: err %d", err); + return err; + } + + if (scan_rsp) { + err = ble_gap_ext_adv_rsp_set_data(inst_id, scan_rsp); + if (err != 0) { + BT_ERR("scan rsp set failed: err %d", err); + return err; + } else { + BT_INFO("scan rsp set succeed\n"); + } + } + +again: + + if (param->adv_duration < 10 && + param->adv_duration != 0) { + BT_WARN("adv duration shall not be less than 10ms"); + } + + err = ble_gap_ext_adv_start(inst_id, param->adv_duration ? + 2 + param->adv_duration / 10 : 0, param->adv_count); + if (err) { + if (err == BLE_HS_EALREADY) { + ble_gap_ext_adv_stop(inst_id); + goto again; + } + + BT_ERR("Advertising start failed: err %d", err); + return err; + } + +#if BLE_MESH_DEV + bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); + + if (!(param->options & BLE_MESH_ADV_OPT_ONE_TIME)) { + bt_mesh_atomic_set_bit(bt_mesh_dev.flags, BLE_MESH_DEV_KEEP_ADVERTISING); + } +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ /* APIs functions */ int bt_le_adv_start(const struct bt_mesh_adv_param *param, const struct bt_mesh_adv_data *ad, size_t ad_len, @@ -877,8 +1382,156 @@ again: return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_SUPPORT_BLE_ADV +#if CONFIG_BLE_MESH_USE_BLE_50 +#if !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV +/** + * The current flag is only used to distinguish between BLE ADV + * and proxy ADV in the same adv instance to handle the adv + * completed events. + * + * This flag is not needed in the case of multiple adv instances. + */ +static bool _ble_adv_running_flag; + +static inline void bt_mesh_set_ble_adv_running() +{ + _ble_adv_running_flag = true; +} + +static inline void bt_mesh_unset_ble_adv_running() +{ + _ble_adv_running_flag = false; +} + +static inline bool bt_mesh_is_ble_adv_running() +{ + return _ble_adv_running_flag == true; +} +#endif /* BLE_MESH_SUPPORT_MULTI_ADV */ + +int bt_mesh_ble_ext_adv_start(const uint8_t inst_id, + const struct bt_mesh_ble_adv_param *param, + const struct bt_mesh_ble_adv_data *adv_data) +{ + struct ble_gap_ext_adv_params adv_params = {0}; + struct os_mbuf *data = NULL; + int err = 0; + + assert(param); + + switch (param->adv_type) { + case BLE_MESH_ADV_IND: + adv_params.connectable = true; + adv_params.scannable = true; + adv_params.legacy_pdu = true; + break; + case BLE_MESH_ADV_DIRECT_IND: + adv_params.connectable = true; + adv_params.scannable = false; + adv_params.directed = true; + adv_params.high_duty_directed = false; + adv_params.legacy_pdu = true; + break; + case BLE_MESH_ADV_SCAN_IND: + adv_params.connectable = false; + adv_params.scannable = true; + adv_params.directed = false; + adv_params.high_duty_directed = false; + adv_params.legacy_pdu = true; + break; + case BLE_MESH_ADV_NONCONN_IND: + adv_params.connectable = false; + adv_params.scannable = false; + adv_params.directed = false; + adv_params.high_duty_directed = false; + adv_params.legacy_pdu = true; + break; + case BLE_MESH_ADV_DIRECT_IND_LOW_DUTY: + adv_params.connectable = true; + adv_params.scannable = false; + adv_params.directed = true; + adv_params.high_duty_directed = true; + adv_params.legacy_pdu = true; + break; + } + + adv_params.itvl_min = param->interval; + adv_params.itvl_max = param->interval; + adv_params.channel_map = BLE_MESH_ADV_CHNL_37 | BLE_MESH_ADV_CHNL_38 | BLE_MESH_ADV_CHNL_39; + adv_params.filter_policy = BLE_MESH_AP_SCAN_CONN_ALL; + adv_params.primary_phy = BLE_MESH_ADV_PHY_1M; + adv_params.secondary_phy = BLE_MESH_ADV_PHY_1M; + + if (param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID || + param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID || + param->adv_type == BLE_MESH_ADV_DIRECT_IND || + param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { + adv_params.peer.type = param->peer_addr_type; + memcpy(adv_params.peer.val, param->peer_addr, BLE_MESH_ADDR_LEN); + } + + + if (ble_gap_ext_adv_configure(inst_id, &adv_params, NULL, + gap_event_cb, NULL)) { + BT_ERR("ble adv configure failed\n"); + return -EINVAL; + } + + if (adv_data && param->adv_type != BLE_MESH_ADV_DIRECT_IND && + param->adv_type != BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) { + if (adv_data->adv_data_len) { + data = os_msys_get_pkthdr(adv_data->adv_data_len, 0); + if (!data) { + BT_ERR("Failed to alloc buffer for ble"); + return -ENOMEM; + } + + if (os_mbuf_append(data, adv_data->adv_data, adv_data->adv_data_len)) { + BT_ERR("Append data failed"); + return -EINVAL; + } + + err = ble_gap_ext_adv_set_data(inst_id, data); + if (err) { + BT_ERR("Failed to set advertising data, err %d", err); + return err; + } + } + if (adv_data->scan_rsp_data_len && param->adv_type != BLE_MESH_ADV_NONCONN_IND) { + data = os_msys_get_pkthdr(adv_data->scan_rsp_data_len, 0); + if (!data) { + BT_ERR("Failed to alloc buffer for ble"); + return -ENOMEM; + } + + if (os_mbuf_append(data, adv_data->scan_rsp_data, adv_data->scan_rsp_data_len)) { + BT_ERR("Append data failed"); + return -EINVAL; + } + err = ble_gap_ext_adv_rsp_set_data(inst_id, data); + if (err) { + BT_ERR("Failed to set scan rsp data, err %d", err); + return err; + } + } + } + + err = ble_gap_ext_adv_start(inst_id, 2 + param->duration / 10, param->count); + if (err) { + BT_ERR("Failed to start advertising, err %d", err); + return err; + } + +#if !CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + bt_mesh_set_ble_adv_running(); +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, const struct bt_mesh_ble_adv_data *data) { @@ -949,8 +1602,27 @@ int bt_mesh_ble_adv_start(const struct bt_mesh_ble_adv_param *param, return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */ +#if CONFIG_BLE_MESH_USE_BLE_50 +int bt_le_ext_adv_stop(uint8_t inst_id) +{ +#if BLE_MESH_DEV + bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_KEEP_ADVERTISING); + if (!bt_mesh_atomic_test_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING)) { + return 0; + } +#endif + ble_gap_ext_adv_stop(inst_id); + +#if BLE_MESH_DEV + bt_mesh_atomic_clear_bit(bt_mesh_dev.flags, BLE_MESH_DEV_ADVERTISING); +#endif + + return 0; +} +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_le_adv_stop(void) { #if BLE_MESH_DEV @@ -967,6 +1639,7 @@ int bt_le_adv_stop(void) return 0; } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ int bt_le_scan_start(const struct bt_mesh_scan_param *param, bt_mesh_scan_cb_t cb) { @@ -987,6 +1660,7 @@ int bt_le_scan_start(const struct bt_mesh_scan_param *param, bt_mesh_scan_cb_t c err = start_le_scan(param->type, param->interval, param->window, param->filter_dup); if (err) { + BT_ERR("Failed to start advertising, err %d", err); return err; } @@ -1309,7 +1983,6 @@ int bt_mesh_gatts_service_stop(struct bt_mesh_gatt_service *svc) { int rc; uint16_t handle; - const ble_uuid_t *uuid; if (!svc) { BT_ERR("%s, Invalid parameter", __func__); @@ -1317,12 +1990,11 @@ int bt_mesh_gatts_service_stop(struct bt_mesh_gatt_service *svc) } if (BLE_MESH_UUID_16(svc->attrs[0].user_data)->val == BT_UUID_MESH_PROXY_VAL) { - uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL); + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), &handle); } else { - uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL); + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); } - rc = ble_gatts_find_svc(uuid, &handle); assert(rc == 0); ble_gatts_svc_set_visibility(handle, 0); @@ -1336,15 +2008,13 @@ int bt_mesh_gatts_service_start(struct bt_mesh_gatt_service *svc) { int rc; uint16_t handle; - const ble_uuid_t *uuid; if (BLE_MESH_UUID_16(svc->attrs[0].user_data)->val == BT_UUID_MESH_PROXY_VAL) { - uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL); + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROXY_VAL), &handle); } else { - uuid = BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL); + rc = ble_gatts_find_svc(BLE_UUID16_DECLARE(BT_UUID_MESH_PROV_VAL), &handle); } - rc = ble_gatts_find_svc(uuid, &handle); assert(rc == 0); ble_gatts_svc_set_visibility(handle, 1); @@ -1361,7 +2031,8 @@ int bt_mesh_gatts_set_local_device_name(const char *name) #endif /* CONFIG_BLE_MESH_NODE */ #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) void bt_mesh_gattc_conn_cb_register(struct bt_mesh_prov_conn_cb *cb) { bt_mesh_gattc_conn_cb = cb; @@ -1558,6 +2229,7 @@ int bt_mesh_gattc_write_no_rsp(struct bt_mesh_conn *conn, om = ble_hs_mbuf_from_flat(data, len); if (om == NULL) { + BT_ERR("om buffer alloc failed"); return -1; } @@ -1602,7 +2274,10 @@ void bt_mesh_gattc_disconnect(struct bt_mesh_conn *conn) * Mesh Proxy Data In: 0x2ADD * Mesh PROXY Data Out: 0x2ADE */ -#endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ + +#endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT)*/ struct bt_mesh_conn *bt_mesh_conn_ref(struct bt_mesh_conn *conn) { @@ -1626,9 +2301,19 @@ static int proxy_char_access_cb(uint16_t conn_handle, uint16_t attr_handle, { if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR || ctxt->op == BLE_GATT_ACCESS_OP_WRITE_DSC) { struct bt_mesh_gatt_attr *attr = bt_mesh_gatts_find_attr_by_handle(attr_handle); - uint8_t index = BLE_MESH_GATT_GET_CONN_ID(conn_handle); + int index = 0; uint16_t len = 0; +#if CONFIG_BLE_MESH_USE_BLE_50 + index = bt_mesh_find_conn_idx(BLE_MESH_GATT_GET_CONN_ID(conn_handle)); + if (index == -ENODEV) { + BT_ERR("Unknown conn handle"); + return 0; + } +#else + index = BLE_MESH_GATT_GET_CONN_ID(conn_handle); +#endif + BT_DBG("write, handle %d, len %d, data %s", attr_handle, ctxt->om->om_len, bt_hex(ctxt->om->om_data, ctxt->om->om_len)); @@ -1717,6 +2402,58 @@ void gatt_register_cb(struct ble_gatt_register_ctxt *ctxt, } } +#if CONFIG_BLE_MESH_USE_BLE_50 +void bt_mesh_gatts_svcs_add(void) +{ + ble_hs_cfg.gatts_register_cb = gatt_register_cb; + +#if CONFIG_BLE_MESH_NODE + int rc = 0; + + ble_svc_gap_init(); + ble_svc_gatt_init(); + + rc = ble_gatts_count_cfg(svc_defs); + assert(rc == 0); + + rc = ble_gatts_add_svcs(svc_defs); + assert(rc == 0); + + g_gatts_svcs_add = true; +#endif +} + +void bt_mesh_gatt_init(void) +{ + ble_att_set_preferred_mtu(BLE_MESH_GATT_DEF_MTU_SIZE); + +#if CONFIG_BLE_MESH_NODE + static bool init = false; + + if (init == false) { + + __ASSERT(g_gatts_svcs_add, "func bt_mesh_gatts_svcs_add should be called before mesh init"); + + ble_gatts_svc_set_visibility(prov_svc_start_handle, 1); + ble_gatts_svc_set_visibility(proxy_svc_start_handle, 0); + +#if CONFIG_BLE_MESH_USE_BLE_50 + bt_mesh_gatts_conn_init(); +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + init = true; + } +#endif /* CONFIG_BLE_MESH_NODE */ + +#if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT + for (int i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { + bt_mesh_gattc_info[i].conn.handle = 0xFFFF; + bt_mesh_gattc_info[i].mtu = BLE_ATT_MTU_DFLT; + bt_mesh_gattc_info[i].wr_desc_done = false; + } +#endif +} +#else void bt_mesh_gatt_init(void) { ble_att_set_preferred_mtu(BLE_ATT_MTU_DFLT); @@ -1747,7 +2484,8 @@ void bt_mesh_gatt_init(void) #endif /* CONFIG_BLE_MESH_NODE */ #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) for (int i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { bt_mesh_gattc_info[i].conn.handle = 0xFFFF; bt_mesh_gattc_info[i].mtu = BLE_ATT_MTU_DFLT; @@ -1755,6 +2493,7 @@ void bt_mesh_gatt_init(void) } #endif } +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ #if CONFIG_BLE_MESH_DEINIT void bt_mesh_gatt_deinit(void) @@ -1765,7 +2504,8 @@ void bt_mesh_gatt_deinit(void) #endif #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) for (int i = 0; i < ARRAY_SIZE(bt_mesh_gattc_info); i++) { bt_mesh_gattc_info[i].conn.handle = 0xFFFF; memset(&bt_mesh_gattc_info[i].addr, 0, sizeof(bt_mesh_addr_t)); @@ -1985,12 +2725,12 @@ int bt_mesh_update_exceptional_list(uint8_t sub_code, uint32_t type, void *info) if ((sub_code > BLE_MESH_EXCEP_LIST_SUB_CODE_CLEAN) || (sub_code < BLE_MESH_EXCEP_LIST_SUB_CODE_CLEAN && - type > BLE_MESH_EXCEP_LIST_TYPE_MESH_PROXY_ADV) || + type > BLE_MESH_EXCEP_LIST_TYPE_MAX) || (sub_code == BLE_MESH_EXCEP_LIST_SUB_CODE_CLEAN && !(type & BLE_MESH_EXCEP_LIST_CLEAN_ALL_LIST))) { BT_ERR("%s, Invalid parameter", __func__); return -EINVAL; - } + } if (type == BLE_MESH_EXCEP_LIST_TYPE_MESH_LINK_ID) { if (!info) { diff --git a/lib/bt/esp_ble_mesh/core/prov_common.c b/lib/bt/esp_ble_mesh/core/prov_common.c index 655c4712..6f9e1dfa 100644 --- a/lib/bt/esp_ble_mesh/core/prov_common.c +++ b/lib/bt/esp_ble_mesh/core/prov_common.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -135,6 +135,9 @@ bool bt_mesh_prov_pdu_check(uint8_t type, uint16_t length, uint8_t *reason) #define CLOSE_XMIT BLE_MESH_TRANSMIT(2, 20) #define CLOSE_TIMEOUT K_MSEC(100) +#define CLOSE_RETRANS_CNT 3 +#define CLOSE_RETRANS_WITH_REASON(cnt, rsn) (((cnt) << 4) | ((rsn) & 0x0f)) +#define CLOSE_RETRANS_GET(rsn) ((rsn) >> 4) #define BUF_TIMEOUT K_MSEC(400) @@ -143,7 +146,7 @@ bool bt_mesh_prov_pdu_check(uint8_t type, uint16_t length, uint8_t *reason) static uint8_t bt_mesh_prov_buf_type_get(struct net_buf_simple *buf) { - return buf->data[PROV_BUF_HEADROOM]; + return buf->__buf[PROV_BUF_HEADROOM]; } uint8_t node_next_xact_id(struct bt_mesh_prov_link *link) @@ -359,7 +362,7 @@ static void free_segments(struct bt_mesh_prov_link *link) link->tx.buf[i] = NULL; bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); /* Mark as canceled */ - BLE_MESH_ADV(buf)->busy = 0U; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 0); net_buf_unref(buf); } } @@ -457,12 +460,19 @@ static void prov_retransmit(struct k_work *work) if (link->pb_remote_close) { link->pb_remote_close(link, link->reason); } + return; } else { - if (link->reset_adv_link) { - link->reset_adv_link(link, link->reason); + uint8_t retrans_cnt = CLOSE_RETRANS_GET(link->reason); + if (!retrans_cnt) { + if (link->reset_adv_link) { + link->reset_adv_link(link, link->reason); + } + return; + } else { + retrans_cnt--; + link->reason = CLOSE_RETRANS_WITH_REASON(retrans_cnt, link->reason); } } - return; } bt_mesh_mutex_lock(&link->buf_lock); @@ -474,7 +484,7 @@ static void prov_retransmit(struct k_work *work) break; } - if (BLE_MESH_ADV(buf)->busy) { + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(buf))) { continue; } @@ -547,7 +557,14 @@ int bt_mesh_prov_bearer_ctl_send(struct bt_mesh_prov_link *link, uint8_t op, if (op == LINK_CLOSE) { bt_mesh_atomic_clear_bit(link->flags, LINK_ACTIVE); bt_mesh_atomic_set_bit(link->flags, LINK_CLOSING); - link->reason = *((uint8_t *)data); + /** We can also use buf->ref and a flag to decide that + * link close has been sent 3 times. + * Here we use another way: use retransmit timer and need + * to make sure the timer is not cancelled during sending + * link close pdu, Therefore, use the higher four bits + * of reason as a retransmit count. + */ + link->reason = CLOSE_RETRANS_WITH_REASON(CLOSE_RETRANS_CNT, (*((uint8_t *)data))); } return 0; diff --git a/lib/bt/esp_ble_mesh/core/prov_common.h b/lib/bt/esp_ble_mesh/core/prov_common.h index 561712ef..d2a8771b 100644 --- a/lib/bt/esp_ble_mesh/core/prov_common.h +++ b/lib/bt/esp_ble_mesh/core/prov_common.h @@ -17,7 +17,9 @@ #include "mesh/timer.h" #include "mesh/adapter.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #ifdef __cplusplus extern "C" { diff --git a/lib/bt/esp_ble_mesh/core/prov_node.c b/lib/bt/esp_ble_mesh/core/prov_node.c index 4871a1cb..cf789470 100644 --- a/lib/bt/esp_ble_mesh/core/prov_node.c +++ b/lib/bt/esp_ble_mesh/core/prov_node.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,7 +22,9 @@ #include "prov_common.h" #include "prov_node.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if CONFIG_BLE_MESH_NODE @@ -80,12 +82,12 @@ static void reset_state(void) } #endif /* CONFIG_BLE_MESH_PB_GATT */ -#if CONFIG_BLE_MESH_PB_ADV /* Clear everything except the retransmit and protocol timer * delayed work objects. */ (void)memset(&prov_link, 0, offsetof(struct bt_mesh_prov_link, tx.retransmit)); +#if CONFIG_BLE_MESH_PB_ADV prov_link.pending_ack = PROV_XACT_NVAL; prov_link.rx.prev_id = PROV_XACT_NVAL; @@ -152,7 +154,7 @@ static int prov_send_gatt(struct bt_mesh_prov_link *link, struct net_buf_simple /* Changed by Espressif, add provisioning timeout timer operations. * When sending a provisioning PDU successfully, restart the 60s timer. */ -#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT && CONFIG_BLE_MESH_RPR_SRV +#if CONFIG_BLE_MESH_RPR_SRV if (bt_mesh_atomic_test_bit(link->flags, PB_REMOTE)) { err = bt_mesh_proxy_client_send(link->conn, BLE_MESH_PROXY_PROV, msg); @@ -1073,10 +1075,19 @@ static void link_ack(struct prov_rx *rx, struct net_buf_simple *buf) bt_mesh_prov_clear_tx(&prov_link, true); bt_mesh_rpr_srv_recv_link_ack(prov_link.pb_remote_uuid, true); } else { - BT_INFO("Link ACK for PB-Remote already received"); + BT_DBG("Link ACK for PB-Remote already received"); + return; } } #endif /* CONFIG_BLE_MESH_RPR_SRV */ + + if (!k_delayed_work_remaining_get(&prov_link.prot_timer)) { + /** + * When the link is opened, the provisioner and the unprovisioned device + * shall start the link timer with the timeout value set to 60 seconds. + */ + k_delayed_work_submit(&prov_link.prot_timer, PROTOCOL_TIMEOUT); + } } static void link_close(struct prov_rx *rx, struct net_buf_simple *buf) @@ -1432,6 +1443,11 @@ int bt_mesh_pb_gatt_open(struct bt_mesh_conn *conn) { BT_DBG("conn %p", conn); + /** + * It's necessary to determine if it is PB_REMOTE because when the + * node acts as an RPR server, LINK_ACTIVE has already been set upon + * receiving the link open from the RPR client. + */ if (!bt_mesh_atomic_test_bit(prov_link.flags, PB_REMOTE) && bt_mesh_atomic_test_and_set_bit(prov_link.flags, LINK_ACTIVE)) { BT_ERR("Link is busy"); @@ -1449,6 +1465,14 @@ int bt_mesh_pb_gatt_open(struct bt_mesh_conn *conn) prov_link.expect = PROV_INVITE; } + /** + * Just like ADV Link, start provision timeout timer after + * establishing the link to prevent the RPR server from + * being unable to recover to a configurable network state + * during remote provisioning. + */ + k_delayed_work_submit(&prov_link.prot_timer, PROTOCOL_TIMEOUT); + if (bt_mesh_prov_get()->link_open) { bt_mesh_prov_get()->link_open(BLE_MESH_PROV_GATT); } @@ -1469,6 +1493,9 @@ int bt_mesh_pb_gatt_close(struct bt_mesh_conn *conn, uint8_t reason) if (bt_mesh_atomic_test_bit(prov_link.flags, PB_REMOTE)) { prov_link.pb_remote_cbd = true; prov_link.pb_remote_reset = true; + /* @todo: the close reason is disconnect reason, not the + * link close reason, should change it to link close reason? + */ prov_link.pb_remote_close(&prov_link, reason); } #endif @@ -1494,7 +1521,7 @@ static void protocol_timeout(struct k_work *work) #if CONFIG_BLE_MESH_PB_GATT if (prov_link.conn) { -#if CONFIG_BLE_MESH_GATT_PROXY_CLIENT && CONFIG_BLE_MESH_RPR_SRV +#if CONFIG_BLE_MESH_RPR_SRV if (bt_mesh_atomic_test_bit(prov_link.flags, PB_REMOTE)) { prov_link.pb_remote_reset = true; bt_mesh_gattc_disconnect(prov_link.conn); diff --git a/lib/bt/esp_ble_mesh/core/prov_pvnr.c b/lib/bt/esp_ble_mesh/core/prov_pvnr.c index e2e0fe58..091e3e86 100644 --- a/lib/bt/esp_ble_mesh/core/prov_pvnr.c +++ b/lib/bt/esp_ble_mesh/core/prov_pvnr.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,7 +22,9 @@ #include "prov_pvnr.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if CONFIG_BLE_MESH_PROVISIONER @@ -45,6 +47,10 @@ _Static_assert(BLE_MESH_MAX_CONN >= CONFIG_BLE_MESH_PBG_SAME_TIME, */ static struct bt_mesh_prov_link prov_links[BLE_MESH_PROV_SAME_TIME]; +#if CONFIG_BLE_MESH_RPR_CLI +extern struct bt_mesh_prov_link rpr_links[CONFIG_BLE_MESH_RPR_CLI_PROV_SAME_TIME]; +#endif + struct bt_mesh_prov_ctx { /* Primary element address of Provisioner */ uint16_t primary_addr; @@ -242,7 +248,7 @@ void bt_mesh_provisioner_restore_prov_info(uint16_t primary_addr, uint16_t alloc } #endif /* CONFIG_BLE_MESH_SETTINGS */ -static bool is_unprov_dev_being_provision(const uint8_t uuid[16]) +bool bt_mesh_is_unprov_dev_being_prov(const uint8_t uuid[16]) { int i; @@ -259,6 +265,15 @@ static bool is_unprov_dev_being_provision(const uint8_t uuid[16]) } #endif /* CONFIG_BLE_MESH_FAST_PROV */ +#if CONFIG_BLE_MESH_RPR_CLI + for (i = 0; i < CONFIG_BLE_MESH_RPR_CLI_PROV_SAME_TIME;i++) { + if (!memcmp(rpr_links[i].pb_remote_uuid, uuid, 16)) { + BT_WARN("Device is being provisioning by Remote Provisioning"); + return true; + } + } +#endif + for (i = 0; i < BLE_MESH_PROV_SAME_TIME; i++) { if (bt_mesh_atomic_test_bit(prov_links[i].flags, LINK_ACTIVE) #if CONFIG_BLE_MESH_PB_GATT @@ -309,7 +324,7 @@ static int provisioner_check_unprov_dev_info(const uint8_t uuid[16], bt_mesh_pro * receive the connectable prov adv pkt from this device. * Here we check both PB-GATT and PB-ADV link status. */ - if (is_unprov_dev_being_provision(uuid)) { + if (bt_mesh_is_unprov_dev_being_prov(uuid)) { return -EALREADY; } @@ -364,7 +379,7 @@ static int provisioner_start_prov_pb_adv(const uint8_t uuid[16], const bt_mesh_a return -EIO; } - if (is_unprov_dev_being_provision(uuid)) { + if (bt_mesh_is_unprov_dev_being_prov(uuid)) { bt_mesh_pb_adv_unlock(); return 0; } @@ -426,7 +441,7 @@ static int provisioner_start_prov_pb_gatt(const uint8_t uuid[16], const bt_mesh_ return -EIO; } - if (is_unprov_dev_being_provision(uuid)) { + if (bt_mesh_is_unprov_dev_being_prov(uuid)) { bt_mesh_pb_gatt_unlock(); return 0; } @@ -1413,7 +1428,7 @@ static int prov_auth(struct bt_mesh_prov_link *link, return -EINVAL; } - /* Provisioner ouput number/string and wait for device's Provisioning Input Complete PDU */ + /* Provisioner output number/string and wait for device's Provisioning Input Complete PDU */ link->expect = PROV_INPUT_COMPLETE; /* NOTE: The Bluetooth SIG recommends that mesh implementations enforce a randomly @@ -1957,6 +1972,7 @@ static void send_prov_data(struct bt_mesh_prov_link *link) uint8_t session_key[16] = {0}; uint8_t nonce[13] = {0}; uint8_t pdu[25] = {0}; + uint8_t *dev_uuid = NULL; PROV_BUF(buf, 34); int err = 0; @@ -2012,7 +2028,13 @@ static void send_prov_data(struct bt_mesh_prov_link *link) */ /* Check if this device is a re-provisioned device */ - node = bt_mesh_provisioner_get_node_with_uuid(link->uuid); + if (bt_mesh_atomic_test_bit(link->flags, PB_REMOTE)) { + dev_uuid = link->pb_remote_uuid; + } else { + dev_uuid = link->uuid; + } + + node = bt_mesh_provisioner_get_node_with_uuid(dev_uuid); if (node) { if (link->element_num <= node->element_num && link->pb_remote_nppi != NPPI_NODE_ADDR_REFRESH) { @@ -2027,7 +2049,7 @@ static void send_prov_data(struct bt_mesh_prov_link *link) */ if (!bt_mesh_atomic_test_bit(link->flags, PB_REMOTE) || link->pb_remote_nppi == NPPI_UNKNOWN) { - bt_mesh_provisioner_remove_node(link->uuid); + bt_mesh_provisioner_remove_node(dev_uuid); } } @@ -2211,6 +2233,7 @@ static void prov_complete(struct bt_mesh_prov_link *link, uint16_t net_idx = 0U; uint16_t index = 0U; bool nppi = false; + uint8_t *dev_uuid = NULL; int err = 0; int i; @@ -2227,12 +2250,16 @@ static void prov_complete(struct bt_mesh_prov_link *link, net_idx = prov_ctx.net_idx; } - if (bt_mesh_atomic_test_bit(link->flags, PB_REMOTE) && - link->pb_remote_nppi != NPPI_UNKNOWN) { - nppi = true; + if (bt_mesh_atomic_test_bit(link->flags, PB_REMOTE)) { + if (link->pb_remote_nppi != NPPI_UNKNOWN) { + nppi = true; + } + dev_uuid = link->pb_remote_uuid; + } else { + dev_uuid = link->uuid; } - err = bt_mesh_provisioner_provision(&link->addr, link->uuid, link->oob_info, + err = bt_mesh_provisioner_provision(&link->addr, dev_uuid, link->oob_info, link->unicast_addr, link->element_num, net_idx, link->kri_flags, bt_mesh.iv_index, device_key, &index, nppi); @@ -2264,13 +2291,13 @@ static void prov_complete(struct bt_mesh_prov_link *link, #endif /* CONFIG_BLE_MESH_RPR_CLI */ if (bt_mesh_prov_get()->prov_complete) { - bt_mesh_prov_get()->prov_complete(index, link->uuid, link->unicast_addr, + bt_mesh_prov_get()->prov_complete(index, dev_uuid, link->unicast_addr, link->element_num, net_idx); } /* Find if the device is in the device queue */ for (i = 0; i < ARRAY_SIZE(unprov_dev); i++) { - if (!memcmp(unprov_dev[i].uuid, link->uuid, 16) && + if (!memcmp(unprov_dev[i].uuid, dev_uuid, 16) && (unprov_dev[i].flags & RM_AFTER_PROV)) { memset(&unprov_dev[i], 0, sizeof(struct unprov_dev_queue)); break; diff --git a/lib/bt/esp_ble_mesh/core/prov_pvnr.h b/lib/bt/esp_ble_mesh/core/prov_pvnr.h index 0553a72d..b3eb5048 100644 --- a/lib/bt/esp_ble_mesh/core/prov_pvnr.h +++ b/lib/bt/esp_ble_mesh/core/prov_pvnr.h @@ -379,6 +379,8 @@ uint16_t bt_mesh_provisioner_get_fast_prov_net_idx(void); */ uint8_t bt_mesh_set_fast_prov_unicast_addr_range(uint16_t min, uint16_t max); +bool bt_mesh_is_unprov_dev_being_prov(const uint8_t uuid[16]); + int bt_mesh_rpr_cli_pdu_recv(struct bt_mesh_prov_link *link, uint8_t type, struct net_buf_simple *buf); diff --git a/lib/bt/esp_ble_mesh/core/proxy_client.c b/lib/bt/esp_ble_mesh/core/proxy_client.c index 9382cf61..ac05f92f 100644 --- a/lib/bt/esp_ble_mesh/core/proxy_client.c +++ b/lib/bt/esp_ble_mesh/core/proxy_client.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,14 +21,17 @@ #include "pvnr_mgmt.h" #include "mesh/adapter.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) static struct bt_mesh_proxy_server { struct bt_mesh_conn *conn; - + bt_mesh_addr_t addr; enum __attribute__((packed)) { CLI_NONE, CLI_PROV, @@ -83,6 +86,22 @@ static void proxy_sar_timeout(struct k_work *work) bt_mesh_gattc_disconnect(server->conn); } +#if (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) +int bt_mesh_rpr_srv_set_waiting_prov_link(struct bt_mesh_prov_link *link, + bt_mesh_addr_t *addr) +{ + for (size_t i = 0; i < ARRAY_SIZE(waiting_conn_link);i++) { + if (waiting_conn_link[i].link == NULL) { + waiting_conn_link[i].link = link; + memcpy(&waiting_conn_link[i].addr, addr, sizeof(bt_mesh_addr_t)); + return 0; + } + } + + return -ENOBUFS; +} +#endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT */ + #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT /** * The following callbacks are used to notify proper information @@ -113,22 +132,6 @@ void bt_mesh_proxy_client_set_filter_status_cb(proxy_client_recv_filter_status_c proxy_client_filter_status_recv_cb = cb; } -#if (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) -int bt_mesh_rpr_srv_set_waiting_prov_link(struct bt_mesh_prov_link *link, - bt_mesh_addr_t *addr) -{ - for (size_t i = 0; i < ARRAY_SIZE(waiting_conn_link);i++) { - if (waiting_conn_link[i].link == NULL) { - waiting_conn_link[i].link = link; - memcpy(&waiting_conn_link[i].addr, addr, sizeof(bt_mesh_addr_t)); - return 0; - } - } - - return -ENOBUFS; -} -#endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT */ - static void filter_status(struct bt_mesh_proxy_server *server, struct bt_mesh_net_rx *rx, struct net_buf_simple *buf) @@ -264,7 +267,9 @@ static void proxy_complete_pdu(struct bt_mesh_proxy_server *server) } else #endif { +#if CONFIG_BLE_MESH_PROVISIONER bt_mesh_provisioner_pb_gatt_recv(server->conn, &server->buf); +#endif } break; #endif @@ -460,6 +465,7 @@ static void proxy_connected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, int server->conn = bt_mesh_conn_ref(conn); server->conn_type = CLI_NONE; + memcpy(&server->addr, addr, sizeof(bt_mesh_addr_t)); net_buf_simple_reset(&server->buf); #if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT @@ -492,6 +498,7 @@ static void proxy_disconnected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, if (bt_mesh_prov_node_get_link()->conn == conn) { for (size_t i = 0; i < ARRAY_SIZE(waiting_conn_link); i++) { if (waiting_conn_link[i].link->conn == conn) { + waiting_conn_link[i].link = NULL; memset(&waiting_conn_link[i].addr, 0, sizeof(bt_mesh_addr_t)); break; } @@ -501,7 +508,9 @@ static void proxy_disconnected(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn, } else #endif /* CONFIG_BLE_MESH_RPR_SRV */ { +#if CONFIG_BLE_MESH_PROVISIONER bt_mesh_provisioner_pb_gatt_close(conn, reason); +#endif /* CONFIG_BLE_MESH_PROVISIONER */ } } #endif /* CONFIG_BLE_MESH_PB_GATT && (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) */ @@ -548,7 +557,9 @@ static ssize_t prov_write_ccc(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn) } #endif +#if CONFIG_BLE_MESH_PROVISIONER return bt_mesh_provisioner_pb_gatt_open(conn, addr->val); +#endif } return -ENOMEM; @@ -619,6 +630,12 @@ static ssize_t proxy_write_ccc(bt_mesh_addr_t *addr, struct bt_mesh_conn *conn) return 0; } +#if CONFIG_BLE_MESH_BQB_TEST + /* notify maybe received first */ + if (server->conn_type == CLI_PROXY) { + return 0; + } +#endif return -EINVAL; } @@ -631,6 +648,16 @@ static ssize_t proxy_recv_ntf(struct bt_mesh_conn *conn, uint8_t *data, uint16_t return -ENOTCONN; } +#if CONFIG_BLE_MESH_BQB_TEST + /* update conn type if notify received before write ccc */ + if (server->conn_type == CLI_NONE) { + server->conn_type = CLI_PROXY; + if (proxy_client_connect_cb) { + proxy_client_connect_cb(&server->addr, server - servers, server->net_idx); + } + } +#endif + if (server->conn_type == CLI_PROXY) { return proxy_recv(conn, NULL, data, len, 0, 0); } @@ -692,10 +719,12 @@ int bt_mesh_proxy_client_gatt_disable(void) static struct bt_mesh_prov_conn_cb conn_callbacks = { .connected = proxy_connected, .disconnected = proxy_disconnected, -#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT +#if (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) && \ + CONFIG_BLE_MESH_PB_GATT .prov_write_descr = prov_write_ccc, .prov_notify = prov_recv_ntf, -#endif /* CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT */ +#endif /* (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) && \ + CONFIG_BLE_MESH_PB_GATT */ #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT .proxy_write_descr = proxy_write_ccc, .proxy_notify = proxy_recv_ntf, @@ -818,6 +847,23 @@ int bt_mesh_proxy_client_disconnect(uint8_t conn_handle) return 0; } +uint16_t bt_mesh_proxy_client_get_conn_count(void) +{ + uint16_t count = 0; + + for (size_t i = 0; i < ARRAY_SIZE(servers); i++) { + struct bt_mesh_proxy_server *server = &servers[i]; + + if (!server->conn || server->conn_type != CLI_PROXY) { + continue; + } + + count++; + } + + return count; +} + bool bt_mesh_proxy_client_relay(struct net_buf_simple *buf, uint16_t dst) { bool send = false; @@ -1123,4 +1169,5 @@ int bt_mesh_proxy_client_deinit(void) #endif /* CONFIG_BLE_MESH_DEINIT */ #endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT */ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) */ diff --git a/lib/bt/esp_ble_mesh/core/proxy_client.h b/lib/bt/esp_ble_mesh/core/proxy_client.h index d2d85017..6bc0732d 100644 --- a/lib/bt/esp_ble_mesh/core/proxy_client.h +++ b/lib/bt/esp_ble_mesh/core/proxy_client.h @@ -11,7 +11,9 @@ #include "mesh/adapter.h" #include "prov_common.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #ifdef __cplusplus extern "C" { @@ -102,6 +104,8 @@ int bt_mesh_proxy_client_disconnect(uint8_t conn_handle); bool bt_mesh_proxy_client_beacon_send(struct bt_mesh_subnet *sub, bool private); +uint16_t bt_mesh_proxy_client_get_conn_count(void); + bool bt_mesh_proxy_client_relay(struct net_buf_simple *buf, uint16_t dst); int bt_mesh_proxy_client_cfg_send(uint8_t conn_handle, uint16_t net_idx, diff --git a/lib/bt/esp_ble_mesh/core/proxy_server.c b/lib/bt/esp_ble_mesh/core/proxy_server.c index 020793dc..e8069155 100644 --- a/lib/bt/esp_ble_mesh/core/proxy_server.c +++ b/lib/bt/esp_ble_mesh/core/proxy_server.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,17 +22,23 @@ #include "prov_common.h" #include "prov_node.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if (CONFIG_BLE_MESH_NODE && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_SERVER -#if !CONFIG_BLE_MESH_BQB_TEST +#if !CONFIG_BLE_MESH_BQB_TEST && !CONFIG_BLE_MESH_PROXY_CLI_SRV_COEXIST && !CONFIG_BLE_MESH_RPR_SRV /* Not support enabling Proxy Client and Proxy Server simultaneously */ _Static_assert(!(IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_SERVER) && IS_ENABLED(CONFIG_BLE_MESH_GATT_PROXY_CLIENT)), "Not support Proxy Server and Proxy Client simultaneously"); #endif +#if CONFIG_BLE_MESH_USE_BLE_50 +static uint8_t proxy_adv_inst = BLE_MESH_ADV_INS_UNUSED; +#endif + #define ADV_OPT (BLE_MESH_ADV_OPT_CONNECTABLE | BLE_MESH_ADV_OPT_ONE_TIME) #if CONFIG_BLE_MESH_GATT_PROXY_SERVER && \ @@ -50,12 +56,24 @@ static const struct bt_mesh_adv_param slow_adv_param = { .options = ADV_OPT, .interval_min = BLE_MESH_GAP_ADV_SLOW_INT_MIN, .interval_max = BLE_MESH_GAP_ADV_SLOW_INT_MAX, +#if CONFIG_BLE_MESH_USE_BLE_50 + .primary_phy = BLE_MESH_ADV_PHY_1M, + .secondary_phy = BLE_MESH_ADV_PHY_1M, + .adv_duration = 0, + .adv_count = 0, +#endif }; static const struct bt_mesh_adv_param fast_adv_param = { .options = ADV_OPT, .interval_min = BLE_MESH_GAP_ADV_FAST_INT_MIN_0, .interval_max = BLE_MESH_GAP_ADV_FAST_INT_MAX_0, +#if CONFIG_BLE_MESH_USE_BLE_50 + .primary_phy = BLE_MESH_ADV_PHY_1M, + .secondary_phy = BLE_MESH_ADV_PHY_1M, + .adv_duration = 0, + .adv_count = 0, +#endif }; static bool proxy_adv_enabled; @@ -152,6 +170,11 @@ static void proxy_sar_timeout(struct k_work *work) bt_mesh_gatts_disconnect(client->conn, 0x13); } +void bt_mesh_proxy_server_adv_flag_set(bool enable) +{ + proxy_adv_enabled = enable; +} + #if CONFIG_BLE_MESH_GATT_PROXY_SERVER /** * The following callbacks are used to notify proper information @@ -826,10 +849,18 @@ static void proxy_connected(struct bt_mesh_conn *conn, uint8_t err) BT_DBG("conn %p err 0x%02x", conn, err); + if (gatt_svc == MESH_GATT_PROV && conn_count == 1) { + BT_WARN("Only one prov connection could exists"); + bt_mesh_gatts_disconnect(conn, 0x13); + return; + } + conn_count++; /* Since we use ADV_OPT_ONE_TIME */ - proxy_adv_enabled = false; +#if !CONFIG_BLE_MESH_USE_BLE_50 + bt_mesh_proxy_server_adv_flag_set(false); +#endif #if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX /* Before re-enabling advertising, stop advertising @@ -1019,7 +1050,6 @@ int bt_mesh_proxy_server_prov_enable(void) } } - return 0; } @@ -1333,7 +1363,7 @@ int bt_mesh_proxy_server_segment_send(struct bt_mesh_conn *conn, uint8_t type, net_buf_simple_pull(msg, mtu); while (msg->len) { - if (msg->len + 1 < mtu) { + if (msg->len + 1 <= mtu) { net_buf_simple_push_u8(msg, BLE_MESH_PROXY_PDU_HDR(BLE_MESH_PROXY_SAR_LAST, type)); proxy_send(conn, msg->data, msg->len); break; @@ -1463,14 +1493,19 @@ static int node_id_adv(struct bt_mesh_subnet *sub) memcpy(proxy_svc_data + 3, tmp + 8, 8); proxy_sd_len = gatt_proxy_adv_create(&proxy_sd); - err = bt_le_adv_start(&fast_adv_param, node_id_ad, - ARRAY_SIZE(node_id_ad), &proxy_sd, proxy_sd_len); +#if CONFIG_BLE_MESH_USE_BLE_50 + err = bt_le_ext_adv_start(proxy_adv_inst, &fast_adv_param, node_id_ad, + ARRAY_SIZE(node_id_ad), &proxy_sd, proxy_sd_len); +#else + err = bt_le_adv_start(&fast_adv_param, node_id_ad, + ARRAY_SIZE(node_id_ad), &proxy_sd, proxy_sd_len); +#endif if (err) { BT_WARN("Failed to advertise using Node ID (err %d)", err); return err; } - proxy_adv_enabled = true; + bt_mesh_proxy_server_adv_flag_set(true); return 0; } @@ -1489,14 +1524,19 @@ static int net_id_adv(struct bt_mesh_subnet *sub) memcpy(proxy_svc_data + 3, sub->keys[sub->kr_flag].net_id, 8); proxy_sd_len = gatt_proxy_adv_create(&proxy_sd); - err = bt_le_adv_start(&slow_adv_param, net_id_ad, - ARRAY_SIZE(net_id_ad), &proxy_sd, proxy_sd_len); +#if CONFIG_BLE_MESH_USE_BLE_50 + err = bt_le_ext_adv_start(proxy_adv_inst, &slow_adv_param, net_id_ad, + ARRAY_SIZE(net_id_ad), &proxy_sd, proxy_sd_len); +#else + err = bt_le_adv_start(&slow_adv_param, net_id_ad, + ARRAY_SIZE(net_id_ad), &proxy_sd, proxy_sd_len); +#endif if (err) { BT_WARN("Failed to advertise using Network ID (err %d)", err); return err; } - proxy_adv_enabled = true; + bt_mesh_proxy_server_adv_flag_set(true); return 0; } @@ -1559,7 +1599,7 @@ static int private_node_id_adv(struct bt_mesh_subnet *sub) return err; } - proxy_adv_enabled = true; + bt_mesh_proxy_server_adv_flag_set(true); return 0; } @@ -1603,7 +1643,7 @@ static int private_net_id_adv(struct bt_mesh_subnet *sub) return err; } - proxy_adv_enabled = true; + bt_mesh_proxy_server_adv_flag_set(true); return 0; } @@ -1715,6 +1755,7 @@ static int32_t gatt_proxy_advertise(struct bt_mesh_subnet *sub) && sub->private_node_id == BLE_MESH_PRIVATE_NODE_IDENTITY_STOPPED #endif ) { + /* advertising node identity forever */ if (bt_mesh_gatt_proxy_get() == BLE_MESH_GATT_PROXY_ENABLED) { net_id_adv(sub); } @@ -1830,17 +1871,25 @@ static int32_t solic_adv_private_net_id(void) int32_t bt_mesh_proxy_server_adv_start(void) { + BT_DBG("proxy server start"); + if (gatt_svc == MESH_GATT_NONE) { return K_FOREVER; } +#if CONFIG_BLE_MESH_USE_BLE_50 + if (proxy_adv_inst == BLE_MESH_ADV_INS_UNUSED) { + return K_FOREVER; + } +#endif + #if CONFIG_BLE_MESH_PB_GATT if (prov_fast_adv) { prov_start_time = k_uptime_get_32(); } if (!bt_mesh_is_provisioned()) { - const struct bt_mesh_adv_param *param; + const struct bt_mesh_adv_param *param = NULL; struct bt_mesh_adv_data prov_sd[2]; size_t prov_sd_len; @@ -1852,9 +1901,15 @@ int32_t bt_mesh_proxy_server_adv_start(void) prov_sd_len = gatt_prov_adv_create(prov_sd); +#if CONFIG_BLE_MESH_USE_BLE_50 + if (bt_le_ext_adv_start(proxy_adv_inst, param, prov_ad, ARRAY_SIZE(prov_ad), + prov_sd, prov_sd_len) == 0) { +#else /* CONFIG_BLE_MESH_USE_BLE_50 */ if (bt_le_adv_start(param, prov_ad, ARRAY_SIZE(prov_ad), prov_sd, prov_sd_len) == 0) { - proxy_adv_enabled = true; +#endif /* CONFIG_BLE_MESH_USE_BLE_50 */ + + bt_mesh_proxy_server_adv_flag_set(true); /* Advertise 60 seconds using fast interval */ if (prov_fast_adv) { @@ -1884,25 +1939,35 @@ int32_t bt_mesh_proxy_server_adv_start(void) } #endif /* GATT_PROXY */ + /* used to indicate proxy advertising could be stopped */ return K_FOREVER; } -void bt_mesh_proxy_server_adv_stop(void) +int bt_mesh_proxy_server_adv_stop(void) { int err = 0; - BT_DBG("adv_enabled %u", proxy_adv_enabled); - if (!proxy_adv_enabled) { - return; + return -EALREADY; } +#if CONFIG_BLE_MESH_USE_BLE_50 + if (proxy_adv_inst == BLE_MESH_ADV_INS_UNUSED) { + BT_ERR("Proxy adv inst is not initialized!"); + return -EINVAL; + } + + err = bt_le_ext_adv_stop(proxy_adv_inst); +#else err = bt_le_adv_stop(); +#endif if (err) { BT_ERR("Failed to stop advertising (err %d)", err); - } else { - proxy_adv_enabled = false; + return -EINVAL; } + + bt_mesh_proxy_server_adv_flag_set(false); + return 0; } static struct bt_mesh_conn_cb conn_callbacks = { @@ -1914,6 +1979,14 @@ int bt_mesh_proxy_server_init(void) { int i; +#if CONFIG_BLE_MESH_USE_BLE_50 +#if CONFIG_BLE_MESH_SUPPORT_MULTI_ADV + proxy_adv_inst = CONFIG_BLE_MESH_PROXY_ADV_INST_ID; +#else /* CONFIG_BLE_MESH_SUPPORT_MULTI_ADV */ + proxy_adv_inst = CONFIG_BLE_MESH_ADV_INST_ID; +#endif +#endif + #if CONFIG_BLE_MESH_GATT_PROXY_SERVER bt_mesh_gatts_service_register(&proxy_svc); #endif @@ -1952,7 +2025,11 @@ int bt_mesh_proxy_server_deinit(void) { int i; - proxy_adv_enabled = false; +#if CONFIG_BLE_MESH_USE_BLE_50 + proxy_adv_inst = BLE_MESH_ADV_INS_UNUSED; +#endif + + bt_mesh_proxy_server_adv_flag_set(false); gatt_svc = MESH_GATT_NONE; #if CONFIG_BLE_MESH_GATT_PROXY_SERVER diff --git a/lib/bt/esp_ble_mesh/core/proxy_server.h b/lib/bt/esp_ble_mesh/core/proxy_server.h index b9872891..fc4041f8 100644 --- a/lib/bt/esp_ble_mesh/core/proxy_server.h +++ b/lib/bt/esp_ble_mesh/core/proxy_server.h @@ -12,6 +12,7 @@ #include "net.h" #include "mesh/adapter.h" +#include "adv.h" #ifdef __cplusplus extern "C" { @@ -94,7 +95,7 @@ void bt_mesh_proxy_server_beacon_send(struct bt_mesh_subnet *sub); struct net_buf_simple *bt_mesh_proxy_server_get_buf(void); int32_t bt_mesh_proxy_server_adv_start(void); -void bt_mesh_proxy_server_adv_stop(void); +int bt_mesh_proxy_server_adv_stop(void); void bt_mesh_proxy_server_update_net_id_rand(void); void bt_mesh_proxy_server_update_net_id_rand_stop(void); @@ -117,6 +118,7 @@ void bt_mesh_proxy_server_identity_stop(struct bt_mesh_subnet *sub); bool bt_mesh_proxy_server_relay(struct net_buf_simple *buf, uint16_t dst); void bt_mesh_proxy_server_addr_add(struct net_buf_simple *buf, uint16_t addr); +void bt_mesh_proxy_server_adv_flag_set(bool enable); int bt_mesh_proxy_server_init(void); int bt_mesh_proxy_server_deinit(void); diff --git a/lib/bt/esp_ble_mesh/core/pvnr_mgmt.c b/lib/bt/esp_ble_mesh/core/pvnr_mgmt.c index 2531a2d2..96ad2feb 100644 --- a/lib/bt/esp_ble_mesh/core/pvnr_mgmt.c +++ b/lib/bt/esp_ble_mesh/core/pvnr_mgmt.c @@ -22,7 +22,9 @@ #include "prov_pvnr.h" #include "pvnr_mgmt.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #if CONFIG_BLE_MESH_PROVISIONER diff --git a/lib/bt/esp_ble_mesh/core/scan.c b/lib/bt/esp_ble_mesh/core/scan.c index e1b43dd2..192f63f8 100644 --- a/lib/bt/esp_ble_mesh/core/scan.c +++ b/lib/bt/esp_ble_mesh/core/scan.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,7 +27,9 @@ #include "prov_pvnr.h" #include "mesh/adapter.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif /* Scan Window and Interval are equal for continuous scanning */ #define SCAN_INTERVAL 0x20 @@ -39,6 +41,22 @@ #define PROXY_SVC_DATA_LEN_PRIVATE_NET_ID 0x11 #define PROXY_SVC_DATA_LEN_PRIVATE_NODE_ID 0x11 +static struct bt_mesh_scan_param scan_param = { +#if CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN + .type = BLE_MESH_SCAN_ACTIVE, +#else + .type = BLE_MESH_SCAN_PASSIVE, +#endif +#if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN + .filter_dup = BLE_MESH_SCAN_FILTER_DUP_ENABLE, +#else + .filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE, +#endif + .interval = SCAN_INTERVAL, + .window = SCAN_WINDOW, + .scan_fil_policy = BLE_MESH_SP_ADV_ALL, +}; + #if (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) static const bt_mesh_addr_t *unprov_dev_addr; static uint8_t current_adv_type; @@ -84,13 +102,14 @@ int bt_mesh_unprov_dev_info_query(uint8_t uuid[16], uint8_t addr[6], { uint8_t idx = 0; uint8_t cnt = 0; + uint8_t pair_num = unprov_dev_info_fifo.pair_num; - if (uuid == NULL || addr == NULL) { + if (uuid == NULL && addr == NULL) { BT_WARN("No available information to query"); return -1; } - while (cnt < unprov_dev_info_fifo.pair_num) { + while (cnt < pair_num) { idx = (cnt + unprov_dev_info_fifo.start_idx) % BLE_MESH_STORE_UNPROV_INFO_MAX_NUM; if (query_type & BLE_MESH_STORE_UNPROV_INFO_QUERY_TYPE_UUID) { if (!memcmp(unprov_dev_info_fifo.info[idx].addr, addr, 6)) { @@ -116,8 +135,7 @@ int bt_mesh_unprov_dev_info_query(uint8_t uuid[16], uint8_t addr[6], cnt++; } - if (cnt == unprov_dev_info_fifo.pair_num) { - BT_WARN("Didn't find info for %d", query_type); + if (cnt == pair_num) { return -1; } @@ -134,6 +152,11 @@ int bt_mesh_unprov_dev_fifo_enqueue(uint8_t uuid[16], const uint8_t addr[6], uin return -EINVAL; } + if (!bt_mesh_unprov_dev_info_query(uuid, NULL, NULL, BLE_MESH_STORE_UNPROV_INFO_QUERY_TYPE_ADDR | + BLE_MESH_STORE_UNPROV_INFO_QUERY_TYPE_EXISTS)) { + return 0; + } + if (unprov_dev_info_fifo.pair_num == BLE_MESH_STORE_UNPROV_INFO_MAX_NUM) { bt_mesh_unprov_dev_fifo_dequeue(NULL, NULL); } @@ -164,7 +187,8 @@ uint8_t bt_mesh_get_adv_type(void) #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ - CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX + CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) static bool adv_flags_valid(struct net_buf_simple *buf) { uint8_t flags = 0U; @@ -251,8 +275,10 @@ static void handle_adv_service_data(struct net_buf_simple *buf, } switch (type) { -#if CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT +#if (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) && \ + CONFIG_BLE_MESH_PB_GATT case BLE_MESH_UUID_MESH_PROV_VAL: +#if CONFIG_BLE_MESH_PROVISIONER if (bt_mesh_is_provisioner_en()) { if (buf->len != PROV_SVC_DATA_LEN) { BT_WARN("Invalid Mesh Prov Service Data length %d", buf->len); @@ -262,15 +288,19 @@ static void handle_adv_service_data(struct net_buf_simple *buf, BT_DBG("Start to handle Mesh Prov Service Data"); bt_mesh_provisioner_prov_adv_recv(buf, addr, rssi); } +#endif /* CONFIG_BLE_MESH_PROVISIONER */ - if (IS_ENABLED(CONFIG_BLE_MESH_RPR_SRV) && - bt_mesh_is_provisioned()) { +#if CONFIG_BLE_MESH_RPR_SRV + if (bt_mesh_is_provisioned()) { const bt_mesh_addr_t *addr = bt_mesh_get_unprov_dev_addr(); bt_mesh_unprov_dev_fifo_enqueue(buf->data, addr->val, bt_mesh_get_adv_type()); bt_mesh_rpr_srv_unprov_beacon_recv(buf, bt_mesh_get_adv_type(), addr, rssi); } +#endif /* CONFIG_BLE_MESH_RPR_SRV */ +#endif /* (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) && + CONFIG_BLE_MESH_PB_GATT */ break; -#endif + #if CONFIG_BLE_MESH_GATT_PROXY_CLIENT case BLE_MESH_UUID_MESH_PROXY_VAL: if (buf->len != PROXY_SVC_DATA_LEN_NET_ID && @@ -303,8 +333,9 @@ static void handle_adv_service_data(struct net_buf_simple *buf, } } #endif /* (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ - CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX */ + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) */ #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN static bool ble_scan_en; @@ -333,13 +364,27 @@ int bt_mesh_stop_ble_scan(void) return 0; } +bool bt_mesh_ble_scan_state_get(void) +{ + return ble_scan_en; +} + static void inline callback_ble_adv_pkt(const bt_mesh_addr_t *addr, uint8_t adv_type, uint8_t data[], uint16_t length, int8_t rssi) { +#if !CONFIG_BLE_MESH_USE_BLE_50 + bt_mesh_ble_adv_report_t adv_rpt = {0}; if (ble_scan_en) { - bt_mesh_ble_scan_cb_evt_to_btc(addr, adv_type, data, length, rssi); + memcpy(adv_rpt.addr, addr->val, BD_ADDR_LEN); + adv_rpt.addr_type = addr->type; + adv_rpt.adv_type = adv_type; + adv_rpt.length = length; + adv_rpt.data = data; + adv_rpt.rssi = rssi; + bt_mesh_ble_scan_cb_evt_to_btc(&adv_rpt); } +#endif } #endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ @@ -361,14 +406,15 @@ static bool rpr_ext_scan_handle_adv_pkt(const bt_mesh_addr_t *addr, } #endif /* CONFIG_BLE_MESH_RPR_SRV */ -static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, - int8_t rssi, uint8_t adv_type, - struct net_buf_simple *buf, - uint8_t scan_rsp_len) +static void bt_mesh_scan_cb(struct bt_mesh_adv_report *adv_rpt) { + struct net_buf_simple_state buf_state = {0}; + struct net_buf_simple *buf = &adv_rpt->adv_data; + #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ - CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ - CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX + CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ + CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) uint16_t uuid = 0U; #endif #if (CONFIG_BLE_MESH_RPR_SRV || CONFIG_BLE_MESH_SUPPORT_BLE_SCAN) @@ -376,19 +422,43 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, uint16_t adv_len = buf->len; #endif - if (adv_type != BLE_MESH_ADV_NONCONN_IND && adv_type != BLE_MESH_ADV_IND) { + net_buf_simple_save(buf, &buf_state); + + if (adv_rpt->adv_type != BLE_MESH_ADV_NONCONN_IND && + adv_rpt->adv_type != BLE_MESH_ADV_IND +#if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN + && adv_rpt->adv_type != BLE_MESH_ADV_SCAN_RSP +#endif + ) { #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); return; } BT_DBG("scan, len %u: %s", buf->len, bt_hex(buf->data, buf->len)); #if (CONFIG_BLE_MESH_PROVISIONER || CONFIG_BLE_MESH_RPR_SRV) - unprov_dev_addr = addr; - current_adv_type = adv_type; + unprov_dev_addr = &adv_rpt->addr; + current_adv_type = adv_rpt->adv_type; +#endif + +#if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN + if (adv_rpt->adv_type == BLE_MESH_ADV_SCAN_RSP) { + /** + * scan response is only visible for remote provisioning extend scan. + */ + if (rpr_ext_scan_handle_adv_pkt(&adv_rpt->addr, adv_data, adv_len)) { + return; + } else { +#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); + } + } +#endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN */ while (buf->len > 1) { struct net_buf_simple_state state; @@ -398,16 +468,18 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, /* Check for early termination */ if (len == 0U) { #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); return; } if (len > buf->len) { BT_DBG("AD malformed"); #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); return; } @@ -418,14 +490,17 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, buf->len = len - 1; if ((type == BLE_MESH_DATA_MESH_PROV || type == BLE_MESH_DATA_MESH_MESSAGE || - type == BLE_MESH_DATA_MESH_BEACON) && (adv_type != BLE_MESH_ADV_NONCONN_IND)) { - BT_DBG("Ignore mesh packet (type 0x%02x) with adv_type 0x%02x", type, adv_type); + type == BLE_MESH_DATA_MESH_BEACON) && (adv_rpt->adv_type != BLE_MESH_ADV_NONCONN_IND)) { + BT_DBG("Ignore mesh packet (type 0x%02x) with adv_type 0x%02x", type, adv_rpt->adv_type); return; } switch (type) { case BLE_MESH_DATA_MESH_MESSAGE: - bt_mesh_net_recv(buf, rssi, BLE_MESH_NET_IF_ADV); + struct bt_mesh_net_rx rx = { + .ctx.recv_rssi = adv_rpt->rssi, + }; + bt_mesh_generic_net_recv(buf, &rx, BLE_MESH_NET_IF_ADV); break; #if CONFIG_BLE_MESH_PB_ADV case BLE_MESH_DATA_MESH_PROV: @@ -438,17 +513,19 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, break; #endif /* CONFIG_BLE_MESH_PB_ADV */ case BLE_MESH_DATA_MESH_BEACON: - bt_mesh_beacon_recv(buf, rssi); + bt_mesh_beacon_recv(buf, adv_rpt->rssi); break; #if (CONFIG_BLE_MESH_PROVISIONER && CONFIG_BLE_MESH_PB_GATT) || \ CONFIG_BLE_MESH_GATT_PROXY_CLIENT || \ - CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX + CONFIG_BLE_MESH_PROXY_SOLIC_PDU_RX || \ + (CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_PB_GATT) case BLE_MESH_DATA_FLAGS: if (!adv_flags_valid(buf)) { BT_DBG("Adv Flags mismatch, ignore this adv pkt"); #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); return; } break; @@ -456,7 +533,7 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, if (!adv_service_uuid_valid(buf, &uuid)) { BT_DBG("Adv Service UUID mismatch, ignore this adv pkt"); #if CONFIG_BLE_MESH_RPR_SRV - if (rpr_ext_scan_handle_adv_pkt(addr, adv_data, adv_len)) { + if (rpr_ext_scan_handle_adv_pkt(&adv_rpt->addr, adv_data, adv_len)) { /* If handled as extended scan report successfully, then not * notify to the application layer as normal BLE adv packet. */ @@ -464,18 +541,19 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, } #endif #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); return; } break; case BLE_MESH_DATA_SVC_DATA16: - handle_adv_service_data(buf, addr, uuid, rssi); + handle_adv_service_data(buf, &adv_rpt->addr, uuid, adv_rpt->rssi); break; #endif default: #if CONFIG_BLE_MESH_RPR_SRV - if (rpr_ext_scan_handle_adv_pkt(addr, adv_data, adv_len)) { + if (rpr_ext_scan_handle_adv_pkt(&adv_rpt->addr, adv_data, adv_len)) { /* If handled as extended scan report successfully, then not * notify to the application layer as normal BLE adv packet. */ @@ -483,44 +561,21 @@ static void bt_mesh_scan_cb(const bt_mesh_addr_t *addr, } #endif #if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN - callback_ble_adv_pkt(addr, adv_type, adv_data, adv_len, rssi); + callback_ble_adv_pkt(&adv_rpt->addr, adv_rpt->adv_type, adv_data, adv_len, adv_rpt->rssi); #endif + net_buf_simple_restore(buf, &buf_state); return; } net_buf_simple_restore(buf, &state); net_buf_simple_pull(buf, len); } -#if CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN - if (scan_rsp_len != 0) { - /** - * scan response is only visible for remote provisioning extend scan. - */ - rpr_ext_scan_handle_adv_pkt(addr, adv_data + adv_len, scan_rsp_len); - } -#endif /* CONFIG_BLE_MESH_RPR_SRV && CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN */ } int bt_mesh_scan_enable(void) { int err = 0; - struct bt_mesh_scan_param scan_param = { -#if CONFIG_BLE_MESH_RPR_SRV_ACTIVE_SCAN - .type = BLE_MESH_SCAN_ACTIVE, -#else - .type = BLE_MESH_SCAN_PASSIVE, -#endif -#if CONFIG_BLE_MESH_USE_DUPLICATE_SCAN - .filter_dup = BLE_MESH_SCAN_FILTER_DUP_ENABLE, -#else - .filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE, -#endif - .interval = SCAN_INTERVAL, - .window = SCAN_WINDOW, - .scan_fil_policy = BLE_MESH_SP_ADV_ALL, - }; - err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb); if (err && err != -EALREADY) { BT_ERR("starting scan failed (err %d)", err); @@ -543,6 +598,49 @@ int bt_mesh_scan_disable(void) return 0; } +int bt_mesh_scan_param_update(struct bt_mesh_scan_param *param) +{ + int err = 0; + + if (param == NULL || + param->interval == 0 || + param->interval < param->window) { + return -EINVAL; + } + + scan_param.interval = param->interval; + scan_param.window = param->window; + + err = bt_le_scan_stop(); + if (err) { + if (err == -EALREADY) { + BT_INFO("New scan parameters will take effect after scan starts"); + return 0; + } + BT_ERR("Failed to stop scan (err %d)", err); + return err; + } + + /** + * Since the user only needs to set the scan interval + * and scan window parameters, only the interval and + * window parameters in the `param` are correct. + * + * For the aforementioned reason, when updating the scan + * parameters, the other parameters also need to be set + * correctly, and these other parameters are saved in the + * `scan_param`. Therefore, `scan_param` must be used instead + * of `param` here. + */ + err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb); + if (err && err != -EALREADY) { + BT_ERR("Failed to start scan (err %d)", err); + return err; + } + + return 0; +} + #if CONFIG_BLE_MESH_TEST_USE_WHITE_LIST int bt_mesh_scan_with_wl_enable(void) { diff --git a/lib/bt/esp_ble_mesh/core/scan.h b/lib/bt/esp_ble_mesh/core/scan.h index b7d0555c..612751d3 100644 --- a/lib/bt/esp_ble_mesh/core/scan.h +++ b/lib/bt/esp_ble_mesh/core/scan.h @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,16 +33,22 @@ int bt_mesh_scan_enable(void); int bt_mesh_scan_disable(void); +int bt_mesh_scan_param_update(struct bt_mesh_scan_param *scan_param); + int bt_mesh_scan_with_wl_enable(void); struct bt_mesh_ble_scan_param { uint32_t duration; }; +#if CONFIG_BLE_MESH_SUPPORT_BLE_SCAN int bt_mesh_start_ble_scan(struct bt_mesh_ble_scan_param *param); int bt_mesh_stop_ble_scan(void); +bool bt_mesh_ble_scan_state_get(void); +#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_SCAN */ + #ifdef __cplusplus } #endif diff --git a/lib/bt/esp_ble_mesh/core/storage/settings.c b/lib/bt/esp_ble_mesh/core/storage/settings.c index 34a40d2d..40cf117f 100644 --- a/lib/bt/esp_ble_mesh/core/storage/settings.c +++ b/lib/bt/esp_ble_mesh/core/storage/settings.c @@ -22,7 +22,9 @@ #include "pvnr_mgmt.h" #include "prov_pvnr.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif /* BLE Mesh NVS Key and corresponding data struct. * Note: The length of nvs key must be <= 15. @@ -1481,6 +1483,8 @@ int settings_core_commit(void) struct bt_mesh_hb_pub *hb_pub = NULL; struct bt_mesh_cfg_srv *cfg = NULL; + bt_mesh_atomic_set_bit(bt_mesh.flags, BLE_MESH_VALID); + hb_pub = bt_mesh_hb_pub_get(); if (hb_pub && hb_pub->dst != BLE_MESH_ADDR_UNASSIGNED && hb_pub->count && hb_pub->period) { @@ -1499,7 +1503,6 @@ int settings_core_commit(void) cfg->default_ttl = stored_cfg.cfg.default_ttl; } - bt_mesh_atomic_set_bit(bt_mesh.flags, BLE_MESH_VALID); bt_mesh_net_start(); } #endif /* CONFIG_BLE_MESH_NODE */ diff --git a/lib/bt/esp_ble_mesh/core/tag.h b/lib/bt/esp_ble_mesh/core/tag.h new file mode 100644 index 00000000..d1b98310 --- /dev/null +++ b/lib/bt/esp_ble_mesh/core/tag.h @@ -0,0 +1,53 @@ +/* + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _BLE_MESH_v11_TAG_H_ +#define _BLE_MESH_v11_TAG_H_ + +#include +#include + +#include "mesh.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !CONFIG_BLE_MESH_V11_SUPPORT + +/* TAG - additional metadata */ +#define BLE_MESH_TAG_SEND_SEGMENTED BIT(0) +#define BLE_MESH_TAG_IMMUTABLE_CRED BIT(1) +#define BLE_MESH_TAG_RELAY BIT(3) +#define BLE_MESH_TAG_FRIENDSHIP BIT(4) + +static inline bool bt_mesh_tag_send_segmented(uint8_t tag) +{ + return (tag & BLE_MESH_TAG_SEND_SEGMENTED); +} + +static inline bool bt_mesh_tag_immutable_cred(uint8_t tag) +{ + return (tag & BLE_MESH_TAG_IMMUTABLE_CRED); +} + +static inline bool bt_mesh_tag_relay(uint8_t tag) +{ + return (tag & BLE_MESH_TAG_RELAY); +} + +static inline bool bt_mesh_tag_friendship(uint8_t tag) +{ + return (tag & BLE_MESH_TAG_FRIENDSHIP); +} + +#endif /* !CONFIG_BLE_MESH_V11_SUPPORT */ + +#ifdef __cplusplus +} +#endif + +#endif /* _BLE_MESH_v11_TAG_H_ */ diff --git a/lib/bt/esp_ble_mesh/core/transport.c b/lib/bt/esp_ble_mesh/core/transport.c index 64ac566a..fd3fd60a 100644 --- a/lib/bt/esp_ble_mesh/core/transport.c +++ b/lib/bt/esp_ble_mesh/core/transport.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,7 @@ #include #include "crypto.h" +#include "tag.h" #include "adv.h" #include "mesh.h" #include "lpn.h" @@ -26,7 +27,9 @@ #include "mesh/cfg_srv.h" #include "heartbeat.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif /* The transport layer needs at least three buffers for itself to avoid * deadlocks. Ensure that there are a sufficient number of advertising @@ -310,7 +313,15 @@ static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx) { bt_mesh_adv_buf_ref_debug(__func__, tx->seg[seg_idx], 3U, BLE_MESH_BUF_REF_SMALL); - BLE_MESH_ADV(tx->seg[seg_idx])->busy = 0U; + /** + * When cancelling a segment that is still in the adv sending queue, `tx->seg_pending` + * must else be decremented by one. More detailed information + * can be found in BLEMESH24-26. + */ + if (bt_mesh_atomic_cas(&BLE_MESH_ADV_BUSY(tx->seg[seg_idx]), 1, 0)) { + tx->seg_pending--; + } + net_buf_unref(tx->seg[seg_idx]); tx->seg[seg_idx] = NULL; tx->nack_count--; @@ -369,6 +380,20 @@ static inline void seg_tx_complete(struct seg_tx *tx, int err) static void schedule_retransmit(struct seg_tx *tx) { + /* It's possible that a segment broadcast hasn't finished, + * but the tx are already released. Only the seg_pending + * of this segment remains unprocessed. So, here, we + * determine if the tx are released by checking if the + * destination (dst) is unassigned, and then process + * the seg_pending of this segment. + * See BLEMESH25-92 for details */ + if (tx->dst == BLE_MESH_ADDR_UNASSIGNED) { + if (tx->seg_pending) { + tx->seg_pending--; + } + return; + } + if (--tx->seg_pending) { return; } @@ -443,7 +468,7 @@ static void seg_tx_send_unacked(struct seg_tx *tx) continue; } - if (BLE_MESH_ADV(seg)->busy) { + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(seg))) { BT_DBG("Skipping segment that's still advertising"); continue; } @@ -493,7 +518,15 @@ static int send_seg(struct bt_mesh_net_tx *net_tx, struct net_buf_simple *sdu, net_tx->aszmic, sdu->len); for (tx = NULL, i = 0; i < ARRAY_SIZE(seg_tx); i++) { - if (!seg_tx[i].nack_count) { + if (!seg_tx[i].nack_count && + /* In some critical conditions, the tx might be + * reset before a segment broadcast is finished. + * If this happens, the seg_pending of the segment + * hasn't been processed. To avoid assigning this + * uncleared tx to a new message, extra checks for + * seg_pending being 0 are added. See BLEMESH25-92 + * for details.*/ + !seg_tx[i].seg_pending) { tx = &seg_tx[i]; break; } @@ -1031,18 +1064,18 @@ static int ctl_recv(struct bt_mesh_net_rx *rx, uint8_t hdr, return 0; } - if (IS_ENABLED(CONFIG_BLE_MESH_DF_SRV)) { - switch (ctl_op) { - case TRANS_CTL_OP_PATH_REQ: - case TRANS_CTL_OP_PATH_REPLY: - case TRANS_CTL_OP_PATH_CFM: - case TRANS_CTL_OP_PATH_ECHO_REQ: - case TRANS_CTL_OP_PATH_ECHO_REPLY: - case TRANS_CTL_OP_DEP_NODE_UPDATE: - case TRANS_CTL_OP_PATH_REQ_SOLIC: - return bt_mesh_directed_forwarding_ctl_recv(ctl_op, rx, buf); - } +#if CONFIG_BLE_MESH_DF_SRV + switch (ctl_op) { + case TRANS_CTL_OP_PATH_REQ: + case TRANS_CTL_OP_PATH_REPLY: + case TRANS_CTL_OP_PATH_CFM: + case TRANS_CTL_OP_PATH_ECHO_REQ: + case TRANS_CTL_OP_PATH_ECHO_REPLY: + case TRANS_CTL_OP_DEP_NODE_UPDATE: + case TRANS_CTL_OP_PATH_REQ_SOLIC: + return bt_mesh_directed_forwarding_ctl_recv(ctl_op, rx, buf); } +#endif if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && !bt_mesh_lpn_established()) { switch (ctl_op) { @@ -1528,7 +1561,7 @@ static int trans_seg(struct net_buf_simple *buf, struct bt_mesh_net_rx *net_rx, * eventually be freed up and we'll be able to process * this one. */ - BT_WARN("No free slots for new incoming segmented messages"); + BT_WARN("No free slots for new incoming segmented messages, src: %04x", net_rx->ctx.addr); return -ENOMEM; } @@ -1751,8 +1784,6 @@ void bt_mesh_trans_init(void) { int i; - bt_mesh_sar_init(); - for (i = 0; i < ARRAY_SIZE(seg_tx); i++) { k_delayed_work_init(&seg_tx[i].rtx_timer, seg_retransmit); } diff --git a/lib/bt/esp_ble_mesh/core/transport.enh.c b/lib/bt/esp_ble_mesh/core/transport.enh.c index 6ef6c0a5..a4a5130e 100644 --- a/lib/bt/esp_ble_mesh/core/transport.enh.c +++ b/lib/bt/esp_ble_mesh/core/transport.enh.c @@ -350,7 +350,7 @@ static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx) */ bt_mesh_adv_buf_ref_debug(__func__, tx->seg[seg_idx], 4U, BLE_MESH_BUF_REF_SMALL); - BLE_MESH_ADV(tx->seg[seg_idx])->busy = 0U; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(tx->seg[seg_idx]), 0); net_buf_unref(tx->seg[seg_idx]); tx->seg[seg_idx] = NULL; @@ -498,7 +498,7 @@ static bool send_next_segment(struct seg_tx *tx, int *result) /* The segment may have already been transmitted, for example, the * Segment Retransmission timer is expired earlier. */ - if (BLE_MESH_ADV(seg)->busy) { + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(seg))) { return false; } @@ -768,7 +768,7 @@ static bool resend_unacked_seg(struct seg_tx *tx, int *result) * A is still going to be retransmitted, but at this moment we could * find that the "busy" flag of Segment A is 1. */ - if (BLE_MESH_ADV(seg)->busy) { + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(seg))) { return false; } diff --git a/lib/bt/esp_ble_mesh/lib/ext.c b/lib/bt/esp_ble_mesh/lib/ext.c index ca779960..d9803b83 100644 --- a/lib/bt/esp_ble_mesh/lib/ext.c +++ b/lib/bt/esp_ble_mesh/lib/ext.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,6 +8,8 @@ #include #include +#include "esp_log.h" + #if CONFIG_BT_BLUEDROID_ENABLED #include "bta/bta_api.h" #endif @@ -79,6 +81,25 @@ #define RPL(a) ((struct bt_mesh_rpl *)(a)) #define VOID(a) ((void *)(a)) +/* Declare Lib Variables */ +uint8_t __meshlib_var_BLE_MESH_ADV_PROV = BLE_MESH_ADV_PROV; +uint8_t __meshlib_var_BLE_MESH_ADV_DATA = BLE_MESH_ADV_DATA; +#if CONFIG_BLE_MESH_FRIEND +uint8_t __meshlib_var_BLE_MESH_ADV_FRIEND = BLE_MESH_ADV_FRIEND; +#endif +#if CONFIG_BLE_MESH_RELAY_ADV_BUF +uint8_t __meshlib_var_BLE_MESH_ADV_RELAY_DATA = BLE_MESH_ADV_RELAY_DATA; +#endif +uint8_t __meshlib_var_BLE_MESH_ADV_BEACON = BLE_MESH_ADV_BEACON; +uint8_t __meshlib_var_BLE_MESH_ADV_URI = BLE_MESH_ADV_URI; +#if CONFIG_BLE_MESH_PROXY_SOLIC_PDU_TX +uint8_t __meshlib_var_BLE_MESH_ADV_PROXY_SOLIC = BLE_MESH_ADV_PROXY_SOLIC; +#endif +#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV +uint8_t __meshlib_var_BLE_MESH_ADV_BLE = BLE_MESH_ADV_BLE; +#endif +uint8_t __meshlib_var_BLE_MESH_ADV_TYPES_NUM = BLE_MESH_ADV_TYPES_NUM; + /* Sys utilities */ void bt_mesh_ext_put_be16(uint16_t val, uint8_t dst[2]) { @@ -190,6 +211,11 @@ void bt_mesh_ext_mem_swap(void *buf, size_t length) sys_mem_swap(buf, length); } +uint32_t bt_mesh_ext_log_timestamp(void) +{ + return esp_log_timestamp(); +} + /* Net buf */ void bt_mesh_ext_buf_simple_init(struct net_buf_simple *buf, size_t reserve_head) { @@ -498,6 +524,11 @@ float bt_mesh_ext_log2(float num) return bt_mesh_log2(num); } +const char *bt_mesh_ext_hex(const void *buf, size_t len) +{ + return bt_hex(buf, len); +} + /* Crypto */ bool bt_mesh_ext_s1(const char *m, uint8_t salt[16]) { @@ -1147,17 +1178,17 @@ uint8_t *bt_mesh_ext_net_get_dev_key_ca(void) return bt_mesh.dev_key_ca; } -uint8_t bt_mesh_ext_net_get_rpl_count(void) +uint16_t bt_mesh_ext_net_get_rpl_count(void) { return ARRAY_SIZE(bt_mesh.rpl); } -uint16_t bt_mesh_ext_net_get_rpl_src(uint8_t index) +uint16_t bt_mesh_ext_net_get_rpl_src(uint16_t index) { return bt_mesh.rpl[index].src; } -void bt_mesh_ext_net_reset_rpl(uint8_t index) +void bt_mesh_ext_net_reset_rpl(uint16_t index) { memset(&bt_mesh.rpl[index], 0, sizeof(bt_mesh.rpl[index])); } @@ -1494,6 +1525,11 @@ void bt_mesh_ext_prov_link_set_expect(void *link, uint8_t val) LINK(link)->expect = val; } +uint8_t bt_mesh_ext_prov_link_get_expect(void *link) +{ + return LINK(link)->expect; +} + uint8_t bt_mesh_ext_prov_link_get_pub_key_type(void *link) { return LINK(link)->public_key; @@ -1621,6 +1657,16 @@ uint8_t *bt_mesh_ext_prov_link_get_pb_remote_uuid(void *link) return LINK(link)->pb_remote_uuid; } +void *bt_mesh_ext_prov_link_get_prot_timer(void *link) +{ + return &(LINK(link)->prot_timer); +} + +void *bt_mesh_ext_prov_link_get_with_work(void *work) +{ + return CONTAINER_OF(work, struct bt_mesh_prov_link, prot_timer.work); +} + uint8_t bt_mesh_ext_prov_link_get_pb_remote_timeout(void *link) { return LINK(link)->pb_remote_timeout; @@ -2037,9 +2083,19 @@ int bt_mesh_ext_rpr_cli_pdu_recv(void *link, uint8_t type, struct net_buf_simple } #if CONFIG_BLE_MESH_RPR_CLI -static struct bt_mesh_prov_link rpr_links[CONFIG_BLE_MESH_RPR_CLI_PROV_SAME_TIME]; +struct bt_mesh_prov_link rpr_links[CONFIG_BLE_MESH_RPR_CLI_PROV_SAME_TIME]; #endif /* CONFIG_BLE_MESH_RPR_CLI */ +bool bt_mesh_ext_bt_mesh_is_unprov_dev_being_prov(void *uuid) +{ +#if CONFIG_BLE_MESH_RPR_CLI + return bt_mesh_is_unprov_dev_being_prov(uuid); +#else + assert(0); + return 0; +#endif +} + void *bt_mesh_ext_rpr_cli_get_rpr_link(uint8_t index) { #if CONFIG_BLE_MESH_RPR_CLI @@ -2071,16 +2127,12 @@ int bt_mesh_ext_rpr_srv_nppi_pdu_recv(uint8_t type, const uint8_t *data) int bt_mesh_ext_rpr_srv_set_waiting_prov_link(void* link, bt_mesh_addr_t *addr) { -#if (CONFIG_BLE_MESH_GATT_PROXY_CLIENT && \ - CONFIG_BLE_MESH_PB_GATT && \ - CONFIG_BLE_MESH_RPR_SRV) +#if (CONFIG_BLE_MESH_PB_GATT && CONFIG_BLE_MESH_RPR_SRV) return bt_mesh_rpr_srv_set_waiting_prov_link(link, addr); #else assert(0); return 0; -#endif /* (CONFIG_BLE_MESH_GATT_PROXY_CLIENT && \ - CONFIG_BLE_MESH_PB_GATT && \ - CONFIG_BLE_MESH_RPR_SRV) */ +#endif /* CONFIG_BLE_MESH_PB_GATT && CONFIG_BLE_MESH_RPR_SRV) */ } /* Friend */ @@ -3764,7 +3816,7 @@ void *bt_mesh_ext_brc_srv_get_bridge_table_entry(void *srv, uint8_t index) #endif /* CONFIG_BLE_MESH_BRC_SRV */ } -void *bt_mesh_ext_brc_srv_get_bridge_rpl(uint8_t index) +void *bt_mesh_ext_brc_srv_get_bridge_rpl(uint16_t index) { #if CONFIG_BLE_MESH_BRC_SRV return &bridge_rpl[index]; @@ -3954,6 +4006,9 @@ void bt_mesh_ext_mbt_server_cb_evt_to_btc(uint8_t event, void *model, void *ctx) } typedef struct { + uint64_t config_ble_mesh_stack_trace_level : 3; + + uint64_t config_ble_mesh_use_ble_50: 1; uint64_t config_ble_mesh_use_duplicate_scan : 1; uint64_t config_ble_mesh_pb_adv : 1; uint64_t config_ble_mesh_pb_gatt : 1; @@ -3997,6 +4052,7 @@ typedef struct { uint64_t config_ble_mesh_srpl_cli : 1; uint64_t config_ble_mesh_srpl_srv : 1; + uint32_t config_ble_mesh_prov_protocol_timeout; uint16_t config_ble_mesh_record_frag_max_size; uint16_t config_ble_mesh_crpl; uint16_t config_ble_mesh_proxy_solic_rx_crpl; @@ -4116,6 +4172,9 @@ typedef struct { } bt_mesh_ext_config_t; static const bt_mesh_ext_config_t bt_mesh_ext_cfg = { + .config_ble_mesh_stack_trace_level = BLE_MESH_LOG_LEVEL, + + .config_ble_mesh_use_ble_50 = IS_ENABLED(CONFIG_BLE_MESH_USE_BLE_50), .config_ble_mesh_use_duplicate_scan = IS_ENABLED(CONFIG_BLE_MESH_USE_DUPLICATE_SCAN), .config_ble_mesh_pb_adv = IS_ENABLED(CONFIG_BLE_MESH_PB_ADV), .config_ble_mesh_pb_gatt = IS_ENABLED(CONFIG_BLE_MESH_PB_GATT), @@ -4160,6 +4219,7 @@ static const bt_mesh_ext_config_t bt_mesh_ext_cfg = { .config_ble_mesh_sar_srv = IS_ENABLED(CONFIG_BLE_MESH_SAR_SRV), .config_ble_mesh_srpl_cli = IS_ENABLED(CONFIG_BLE_MESH_SRPL_CLI), .config_ble_mesh_srpl_srv = IS_ENABLED(CONFIG_BLE_MESH_SRPL_SRV), + .config_ble_mesh_prov_protocol_timeout = PROTOCOL_TIMEOUT, #if CONFIG_BLE_MESH_CERT_BASED_PROV .config_ble_mesh_record_frag_max_size = CONFIG_BLE_MESH_RECORD_FRAG_MAX_SIZE, @@ -4495,6 +4555,7 @@ typedef struct { int (*_bt_mesh_ext_rpr_cli_pdu_send)(void *link, uint8_t type); int (*_bt_mesh_ext_rpr_cli_recv_pub_key_outbound_report)(void *link); int (*_bt_mesh_ext_rpr_cli_pdu_recv)(void *link, uint8_t type, struct net_buf_simple *buf); + bool (*_bt_mesh_ext_bt_mesh_is_unprov_dev_being_prov)(void *uuid); void *(*_bt_mesh_ext_rpr_cli_get_rpr_link)(uint8_t index); /* CONFIG_BLE_MESH_RPR_CLI */ @@ -4526,7 +4587,7 @@ typedef struct { uint16_t (*_bt_mesh_ext_sub_get_sbr_net_idx)(void *sub); void (*_bt_mesh_ext_sub_set_sbr_net_idx)(void *sub, uint16_t sbr_net_idx); void *(*_bt_mesh_ext_brc_srv_get_bridge_table_entry)(void *srv, uint8_t index); - void *(*_bt_mesh_ext_brc_srv_get_bridge_rpl)(uint8_t index); + void *(*_bt_mesh_ext_brc_srv_get_bridge_rpl)(uint16_t index); /* CONFIG_BLE_MESH_BRC_SRV */ /* CONFIG_BLE_MESH_AGG_CLI */ @@ -4816,6 +4877,7 @@ static const bt_mesh_ext_funcs_t bt_mesh_ext_func = { ._bt_mesh_ext_rpr_cli_pdu_send = bt_mesh_ext_rpr_cli_pdu_send, ._bt_mesh_ext_rpr_cli_recv_pub_key_outbound_report = bt_mesh_ext_rpr_cli_recv_pub_key_outbound_report, ._bt_mesh_ext_rpr_cli_pdu_recv = bt_mesh_ext_rpr_cli_pdu_recv, + ._bt_mesh_ext_bt_mesh_is_unprov_dev_being_prov = bt_mesh_ext_bt_mesh_is_unprov_dev_being_prov, ._bt_mesh_ext_rpr_cli_get_rpr_link = bt_mesh_ext_rpr_cli_get_rpr_link, /* CONFIG_BLE_MESH_RPR_CLI */ diff --git a/lib/bt/esp_ble_mesh/lib/include/mesh_v1.1/utils.h b/lib/bt/esp_ble_mesh/lib/include/mesh_v1.1/utils.h index 71a02314..d8e80b19 100644 --- a/lib/bt/esp_ble_mesh/lib/include/mesh_v1.1/utils.h +++ b/lib/bt/esp_ble_mesh/lib/include/mesh_v1.1/utils.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/lib/bt/esp_ble_mesh/lib/lib/esp32/libble_mesh.a b/lib/bt/esp_ble_mesh/lib/lib/esp32/libble_mesh.a index 5f8b75a3..73d2771c 100644 Binary files a/lib/bt/esp_ble_mesh/lib/lib/esp32/libble_mesh.a and b/lib/bt/esp_ble_mesh/lib/lib/esp32/libble_mesh.a differ diff --git a/lib/bt/esp_ble_mesh/lib/lib/esp32c3/libble_mesh.a b/lib/bt/esp_ble_mesh/lib/lib/esp32c3/libble_mesh.a index ffc32db1..27e93069 100644 Binary files a/lib/bt/esp_ble_mesh/lib/lib/esp32c3/libble_mesh.a and b/lib/bt/esp_ble_mesh/lib/lib/esp32c3/libble_mesh.a differ diff --git a/lib/bt/esp_ble_mesh/lib/lib/esp32c5/libble_mesh.a b/lib/bt/esp_ble_mesh/lib/lib/esp32c5/libble_mesh.a new file mode 100644 index 00000000..27e93069 Binary files /dev/null and b/lib/bt/esp_ble_mesh/lib/lib/esp32c5/libble_mesh.a differ diff --git a/lib/bt/esp_ble_mesh/lib/lib/esp32c6/libble_mesh.a b/lib/bt/esp_ble_mesh/lib/lib/esp32c6/libble_mesh.a index ffc32db1..27e93069 100644 Binary files a/lib/bt/esp_ble_mesh/lib/lib/esp32c6/libble_mesh.a and b/lib/bt/esp_ble_mesh/lib/lib/esp32c6/libble_mesh.a differ diff --git a/lib/bt/esp_ble_mesh/lib/lib/esp32c61/libble_mesh.a b/lib/bt/esp_ble_mesh/lib/lib/esp32c61/libble_mesh.a new file mode 100644 index 00000000..27e93069 Binary files /dev/null and b/lib/bt/esp_ble_mesh/lib/lib/esp32c61/libble_mesh.a differ diff --git a/lib/bt/esp_ble_mesh/lib/lib/esp32h2/libble_mesh.a b/lib/bt/esp_ble_mesh/lib/lib/esp32h2/libble_mesh.a index ffc32db1..27e93069 100644 Binary files a/lib/bt/esp_ble_mesh/lib/lib/esp32h2/libble_mesh.a and b/lib/bt/esp_ble_mesh/lib/lib/esp32h2/libble_mesh.a differ diff --git a/lib/bt/esp_ble_mesh/lib/lib/esp32s3/libble_mesh.a b/lib/bt/esp_ble_mesh/lib/lib/esp32s3/libble_mesh.a index 5f8b75a3..a72cd64c 100644 Binary files a/lib/bt/esp_ble_mesh/lib/lib/esp32s3/libble_mesh.a and b/lib/bt/esp_ble_mesh/lib/lib/esp32s3/libble_mesh.a differ diff --git a/lib/bt/esp_ble_mesh/models/client/client_common.c b/lib/bt/esp_ble_mesh/models/client/client_common.c index db878516..7e544870 100644 --- a/lib/bt/esp_ble_mesh/models/client/client_common.c +++ b/lib/bt/esp_ble_mesh/models/client/client_common.c @@ -14,7 +14,9 @@ #include "mesh/client_common.h" #include "mesh/common.h" +#if CONFIG_BLE_MESH_V11_SUPPORT #include "mesh_v1.1/utils.h" +#endif #define HCI_TIME_FOR_START_ADV K_MSEC(5) /* Three adv related hci commands may take 4 ~ 5ms */ diff --git a/lib/bt/esp_ble_mesh/models/server/time_scene_server.c b/lib/bt/esp_ble_mesh/models/server/time_scene_server.c index 3494653a..a63550bc 100644 --- a/lib/bt/esp_ble_mesh/models/server/time_scene_server.c +++ b/lib/bt/esp_ble_mesh/models/server/time_scene_server.c @@ -244,7 +244,8 @@ static void time_get(struct bt_mesh_model *model, change.time_status.subsecond = srv->state->time.subsecond; change.time_status.uncertainty = srv->state->time.uncertainty; change.time_status.time_authority = srv->state->time.time_authority; - change.time_status.tai_utc_delta_curr = srv->state->time.subsecond; + change.time_status.tai_utc_delta_curr = srv->state->time.tai_utc_delta_curr; + change.time_status.time_zone_offset_curr = srv->state->time.time_zone_offset_curr; bt_mesh_time_scene_server_cb_evt_to_btc(BTC_BLE_MESH_EVT_TIME_SCENE_SERVER_STATE_CHANGE, model, ctx, (const uint8_t *)&change, sizeof(change)); @@ -386,7 +387,8 @@ static void time_set(struct bt_mesh_model *model, change.time_set.subsecond = srv->state->time.subsecond; change.time_set.uncertainty = srv->state->time.uncertainty; change.time_set.time_authority = srv->state->time.time_authority; - change.time_set.tai_utc_delta_curr = srv->state->time.subsecond; + change.time_set.tai_utc_delta_curr = srv->state->time.tai_utc_delta_curr; + change.time_set.time_zone_offset_curr = srv->state->time.time_zone_offset_curr; break; case BLE_MESH_MODEL_OP_TIME_ZONE_SET: change.time_zone_set.time_zone_offset_new = srv->state->time.time_zone_offset_new; diff --git a/lib/bt/esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c b/lib/bt/esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c index 5ab2cd17..de5550ce 100644 --- a/lib/bt/esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c +++ b/lib/bt/esp_ble_mesh/v1.1/api/core/esp_ble_mesh_rpr_model_api.c @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include "btc/btc_manage.h" @@ -91,4 +92,34 @@ esp_err_t esp_ble_mesh_register_rpr_server_callback(esp_ble_mesh_rpr_server_cb_t return (btc_profile_cb_set(BTC_PID_RPR_SERVER, callback) == 0 ? ESP_OK : ESP_FAIL); } + +esp_err_t esp_ble_mesh_rpr_server_set_uuid_match(const uint8_t *match_val, uint8_t match_len, uint8_t offset) +{ + btc_ble_mesh_rpr_server_args_t arg = {0}; + btc_msg_t msg = {0}; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_RPR_SERVER; + msg.act = BTC_BLE_MESH_ACT_RPR_SRV_SET_UUID_MATCH; + + if (!match_len || match_len > 16 || + !match_val || offset >= 16 || + offset + match_len > 16) { + return ESP_ERR_INVALID_ARG; + } + + arg.set_uuid_match.match_val = bt_mesh_calloc(match_len); + if (!arg.set_uuid_match.match_val) { + BT_ERR("%s:Out of memory", __func__); + return ESP_ERR_NO_MEM; + } + + memcpy(arg.set_uuid_match.match_val, match_val, match_len); + arg.set_uuid_match.match_len = match_len; + arg.set_uuid_match.offset = offset; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_rpr_server_args_t), + btc_ble_mesh_rpr_server_arg_deep_copy, + btc_ble_mesh_rpr_server_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} #endif /* CONFIG_BLE_MESH_RPR_SRV */ diff --git a/lib/bt/esp_ble_mesh/v1.1/api/core/include/esp_ble_mesh_rpr_model_api.h b/lib/bt/esp_ble_mesh/v1.1/api/core/include/esp_ble_mesh_rpr_model_api.h index 31d0923e..a19e5539 100644 --- a/lib/bt/esp_ble_mesh/v1.1/api/core/include/esp_ble_mesh_rpr_model_api.h +++ b/lib/bt/esp_ble_mesh/v1.1/api/core/include/esp_ble_mesh_rpr_model_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -396,6 +396,13 @@ typedef union { uint16_t net_idx; /*!< NetKey Index used by Remote Provisioning Client */ uint16_t rpr_cli_addr; /*!< Unicast address of Remote Provisioning Client */ } prov_comp; + + /** + * @brief ESP_BLE_MESH_RPR_SERVER_SET_UUID_MATCH_COMP_EVT + */ + struct { + int err_code; /*!< Indicate the result of setting Device UUID match value by the Remote Provisioning Server */ + } set_uuid_match_comp; } esp_ble_mesh_rpr_server_cb_param_t; /** This enum value is the event of Remote Provisioning Server model */ @@ -407,6 +414,7 @@ typedef enum { ESP_BLE_MESH_RPR_SERVER_LINK_OPEN_EVT, ESP_BLE_MESH_RPR_SERVER_LINK_CLOSE_EVT, ESP_BLE_MESH_RPR_SERVER_PROV_COMP_EVT, + ESP_BLE_MESH_RPR_SERVER_SET_UUID_MATCH_COMP_EVT, ESP_BLE_MESH_RPR_SERVER_EVT_MAX, } esp_ble_mesh_rpr_server_cb_event_t; @@ -474,6 +482,18 @@ typedef void (* esp_ble_mesh_rpr_server_cb_t)(esp_ble_mesh_rpr_server_cb_event_t */ esp_err_t esp_ble_mesh_register_rpr_server_callback(esp_ble_mesh_rpr_server_cb_t callback); +/** + * @brief This function is called by Remote Provisioning Server to set the part of + * the device UUID to be compared before starting to remote provision. + * + * @param[in] match_val: Value to be compared with the part of the device UUID. + * @param[in] match_len: Length of the compared match value. + * @param[in] offset: Offset of the device UUID to be compared (based on zero). + * + * @return ESP_OK on success or error code otherwise. +*/ +esp_err_t esp_ble_mesh_rpr_server_set_uuid_match(const uint8_t *match_val, uint8_t match_len, uint8_t offset); + #ifdef __cplusplus } #endif diff --git a/lib/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c b/lib/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c index 5e4437f4..e5200d7c 100644 --- a/lib/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c +++ b/lib/bt/esp_ble_mesh/v1.1/btc/btc_ble_mesh_rpr_model.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -451,6 +451,61 @@ void btc_ble_mesh_rpr_client_cb_handler(btc_msg_t *msg) #if CONFIG_BLE_MESH_RPR_SRV /* Remote Provisioning Server model related functions */ +extern int bt_mesh_rpr_srv_scan_set_dev_uuid_match(uint8_t offset, uint8_t length,const uint8_t *match); + +void btc_ble_mesh_rpr_server_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + btc_ble_mesh_rpr_server_args_t *dst = p_dest; + btc_ble_mesh_rpr_server_args_t *src = p_src; + + if (!msg || !dst || !src) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + switch(msg->act) { + case BTC_BLE_MESH_ACT_RPR_SRV_SET_UUID_MATCH: + dst->set_uuid_match.match_val = bt_mesh_calloc(src->set_uuid_match.match_len); + if (dst->set_uuid_match.match_val) { + memcpy(dst->set_uuid_match.match_val, src->set_uuid_match.match_val, src->set_uuid_match.match_len); + dst->set_uuid_match.match_len = src->set_uuid_match.match_len; + dst->set_uuid_match.offset = src->set_uuid_match.offset; + } else { + BT_ERR("%s, Out of memory, act %d", __func__, msg->act); + } + bt_mesh_free(src->set_uuid_match.match_val); + break; + default: + BT_DBG("%s, Unknown act %d", __func__, msg->act); + break; + } + + return; +} + +void btc_ble_mesh_rpr_server_arg_deep_free(btc_msg_t *msg) +{ + btc_ble_mesh_rpr_server_args_t *arg = NULL; + + if (!msg) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + arg = (btc_ble_mesh_rpr_server_args_t *)msg->arg; + + switch(msg->act) { + case BTC_BLE_MESH_ACT_RPR_SRV_SET_UUID_MATCH: + if (arg->set_uuid_match.match_val) { + bt_mesh_free(arg->set_uuid_match.match_val); + } + break; + default: + break; + } + + return; +} static inline void btc_ble_mesh_rpr_server_cb_to_app(esp_ble_mesh_rpr_server_cb_event_t event, esp_ble_mesh_rpr_server_cb_param_t *param) @@ -522,6 +577,33 @@ void bt_mesh_rpr_server_cb_evt_to_btc(uint8_t event, const void *val, size_t len btc_ble_mesh_rpr_server_cb(&cb_params, act); } +void btc_ble_mesh_rpr_server_call_handler(btc_msg_t *msg) +{ + esp_ble_mesh_rpr_server_cb_param_t cb = {0}; + btc_ble_mesh_rpr_server_args_t *arg = NULL; + + if (!msg) { + BT_ERR("%s, Invalid parameter", __func__); + return; + } + + arg = (btc_ble_mesh_rpr_server_args_t *)msg->arg; + + switch (msg->act) { + case BTC_BLE_MESH_ACT_RPR_SRV_SET_UUID_MATCH: + cb.set_uuid_match_comp.err_code = bt_mesh_rpr_srv_scan_set_dev_uuid_match(arg->set_uuid_match.offset, + arg->set_uuid_match.match_len, + arg->set_uuid_match.match_val); + + btc_ble_mesh_rpr_server_cb(&cb, ESP_BLE_MESH_RPR_SERVER_SET_UUID_MATCH_COMP_EVT); + break; + default: + break; + } + + btc_ble_mesh_rpr_server_arg_deep_free(msg); +} + void btc_ble_mesh_rpr_server_cb_handler(btc_msg_t *msg) { esp_ble_mesh_rpr_server_cb_param_t *arg = NULL; diff --git a/lib/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_rpr_model.h b/lib/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_rpr_model.h index e5217782..5b78299a 100644 --- a/lib/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_rpr_model.h +++ b/lib/bt/esp_ble_mesh/v1.1/btc/include/btc_ble_mesh_rpr_model.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -64,6 +64,11 @@ void bt_mesh_rpr_client_cb_evt_to_btc(uint32_t opcode, uint8_t event, struct bt_mesh_msg_ctx *ctx, const void *val, size_t len); +typedef enum { + BTC_BLE_MESH_ACT_RPR_SRV_SET_UUID_MATCH, + BTC_BLE_MESH_ACT_RPR_SRV_MAX, +} btc_ble_mesh_rpr_server_act_t; + typedef enum { BTC_BLE_MESH_EVT_RPR_SERVER_SCAN_START, BTC_BLE_MESH_EVT_RPR_SERVER_SCAN_STOP, @@ -72,9 +77,22 @@ typedef enum { BTC_BLE_MESH_EVT_RPR_SERVER_LINK_OPEN, BTC_BLE_MESH_EVT_RPR_SERVER_LINK_CLOSE, BTC_BLE_MESH_EVT_RPR_SERVER_PROV_COMP, + BTC_BLE_MESH_EVT_RPR_SERVER_SET_UUID_MATCH_COMP, BTC_BLE_MESH_EVT_RPR_SERVER_MAX, } btc_ble_mesh_rpr_server_evt_t; +typedef union { + struct { + uint8_t *match_val; + uint8_t match_len; + uint8_t offset; + } set_uuid_match; +} btc_ble_mesh_rpr_server_args_t; + +void btc_ble_mesh_rpr_server_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); +void btc_ble_mesh_rpr_server_arg_deep_free(btc_msg_t *msg); + +void btc_ble_mesh_rpr_server_call_handler(btc_msg_t *msg); void btc_ble_mesh_rpr_server_cb_handler(btc_msg_t *msg); void bt_mesh_rpr_server_cb_evt_to_btc(uint8_t event, const void *val, size_t len); diff --git a/lib/bt/host/bluedroid/Kconfig.in b/lib/bt/host/bluedroid/Kconfig.in index 58859d35..64b1d92d 100644 --- a/lib/bt/host/bluedroid/Kconfig.in +++ b/lib/bt/host/bluedroid/Kconfig.in @@ -43,7 +43,8 @@ config BT_BLUEDROID_MEM_DEBUG config BT_BLUEDROID_ESP_COEX_VSC bool "Enable Espressif Vendor-specific HCI commands for coexist status configuration" depends on BT_BLUEDROID_ENABLED - default y + default y if (ESP_COEX_SW_COEXIST_ENABLE || BT_CONTROLLER_DISABLED) + default n help Enable Espressif Vendor-specific HCI commands for coexist status configuration @@ -84,8 +85,38 @@ config BT_A2DP_ENABLE bool "A2DP" depends on BT_CLASSIC_ENABLED default n + select BT_AVRCP_ENABLED + help + Advanced Audio Distribution Profile + +config BT_A2DP_USE_EXTERNAL_CODEC + bool "Use External Codec for A2DP" + depends on BT_A2DP_ENABLE + default n + help + If enable, user shall register audio codec capability to A2DP and encode/decode + audio data in application layer. The internal codec in A2DP will be remove in + the future, it is recommend to use external codec for new design. + +config BT_AVRCP_ENABLED + bool + depends on BT_A2DP_ENABLE + default y help - Advanced Audio Distrubution Profile + Audio/Video Remote Control Profile, AVRCP and A2DP are coupled in Bluedroid, + AVRCP still controlled by A2DP option, this is a dummy option currently + +menu "AVRCP Features" + depends on BT_AVRCP_ENABLED + + config BT_AVRCP_CT_COVER_ART_ENABLED + bool "AVRCP CT Cover Art" + default y + select BT_GOEPC_ENABLED + help + This enable Cover Art feature of AVRCP CT role + +endmenu config BT_SPP_ENABLED bool "SPP" @@ -102,6 +133,34 @@ config BT_L2CAP_ENABLED This enables the Logical Link Control and Adaptation Layer Protocol. Only supported classic bluetooth. +config BT_SDP_COMMON_ENABLED + bool "BT SDP COMMON" + depends on BT_CLASSIC_ENABLED + default y if BT_L2CAP_ENABLED + default n + help + This enables common SDP operation, such as SDP record creation and deletion. + +config BT_SDP_PAD_LEN + int "One or more BT SDP attributes total allocated length (bytes)" + depends on BT_CLASSIC_ENABLED + default 300 + range BT_SDP_ATTR_LEN 1024 + help + This is the total size of all SDP attributes allowed. + Any attributes that exceed this size are truncated. + The default value is 300. + +config BT_SDP_ATTR_LEN + int "Single BT SDP attribute allocated length (bytes)" + depends on BT_CLASSIC_ENABLED + default 300 + range 300 1024 + help + This is the maximum allowed size for a single SDP attribute. + Any attributes that exceed this size are truncated. + The default value is 300. + menuconfig BT_HFP_ENABLE bool "Hands Free/Handset Profile" depends on BT_CLASSIC_ENABLED @@ -134,21 +193,29 @@ choice BT_HFP_AUDIO_DATA_PATH bool "HCI" endchoice +config BT_HFP_USE_EXTERNAL_CODEC + bool "Use External Codec for HFP" + depends on BT_HFP_ENABLE && BT_HFP_AUDIO_DATA_PATH_HCI + default n + help + If enable, user shall encode/decode audio data in application layer. The internal + codec in HFP will be remove in the future, it is recommend to use external codec + for new design. + config BT_HFP_WBS_ENABLE bool "Wide Band Speech" - depends on BT_HFP_AUDIO_DATA_PATH_HCI + depends on BT_HFP_ENABLE && BT_HFP_AUDIO_DATA_PATH_HCI default y help This enables Wide Band Speech. Should disable it when SCO data path is PCM. - Otherwise there will be no data transmited via GPIOs. - + Otherwise there will be no data transmitted via GPIOs. menuconfig BT_HID_ENABLED bool "Classic BT HID" depends on BT_CLASSIC_ENABLED default n help - This enables the BT HID Host + This enables the BT HID functionalities config BT_HID_HOST_ENABLED bool "Classic BT HID Host" @@ -163,6 +230,44 @@ config BT_HID_DEVICE_ENABLED help This enables the BT HID Device +config BT_HID_REMOVE_DEVICE_BONDING_ENABLED + bool "Remove Device Bonding Information when HID Virtual Cable Unplugging" + depends on BT_HID_ENABLED + default y + help + This enables the BT HID to remove device bonding information when virtual cable unplugging, + removing device bonding information is optional in HID 1.0 but mandatory in HID 1.1 + +menuconfig BT_PBAC_ENABLED + bool "PBAP Client" + depends on BT_CLASSIC_ENABLED + default n + select BT_GOEPC_ENABLED + help + This enables the Phone Book Access Profile Client + +config BT_PBAC_SUPPORTED_FEAT + hex "PBAP Client Supported Features" + depends on BT_PBAC_ENABLED + default 0x000003FF + help + Set the supported features of PBAP Client, the default value is supported all features + +config BT_PBAC_PREFERRED_MTU + int "PBAP Client Preferred MTU" + depends on BT_PBAC_ENABLED + default 0 + help + MTU is limited by the max MTU of transport layer, and should not be smaller than 255, + but can be set to zero to use a default MTU of transport layer + +config BT_GOEPC_ENABLED + bool + depends on BT_CLASSIC_ENABLED + default n + help + This enables the BT GOEP Profile Client role + config BT_BLE_ENABLED bool "Bluetooth Low Energy" depends on BT_BLUEDROID_ENABLED @@ -170,7 +275,7 @@ config BT_BLE_ENABLED help This enables Bluetooth Low Energy -config BT_GATTS_ENABLE +menuconfig BT_GATTS_ENABLE bool "Include GATT server module(GATTS)" depends on BT_BLE_ENABLED default y @@ -182,8 +287,9 @@ config BT_GATTS_PPCP_CHAR_GAP depends on BT_GATTS_ENABLE default n help - This enables "Peripheral Preferred Connection Parameters" characteristic (UUID: 0x2A04) in GAP service that has - connection parameters like min/max connection interval, slave latency and supervision timeout multiplier + This enables "Peripheral Preferred Connection Parameters" characteristic (UUID: 0x2A04) + in GAP service that has connection parameters like min/max connection interval, slave + latency and supervision timeout multiplier config BT_BLE_BLUFI_ENABLE bool "Include blufi function" @@ -259,7 +365,7 @@ config BT_GATTS_APPEARANCE_WRITABLE help Enabling this option allows remote GATT clients to write appearance -config BT_GATTC_ENABLE +menuconfig BT_GATTC_ENABLE bool "Include GATT client module(GATTC)" depends on BT_BLE_ENABLED default y @@ -297,7 +403,16 @@ config BT_GATTC_CONNECT_RETRY_COUNT help The number of attempts to reconnect if the connection establishment failed -config BT_BLE_SMP_ENABLE +config BT_BLE_ESTAB_LINK_CONN_TOUT + int "Timeout of BLE connection establishment" + depends on BT_GATTC_ENABLE + range 1 60 + default 30 + help + Bluetooth Connection establishment maximum time, if connection time exceeds this value, the connection + establishment fails, ESP_GATTC_OPEN_EVT or ESP_GATTS_OPEN_EVT is triggered. + +menuconfig BT_BLE_SMP_ENABLE bool "Include BLE security module(SMP)" depends on BT_BLE_ENABLED default y @@ -312,6 +427,41 @@ config BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE In order to reduce the pairing time, slave actively initiates connection parameters update during pairing. +config BT_BLE_SMP_ID_RESET_ENABLE + bool "Reset device identity when all bonding records are deleted" + depends on BT_BLE_SMP_ENABLE + default n + help + There are tracking risks associated with using a fixed or static IRK. + If enabled this option, Bluedroid will assign a new randomly-generated IRK + when all pairing and bonding records are deleted. This would decrease the ability + of a previously paired peer to be used to determine whether a device + with which it previously shared an IRK is within range. + +config BT_BLE_SMP_BOND_NVS_FLASH + bool "Save SMP bonding keys to nvs flash" + depends on BT_BLE_SMP_ENABLE + default y + help + This select can save SMP bonding keys to nvs flash + +config BT_BLE_RPA_SUPPORTED + bool "Update RPA to Controller" + depends on (BT_BLE_SMP_ENABLE && ((BT_CONTROLLER_ENABLED && !SOC_BLE_DEVICE_PRIVACY_SUPPORTED) || BT_CONTROLLER_DISABLED)) # NOERROR + default n if (BT_CONTROLLER_ENABLED && !SOC_BLE_DEVICE_PRIVACY_SUPPORTED) + default y if BT_CONTROLLER_DISABLED + help + This enables controller RPA list function. + For ESP32, ESP32 only support network privacy mode. If this option is enabled, ESP32 will only accept + advertising packets from peer devices that contain private address, HW will not receive the advertising + packets contain identity address after IRK changed. If this option is disabled, address resolution will + be performed in the host, so the functions that require controller to resolve address in the white list + cannot be used. This option is disabled by default on ESP32, please enable or disable this option according + to your own needs. + + For other BLE chips, devices support network privacy mode and device privacy mode, + users can switch the two modes according to their own needs. So this option is enabled by default. + config BT_STACK_NO_LOG bool "Disable BT debug logs (minimize bin size)" depends on BT_BLUEDROID_ENABLED @@ -1072,7 +1222,7 @@ config BT_ACL_CONNECTIONS is used. config BT_MULTI_CONNECTION_ENBALE - bool "Enable BLE multi-conections" + bool "Enable BLE multi-connections" depends on BT_BLE_ENABLED default y help @@ -1092,15 +1242,6 @@ config BT_BLE_DYNAMIC_ENV_MEMORY help This select can make the allocation of memory will become more flexible -config BT_BLE_HOST_QUEUE_CONG_CHECK - bool "BLE queue congestion check" - depends on BT_BLE_ENABLED - default n - help - When scanning and scan duplicate is not enabled, if there are a lot of adv packets around - or application layer handling adv packets is slow, it will cause the controller memory - to run out. if enabled, adv packets will be lost when host queue is congested. - config BT_SMP_ENABLE bool depends on BT_BLUEDROID_ENABLED @@ -1125,15 +1266,6 @@ config BT_BLE_ACT_SCAN_REP_ADV_SCAN # Memory reserved at start of DRAM for Bluetooth stack -config BT_BLE_ESTAB_LINK_CONN_TOUT - int "Timeout of BLE connection establishment" - depends on BT_BLE_ENABLED - range 1 60 - default 30 - help - Bluetooth Connection establishment maximum time, if connection time exceeds this value, the connection - establishment fails, ESP_GATTC_OPEN_EVT or ESP_GATTS_OPEN_EVT is triggered. - config BT_MAX_DEVICE_NAME_LEN int "length of bluetooth device name" depends on BT_BLUEDROID_ENABLED @@ -1144,23 +1276,6 @@ config BT_MAX_DEVICE_NAME_LEN the complete device name, then only the shortname will be displayed, the rest parts that can't fit in will be truncated. -config BT_BLE_RPA_SUPPORTED - bool "Update RPA to Controller" - depends on (BT_BLUEDROID_ENABLED && ((BT_CONTROLLER_ENABLED && !SOC_BLE_DEVICE_PRIVACY_SUPPORTED) || BT_CONTROLLER_DISABLED)) # NOERROR - default n if (BT_CONTROLLER_ENABLED && !SOC_BLE_DEVICE_PRIVACY_SUPPORTED) - default y if BT_CONTROLLER_DISABLED - help - This enables controller RPA list function. - For ESP32, ESP32 only support network privacy mode. If this option is enabled, ESP32 will only accept - advertising packets from peer devices that contain private address, HW will not receive the advertising - packets contain identity address after IRK changed. If this option is disabled, address resolution will - be performed in the host, so the functions that require controller to resolve address in the white list - cannot be used. This option is disabled by default on ESP32, please enable or disable this option according - to your own needs. - - For other BLE chips, devices support network privacy mode and device privacy mode, - users can switch the two modes according to their own needs. So this option is enabled by default. - config BT_BLE_RPA_TIMEOUT int "Timeout of resolvable private address" depends on BT_BLE_ENABLED @@ -1170,20 +1285,49 @@ config BT_BLE_RPA_TIMEOUT This set RPA timeout of Controller and Host. Default is 900 s (15 minutes). Range is 1 s to 1 hour (3600 s). -config BT_BLE_50_FEATURES_SUPPORTED - bool "Enable BLE 5.0 features" +menuconfig BT_BLE_50_FEATURES_SUPPORTED + bool "Enable BLE 5.0 features(please disable BLE 4.2 if enable BLE 5.0)" depends on (BT_BLE_ENABLED && ((BT_CONTROLLER_ENABLED && SOC_BLE_50_SUPPORTED) || BT_CONTROLLER_DISABLED)) default y help Enabling this option activates BLE 5.0 features. This option is universally supported in chips that support BLE, except for ESP32. + BLE 4.2 and BLE 5.0 cannot be used simultaneously. -config BT_BLE_42_FEATURES_SUPPORTED - bool "Enable BLE 4.2 features" - depends on (BT_BLE_ENABLED && ((BT_CONTROLLER_ENABLED && SOC_BLE_SUPPORTED) || BT_CONTROLLER_DISABLED)) - default n +config BT_BLE_50_EXTEND_ADV_EN + bool "Enable BLE extend advertising" + depends on BT_BLE_50_FEATURES_SUPPORTED + default y help - This enables BLE 4.2 features. + This enables BLE extend advertising + +config BT_BLE_50_PERIODIC_ADV_EN + bool "Enable BLE periodic advertising" + depends on BT_BLE_50_FEATURES_SUPPORTED + default y + help + This enables BLE periodic advertising + +config BT_BLE_50_EXTEND_SCAN_EN + bool "Enable BLE extend scan" + depends on BT_BLE_50_FEATURES_SUPPORTED + default y + help + This enables BLE extend scan + +config BT_BLE_50_EXTEND_SYNC_EN + bool "Enable BLE periodic advertising sync" + depends on BT_BLE_50_FEATURES_SUPPORTED + default y + help + This enables BLE periodic advertising sync + +config BT_BLE_50_DTM_TEST_EN + bool "Enable BLE 5.0 DTM test" + depends on BT_BLE_50_FEATURES_SUPPORTED + default y + help + This enables BLE 5.0 direct test mode config BT_BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER bool "Enable BLE periodic advertising sync transfer feature" @@ -1206,9 +1350,166 @@ config BT_BLE_FEAT_CREATE_SYNC_ENH help Enable the create sync enhancements +menuconfig BT_BLE_42_FEATURES_SUPPORTED + bool "Enable BLE 4.2 features(please disable BLE 5.0 if enable BLE 4.2)" + depends on BT_BLE_ENABLED + default y if IDF_TARGET_ESP32 + default n + help + This enables BLE 4.2 features. + This option is universally supported by all ESP chips with BLE capabilities. + BLE 4.2 and BLE 5.0 cannot be used simultaneously. + +config BT_BLE_42_DTM_TEST_EN + bool "Enable BLE 4.2 DTM test" + depends on BT_BLE_42_FEATURES_SUPPORTED + default y + help + This enables BLE 4.2 direct test mode + +config BT_BLE_42_ADV_EN + bool "Enable BLE 4.2 advertising" + depends on BT_BLE_42_FEATURES_SUPPORTED + default y + help + This enables BLE v4.2 advertising + +config BT_BLE_42_SCAN_EN + bool "Enable BLE 4.2 scan" + depends on BT_BLE_42_FEATURES_SUPPORTED + default y + help + This enables BLE v4.2 scan + +menuconfig BT_BLE_FEAT_ISO_EN + bool "Enable BLE 5.2 iso feature" + depends on (BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_BLE_AUDIO_SUPPORTED) || BT_CONTROLLER_DISABLED)) # NOERROR + default n + help + Enable BLE 5.2 iso + +config BT_BLE_FEAT_ISO_60_EN + bool "Enable ISO v6.0 feature" + depends on BT_BLE_FEAT_ISO_EN + default n + help + Enable iso 6.0 feature + +config BT_BLE_FEAT_ISO_BIG_BROCASTER + bool "Enable BLE iso BIG brocaster" + depends on BT_BLE_FEAT_ISO_EN + default y + help + Enable BLE 5.2 BIG brocaster + +config BT_BLE_FEAT_ISO_BIG_SYNCER + bool "Enable BLE iso BIG syncer" + depends on BT_BLE_FEAT_ISO_EN + default y + help + Enable BLE 5.2 BIG syncer + +config BT_BLE_ISO_BIS_MAX_COUNT + int "Maximum bis count" + depends on BT_BLE_FEAT_ISO_EN && (BT_BLE_FEAT_ISO_BIG_BROCASTER || BT_BLE_FEAT_ISO_BIG_SYNCER) + default 2 + range 1 31 + help + Enable BLE 5.2 CIG peripheral + +config BT_BLE_FEAT_ISO_CIG_CENTRAL + bool "Enable BLE iso CIG central" + depends on BT_BLE_FEAT_ISO_EN + default y + help + Enable BLE 5.2 CIG central + +config BT_BLE_FEAT_ISO_CIG_PERIPHERAL + bool "Enable BLE iso CIG peripheral" + depends on BT_BLE_FEAT_ISO_EN + default y + help + Enable BLE 5.2 CIG peripheral + +config BT_BLE_ISO_CIS_MAX_COUNT + int "Maximum cis count" + depends on BT_BLE_FEAT_ISO_EN && (BT_BLE_FEAT_ISO_CIG_CENTRAL || BT_BLE_FEAT_ISO_CIG_PERIPHERAL) + default 2 + range 1 31 + help + Enable BLE 5.2 CIG peripheral + +choice BT_BLE_ISO_FLOW_CONTROL + prompt "Select ISO flow control type" + depends on BT_BLE_FEAT_ISO_EN + default BT_BLE_ISO_NON_STD_FLOW_CTRL + help + Select ISO flow control type + + config BT_BLE_ISO_STD_FLOW_CTRL + bool "ISO standard flow control" + help + Enable ISO standard flow control + + config BT_BLE_ISO_NON_STD_FLOW_CTRL + bool "ISO non-standard flow control" + help + Enable ISO non-standard flow control + +endchoice + +menuconfig BT_BLE_FEAT_CTE_EN + bool "Enable BLE CTE feature" + depends on (BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_BLE_CTE_SUPPORTED) || BT_CONTROLLER_DISABLED)) # NOERROR + default n + help + Enable BLE 5.1 CTE + +config BT_BLE_FEAT_CTE_CONNECTIONLESS_EN + bool "Enable BLE CTE connectionless feature" + depends on BT_BLE_FEAT_CTE_EN + default y + help + Transmission of CTE in periodic advertising + +config BT_BLE_FEAT_CTE_CONNECTION_EN + bool "Enable BLE CTE connection feature" + depends on BT_BLE_FEAT_CTE_EN + default y + help + Transmission of CTE by ACL connection + +config BT_BLE_FEAT_POWER_CONTROL + bool "Enable BLE power control feature" + depends on (BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_BLE_POWER_CONTROL_SUPPORTED) || BT_CONTROLLER_DISABLED)) # NOERROR + default n + help + Enable BLE power control feature + +config BT_BLE_FEAT_CONN_SUBRATING + bool "Enable BLE connection subrating feature" + depends on (BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_BLE_SUBRATE_SUPPORTED) || BT_CONTROLLER_DISABLED)) # NOERROR + default n + help + Enable BLE connection subrating feature + +config BT_BLE_VENDOR_HCI_EN + bool "Enable BLE Vendor HCI command and event" + depends on BT_BLE_ENABLED + default y + help + This enables BLE vendor HCI command and event + config BT_BLE_HIGH_DUTY_ADV_INTERVAL bool "Enable BLE high duty advertising interval feature" depends on BT_BLE_ENABLED default n help This enable BLE high duty advertising interval feature + +config BT_ABORT_WHEN_ALLOCATION_FAILS + bool "Abort when memory allocation fails in BT/BLE stack" + depends on BT_BLUEDROID_ENABLED + default n + help + This enables abort when memory allocation fails diff --git a/lib/bt/host/bluedroid/api/esp_a2dp_api.c b/lib/bt/host/bluedroid/api/esp_a2dp_api.c index be8adcf2..254c43d5 100644 --- a/lib/bt/host/bluedroid/api/esp_a2dp_api.c +++ b/lib/bt/host/bluedroid/api/esp_a2dp_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +14,37 @@ #if BTC_AV_INCLUDED +esp_a2d_audio_buff_t *esp_a2d_audio_buff_alloc(uint16_t size) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return NULL; + } + + if (size == 0) { + return NULL; + } + + uint8_t *p_buf = NULL, *p_data; + btc_av_audio_buff_alloc(size, &p_buf, &p_data); + if (p_buf == NULL) { + return NULL; + } + + esp_a2d_audio_buff_t *audio_buf = (esp_a2d_audio_buff_t *)p_buf; + audio_buf->buff_size = size; + audio_buf->data_len = 0; + audio_buf->data = p_data; + return audio_buf; +} + +void esp_a2d_audio_buff_free(esp_a2d_audio_buff_t *audio_buf) +{ + if (audio_buf == NULL) { + return; + } + btc_av_audio_buff_free((uint8_t *)audio_buf); +} + #if BTC_AV_SINK_INCLUDED esp_err_t esp_a2d_sink_init(void) { @@ -36,6 +67,35 @@ esp_err_t esp_a2d_sink_init(void) return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } +esp_err_t esp_a2d_sink_register_stream_endpoint(uint8_t seid, const esp_a2d_mcc_t *mcc) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (g_a2dp_on_deinit || g_a2dp_sink_ongoing_deinit) { + return ESP_ERR_INVALID_STATE; + } + + if (seid >= ESP_A2D_MAX_SEPS) { + return ESP_ERR_INVALID_ARG; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_A2DP; + msg.act = BTC_AV_SINK_API_REG_SEP_EVT; + + btc_av_args_t arg; + memset(&arg, 0, sizeof(btc_av_args_t)); + arg.reg_sep.seid = seid; + memcpy(&arg.reg_sep.mcc, mcc, sizeof(esp_a2d_mcc_t)); + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + esp_err_t esp_a2d_sink_deinit(void) { if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { @@ -81,6 +141,30 @@ esp_err_t esp_a2d_sink_register_data_callback(esp_a2d_sink_data_cb_t callback) return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } +esp_err_t esp_a2d_sink_register_audio_data_callback(esp_a2d_sink_audio_data_cb_t callback) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (g_a2dp_sink_ongoing_deinit) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_A2DP; + msg.act = BTC_AV_SINK_API_REG_AUDIO_DATA_CB_EVT; + + btc_av_args_t arg; + memset(&arg, 0, sizeof(btc_av_args_t)); + arg.audio_data_cb = callback; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + esp_err_t esp_a2d_sink_connect(esp_bd_addr_t remote_bda) { if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { @@ -229,6 +313,21 @@ esp_err_t esp_a2d_media_ctrl(esp_a2d_media_ctrl_t ctrl) return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } +esp_err_t esp_a2d_get_profile_status(esp_a2d_profile_status_t *profile_status) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + if (profile_status == NULL) { + return ESP_ERR_INVALID_ARG; + } + + memset(profile_status, 0, sizeof(esp_a2d_profile_status_t)); + btc_a2dp_get_profile_status(profile_status); + + return ESP_OK; +} + #if BTC_AV_SRC_INCLUDED esp_err_t esp_a2d_source_init(void) { @@ -251,6 +350,35 @@ esp_err_t esp_a2d_source_init(void) return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } +esp_err_t esp_a2d_source_register_stream_endpoint(uint8_t seid, const esp_a2d_mcc_t *mcc) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (g_a2dp_on_deinit || g_a2dp_sink_ongoing_deinit) { + return ESP_ERR_INVALID_STATE; + } + + if (seid >= ESP_A2D_MAX_SEPS) { + return ESP_ERR_INVALID_ARG; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_A2DP; + msg.act = BTC_AV_SRC_API_REG_SEP_EVT; + + btc_av_args_t arg; + memset(&arg, 0, sizeof(btc_av_args_t)); + arg.reg_sep.seid = seid; + memcpy(&arg.reg_sep.mcc, mcc, sizeof(esp_a2d_mcc_t)); + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + esp_err_t esp_a2d_source_deinit(void) { if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { @@ -348,6 +476,26 @@ esp_err_t esp_a2d_source_register_data_callback(esp_a2d_source_data_cb_t callbac return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } +esp_err_t esp_a2d_source_audio_data_send(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED || !btc_av_is_started()) { + return ESP_ERR_INVALID_STATE; + } + + if (audio_buf == NULL || audio_buf->data_len == 0 || conn_hdl == 0) { + return ESP_ERR_INVALID_ARG; + } + + if (!btc_a2d_src_audio_mtu_check(audio_buf->data_len)) { + return ESP_ERR_INVALID_SIZE; + } + + if (btc_a2d_src_audio_data_send(conn_hdl, audio_buf) != BT_STATUS_SUCCESS) { + return ESP_FAIL; + } + return ESP_OK; +} + #endif /* BTC_AV_SRC_INCLUDED */ #endif /* #if BTC_AV_INCLUDED */ diff --git a/lib/bt/host/bluedroid/api/esp_avrc_api.c b/lib/bt/host/bluedroid/api/esp_avrc_api.c index 2d3e1532..ff4f601c 100644 --- a/lib/bt/host/bluedroid/api/esp_avrc_api.c +++ b/lib/bt/host/bluedroid/api/esp_avrc_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -232,6 +232,174 @@ esp_err_t esp_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code, uint8_t return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } +esp_err_t esp_avrc_ct_send_get_play_status_cmd(uint8_t tl) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (tl > ESP_AVRC_TRANS_LABEL_MAX) { + return ESP_ERR_INVALID_ARG; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_AVRC_CT; + msg.act = BTC_AVRC_STATUS_API_SND_GET_PLAY_STATUS_EVT; + + btc_avrc_args_t arg; + memset(&arg, 0, sizeof(btc_avrc_args_t)); + + arg.get_play_status_cmd.tl = tl; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), NULL, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +#if BTC_AV_CA_INCLUDED + +esp_err_t esp_avrc_ct_cover_art_connect(uint16_t mtu) +{ + if ((esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) || + (!btc_avrc_ct_connected_p())) { + return ESP_ERR_INVALID_STATE; + } + + if (!btc_avrc_ct_check_cover_art_support()) { + return ESP_ERR_NOT_SUPPORTED; + } + + if (mtu > ESP_AVRC_CA_MTU_MAX || mtu < ESP_AVRC_CA_MTU_MIN) { + mtu = ESP_AVRC_CA_MTU_MAX; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_AVRC_CT; + msg.act = BTC_AVRC_CT_API_COVER_ART_CONNECT_EVT; + + btc_avrc_args_t arg; + memset(&arg, 0, sizeof(btc_avrc_args_t)); + arg.ca_conn.mtu = mtu; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), NULL, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_avrc_ct_cover_art_disconnect(void) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (!btc_avrc_ct_check_cover_art_support()) { + return ESP_ERR_NOT_SUPPORTED; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_AVRC_CT; + msg.act = BTC_AVRC_CT_API_COVER_ART_DISCONNECT_EVT; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_avrc_ct_cover_art_get_image_properties(uint8_t *image_handle) +{ + if ((esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) || + (!btc_avrc_ct_connected_p())) { + return ESP_ERR_INVALID_STATE; + } + + if (!btc_avrc_ct_check_cover_art_support()) { + return ESP_ERR_NOT_SUPPORTED; + } + + if (image_handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_AVRC_CT; + msg.act = BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_PROPERTIES_EVT; + + btc_avrc_args_t arg; + memset(&arg, 0, sizeof(btc_avrc_args_t)); + memcpy(arg.ca_get_img_prop.image_handle, image_handle, ESP_AVRC_CA_IMAGE_HANDLE_LEN); + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), NULL, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_avrc_ct_cover_art_get_image(uint8_t *image_handle, uint8_t *image_descriptor, uint16_t image_descriptor_len) +{ + if ((esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) || + (!btc_avrc_ct_connected_p())) { + return ESP_ERR_INVALID_STATE; + } + + if (!btc_avrc_ct_check_cover_art_support()) { + return ESP_ERR_NOT_SUPPORTED; + } + + if (image_handle == NULL || image_descriptor == NULL || image_descriptor_len == 0) { + return ESP_ERR_INVALID_ARG; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_AVRC_CT; + msg.act = BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_EVT; + + btc_avrc_args_t arg; + memset(&arg, 0, sizeof(btc_avrc_args_t)); + + memcpy(arg.ca_get_img.image_handle, image_handle, ESP_AVRC_CA_IMAGE_HANDLE_LEN); + arg.ca_get_img.image_descriptor_len = image_descriptor_len; + arg.ca_get_img.image_descriptor = image_descriptor; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), btc_avrc_arg_deep_copy, btc_avrc_arg_deep_free); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_avrc_ct_cover_art_get_linked_thumbnail(uint8_t *image_handle) +{ + if ((esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) || + (!btc_avrc_ct_connected_p())) { + return ESP_ERR_INVALID_STATE; + } + + if (!btc_avrc_ct_check_cover_art_support()) { + return ESP_ERR_NOT_SUPPORTED; + } + + if (image_handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_AVRC_CT; + msg.act = BTC_AVRC_CT_API_COVER_ART_GET_LINKED_THUMBNAIL_EVT; + + btc_avrc_args_t arg; + memset(&arg, 0, sizeof(btc_avrc_args_t)); + memcpy(arg.ca_get_lk_thn.image_handle, image_handle, ESP_AVRC_CA_IMAGE_HANDLE_LEN); + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_avrc_args_t), NULL, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +#endif /* #if BTC_AV_CA_INCLUDED */ + /*********************************************************************************************/ /** following is the API of AVRCP target role **/ /*********************************************************************************************/ @@ -474,4 +642,19 @@ esp_err_t esp_avrc_tg_send_rn_rsp(esp_avrc_rn_event_ids_t event_id, esp_avrc_rn_ } +esp_err_t esp_avrc_get_profile_status(esp_avrc_profile_status_t *profile_status) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + if (profile_status == NULL) { + return ESP_ERR_INVALID_ARG; + } + + memset(profile_status, 0, sizeof(esp_avrc_profile_status_t)); + btc_avrc_get_profile_status(profile_status); + + return ESP_OK; +} + #endif /* #if BTC_AV_INCLUDED */ diff --git a/lib/bt/host/bluedroid/api/esp_ble_cte_api.c b/lib/bt/host/bluedroid/api/esp_ble_cte_api.c new file mode 100644 index 00000000..37503c47 --- /dev/null +++ b/lib/bt/host/bluedroid/api/esp_ble_cte_api.c @@ -0,0 +1,224 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_bt_device.h" +#include "esp_bt_main.h" +#if (BLE_FEAT_CTE_EN == TRUE) +#include "esp_ble_cte_api.h" +#include "btc_ble_cte.h" +#include "btc/btc_manage.h" + + +esp_err_t esp_ble_cte_register_callback(esp_ble_cte_cb_t callback) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + return (btc_profile_cb_set(BTC_PID_BLE_CTE, callback) == 0 ? ESP_OK : ESP_FAIL); +} + +esp_ble_cte_cb_t esp_ble_cte_get_callback(void) +{ + return (esp_ble_cte_cb_t) btc_profile_cb_get(BTC_PID_BLE_CTE); +} + +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +esp_err_t esp_ble_cte_set_connectionless_trans_params(esp_ble_cte_connless_trans_params_t *cte_trans_params) +{ + btc_msg_t msg; + btc_ble_cte_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if ((cte_trans_params == NULL) || (cte_trans_params->antenna_ids == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_BLE_CTE; + msg.act = BTC_CTE_ACT_SET_TRANS_PARAMS; + + arg.cte_trans_params.adv_handle = cte_trans_params->adv_handle; + arg.cte_trans_params.cte_len = cte_trans_params->cte_len; + arg.cte_trans_params.cte_type = cte_trans_params->cte_type; + arg.cte_trans_params.cte_count = cte_trans_params->cte_count; + arg.cte_trans_params.switching_pattern_len = cte_trans_params->switching_pattern_len; + arg.cte_trans_params.antenna_ids = cte_trans_params->antenna_ids; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_cte_args_t), btc_ble_cte_arg_deep_copy, btc_ble_cte_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cte_set_connectionless_trans_enable(esp_ble_cte_trans_enable_params_t *cte_trans_enable) +{ + btc_msg_t msg; + btc_ble_cte_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (cte_trans_enable == NULL) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_BLE_CTE; + msg.act = BTC_CTE_ACT_SET_TRANS_ENABLE; + + arg.cte_trans_enable.adv_handle = cte_trans_enable->adv_handle; + arg.cte_trans_enable.cte_enable = cte_trans_enable->cte_enable; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_cte_args_t), NULL , NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cte_set_connectionless_iq_sampling_enable(esp_ble_cte_iq_sampling_params_t *iq_sampling_en) +{ + btc_msg_t msg; + btc_ble_cte_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if ((iq_sampling_en == NULL) || (iq_sampling_en->antenna_ids == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_BLE_CTE; + msg.act = BTC_CTE_ACT_SET_IQ_SAMPLING_EN; + + arg.cte_iq_sampling_en.sync_handle = iq_sampling_en->sync_handle; + arg.cte_iq_sampling_en.sampling_en = iq_sampling_en->sampling_en; + arg.cte_iq_sampling_en.slot_dur = iq_sampling_en->slot_dur; + arg.cte_iq_sampling_en.max_sampled_ctes = iq_sampling_en->max_sampled_ctes; + arg.cte_iq_sampling_en.switching_pattern_len = iq_sampling_en->switching_pattern_len; + arg.cte_iq_sampling_en.antenna_ids = iq_sampling_en->antenna_ids; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_cte_args_t), btc_ble_cte_arg_deep_copy, btc_ble_cte_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +esp_err_t esp_ble_cte_set_connection_receive_params(esp_ble_cte_recv_params_params_t *cte_recv_params) +{ + btc_msg_t msg; + btc_ble_cte_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if ((cte_recv_params == NULL) || (cte_recv_params->antenna_ids == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_BLE_CTE; + msg.act = BTC_CTE_ACT_SET_CONN_CTE_RECV_PARAMS; + + arg.cte_recv_params.conn_handle = cte_recv_params->conn_handle; + arg.cte_recv_params.sampling_en = cte_recv_params->sampling_en; + arg.cte_recv_params.slot_dur = cte_recv_params->slot_dur; + arg.cte_recv_params.switching_pattern_len = cte_recv_params->switching_pattern_len; + arg.cte_recv_params.antenna_ids = cte_recv_params->antenna_ids; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_cte_args_t), btc_ble_cte_arg_deep_copy, btc_ble_cte_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cte_set_connection_transmit_params(esp_ble_cte_conn_trans_params_t *cte_conn_trans_params) +{ + btc_msg_t msg; + btc_ble_cte_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if ((cte_conn_trans_params == NULL) || (cte_conn_trans_params->antenna_ids == NULL)) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_BLE_CTE; + msg.act = BTC_CTE_ACT_SET_CONN_CTE_TRANS_PARAMS; + + arg.cte_conn_trans_params.conn_handle = cte_conn_trans_params->conn_handle; + arg.cte_conn_trans_params.cte_types = cte_conn_trans_params->cte_types; + arg.cte_conn_trans_params.switching_pattern_len = cte_conn_trans_params->switching_pattern_len; + arg.cte_conn_trans_params.antenna_ids = cte_conn_trans_params->antenna_ids; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_cte_args_t), btc_ble_cte_arg_deep_copy, btc_ble_cte_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cte_connection_cte_request_enable(esp_ble_cte_req_en_params_t *cte_conn_req_en) +{ + btc_msg_t msg; + btc_ble_cte_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (cte_conn_req_en == NULL) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_BLE_CTE; + msg.act = BTC_CTE_ACT_SET_CONN_CTE_REQUEST_EN; + + arg.cte_req_en.conn_handle = cte_conn_req_en->conn_handle; + arg.cte_req_en.enable = cte_conn_req_en->enable; + arg.cte_req_en.cte_req_interval = cte_conn_req_en->cte_req_interval; + arg.cte_req_en.req_cte_len = cte_conn_req_en->req_cte_len; + arg.cte_req_en.req_cte_Type = cte_conn_req_en->req_cte_Type; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_cte_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_cte_connection_cte_response_enable(esp_ble_cte_rsp_en_params_t *cte_conn_rsp_en) +{ + btc_msg_t msg; + btc_ble_cte_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (cte_conn_rsp_en == NULL) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_BLE_CTE; + msg.act = BTC_CTE_ACT_SET_CONN_CTE_RESPONSE_EN; + + arg.cte_rsp_en.conn_handle = cte_conn_rsp_en->conn_handle; + arg.cte_rsp_en.enable = cte_conn_rsp_en->enable; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_cte_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + +esp_err_t esp_ble_cte_read_antenna_information(void) +{ + btc_msg_t msg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_BLE_CTE; + msg.act = BTC_CTE_ACT_READ_ANTENNA_INFOR; + + return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +#endif // #if (BLE_FEAT_CTE_EN == TRUE) diff --git a/lib/bt/host/bluedroid/api/esp_ble_iso_api.c b/lib/bt/host/bluedroid/api/esp_ble_iso_api.c new file mode 100644 index 00000000..826991e6 --- /dev/null +++ b/lib/bt/host/bluedroid/api/esp_ble_iso_api.c @@ -0,0 +1,425 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_bt_device.h" +#include "esp_bt_main.h" +#include "esp_ble_iso_api.h" +#include "btc_iso_ble.h" +#include "btc/btc_manage.h" + + +esp_err_t esp_ble_iso_register_callback(esp_ble_iso_cb_t callback) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + return (btc_profile_cb_set(BTC_PID_ISO_BLE, callback) == 0 ? ESP_OK : ESP_FAIL); +} + +esp_ble_iso_cb_t esp_ble_iso_get_callback(void) +{ + return (esp_ble_iso_cb_t) btc_profile_cb_get(BTC_PID_ISO_BLE); +} + +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +esp_err_t esp_ble_iso_create_big(esp_ble_iso_big_creat_params_t *big_creat_param) +{ + + btc_msg_t msg; + btc_ble_iso_args_t arg; + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + if (big_creat_param == NULL) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_BIG_CREATE; + + memcpy(&arg.iso_big_creat_params, big_creat_param, sizeof(esp_ble_iso_big_creat_params_t)); + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_iso_create_big_test(esp_ble_iso_big_creat_test_params_t *big_creat_test_param) +{ + btc_msg_t msg; + btc_ble_iso_args_t arg; + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + if (big_creat_test_param == NULL) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_BIG_CREATE_TEST; + + memcpy(&arg.iso_big_creat_test_params, big_creat_test_param, sizeof(esp_ble_iso_big_creat_test_params_t)); + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_iso_terminate_big(uint8_t big_handle, uint8_t reason) +{ + btc_msg_t msg; + btc_ble_iso_args_t arg; + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_BIG_TERMINATE; + + arg.iso_big_terminate_params.big_handle = big_handle; + arg.iso_big_terminate_params.reason = reason; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +esp_err_t esp_ble_iso_big_create_sync(esp_ble_iso_big_sync_creat_params_t *big_sync_create_param) +{ + btc_msg_t msg; + btc_ble_iso_args_t arg; + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + if (big_sync_create_param == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (big_sync_create_param->num_bis > BLE_ISO_BIS_MAX_COUNT) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_BIG_SYNC_CREATE; + + arg.iso_big_sync_creat_params.big_handle = big_sync_create_param->big_handle; + arg.iso_big_sync_creat_params.sync_handle = big_sync_create_param->sync_handle; + arg.iso_big_sync_creat_params.encryption = big_sync_create_param->encryption; + memcpy(&arg.iso_big_sync_creat_params.bc_code[0], &big_sync_create_param->bc_code[0], 16); + arg.iso_big_sync_creat_params.mse = big_sync_create_param->mse; + arg.iso_big_sync_creat_params.big_sync_timeout = big_sync_create_param->big_sync_timeout; + arg.iso_big_sync_creat_params.num_bis = big_sync_create_param->num_bis; + for (uint8_t i = 0; i < big_sync_create_param->num_bis; i++) + { + arg.iso_big_sync_creat_params.bis[i] = big_sync_create_param->bis[i]; + } + + // memcpy(&arg.iso_big_sync_creat_params, big_sync_create_param, sizeof(esp_ble_iso_big_sync_creat_params_t)); + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_iso_big_terminate_sync(uint8_t big_handle) +{ + btc_msg_t msg; + btc_ble_iso_args_t arg; + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_BIG_SYNC_TERMINATE; + + arg.iso_big_sync_terminate_params.big_handle = big_handle; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + +esp_err_t esp_ble_iso_set_iso_data_path(esp_ble_iso_set_data_path_params_t *data_path_params) +{ + btc_msg_t msg = {0}; + btc_ble_iso_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (data_path_params == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (data_path_params->codec_cfg_len && (!data_path_params->codec_cfg)) { + return ESP_ERR_INVALID_ARG; + } + + if (data_path_params->codec_cfg && (!data_path_params->codec_cfg_len)) { + return ESP_ERR_INVALID_ARG; + } + + if (data_path_params->data_path_dir > ESP_BLE_ISO_DATA_PATH_DIR_OUTPUT) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_SET_DATA_PATH; + + arg.iso_set_data_path_params.conn_handle = data_path_params->iso_handle; + arg.iso_set_data_path_params.data_path_dir = data_path_params->data_path_dir; + arg.iso_set_data_path_params.data_path_id = data_path_params->data_path_id; + arg.iso_set_data_path_params.coding_fmt = data_path_params->coding_fmt; + arg.iso_set_data_path_params.company_id = data_path_params->company_id; + arg.iso_set_data_path_params.vs_codec_id = data_path_params->vs_codec_id; + arg.iso_set_data_path_params.controller_delay = data_path_params->controller_delay; + arg.iso_set_data_path_params.codec_cfg_len = data_path_params->codec_cfg_len; + arg.iso_set_data_path_params.codec_cfg = data_path_params->codec_cfg; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), btc_iso_ble_arg_deep_copy, btc_iso_ble_arg_deep_free) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_iso_remove_iso_data_path(esp_ble_iso_remove_data_path_params_t *data_path_params) +{ + btc_msg_t msg = {0}; + btc_ble_iso_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (data_path_params == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (data_path_params->data_path_dir == 0 || data_path_params->data_path_dir > ESP_BLE_ISO_DATA_PATH_DIR_ALL_BIT_MASK) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_REMOVE_DATA_PATH; + + arg.iso_remove_data_path_params.conn_handle = data_path_params->iso_handle; + arg.iso_remove_data_path_params.data_path_dir = data_path_params->data_path_dir; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_iso_read_iso_tx_sync(uint16_t iso_handle) +{ + btc_msg_t msg = {0}; + btc_ble_iso_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_READ_ISO_TX_SYNC; + + arg.iso_read_tx_sync_params.iso_handle = iso_handle; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_iso_read_link_quality(uint16_t iso_handle) +{ + btc_msg_t msg = {0}; + btc_ble_iso_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_READ_ISO_LINK_QUALITY; + + arg.iso_read_link_quality_params.iso_handle = iso_handle; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +esp_err_t esp_ble_iso_set_cig_parameters(struct esp_ble_iso_set_cig_params *cig_params) +{ + btc_msg_t msg; + btc_ble_iso_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if ((cig_params == NULL) || (cig_params->cis_cnt > BLE_ISO_CIS_MAX_COUNT)) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_SET_CIG_PARAMS; + + arg.set_cig_params.cig_id = cig_params->cig_id; + arg.set_cig_params.sdu_int_c_to_p = cig_params->sdu_int_c_to_p; + arg.set_cig_params.sdu_int_p_to_c = cig_params->sdu_int_p_to_c; + arg.set_cig_params.worse_case_SCA = cig_params->worse_case_SCA; + arg.set_cig_params.packing = cig_params->packing; + arg.set_cig_params.framing = cig_params->framing; + arg.set_cig_params.mtl_c_to_p = cig_params->mtl_c_to_p; + arg.set_cig_params.mtl_p_to_c = cig_params->mtl_p_to_c; + arg.set_cig_params.cis_cnt = cig_params->cis_cnt; + memcpy(&arg.set_cig_params.cis_params[0], &cig_params->cis_params[0], sizeof(struct ble_iso_cis_params) * cig_params->cis_cnt); + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); + +} + +esp_err_t esp_ble_iso_set_cig_parameters_test(struct esp_ble_iso_set_cig_params_test *cig_params_test) +{ + btc_msg_t msg; + btc_ble_iso_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if ((cig_params_test == NULL) || (cig_params_test->cis_cnt > BLE_ISO_CIS_MAX_COUNT)) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_SET_CIG_PARAMS_TEST; + + arg.set_cig_params_test.cig_id = cig_params_test->cig_id; + arg.set_cig_params_test.sdu_int_c_to_p = cig_params_test->sdu_int_c_to_p; + arg.set_cig_params_test.sdu_int_p_to_c = cig_params_test->sdu_int_p_to_c; + arg.set_cig_params_test.ft_c_to_p = cig_params_test->ft_c_to_p; + arg.set_cig_params_test.ft_p_to_c = cig_params_test->ft_p_to_c; + arg.set_cig_params_test.iso_interval = cig_params_test->iso_interval; + arg.set_cig_params_test.worse_case_SCA = cig_params_test->worse_case_SCA; + arg.set_cig_params_test.packing = cig_params_test->packing; + arg.set_cig_params_test.framing = cig_params_test->framing; + arg.set_cig_params_test.cis_cnt = cig_params_test->cis_cnt; + memcpy(&arg.set_cig_params_test.cis_params_test[0], &cig_params_test->cis_params_test[0], sizeof(struct ble_iso_cis_params_test) * cig_params_test->cis_cnt); + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); + +} + +esp_err_t esp_ble_iso_create_cis(struct esp_ble_iso_create_cis_params *creat_cis_params) +{ + btc_msg_t msg; + btc_ble_iso_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if ((creat_cis_params == NULL) || (creat_cis_params->cis_count > BLE_ISO_CIS_MAX_COUNT)) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_CREATE_CIS; + + arg.creat_cis_params.cis_count = creat_cis_params->cis_count; + for (uint8_t i = 0; i < creat_cis_params->cis_count; i++) + { + arg.creat_cis_params.cis_hdls[i].cis_hdl = creat_cis_params->cis_hdl_info[i].cis_hdl; + arg.creat_cis_params.cis_hdls[i].acl_hdl = creat_cis_params->cis_hdl_info[i].acl_hdl; + } + + //memcpy(&arg.creat_cis_params.cis_hdl_info[0], &creat_cis_params->cis_hdl_info[0], creat_cis_params->cis_count * 4); + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_iso_remove_cig(uint8_t cig_id) +{ + btc_msg_t msg; + btc_ble_iso_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_REMOVE_CIG; + + arg.remove_cig_params.cig_id = cig_id; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +esp_err_t esp_ble_iso_accept_cis_request(uint16_t cis_handle) +{ + btc_msg_t msg; + btc_ble_iso_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_ACCEPT_CIS_REQ; + + arg.accept_cis_req_params.cis_handle = cis_handle; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_iso_reject_cis_request(uint16_t cis_handle, uint8_t reason) +{ + btc_msg_t msg; + btc_ble_iso_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_REJECT_CIS_REQ; + + arg.reject_cis_req_params.cis_handle = cis_handle; + arg.reject_cis_req_params.reason = reason; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_EN == TRUE) +esp_err_t esp_ble_iso_disconnect_cis(uint16_t cis_handle, uint8_t reason) +{ + btc_msg_t msg; + btc_ble_iso_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_ISO_BLE; + msg.act = BTC_ISO_ACT_DISCON_CIS; + + arg.discon_cis_params.cis_handle = cis_handle; + arg.discon_cis_params.reason = reason; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_iso_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) diff --git a/lib/bt/host/bluedroid/api/esp_bluedroid_hci.c b/lib/bt/host/bluedroid/api/esp_bluedroid_hci.c index 1676ae88..0e6baf11 100644 --- a/lib/bt/host/bluedroid/api/esp_bluedroid_hci.c +++ b/lib/bt/host/bluedroid/api/esp_bluedroid_hci.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,6 +16,10 @@ #define LOG_TAG "HCI_API" +#if CONFIG_BT_BLE_LOG_SPI_OUT_HCI_ENABLED +#include "ble_log/ble_log_spi_out.h" +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_HCI_ENABLED + static esp_bluedroid_hci_driver_operations_t s_hci_driver_ops = { 0 }; esp_err_t esp_bluedroid_attach_hci_driver(const esp_bluedroid_hci_driver_operations_t *p_ops) @@ -63,6 +67,9 @@ void hci_host_send_packet(uint8_t *data, uint16_t len) #if (BT_HCI_LOG_INCLUDED == TRUE) bt_hci_log_record_hci_data(data[0], &data[1], len - 1); #endif +#if (BT_BLE_LOG_SPI_OUT_HCI_ENABLED && !SOC_ESP_NIMBLE_CONTROLLER) + ble_log_spi_out_write_with_ts(BLE_LOG_SPI_OUT_SOURCE_HCI_DOWNSTREAM, data, len); +#endif // (BT_BLE_LOG_SPI_OUT_HCI_ENABLED && !SOC_ESP_NIMBLE_CONTROLLER) #if (BT_CONTROLLER_INCLUDED == TRUE) esp_vhci_host_send_packet(data, len); #else /* BT_CONTROLLER_INCLUDED == TRUE */ diff --git a/lib/bt/host/bluedroid/api/esp_bt_device.c b/lib/bt/host/bluedroid/api/esp_bt_device.c index ae4ff8ec..d3229e5f 100644 --- a/lib/bt/host/bluedroid/api/esp_bt_device.c +++ b/lib/bt/host/bluedroid/api/esp_bt_device.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -95,6 +95,11 @@ esp_err_t esp_bt_dev_coex_status_config(esp_bt_dev_coex_type_t type, esp_bt_dev_ } #endif +esp_err_t esp_bt_config_file_path_get(char *file_path) +{ + return btc_config_file_path_get(file_path); +} + esp_err_t esp_bt_config_file_path_update(const char *file_path) { ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_UNINITIALIZED); diff --git a/lib/bt/host/bluedroid/api/esp_bt_main.c b/lib/bt/host/bluedroid/api/esp_bt_main.c index 92576442..adb7a12a 100644 --- a/lib/bt/host/bluedroid/api/esp_bt_main.c +++ b/lib/bt/host/bluedroid/api/esp_bt_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -128,6 +128,21 @@ esp_err_t esp_bluedroid_init_with_cfg(esp_bluedroid_config_t *cfg) return ESP_ERR_INVALID_ARG; } + if (cfg->sc_en) { +#if (SC_MODE_INCLUDED == FALSE) + LOG_ERROR("Secure Connections should not be enabled when target controller is ESP32.\n"); + LOG_ERROR("It may trigger unresolved bugs in the controller.\n"); + return ESP_ERR_INVALID_ARG; +#endif // SC_MODE_INCLUDED + + if (!cfg->ssp_en) { + LOG_ERROR("secure simple pairing should be enabled when secure connection host support is enabled\n"); + return ESP_ERR_INVALID_ARG; + } + + LOG_WARN("Please make sure to clear the bond list before enabling the secure connection host support\n"); + } + #if (BT_CONTROLLER_INCLUDED == TRUE) if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { LOG_ERROR("Controller not initialised\n"); @@ -144,7 +159,7 @@ esp_err_t esp_bluedroid_init_with_cfg(esp_bluedroid_config_t *cfg) osi_mem_dbg_init(); #endif - ret = bluedriod_config_init(cfg); + ret = bluedroid_config_init(cfg); if (ret != BT_STATUS_SUCCESS) { LOG_ERROR("Bluedroid stack initialize fail, ret:%d", ret); return ESP_FAIL; @@ -228,7 +243,7 @@ esp_err_t esp_bluedroid_deinit(void) btc_deinit(); - bluedriod_config_deinit(); + bluedroid_config_deinit(); #if (BT_HCI_LOG_INCLUDED == TRUE) bt_hci_log_deinit(); @@ -238,3 +253,14 @@ esp_err_t esp_bluedroid_deinit(void) return ESP_OK; } + +#if defined(CONFIG_EXAMPLE_CI_ID) && defined(CONFIG_EXAMPLE_CI_PIPELINE_ID) +char *esp_bluedroid_get_example_name(void) +{ + static char example_name[ESP_BLE_ADV_NAME_LEN_MAX]; + memset(example_name, 0, sizeof(example_name)); + sprintf(example_name, "BE%02X_%05X_%02X", CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif diff --git a/lib/bt/host/bluedroid/api/esp_gap_ble_api.c b/lib/bt/host/bluedroid/api/esp_gap_ble_api.c index 1d2267e8..a4262fd0 100644 --- a/lib/bt/host/bluedroid/api/esp_gap_ble_api.c +++ b/lib/bt/host/bluedroid/api/esp_gap_ble_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -28,6 +28,7 @@ esp_gap_ble_cb_t esp_ble_gap_get_callback(void) } #if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_ADV_EN == TRUE) esp_err_t esp_ble_gap_config_adv_data(esp_ble_adv_data_t *adv_data) { btc_msg_t msg = {0}; @@ -51,8 +52,9 @@ esp_err_t esp_ble_gap_config_adv_data(esp_ble_adv_data_t *adv_data) return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), btc_gap_ble_arg_deep_copy, btc_gap_ble_arg_deep_free)== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +#endif // #if (BLE_42_ADV_EN == TRUE) - +#if (BLE_42_SCAN_EN == TRUE) esp_err_t esp_ble_gap_set_scan_params(esp_ble_scan_params_t *scan_params) { btc_msg_t msg = {0}; @@ -99,7 +101,9 @@ esp_err_t esp_ble_gap_stop_scanning(void) msg.act = BTC_GAP_BLE_ACT_STOP_SCAN; return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +#endif // #if (BLE_42_SCAN_EN == TRUE) +#if (BLE_42_ADV_EN == TRUE) esp_err_t esp_ble_gap_start_advertising(esp_ble_adv_params_t *adv_params) { btc_msg_t msg = {0}; @@ -127,19 +131,7 @@ esp_err_t esp_ble_gap_stop_advertising(void) return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } - -esp_err_t esp_ble_gap_clear_advertising(void) -{ - btc_msg_t msg; - - ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); - - msg.sig = BTC_SIG_API_CALL; - msg.pid = BTC_PID_GAP_BLE; - msg.act = BTC_GAP_BLE_ACT_CLEAR_ADV; - - return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); -} +#endif // #if (BLE_42_ADV_EN == TRUE) #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) esp_err_t esp_ble_gap_update_conn_params(esp_ble_conn_update_params_t *params) @@ -295,83 +287,17 @@ esp_err_t esp_ble_gap_config_local_privacy (bool privacy_enable) esp_err_t esp_ble_gap_config_local_icon (uint16_t icon) { - esp_err_t ret; btc_msg_t msg = {0}; btc_ble_gap_args_t arg; ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); - switch (icon) { - case ESP_BLE_APPEARANCE_GENERIC_PHONE: - case ESP_BLE_APPEARANCE_GENERIC_COMPUTER: - case ESP_BLE_APPEARANCE_GENERIC_REMOTE: - case ESP_BLE_APPEARANCE_GENERIC_THERMOMETER: - case ESP_BLE_APPEARANCE_THERMOMETER_EAR: - case ESP_BLE_APPEARANCE_GENERIC_HEART_RATE: - case ESP_BLE_APPEARANCE_HEART_RATE_BELT: - case ESP_BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE: - case ESP_BLE_APPEARANCE_BLOOD_PRESSURE_ARM: - case ESP_BLE_APPEARANCE_BLOOD_PRESSURE_WRIST: - case ESP_BLE_APPEARANCE_GENERIC_PULSE_OXIMETER: - case ESP_BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP: - case ESP_BLE_APPEARANCE_PULSE_OXIMETER_WRIST: - case ESP_BLE_APPEARANCE_GENERIC_GLUCOSE: - case ESP_BLE_APPEARANCE_GENERIC_WEIGHT: - case ESP_BLE_APPEARANCE_GENERIC_WALKING: - case ESP_BLE_APPEARANCE_WALKING_IN_SHOE: - case ESP_BLE_APPEARANCE_WALKING_ON_SHOE: - case ESP_BLE_APPEARANCE_WALKING_ON_HIP: - case ESP_BLE_APPEARANCE_GENERIC_WATCH: - case ESP_BLE_APPEARANCE_SPORTS_WATCH: - case ESP_BLE_APPEARANCE_GENERIC_EYEGLASSES: - case ESP_BLE_APPEARANCE_GENERIC_DISPLAY: - case ESP_BLE_APPEARANCE_GENERIC_MEDIA_PLAYER: - case ESP_BLE_APPEARANCE_GENERIC_BARCODE_SCANNER: - case ESP_BLE_APPEARANCE_HID_BARCODE_SCANNER: - case ESP_BLE_APPEARANCE_GENERIC_HID: - case ESP_BLE_APPEARANCE_HID_KEYBOARD: - case ESP_BLE_APPEARANCE_HID_MOUSE: - case ESP_BLE_APPEARANCE_HID_JOYSTICK: - case ESP_BLE_APPEARANCE_HID_GAMEPAD: - case ESP_BLE_APPEARANCE_HID_DIGITIZER_TABLET: - case ESP_BLE_APPEARANCE_HID_CARD_READER: - case ESP_BLE_APPEARANCE_HID_DIGITAL_PEN: - case ESP_BLE_APPEARANCE_UNKNOWN: - case ESP_BLE_APPEARANCE_GENERIC_CLOCK: - case ESP_BLE_APPEARANCE_GENERIC_TAG: - case ESP_BLE_APPEARANCE_GENERIC_KEYRING: - case ESP_BLE_APPEARANCE_GENERIC_CYCLING: - case ESP_BLE_APPEARANCE_CYCLING_COMPUTER: - case ESP_BLE_APPEARANCE_CYCLING_SPEED: - case ESP_BLE_APPEARANCE_CYCLING_CADENCE: - case ESP_BLE_APPEARANCE_CYCLING_POWER: - case ESP_BLE_APPEARANCE_CYCLING_SPEED_CADENCE: - case ESP_BLE_APPEARANCE_GENERIC_PERSONAL_MOBILITY_DEVICE: - case ESP_BLE_APPEARANCE_POWERED_WHEELCHAIR: - case ESP_BLE_APPEARANCE_MOBILITY_SCOOTER: - case ESP_BLE_APPEARANCE_GENERIC_CONTINUOUS_GLUCOSE_MONITOR: - case ESP_BLE_APPEARANCE_GENERIC_INSULIN_PUMP: - case ESP_BLE_APPEARANCE_INSULIN_PUMP_DURABLE_PUMP: - case ESP_BLE_APPEARANCE_INSULIN_PUMP_PATCH_PUMP: - case ESP_BLE_APPEARANCE_INSULIN_PEN: - case ESP_BLE_APPEARANCE_GENERIC_MEDICATION_DELIVERY: - case ESP_BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS: - case ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION: - case ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV: - case ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD: - case ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD_AND_NAV: - case ESP_BLE_APPEARANCE_STANDALONE_SPEAKER: - msg.sig = BTC_SIG_API_CALL; - msg.pid = BTC_PID_GAP_BLE; - msg.act = BTC_GAP_BLE_ACT_CONFIG_LOCAL_ICON; - arg.cfg_local_icon.icon = icon; - ret = (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); - break; - default: - ret = ESP_ERR_INVALID_ARG; - break; - } - return ret; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_ACT_CONFIG_LOCAL_ICON; + arg.cfg_local_icon.icon = icon; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } esp_err_t esp_ble_gap_update_whitelist(bool add_remove, esp_bd_addr_t remote_bda, esp_ble_wl_addr_type_t wl_addr_type) @@ -504,22 +430,39 @@ esp_err_t esp_ble_gap_get_local_used_addr(esp_bd_addr_t local_used_addr, uint8_t return ESP_OK; } -uint8_t *esp_ble_resolve_adv_data( uint8_t *adv_data, uint8_t type, uint8_t *length) +uint8_t *esp_ble_resolve_adv_data_by_type( uint8_t *adv_data, uint16_t adv_data_len, esp_ble_adv_data_type type, uint8_t *length) { + if (length == NULL) { + return NULL; + } + if (((type < ESP_BLE_AD_TYPE_FLAG) || (type > ESP_BLE_AD_TYPE_128SERVICE_DATA)) && (type != ESP_BLE_AD_MANUFACTURER_SPECIFIC_TYPE)) { - LOG_ERROR("the eir type not define, type = %x\n", type); + LOG_ERROR("The advertising data type is not defined, type = %x", type); + *length = 0; return NULL; } + if (adv_data_len == 0) { + *length = 0; + return NULL; + } if (adv_data == NULL) { - LOG_ERROR("Invalid p_eir data.\n"); + LOG_ERROR("Invalid advertising data."); + *length = 0; return NULL; } - return (BTM_CheckAdvData( adv_data, type, length)); + return (BTM_CheckAdvData( adv_data, adv_data_len, type, length)); } + +uint8_t *esp_ble_resolve_adv_data( uint8_t *adv_data, uint8_t type, uint8_t *length) +{ + return esp_ble_resolve_adv_data_by_type( adv_data, ESP_BLE_ADV_DATA_LEN_MAX + ESP_BLE_SCAN_RSP_DATA_LEN_MAX, (esp_ble_adv_data_type) type, length); +} + #if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_ADV_EN == TRUE) esp_err_t esp_ble_gap_config_adv_data_raw(uint8_t *raw_data, uint32_t raw_data_len) { btc_msg_t msg = {0}; @@ -541,6 +484,7 @@ esp_err_t esp_ble_gap_config_adv_data_raw(uint8_t *raw_data, uint32_t raw_data_l btc_gap_ble_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +#endif // #if (BLE_42_ADV_EN == TRUE) #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) esp_err_t esp_ble_gap_read_rssi(esp_bd_addr_t remote_addr) { @@ -558,6 +502,7 @@ esp_err_t esp_ble_gap_read_rssi(esp_bd_addr_t remote_addr) return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } + #if (BLE_42_FEATURE_SUPPORT == TRUE) esp_err_t esp_ble_gap_config_scan_rsp_data_raw(uint8_t *raw_data, uint32_t raw_data_len) { @@ -906,6 +851,26 @@ esp_err_t esp_gap_ble_set_channels(esp_gap_ble_channels channels) return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +esp_err_t esp_ble_gap_read_channel_map(esp_bd_addr_t bd_addr) +{ + if (!bd_addr) { + return ESP_ERR_INVALID_ARG; + } + + btc_msg_t msg; + btc_ble_gap_args_t arg; + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_READ_CHANNEL_MAP; + + memcpy(arg.read_channel_map.bd_addr, bd_addr, ESP_BD_ADDR_LEN); + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + esp_err_t esp_gap_ble_set_authorization(esp_bd_addr_t bd_addr, bool authorize) { if (!bd_addr) { @@ -917,7 +882,7 @@ esp_err_t esp_gap_ble_set_authorization(esp_bd_addr_t bd_addr, bool authorize) return ESP_FAIL; } -#if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_DTM_TEST_EN == TRUE) esp_err_t esp_ble_dtm_tx_start(const esp_ble_dtm_tx_t *tx_params) { btc_msg_t msg = {0}; @@ -957,9 +922,9 @@ esp_err_t esp_ble_dtm_rx_start(const esp_ble_dtm_rx_t *rx_params) return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } -#endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) +#endif // #if (BLE_42_DTM_TEST_EN == TRUE) -#if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_DTM_TEST_EN == TRUE) esp_err_t esp_ble_dtm_enh_tx_start(const esp_ble_dtm_enh_tx_t *tx_params) { btc_msg_t msg = {0}; @@ -999,8 +964,9 @@ esp_err_t esp_ble_dtm_enh_rx_start(const esp_ble_dtm_enh_rx_t *rx_params) return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_5_gap_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } -#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) +#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) esp_err_t esp_ble_dtm_stop(void) { btc_msg_t msg = {0}; @@ -1013,6 +979,7 @@ esp_err_t esp_ble_dtm_stop(void) return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +#endif // #if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) esp_err_t esp_ble_gap_set_privacy_mode(esp_ble_addr_type_t addr_type, esp_bd_addr_t addr, esp_ble_privacy_mode_t mode) { @@ -1092,6 +1059,7 @@ esp_err_t esp_ble_gap_set_preferred_phy(esp_bd_addr_t bd_addr, == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +#if (BLE_50_EXTEND_ADV_EN == TRUE) esp_err_t esp_ble_gap_ext_adv_set_rand_addr(uint8_t instance, esp_bd_addr_t rand_addr) { btc_msg_t msg; @@ -1247,7 +1215,9 @@ esp_err_t esp_ble_gap_ext_adv_set_clear(void) return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) esp_err_t esp_ble_gap_periodic_adv_set_params(uint8_t instance, const esp_ble_gap_periodic_adv_params_t *params) { btc_msg_t msg; @@ -1342,7 +1312,9 @@ esp_err_t esp_ble_gap_periodic_adv_stop(uint8_t instance) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) esp_err_t esp_ble_gap_periodic_adv_create_sync(const esp_ble_gap_periodic_adv_sync_params_t *params) { btc_msg_t msg; @@ -1456,6 +1428,19 @@ esp_err_t esp_ble_gap_periodic_adv_clear_dev(void) } +esp_err_t esp_ble_gap_get_periodic_list_size(uint8_t *size) +{ + if (size == NULL) { + return ESP_FAIL; + } + btc_get_periodic_list_size(size); + + return ESP_OK; +} + +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) + +#if (BLE_50_EXTEND_SCAN_EN == TRUE) esp_err_t esp_ble_gap_set_ext_scan_params(const esp_ble_ext_scan_params_t *params) { btc_msg_t msg; @@ -1507,6 +1492,7 @@ esp_err_t esp_ble_gap_stop_ext_scan(void) return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) esp_err_t esp_ble_gap_prefer_ext_connect_params_set(esp_bd_addr_t addr, esp_ble_gap_phy_mask_t phy_mask, @@ -1697,6 +1683,7 @@ esp_err_t esp_ble_gap_set_periodic_adv_sync_trans_params(esp_bd_addr_t addr, con } #endif //#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_VENDOR_HCI_EN == TRUE) esp_err_t esp_ble_gap_vendor_command_send(esp_ble_vendor_cmd_params_t *vendor_cmd_param) { btc_msg_t msg = {0}; @@ -1724,3 +1711,243 @@ esp_err_t esp_ble_gap_vendor_command_send(esp_ble_vendor_cmd_params_t *vendor_cm return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), btc_gap_ble_arg_deep_copy, btc_gap_ble_arg_deep_free) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } + +esp_err_t esp_ble_gap_set_vendor_event_mask(esp_ble_vendor_evt_mask_t event_mask) +{ + btc_msg_t msg = {0}; + btc_ble_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_ACT_SET_VENDOR_EVT_MASK; + arg.set_vendor_evt_mask.evt_mask = event_mask; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_gap_clear_advertising(void) +{ + btc_msg_t msg; + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_ACT_CLEAR_ADV; + + return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_gap_set_csa_support(uint8_t csa_select) +{ + btc_msg_t msg; + btc_ble_gap_args_t arg; + + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_SET_CSA_SUPPORT; + + arg.set_csa_support.csa_select = csa_select; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // (BLE_VENDOR_HCI_EN == TRUE) + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +esp_err_t esp_ble_gap_enhanced_read_transmit_power_level(uint16_t conn_handle, esp_ble_tx_power_phy_t phy) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_ENH_READ_TRANS_POWER_LEVEL; + arg.enh_read_trans_pwr_level.conn_handle = conn_handle; + arg.enh_read_trans_pwr_level.phy = phy; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_gap_read_remote_transmit_power_level(uint16_t conn_handle, esp_ble_tx_power_phy_t phy) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_READ_REM_TRANS_POWER_LEVEL; + arg.read_rem_trans_pwr_level.conn_handle = conn_handle; + arg.read_rem_trans_pwr_level.phy = phy; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_gap_set_path_loss_reporting_params(esp_ble_path_loss_rpt_params_t *path_loss_rpt_params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_SET_PATH_LOSS_REPORT_PARAMS; + arg.set_path_loss_rpt_params.conn_handle = path_loss_rpt_params->conn_handle; + arg.set_path_loss_rpt_params.high_threshold = path_loss_rpt_params->high_threshold; + arg.set_path_loss_rpt_params.high_hysteresis = path_loss_rpt_params->high_hysteresis; + arg.set_path_loss_rpt_params.low_threshold = path_loss_rpt_params->low_threshold; + arg.set_path_loss_rpt_params.low_hysteresis = path_loss_rpt_params->low_hysteresis; + arg.set_path_loss_rpt_params.min_time_spent = path_loss_rpt_params->min_time_spent; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_gap_set_path_loss_reporting_enable(uint16_t conn_handle, bool enable) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_SET_PATH_LOSS_REPORTING_EN; + arg.set_path_loss_rpt_en.conn_handle = conn_handle; + arg.set_path_loss_rpt_en.enable = enable; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_gap_set_transmit_power_reporting_enable(uint16_t conn_handle, bool local_enable, bool remote_enable) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_SET_TRANS_POWER_REPORTING_EN; + arg.set_trans_pwr_rpting_en.conn_handle = conn_handle; + arg.set_trans_pwr_rpting_en.local_enable = local_enable; + arg.set_trans_pwr_rpting_en.remote_enable = remote_enable; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +esp_err_t esp_ble_gap_set_default_subrate(esp_ble_default_subrate_param_t *default_subrate_params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (!default_subrate_params) { + return ESP_ERR_NOT_ALLOWED; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_SET_DEFALT_SUBRATE; + + arg.default_subrate_param.subrate_min = default_subrate_params->subrate_min; + arg.default_subrate_param.subrate_max = default_subrate_params->subrate_max; + arg.default_subrate_param.max_latency = default_subrate_params->max_latency; + arg.default_subrate_param.continuation_number = default_subrate_params->continuation_number; + arg.default_subrate_param.supervision_timeout = default_subrate_params->supervision_timeout; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_gap_subrate_request(esp_ble_subrate_req_param_t *subrate_req_params) +{ + btc_msg_t msg = {0}; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (!subrate_req_params) { + return ESP_ERR_NOT_ALLOWED; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_SUBRATE_REQUEST; + + arg.subrate_req_param.conn_handle = subrate_req_params->conn_handle; + arg.subrate_req_param.subrate_min = subrate_req_params->subrate_min; + arg.subrate_req_param.subrate_max = subrate_req_params->subrate_max; + arg.subrate_req_param.max_latency = subrate_req_params->max_latency; + arg.subrate_req_param.continuation_number = subrate_req_params->continuation_number; + arg.subrate_req_param.supervision_timeout = subrate_req_params->supervision_timeout; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + +#if (BLE_50_FEATURE_SUPPORT == TRUE) +esp_err_t esp_ble_gap_set_host_feature(uint16_t bit_num, uint8_t bit_val) +{ + btc_msg_t msg; + btc_ble_5_gap_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + +#if (BLE_FEAT_ISO_60_EN == TRUE) + if (bit_num > 0x07BF) { + return ESP_ERR_INVALID_ARG; + } +#else + if (bit_num > 0xFF) { + return ESP_ERR_INVALID_ARG; + } +#endif + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_ACT_SET_HOST_FEATURE; + + arg.set_host_feature_params.bit_num = bit_num; + arg.set_host_feature_params.bit_val = bit_val; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_5_gap_args_t), NULL, NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif //#if (BLE_50_FEATURE_SUPPORT == TRUE) diff --git a/lib/bt/host/bluedroid/api/esp_gap_bt_api.c b/lib/bt/host/bluedroid/api/esp_gap_bt_api.c index 5973a663..86619430 100644 --- a/lib/bt/host/bluedroid/api/esp_gap_bt_api.c +++ b/lib/bt/host/bluedroid/api/esp_gap_bt_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -184,6 +184,7 @@ esp_err_t esp_bt_gap_set_cod(esp_bt_cod_t cod, esp_bt_cod_mode_t mode) } switch (mode) { + case ESP_BT_SET_COD_RESERVED_2: case ESP_BT_SET_COD_MAJOR_MINOR: case ESP_BT_SET_COD_SERVICE_CLASS: case ESP_BT_CLR_COD_SERVICE_CLASS: @@ -321,7 +322,7 @@ esp_err_t esp_bt_gap_set_security_param(esp_bt_sp_param_t param_type, return ESP_ERR_INVALID_STATE; } - if (!(bluedriod_config_get()->get_ssp_enabled())) { + if (!(bluedroid_config_get()->get_ssp_enabled())) { ESP_LOGE(TAG, "%s is not supported when `ssp_en` in `esp_bluedroid_config_t` is disabled!", __func__); return ESP_ERR_NOT_SUPPORTED; } @@ -346,7 +347,7 @@ esp_err_t esp_bt_gap_ssp_passkey_reply(esp_bd_addr_t bd_addr, bool accept, uint3 return ESP_ERR_INVALID_STATE; } - if (!(bluedriod_config_get()->get_ssp_enabled())) { + if (!(bluedroid_config_get()->get_ssp_enabled())) { ESP_LOGE(TAG, "%s is not supported when `ssp_en` in `esp_bluedroid_config_t` is disabled!", __func__); return ESP_ERR_NOT_SUPPORTED; } @@ -370,7 +371,7 @@ esp_err_t esp_bt_gap_ssp_confirm_reply(esp_bd_addr_t bd_addr, bool accept) return ESP_ERR_INVALID_STATE; } - if (!(bluedriod_config_get()->get_ssp_enabled())) { + if (!(bluedroid_config_get()->get_ssp_enabled())) { ESP_LOGE(TAG, "%s is not supported when `ssp_en` in `esp_bluedroid_config_t` is disabled!", __func__); return ESP_ERR_NOT_SUPPORTED; } @@ -553,4 +554,20 @@ esp_err_t esp_bt_gap_get_device_name(void) return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +esp_err_t esp_bt_gap_get_profile_status(esp_bt_gap_profile_status_t *profile_status) +{ + if (profile_status == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + memset(profile_status, 0, sizeof(esp_bt_gap_profile_status_t)); + btc_gap_bt_status_get(profile_status); + + return ESP_OK; +} + #endif /* #if BTC_GAP_BT_INCLUDED == TRUE */ diff --git a/lib/bt/host/bluedroid/api/esp_gattc_api.c b/lib/bt/host/bluedroid/api/esp_gattc_api.c index 5f078b28..83481a85 100644 --- a/lib/bt/host/bluedroid/api/esp_gattc_api.c +++ b/lib/bt/host/bluedroid/api/esp_gattc_api.c @@ -67,46 +67,134 @@ esp_err_t esp_ble_gattc_app_unregister(esp_gatt_if_t gattc_if) return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } -#if (BLE_42_FEATURE_SUPPORT == TRUE) -esp_err_t esp_ble_gattc_open(esp_gatt_if_t gattc_if, esp_bd_addr_t remote_bda, esp_ble_addr_type_t remote_addr_type, bool is_direct) + +esp_err_t esp_ble_gattc_enh_open(esp_gatt_if_t gattc_if, esp_ble_gatt_creat_conn_params_t *creat_conn_params) { btc_msg_t msg = {0}; btc_ble_gattc_args_t arg; + const esp_ble_conn_params_t *conn_params; ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (!creat_conn_params) { + return ESP_ERR_INVALID_ARG; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_OPEN; arg.open.gattc_if = gattc_if; - memcpy(arg.open.remote_bda, remote_bda, ESP_BD_ADDR_LEN); - arg.open.remote_addr_type = remote_addr_type; - arg.open.is_direct = is_direct; - arg.open.is_aux = false; + memcpy(arg.open.remote_bda, creat_conn_params->remote_bda, ESP_BD_ADDR_LEN); + arg.open.remote_addr_type = creat_conn_params->remote_addr_type; + arg.open.is_direct = creat_conn_params->is_direct; + arg.open.is_aux= creat_conn_params->is_aux; + arg.open.own_addr_type = creat_conn_params->own_addr_type; + arg.open.phy_mask = creat_conn_params->phy_mask; + + // If not aux open, shouldn't set 2M and coded PHY connection params + if (!creat_conn_params->is_aux && + ((creat_conn_params->phy_mask & ESP_BLE_PHY_2M_PREF_MASK) || + (creat_conn_params->phy_mask & ESP_BLE_PHY_CODED_PREF_MASK))) { + return ESP_ERR_INVALID_ARG; + } + + if (creat_conn_params->phy_mask & ESP_BLE_PHY_1M_PREF_MASK) { + if (!creat_conn_params->phy_1m_conn_params) { + return ESP_ERR_INVALID_ARG; + } + + conn_params = creat_conn_params->phy_1m_conn_params; + if (ESP_BLE_IS_VALID_PARAM(conn_params->interval_min, ESP_BLE_CONN_INT_MIN, ESP_BLE_CONN_INT_MAX) && + ESP_BLE_IS_VALID_PARAM(conn_params->interval_max, ESP_BLE_CONN_INT_MIN, ESP_BLE_CONN_INT_MAX) && + ESP_BLE_IS_VALID_PARAM(conn_params->supervision_timeout, ESP_BLE_CONN_SUP_TOUT_MIN, ESP_BLE_CONN_SUP_TOUT_MAX) && + (conn_params->latency <= ESP_BLE_CONN_LATENCY_MAX) && + ((conn_params->supervision_timeout * 10) >= ((1 + conn_params->latency) * ((conn_params->interval_max * 5) >> 1))) && + (conn_params->interval_min <= conn_params->interval_max)) { + memcpy(&arg.open.phy_1m_conn_params, conn_params, sizeof(esp_ble_conn_params_t)); + } else { + LOG_ERROR("%s, invalid 1M PHY connection params: min_int = %d, max_int = %d, latency = %d, timeout = %d", __func__, + conn_params->interval_min, + conn_params->interval_max, + conn_params->latency, + conn_params->supervision_timeout); + return ESP_ERR_INVALID_ARG; + } + } + + if (creat_conn_params->phy_mask & ESP_BLE_PHY_2M_PREF_MASK) { + if (!creat_conn_params->phy_2m_conn_params) { + return ESP_ERR_INVALID_ARG; + } + + conn_params = creat_conn_params->phy_2m_conn_params; + if (ESP_BLE_IS_VALID_PARAM(conn_params->interval_min, ESP_BLE_CONN_INT_MIN, ESP_BLE_CONN_INT_MAX) && + ESP_BLE_IS_VALID_PARAM(conn_params->interval_max, ESP_BLE_CONN_INT_MIN, ESP_BLE_CONN_INT_MAX) && + ESP_BLE_IS_VALID_PARAM(conn_params->supervision_timeout, ESP_BLE_CONN_SUP_TOUT_MIN, ESP_BLE_CONN_SUP_TOUT_MAX) && + (conn_params->latency <= ESP_BLE_CONN_LATENCY_MAX) && + ((conn_params->supervision_timeout * 10) >= ((1 + conn_params->latency) * ((conn_params->interval_max * 5) >> 1))) && + (conn_params->interval_min <= conn_params->interval_max)) { + memcpy(&arg.open.phy_2m_conn_params, conn_params, sizeof(esp_ble_conn_params_t)); + } else { + LOG_ERROR("%s, invalid 2M PHY connection params: min_int = %d, max_int = %d, latency = %d, timeout = %d", __func__, + conn_params->interval_min, + conn_params->interval_max, + conn_params->latency, + conn_params->supervision_timeout); + return ESP_ERR_INVALID_ARG; + } + } + + if (creat_conn_params->phy_mask & ESP_BLE_PHY_CODED_PREF_MASK) { + if (!creat_conn_params->phy_coded_conn_params) { + return ESP_ERR_INVALID_ARG; + } + + conn_params = creat_conn_params->phy_coded_conn_params; + if (ESP_BLE_IS_VALID_PARAM(conn_params->interval_min, ESP_BLE_CONN_INT_MIN, ESP_BLE_CONN_INT_MAX) && + ESP_BLE_IS_VALID_PARAM(conn_params->interval_max, ESP_BLE_CONN_INT_MIN, ESP_BLE_CONN_INT_MAX) && + ESP_BLE_IS_VALID_PARAM(conn_params->supervision_timeout, ESP_BLE_CONN_SUP_TOUT_MIN, ESP_BLE_CONN_SUP_TOUT_MAX) && + (conn_params->latency <= ESP_BLE_CONN_LATENCY_MAX) && + ((conn_params->supervision_timeout * 10) >= ((1 + conn_params->latency) * ((conn_params->interval_max * 5) >> 1))) && + (conn_params->interval_min <= conn_params->interval_max)) { + memcpy(&arg.open.phy_coded_conn_params, conn_params, sizeof(esp_ble_conn_params_t)); + } else { + LOG_ERROR("%s, invalid Coded PHY connection params: min_int = %d, max_int = %d, latency = %d, timeout = %d", __func__, + conn_params->interval_min, + conn_params->interval_max, + conn_params->latency, + conn_params->supervision_timeout); + return ESP_ERR_INVALID_ARG; + } + } return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } + +#if (BLE_42_FEATURE_SUPPORT == TRUE) +esp_err_t esp_ble_gattc_open(esp_gatt_if_t gattc_if, esp_bd_addr_t remote_bda, esp_ble_addr_type_t remote_addr_type, bool is_direct) +{ + esp_ble_gatt_creat_conn_params_t creat_conn_params = {0}; + memcpy(creat_conn_params.remote_bda, remote_bda, ESP_BD_ADDR_LEN); + creat_conn_params.remote_addr_type = remote_addr_type; + creat_conn_params.is_direct = is_direct; + creat_conn_params.is_aux = false; + creat_conn_params.own_addr_type = 0xff; //undefined, will use local value + creat_conn_params.phy_mask = 0x0; + return esp_ble_gattc_enh_open(gattc_if, &creat_conn_params); +} #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) #if (BLE_50_FEATURE_SUPPORT == TRUE) esp_err_t esp_ble_gattc_aux_open(esp_gatt_if_t gattc_if, esp_bd_addr_t remote_bda, esp_ble_addr_type_t remote_addr_type, bool is_direct) { - btc_msg_t msg; - btc_ble_gattc_args_t arg; - - ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); - - msg.sig = BTC_SIG_API_CALL; - msg.pid = BTC_PID_GATTC; - msg.act = BTC_GATTC_ACT_AUX_OPEN; - arg.open.gattc_if = gattc_if; - memcpy(arg.open.remote_bda, remote_bda, ESP_BD_ADDR_LEN); - arg.open.remote_addr_type = remote_addr_type; - arg.open.is_direct = is_direct; - arg.open.is_aux = true; - - return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gattc_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); - + esp_ble_gatt_creat_conn_params_t creat_conn_params = {0}; + memcpy(creat_conn_params.remote_bda, remote_bda, ESP_BD_ADDR_LEN); + creat_conn_params.remote_addr_type = remote_addr_type; + creat_conn_params.is_direct = is_direct; + creat_conn_params.is_aux = true; + creat_conn_params.own_addr_type = 0xff; //undefined, will use local value + creat_conn_params.phy_mask = 0x0; + return esp_ble_gattc_enh_open(gattc_if, &creat_conn_params); } #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) @@ -363,10 +451,14 @@ esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_READ_CHAR; @@ -400,10 +492,14 @@ esp_err_t esp_ble_gattc_read_by_type (esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } + if (start_handle == 0 || end_handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_READ_BY_TYPE; @@ -432,7 +528,7 @@ esp_err_t esp_ble_gattc_read_multiple(esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } @@ -468,7 +564,7 @@ esp_err_t esp_ble_gattc_read_multiple_variable(esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } @@ -504,10 +600,14 @@ esp_err_t esp_ble_gattc_read_char_descr (esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_READ_CHAR_DESCR; @@ -537,10 +637,14 @@ esp_err_t esp_ble_gattc_write_char(esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_WRITE_CHAR; @@ -576,10 +680,14 @@ esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_WRITE_CHAR_DESCR; @@ -615,10 +723,14 @@ esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_PREPARE_WRITE; @@ -652,10 +764,14 @@ esp_err_t esp_ble_gattc_prepare_write_char_descr(esp_gatt_if_t gattc_if, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_PREPARE_WRITE_CHAR_DESCR; @@ -694,6 +810,10 @@ esp_err_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_REG_FOR_NOTIFY; @@ -712,6 +832,10 @@ esp_err_t esp_ble_gattc_unregister_for_notify (esp_gatt_if_t gattc_if, ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (handle == 0) { + return ESP_GATT_INVALID_HANDLE; + } + msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GATTC; msg.act = BTC_GATTC_ACT_UNREG_FOR_NOTIFY; diff --git a/lib/bt/host/bluedroid/api/esp_gatts_api.c b/lib/bt/host/bluedroid/api/esp_gatts_api.c index 66fa5c66..03c81860 100644 --- a/lib/bt/host/bluedroid/api/esp_gatts_api.c +++ b/lib/bt/host/bluedroid/api/esp_gatts_api.c @@ -260,6 +260,11 @@ esp_err_t esp_ble_gatts_stop_service(uint16_t service_handle) esp_err_t esp_ble_gatts_send_indicate(esp_gatt_if_t gatts_if, uint16_t conn_id, uint16_t attr_handle, uint16_t value_len, uint8_t *value, bool need_confirm) { + if (value_len > ESP_GATT_MAX_ATTR_LEN) { + LOG_ERROR("%s, value_len > ESP_GATT_MAX_ATTR_LEN.", __func__); + return ESP_ERR_INVALID_SIZE; + } + btc_msg_t msg = {0}; btc_ble_gatts_args_t arg; @@ -272,7 +277,7 @@ esp_err_t esp_ble_gatts_send_indicate(esp_gatt_if_t gatts_if, uint16_t conn_id, } if (L2CA_CheckIsCongest(L2CAP_ATT_CID, p_tcb->peer_bda)) { - LOG_DEBUG("%s, the l2cap chanel is congest.", __func__); + LOG_DEBUG("%s, the l2cap channel is congest.", __func__); return ESP_FAIL; } diff --git a/lib/bt/host/bluedroid/api/esp_hf_ag_api.c b/lib/bt/host/bluedroid/api/esp_hf_ag_api.c index 6eb6a6b5..af3ddb4a 100644 --- a/lib/bt/host/bluedroid/api/esp_hf_ag_api.c +++ b/lib/bt/host/bluedroid/api/esp_hf_ag_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -528,6 +528,23 @@ esp_err_t esp_hf_ag_out_call(esp_bd_addr_t remote_addr, int num_active, int num_ return (status == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } +esp_err_t esp_hf_ag_get_profile_status(esp_hf_profile_status_t *profile_status) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + if (profile_status == NULL) { + return ESP_ERR_INVALID_ARG; + } + + memset(profile_status, 0, sizeof(esp_hf_profile_status_t)); + btc_hf_get_profile_status(profile_status); + + return ESP_OK; +} + +#if (BTM_SCO_HCI_INCLUDED == TRUE) + esp_err_t esp_hf_ag_register_data_callback(esp_hf_incoming_data_cb_t recv, esp_hf_outgoing_data_cb_t send) { if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { @@ -548,7 +565,73 @@ esp_err_t esp_hf_ag_register_data_callback(esp_hf_incoming_data_cb_t recv, esp_h return (status == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } -#if (BTM_SCO_HCI_INCLUDED == TRUE) +esp_err_t esp_hf_ag_register_audio_data_callback(esp_hf_ag_audio_data_cb_t callback) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF; + msg.act = BTC_HF_REGISTER_AUDIO_DATA_CALLBACK_EVT; + + btc_hf_args_t arg; + memset(&arg, 0, sizeof(btc_hf_args_t)); + arg.reg_audio_data_cb.callback = callback; + + /* Switch to BTC context */ + bt_status_t status = btc_transfer_context(&msg, &arg, sizeof(btc_hf_args_t), NULL, NULL); + return (status == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_hf_audio_buff_t *esp_hf_ag_audio_buff_alloc(uint16_t size) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return NULL; + } + + if (size == 0) { + return NULL; + } + + uint8_t *p_buf = NULL, *p_data; + BTA_AgAudioBuffAlloc(size, &p_buf, &p_data); + if (p_buf == NULL) { + return NULL; + } + + esp_hf_audio_buff_t *audio_buf = (esp_hf_audio_buff_t *)p_buf; + audio_buf->buff_size = size; + audio_buf->data_len = 0; + audio_buf->data = p_data; + return audio_buf; +} + +void esp_hf_ag_audio_buff_free(esp_hf_audio_buff_t *audio_buf) +{ + if (audio_buf == NULL) { + return; + } + BTA_AgAudioBuffFree((UINT8 *)audio_buf); +} + +esp_err_t esp_hf_ag_audio_data_send(esp_hf_sync_conn_hdl_t sync_conn_hdl, esp_hf_audio_buff_t *audio_buf) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (audio_buf == NULL || audio_buf->data_len == 0) { + return ESP_ERR_INVALID_ARG; + } + + if (btc_hf_ag_audio_data_send(sync_conn_hdl, (uint8_t *)audio_buf, audio_buf->data, audio_buf->data_len)) { + return ESP_OK; + } + return ESP_FAIL; +} + esp_err_t esp_hf_ag_pkt_stat_nums_get(uint16_t sync_conn_handle) { if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { diff --git a/lib/bt/host/bluedroid/api/esp_hf_client_api.c b/lib/bt/host/bluedroid/api/esp_hf_client_api.c index 9909f442..78347fc9 100644 --- a/lib/bt/host/bluedroid/api/esp_hf_client_api.c +++ b/lib/bt/host/bluedroid/api/esp_hf_client_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -515,6 +515,21 @@ esp_err_t esp_hf_client_register_data_callback(esp_hf_client_incoming_data_cb_t return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } +esp_err_t esp_hf_client_get_profile_status(esp_hf_client_profile_status_t *profile_status) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + if (profile_status == NULL) { + return ESP_ERR_INVALID_ARG; + } + + memset(profile_status, 0, sizeof(esp_hf_client_profile_status_t)); + btc_hf_client_get_profile_status(profile_status); + + return ESP_OK; +} + #if (BTM_SCO_HCI_INCLUDED == TRUE) esp_err_t esp_hf_client_pkt_stat_nums_get(uint16_t sync_conn_handle) { @@ -541,6 +556,71 @@ void esp_hf_client_outgoing_data_ready(void) BTA_HfClientCiData(); } +esp_err_t esp_hf_client_register_audio_data_callback(esp_hf_client_audio_data_cb_t callback) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_REGISTER_AUDIO_DATA_CALLBACK_EVT; + + btc_hf_client_args_t arg; + memset(&arg, 0, sizeof(btc_hf_client_args_t)); + arg.reg_audio_data_cb.callback = callback; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_hf_audio_buff_t *esp_hf_client_audio_buff_alloc(uint16_t size) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return NULL; + } + + if (size == 0) { + return NULL; + } + + uint8_t *p_buf = NULL, *p_data; + BTA_HfClientAudioBuffAlloc(size, &p_buf, &p_data); + if (p_buf == NULL) { + return NULL; + } + + esp_hf_audio_buff_t *audio_buf = (esp_hf_audio_buff_t *)p_buf; + audio_buf->buff_size = size; + audio_buf->data_len = 0; + audio_buf->data = p_data; + return audio_buf; +} + +void esp_hf_client_audio_buff_free(esp_hf_audio_buff_t *audio_buf) +{ + if (audio_buf == NULL) { + return; + } + BTA_HfClientAudioBuffFree((UINT8 *)audio_buf); +} + +esp_err_t esp_hf_client_audio_data_send(esp_hf_sync_conn_hdl_t sync_conn_hdl, esp_hf_audio_buff_t *audio_buf) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (audio_buf == NULL || audio_buf->data_len == 0) { + return ESP_ERR_INVALID_ARG; + } + + BTA_HfClientAudioDataSend(sync_conn_hdl, (uint8_t *)audio_buf, audio_buf->data, audio_buf->data_len); + return ESP_OK; +} + void esp_hf_client_pcm_resample_init(uint32_t src_sps, uint32_t bits, uint32_t channels) { BTA_DmPcmInitSamples(src_sps, bits, channels); diff --git a/lib/bt/host/bluedroid/api/esp_hidd_api.c b/lib/bt/host/bluedroid/api/esp_hidd_api.c index 2906e7a8..d7c04366 100644 --- a/lib/bt/host/bluedroid/api/esp_hidd_api.c +++ b/lib/bt/host/bluedroid/api/esp_hidd_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 * @@ -167,4 +167,17 @@ esp_err_t esp_bt_hid_device_virtual_cable_unplug(void) return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } +esp_err_t esp_bt_hid_device_get_profile_status(esp_hidd_profile_status_t *profile_status) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (profile_status == NULL) { + return ESP_ERR_INVALID_ARG; + } + + memset(profile_status, 0, sizeof(esp_hidd_profile_status_t)); + btc_hd_get_profile_status(profile_status); + + return ESP_OK; +} + #endif /* defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE */ diff --git a/lib/bt/host/bluedroid/api/esp_hidh_api.c b/lib/bt/host/bluedroid/api/esp_hidh_api.c index f9959c39..e029ee65 100644 --- a/lib/bt/host/bluedroid/api/esp_hidh_api.c +++ b/lib/bt/host/bluedroid/api/esp_hidh_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 * @@ -247,4 +247,17 @@ esp_err_t esp_bt_hid_host_send_data(esp_bd_addr_t bd_addr, uint8_t *data, size_t return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } +esp_err_t esp_bt_hid_host_get_profile_status(esp_hidh_profile_status_t *profile_status) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (profile_status == NULL) { + return ESP_ERR_INVALID_ARG; + } + + memset(profile_status, 0, sizeof(esp_hidh_profile_status_t)); + btc_hh_get_profile_status(profile_status); + + return ESP_OK; +} + #endif /* defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE */ diff --git a/lib/bt/host/bluedroid/api/esp_l2cap_bt_api.c b/lib/bt/host/bluedroid/api/esp_l2cap_bt_api.c index c78d6f8d..54f79396 100644 --- a/lib/bt/host/bluedroid/api/esp_l2cap_bt_api.c +++ b/lib/bt/host/bluedroid/api/esp_l2cap_bt_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -116,16 +116,39 @@ esp_err_t esp_bt_l2cap_stop_srv(uint16_t local_psm) esp_err_t esp_bt_l2cap_vfs_register(void) { + btc_msg_t msg; ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); - return btc_l2cap_vfs_register(); + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_L2CAP; + msg.act = BTC_L2CAP_ACT_VFS_REGISTER; + + return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } esp_err_t esp_bt_l2cap_vfs_unregister(void) +{ + btc_msg_t msg; + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_L2CAP; + msg.act = BTC_L2CAP_ACT_VFS_UNREGISTER; + + return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_bt_l2cap_get_protocol_status(esp_bt_l2cap_protocol_status_t *status) { ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (status == NULL) { + return ESP_ERR_INVALID_ARG; + } - return btc_l2cap_vfs_unregister(); + memset(status, 0, sizeof(esp_bt_l2cap_protocol_status_t)); + btc_l2cap_get_protocol_status(status); + + return ESP_OK; } #endif ///defined BTC_L2CAP_INCLUDED && BTC_L2CAP_INCLUDED == TRUE diff --git a/lib/bt/host/bluedroid/api/esp_pbac_api.c b/lib/bt/host/bluedroid/api/esp_pbac_api.c new file mode 100644 index 00000000..3799038f --- /dev/null +++ b/lib/bt/host/bluedroid/api/esp_pbac_api.c @@ -0,0 +1,251 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_err.h" +#include "esp_bt_main.h" +#include "esp_pbac_api.h" +#include "btc/btc_manage.h" +#include "btc_pba_client.h" + +#if BTC_PBA_CLIENT_INCLUDED + +esp_err_t esp_pbac_init(void) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PBA_CLIENT; + msg.act = BTC_PBA_CLIENT_INIT_EVT; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_pbac_deinit(void) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PBA_CLIENT; + msg.act = BTC_PBA_CLIENT_DEINIT_EVT; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_pbac_register_callback(esp_pbac_callback_t callback) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (callback == NULL) { + return ESP_FAIL; + } + + btc_profile_cb_set(BTC_PID_PBA_CLIENT, callback); + return ESP_OK; +} + +esp_err_t esp_pbac_connect(esp_bd_addr_t bd_addr) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (bd_addr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PBA_CLIENT; + msg.act = BTC_PBA_CLIENT_CONNECT_EVT; + + btc_pba_client_args_t args = {0}; + memcpy(args.connect.bd_addr.address, bd_addr, sizeof(esp_bd_addr_t)); + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_pba_client_args_t), NULL, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_pbac_disconnect(esp_pbac_conn_hdl_t handle) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (handle == ESP_PBAC_INVALID_HANDLE) { + return ESP_ERR_INVALID_ARG; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PBA_CLIENT; + msg.act = BTC_PBA_CLIENT_DISCONNECT_EVT; + + btc_pba_client_args_t args = {0}; + args.disconnect.handle = handle; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_pba_client_args_t), NULL, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + + +esp_err_t esp_pbac_pull_phone_book(esp_pbac_conn_hdl_t handle, const char *name, esp_pbac_pull_phone_book_app_param_t *app_param) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (handle == ESP_PBAC_INVALID_HANDLE || name == NULL) { + return ESP_ERR_INVALID_ARG; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PBA_CLIENT; + msg.act = BTC_PBA_CLIENT_PULL_PHONE_BOOK_EVT; + + btc_pba_client_args_t args = {0}; + args.pull_phone_book.handle = handle; + args.pull_phone_book.name = (char *)name; + if (app_param != NULL) { + args.pull_phone_book.include_app_param = true; + memcpy(&args.pull_phone_book.app_param, app_param, sizeof(esp_pbac_pull_phone_book_app_param_t)); + } + else { + args.pull_phone_book.include_app_param = false; + } + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_pba_client_args_t), btc_pba_client_args_deep_copy, btc_pba_client_args_deep_free); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_pbac_set_phone_book(esp_pbac_conn_hdl_t handle, esp_pbac_set_phone_book_flags_t flags, const char *name) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + /* since ESP_PBAC_SET_PHONE_BOOK_FLAGS_ROOT is equal to ESP_PBAC_SET_PHONE_BOOK_FLAGS_DOWN, we dont check XXX_DOWN */ + if (handle == ESP_PBAC_INVALID_HANDLE || (flags != ESP_PBAC_SET_PHONE_BOOK_FLAGS_ROOT && flags != ESP_PBAC_SET_PHONE_BOOK_FLAGS_UP)) { + return ESP_ERR_INVALID_ARG; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PBA_CLIENT; + msg.act = BTC_PBA_CLIENT_SET_PHONE_BOOK_EVT; + + btc_pba_client_args_t args = {0}; + args.set_phone_book.handle = handle; + args.set_phone_book.flags = flags; + /* set phone book name is allowed to be NULL */ + args.set_phone_book.name = (char *)name; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_pba_client_args_t), btc_pba_client_args_deep_copy, btc_pba_client_args_deep_free); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_pbac_set_phone_book2(esp_pbac_conn_hdl_t handle, const char *path) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PBA_CLIENT; + msg.act = BTC_PBA_CLIENT_SET_PHONE_BOOK2_EVT; + + btc_pba_client_args_t args = {0}; + args.set_phone_book.handle = handle; + args.set_phone_book.name = (char *)path; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_pba_client_args_t), btc_pba_client_args_deep_copy, btc_pba_client_args_deep_free); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_pbac_pull_vcard_listing(esp_pbac_conn_hdl_t handle, const char *name, esp_pbac_pull_vcard_listing_app_param_t *app_param) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (handle == ESP_PBAC_INVALID_HANDLE || name == NULL) { + return ESP_ERR_INVALID_ARG; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PBA_CLIENT; + msg.act = BTC_PBA_CLIENT_PULL_VCARD_LISTING_EVT; + + btc_pba_client_args_t args = {0}; + args.pull_vcard_listing.handle = handle; + args.pull_vcard_listing.name = (char *)name; + if (app_param != NULL) { + args.pull_vcard_listing.include_app_param = true; + memcpy(&args.pull_vcard_listing.app_param, app_param, sizeof(esp_pbac_pull_vcard_listing_app_param_t)); + } + else { + args.pull_vcard_listing.include_app_param = false; + } + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_pba_client_args_t), btc_pba_client_args_deep_copy, btc_pba_client_args_deep_free); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_pbac_pull_vcard_entry(esp_pbac_conn_hdl_t handle, const char *name, esp_pbac_pull_vcard_entry_app_param_t *app_param) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (handle == ESP_PBAC_INVALID_HANDLE || name == NULL) { + return ESP_ERR_INVALID_ARG; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PBA_CLIENT; + msg.act = BTC_PBA_CLIENT_PULL_VCARD_ENTRY_EVT; + + btc_pba_client_args_t args = {0}; + args.pull_vcard_entry.handle = handle; + args.pull_vcard_entry.name = (char *)name; + if (app_param != NULL) { + args.pull_vcard_entry.include_app_param = true; + memcpy(&args.pull_vcard_entry.app_param, app_param, sizeof(esp_pbac_pull_vcard_entry_app_param_t)); + } + else { + args.pull_vcard_entry.include_app_param = false; + } + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_pba_client_args_t), btc_pba_client_args_deep_copy, btc_pba_client_args_deep_free); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +#endif diff --git a/lib/bt/host/bluedroid/api/esp_sdp_api.c b/lib/bt/host/bluedroid/api/esp_sdp_api.c index c47c5ba5..41e143a2 100644 --- a/lib/bt/host/bluedroid/api/esp_sdp_api.c +++ b/lib/bt/host/bluedroid/api/esp_sdp_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,12 +8,61 @@ #include "esp_bt_main.h" #include "btc/btc_manage.h" +#include "stack/sdpdefs.h" #include "btc_sdp.h" #include "esp_sdp_api.h" #include "common/bt_target.h" -#if (defined BTC_SDP_INCLUDED && BTC_SDP_INCLUDED == TRUE) +#if (defined BTC_SDP_COMMON_INCLUDED && BTC_SDP_COMMON_INCLUDED == TRUE) + +static bool esp_sdp_record_integrity_check(esp_bluetooth_sdp_record_t *record) +{ + bool ret = true; + + if (record != NULL) { + if (record->hdr.type < ESP_SDP_TYPE_RAW || record->hdr.type > ESP_SDP_TYPE_DIP_SERVER) { + LOG_ERROR("Invalid type!\n"); + return false; + } + switch (record->hdr.type) { + case ESP_SDP_TYPE_DIP_SERVER: + if (record->dip.vendor_id_source != ESP_SDP_VENDOR_ID_SRC_BT && + record->dip.vendor_id_source != ESP_SDP_VENDOR_ID_SRC_USB) { + LOG_ERROR("Invalid vendor_id_source!\n"); + ret = false; + } + break; + case ESP_SDP_TYPE_MAP_MAS: + if ((record->mas.mas_instance_id >> 8) || (record->mas.supported_message_types >> 8)) { + LOG_ERROR("mas_instance_id and supported_message_types are defined as uint8_t in the spec!\n"); + ret = false; + } + break; + case ESP_SDP_TYPE_PBAP_PSE: + if (record->pse.supported_repositories >> 8) { + LOG_ERROR("supported_repositories is defined in the spec as uint8_t!\n"); + ret = false; + } + break; + + default: + break; + } + if (record->hdr.type != ESP_SDP_TYPE_DIP_SERVER) { + if (record->hdr.service_name_length > ESP_SDP_SERVER_NAME_MAX || + strlen(record->hdr.service_name) + 1 != record->hdr.service_name_length) { + LOG_ERROR("Invalid server name!\n"); + ret = false; + } + } + } else { + LOG_ERROR("record is NULL!\n"); + ret = false; + } + + return ret; +} esp_err_t esp_sdp_register_callback(esp_sdp_cb_t callback) { @@ -85,9 +134,7 @@ esp_err_t esp_sdp_create_record(esp_bluetooth_sdp_record_t *record) { ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); - if (record == NULL || record->hdr.service_name_length > ESP_SDP_SERVER_NAME_MAX - || strlen(record->hdr.service_name)+1 != record->hdr.service_name_length) { - LOG_ERROR("Invalid server name!\n"); + if (!esp_sdp_record_integrity_check(record)) { return ESP_ERR_INVALID_ARG; } @@ -100,7 +147,7 @@ esp_err_t esp_sdp_create_record(esp_bluetooth_sdp_record_t *record) msg.act = BTC_SDP_ACT_CREATE_RECORD; memset(&arg, 0, sizeof(btc_sdp_args_t)); - arg.creat_record.record = (bluetooth_sdp_record *)record; + arg.create_record.record = (bluetooth_sdp_record *)record; /* Switch to BTC context */ stat = btc_transfer_context(&msg, &arg, sizeof(btc_sdp_args_t), @@ -127,4 +174,17 @@ esp_err_t esp_sdp_remove_record(int record_handle) return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; } -#endif ///defined BTC_SDP_INCLUDED && BTC_SDP_INCLUDED == TRUE +esp_err_t esp_sdp_get_protocol_status(esp_sdp_protocol_status_t *status) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (status == NULL) { + return ESP_ERR_INVALID_ARG; + } + + memset(status, 0, sizeof(esp_sdp_protocol_status_t)); + btc_sdp_get_protocol_status(status); + + return ESP_OK; +} + +#endif ///defined BTC_SDP_COMMON_INCLUDED && BTC_SDP_COMMON_INCLUDED == TRUE diff --git a/lib/bt/host/bluedroid/api/esp_spp_api.c b/lib/bt/host/bluedroid/api/esp_spp_api.c index fce84be0..5c01aeb2 100644 --- a/lib/bt/host/bluedroid/api/esp_spp_api.c +++ b/lib/bt/host/bluedroid/api/esp_spp_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -252,4 +252,17 @@ esp_err_t esp_spp_vfs_unregister(void) return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +esp_err_t esp_spp_get_profile_status(esp_spp_profile_status_t *profile_status) +{ + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (profile_status == NULL) { + return ESP_ERR_INVALID_ARG; + } + + memset(profile_status, 0, sizeof(esp_spp_profile_status_t)); + btc_spp_get_profile_status(profile_status); + + return ESP_OK; +} + #endif ///defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE diff --git a/lib/bt/host/bluedroid/api/include/api/esp_a2dp_api.h b/lib/bt/host/bluedroid/api/include/api/esp_a2dp_api.h index 7020750c..71d3d597 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_a2dp_api.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_a2dp_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,11 +9,16 @@ #include "esp_err.h" #include "esp_bt_defs.h" +#include "esp_a2dp_legacy_api.h" #ifdef __cplusplus extern "C" { #endif +#define ESP_A2D_MAX_SEPS 1 /*!< Maximum number of Stream Endpoint that supported */ + +typedef uint16_t esp_a2d_conn_hdl_t; /*!< Connection handle, associate with specific device that connected */ + /** * @brief Media codec types supported by A2DP. */ @@ -30,6 +35,102 @@ typedef uint8_t esp_a2d_mct_t; #define ESP_A2D_PSC_DELAY_RPT (1<<0) /*!< Delay Report */ typedef uint16_t esp_a2d_psc_t; +/** + * @brief A2DP SBC sampling frequency bit mask in CIE + */ +#define ESP_A2D_SBC_CIE_SF_16K (0x8) /*!< SBC sampling frequency 16kHz */ +#define ESP_A2D_SBC_CIE_SF_32K (0x4) /*!< SBC sampling frequency 32kHz */ +#define ESP_A2D_SBC_CIE_SF_44K (0x2) /*!< SBC sampling frequency 44.1kHz */ +#define ESP_A2D_SBC_CIE_SF_48K (0x1) /*!< SBC sampling frequency 48kHz */ + +/** + * @brief A2DP SBC channel mode bit mask in CIE + */ +#define ESP_A2D_SBC_CIE_CH_MODE_MONO (0x8) /*!< SBC channel mode Mono */ +#define ESP_A2D_SBC_CIE_CH_MODE_DUAL_CHANNEL (0x4) /*!< SBC channel mode Dual Channel */ +#define ESP_A2D_SBC_CIE_CH_MODE_STEREO (0x2) /*!< SBC channel mode Stereo */ +#define ESP_A2D_SBC_CIE_CH_MODE_JOINT_STEREO (0x1) /*!< SBC channel mode Stereo */ + +/** + * @brief A2DP SBC block length bit mask in CIE + */ +#define ESP_A2D_SBC_CIE_BLOCK_LEN_4 (0x8) /*!< SBC block length 4 */ +#define ESP_A2D_SBC_CIE_BLOCK_LEN_8 (0x4) /*!< SBC block length 8 */ +#define ESP_A2D_SBC_CIE_BLOCK_LEN_12 (0x2) /*!< SBC block length 12 */ +#define ESP_A2D_SBC_CIE_BLOCK_LEN_16 (0x1) /*!< SBC block length 16 */ + +/** + * @brief A2DP SBC number of subbands bit mask in CIE + */ +#define ESP_A2D_SBC_CIE_NUM_SUBBANDS_4 (0x2) /*!< SBC number of subbands 4 */ +#define ESP_A2D_SBC_CIE_NUM_SUBBANDS_8 (0x1) /*!< SBC number of subbands 8 */ + +/** + * @brief A2DP SBC allocation method bit mask in CIE + */ +#define ESP_A2D_SBC_CIE_ALLOC_MTHD_SRN (0x2) /*!< SBC allocation method SNR */ +#define ESP_A2D_SBC_CIE_ALLOC_MTHD_LOUDNESS (0x1) /*!< SBC allocation method Loudness */ + +/** + * @brief A2DP SBC media codec capabilities information struct + */ +typedef struct { + uint8_t ch_mode : 4; /*!< Channel mode */ + uint8_t samp_freq : 4; /*!< Sampling frequency */ + uint8_t alloc_mthd : 2; /*!< Allocation method */ + uint8_t num_subbands : 2; /*!< Number of subbands */ + uint8_t block_len : 4; /*!< Block length */ + uint8_t min_bitpool; /*!< Minimum bitpool */ + uint8_t max_bitpool; /*!< Maximum bitpool */ +} __attribute__((packed)) esp_a2d_cie_sbc_t; + +/** + * @brief A2DP MPEG-1, 2 media codec capabilities information struct (Not supported yet) + */ +typedef struct { + uint8_t ch_mode : 4; /*!< Channel mode */ + uint8_t crc : 1; /*!< CRC protection */ + uint8_t layer : 3; /*!< Layers of MPEG-1,2 Audio */ + uint8_t samp_freq : 6; /*!< Sampling frequency */ + uint8_t mpf : 1; /*!< Media payload format */ + uint8_t rfu : 1; /*!< Reserved */ + uint8_t bri1 : 7; /*!< Bit rate index part 1 */ + uint8_t vbr : 1; /*!< Support of VBR */ + uint8_t bri2; /*!< Bit rate index part 2 */ +} __attribute__((packed)) esp_a2d_cie_m12_t; + +/** + * @brief A2DP MPEG-2, 4 media codec capabilities information struct (Not supported yet) + */ +typedef struct { + uint8_t drc : 1; /*!< Support of MPEG-D DRC */ + uint8_t obj_type : 7; /*!< Object type */ + uint8_t samp_freq1 : 8; /*!< Sampling frequency part 1 */ + uint8_t ch : 4; /*!< Channels */ + uint8_t samp_freq2 : 4; /*!< Sampling frequency part 2 */ + uint8_t br1 : 7; /*!< Bit rate part 1 */ + uint8_t vbr : 1; /*!< Support of VBR */ + uint8_t br2; /*!< Bit rate part 2 */ + uint8_t br3; /*!< Bit rate part 3 */ +} __attribute__((packed)) esp_a2d_cie_m24_t; + +/** + * @brief A2DP ATRAC media codec capabilities information struct (Not supported yet) + */ +typedef struct { + uint8_t rfu1 : 2; /*!< Reserved */ + uint8_t ch_mode : 3; /*!< Channel mode */ + uint8_t version : 3; /*!< Version */ + uint8_t bri1 : 3; /*!< Bit rate index part 1 */ + uint8_t vbr : 1; /*!< Support of VBR */ + uint8_t samp_freq : 2; /*!< Sampling frequency */ + uint8_t rfu2 : 2; /*!< Reserved */ + uint8_t bri2; /*!< Bit rate index part 2 */ + uint8_t bri3; /*!< Bit rate index part 3 */ + uint16_t max_sul; /*!< Maximum SUL */ + uint8_t rfu3; /*!< Reserved */ +} __attribute__((packed)) esp_a2d_cie_atrac_t; + /** * @brief A2DP media codec capabilities union */ @@ -40,10 +141,15 @@ typedef struct { #define ESP_A2D_CIE_LEN_M24 (6) #define ESP_A2D_CIE_LEN_ATRAC (7) union { - uint8_t sbc[ESP_A2D_CIE_LEN_SBC]; /*!< SBC codec capabilities */ - uint8_t m12[ESP_A2D_CIE_LEN_M12]; /*!< MPEG-1,2 audio codec capabilities */ - uint8_t m24[ESP_A2D_CIE_LEN_M24]; /*!< MPEG-2, 4 AAC audio codec capabilities */ - uint8_t atrac[ESP_A2D_CIE_LEN_ATRAC]; /*!< ATRAC family codec capabilities */ + uint8_t sbc[ESP_A2D_CIE_LEN_SBC] __attribute__((deprecated)); /*!< SBC codec capabilities, deprecated, use sbc_info instead */ + uint8_t m12[ESP_A2D_CIE_LEN_M12] __attribute__((deprecated)); /*!< MPEG-1,2 audio codec capabilities, deprecated, use m12_info instead */ + uint8_t m24[ESP_A2D_CIE_LEN_M24] __attribute__((deprecated)); /*!< MPEG-2, 4 AAC audio codec capabilities, deprecated, use m24_info instead */ + uint8_t atrac[ESP_A2D_CIE_LEN_ATRAC] __attribute__((deprecated)); /*!< ATRAC family codec capabilities, deprecated, use atrac_info instead */ + + esp_a2d_cie_sbc_t sbc_info; /*!< SBC codec capabilities */ + esp_a2d_cie_m12_t m12_info; /*!< MPEG-1,2 audio codec capabilities */ + esp_a2d_cie_m24_t m24_info; /*!< MPEG-2, 4 AAC audio codec capabilities */ + esp_a2d_cie_atrac_t atrac_info; /*!< ATRAC family codec capabilities */ } cie; /*!< A2DP codec information element */ } __attribute__((packed)) esp_a2d_mcc_t; @@ -103,6 +209,16 @@ typedef enum { ESP_A2D_INIT_SUCCESS /*!< A2DP profile deinit successful event */ } esp_a2d_init_state_t; +/** + * @brief Bluetooth A2DP SEP register states + */ +typedef enum { + ESP_A2D_SEP_REG_SUCCESS = 0, /*!< A2DP stream endpoint register success */ + ESP_A2D_SEP_REG_FAIL, /*!< A2DP stream endpoint register generic fail */ + ESP_A2D_SEP_REG_UNSUPPORTED, /*!< A2DP stream endpoint register fail, unsupported codec type or param */ + ESP_A2D_SEP_REG_INVALID_STATE, /*!< A2DP stream endpoint register fail, invalid state */ +} esp_a2d_sep_reg_state_t; + /** * @brief Bluetooth A2DP set delay report value states */ @@ -111,21 +227,42 @@ typedef enum { ESP_A2D_SET_INVALID_PARAMS /*!< A2DP profile set delay report value is invalid parameter */ } esp_a2d_set_delay_value_state_t; +/** + * @brief A2DP profile status parameters + */ +typedef struct { + bool a2d_snk_inited; /*!< A2DP sink initialization */ + bool a2d_src_inited; /*!< A2DP source initialization */ + uint8_t conn_num; /*!< Number of connections */ +} esp_a2d_profile_status_t; + /** * @brief A2DP callback events */ typedef enum { ESP_A2D_CONNECTION_STATE_EVT = 0, /*!< connection state changed event */ ESP_A2D_AUDIO_STATE_EVT, /*!< audio stream transmission state changed event */ - ESP_A2D_AUDIO_CFG_EVT, /*!< audio codec is configured, only used for A2DP SINK */ + ESP_A2D_AUDIO_CFG_EVT, /*!< audio codec is configured */ ESP_A2D_MEDIA_CTRL_ACK_EVT, /*!< acknowledge event in response to media control commands */ ESP_A2D_PROF_STATE_EVT, /*!< indicate a2dp init&deinit complete */ + ESP_A2D_SEP_REG_STATE_EVT, /*!< indicate a2dp steam endpoint register status */ ESP_A2D_SNK_PSC_CFG_EVT, /*!< protocol service capabilities configured,only used for A2DP SINK */ ESP_A2D_SNK_SET_DELAY_VALUE_EVT, /*!< indicate a2dp sink set delay report value complete, only used for A2DP SINK */ ESP_A2D_SNK_GET_DELAY_VALUE_EVT, /*!< indicate a2dp sink get delay report value complete, only used for A2DP SINK */ ESP_A2D_REPORT_SNK_DELAY_VALUE_EVT, /*!< report delay value, only used for A2DP SRC */ } esp_a2d_cb_event_t; +/** + * @brief A2DP audio buffer + */ +typedef struct { + uint16_t buff_size; /*!< audio buff size */ + uint16_t number_frame; /*!< number of encoded frame in this buff */ + uint32_t timestamp; /*!< timestamp of the first frame */ + uint16_t data_len; /*!< audio data len */ + uint8_t *data; /*!< pointer to audio data start */ +} esp_a2d_audio_buff_t; /*!< struct to store audio data */ + /** * @brief A2DP state callback parameters */ @@ -136,6 +273,8 @@ typedef union { struct a2d_conn_stat_param { esp_a2d_connection_state_t state; /*!< one of values from esp_a2d_connection_state_t */ esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */ + esp_a2d_conn_hdl_t conn_hdl; /*!< connection handle */ + uint16_t audio_mtu; /*!< MTU of audio connection */ esp_a2d_disc_rsn_t disc_rsn; /*!< reason of disconnection for "DISCONNECTED" */ } conn_stat; /*!< A2DP connection status */ @@ -144,7 +283,8 @@ typedef union { */ struct a2d_audio_stat_param { esp_a2d_audio_state_t state; /*!< one of the values from esp_a2d_audio_state_t */ - esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */ + esp_bd_addr_t remote_bda; /*!< remote bluetooth device address*/ + esp_a2d_conn_hdl_t conn_hdl; /*!< connection handle */ } audio_stat; /*!< audio stream playing state */ /** @@ -152,6 +292,7 @@ typedef union { */ struct a2d_audio_cfg_param { esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */ + esp_a2d_conn_hdl_t conn_hdl; /*!< connection handle */ esp_a2d_mcc_t mcc; /*!< A2DP media codec capability information */ } audio_cfg; /*!< media codec configuration information */ @@ -170,6 +311,14 @@ typedef union { esp_a2d_init_state_t init_state; /*!< a2dp profile state param */ } a2d_prof_stat; /*!< status to indicate a2d prof init or deinit */ + /** + * @brief ESP_A2D_SEP_REG_STATE_EVT + */ + struct a2d_sep_reg_stat_param { + uint8_t seid; /*!< the stream endpoint to register */ + esp_a2d_sep_reg_state_t reg_state; /*!< stream endpoint register state */ + } a2d_sep_reg_stat; /*!< status to indicate a2d sep register success or not */ + /** * @brief ESP_A2D_SNK_PSC_CFG_EVT */ @@ -213,25 +362,31 @@ typedef void (* esp_a2d_cb_t)(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *para /** * @brief A2DP sink data callback function * - * @param[in] buf : pointer to the data received from A2DP source device and is PCM format decoded from SBC decoder; - * buf references to a static memory block and can be overwritten by upcoming data + * @param[in] conn_hdl: connection handle * - * @param[in] len : size(in bytes) in buf + * @param[in] audio_buf: pointer to the data received from A2DP source device, should be freed by + * calling esp_a2d_audio_buff_free */ -typedef void (* esp_a2d_sink_data_cb_t)(const uint8_t *buf, uint32_t len); +typedef void (* esp_a2d_sink_audio_data_cb_t)(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf); /** - * @brief A2DP source data read callback function + * @brief Allocate a audio buffer to store and send audio data, can be used in both sink and source. * - * @param[in] buf : buffer to be filled with PCM data stream from higher layer + * @param[in] size: buffer size to allocate * - * @param[in] len : size(in bytes) of data block to be copied to buf. -1 is an indication to user - * that data buffer shall be flushed + * @return allocated audio buffer, if Bluedroid is not enabled, no memory, or size is + * zeros, will return NULL + * + */ +esp_a2d_audio_buff_t *esp_a2d_audio_buff_alloc(uint16_t size); + +/** + * @brief Free a audio buffer allocated by esp_a2d_audio_buff_alloc. * - * @return size of bytes read successfully, if the argument len is -1, this value is ignored. + * @param[in] audio_buf: audio buffer to free * */ -typedef int32_t (* esp_a2d_source_data_cb_t)(uint8_t *buf, int32_t len); +void esp_a2d_audio_buff_free(esp_a2d_audio_buff_t *audio_buf); /** * @brief Register application callback function to A2DP module. This function should be called @@ -248,23 +403,20 @@ typedef int32_t (* esp_a2d_source_data_cb_t)(uint8_t *buf, int32_t len); */ esp_err_t esp_a2d_register_callback(esp_a2d_cb_t callback); - /** - * @brief Register A2DP sink data output function; For now the output is PCM data stream decoded - * from SBC format. This function should be called only after esp_bluedroid_enable() - * completes successfully, used only by A2DP sink. The callback is invoked in the context - * of A2DP sink task whose stack size is configurable through menuconfig. + * @brief Register A2DP sink audio data output function, the output format is undecoded audio data + * frame in esp_a2d_audio_buff_t, user shall call esp_a2d_audio_buff_free to free the buff + * when the data is consumed. * - * @param[in] callback: A2DP sink data callback function + * @param[in] callback: A2DP sink audio data callback function * * @return * - ESP_OK: success * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled - * - ESP_FAIL: if callback is a NULL function pointer + * - ESP_FAIL: others * */ -esp_err_t esp_a2d_sink_register_data_callback(esp_a2d_sink_data_cb_t callback); - +esp_err_t esp_a2d_sink_register_audio_data_callback(esp_a2d_sink_audio_data_cb_t callback); /** * @@ -282,6 +434,23 @@ esp_err_t esp_a2d_sink_register_data_callback(esp_a2d_sink_data_cb_t callback); */ esp_err_t esp_a2d_sink_init(void); +/** + * @brief Register a a2dp sink Stream Endpoint (SEP) with specific codec capability, shall register + * SEP after a2dp sink initializing and before a2dp connection establishing. Register the same + * SEP index repeatedly will overwrite the old one. + * + * @param[in] seid: local SEP identifier, start from 0, less than ESP_A2D_MAX_SEPS + * + * @param[in] mcc: codec capability, currently only supports SBC + * + * @return + * - ESP_OK: success + * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_ERR_INVALID_ARG: invalid parameter + * - ESP_FAIL: others + * + */ +esp_err_t esp_a2d_sink_register_stream_endpoint(uint8_t seid, const esp_a2d_mcc_t *mcc); /** * @@ -297,7 +466,6 @@ esp_err_t esp_a2d_sink_init(void); */ esp_err_t esp_a2d_sink_deinit(void); - /** * * @brief Connect to remote bluetooth A2DP source device. This API must be called after @@ -313,7 +481,6 @@ esp_err_t esp_a2d_sink_deinit(void); */ esp_err_t esp_a2d_sink_connect(esp_bd_addr_t remote_bda); - /** * * @brief Disconnect from the remote A2DP source device. This API must be called after @@ -359,7 +526,6 @@ esp_err_t esp_a2d_sink_set_delay_value(uint16_t delay_value); */ esp_err_t esp_a2d_sink_get_delay_value(void); - /** * * @brief Media control commands. This API can be used for both A2DP sink and source @@ -375,6 +541,17 @@ esp_err_t esp_a2d_sink_get_delay_value(void); */ esp_err_t esp_a2d_media_ctrl(esp_a2d_media_ctrl_t ctrl); +/** + * @brief This function is used to get the status of A2DP + * + * @param[out] profile_status - A2DP status + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_a2d_get_profile_status(esp_a2d_profile_status_t *profile_status); + /** * @@ -392,6 +569,23 @@ esp_err_t esp_a2d_media_ctrl(esp_a2d_media_ctrl_t ctrl); */ esp_err_t esp_a2d_source_init(void); +/** + * @brief Register a a2dp source Stream Endpoint (SEP) with specific codec capability, shall register + * SEP after a2dp source initializing and before a2dp connection establishing. Register the same + * SEP index repeatedly will overwrite the old one. + * + * @param[in] seid: local SEP identifier, start from 0, less than ESP_A2D_MAX_SEPS + * + * @param[in] mcc: codec capability, currently, only SBC supported + * + * @return + * - ESP_OK: success + * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_ERR_INVALID_ARG: invalid parameter + * - ESP_FAIL: others + * + */ +esp_err_t esp_a2d_source_register_stream_endpoint(uint8_t seid, const esp_a2d_mcc_t *mcc); /** * @@ -407,23 +601,24 @@ esp_err_t esp_a2d_source_init(void); */ esp_err_t esp_a2d_source_deinit(void); - /** - * @brief Register A2DP source data input function. For now, the input shoule be PCM data stream. - * This function should be called only after esp_bluedroid_enable() completes - * successfully. The callback is invoked in the context of A2DP source task whose - * stack size is configurable through menuconfig. + * @brief Send a audio buff with encoded audio data to sink, the audio data len shall not bigger than + * audio connection mtu (retrieved from ESP_A2D_CONNECTION_STATE_EVT). if the return value is + * ESP_OK, then the audio buff is consumed, otherwise, audio buff can be reused by user. + * + * @param[in] conn_hdl: connection handle * - * @param[in] callback: A2DP source data callback function + * @param[in] audio_buf: encoded audio data * * @return * - ESP_OK: success * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled - * - ESP_FAIL: if callback is a NULL function pointer + * - ESP_ERR_INVALID_ARG: invalid parameter + * - ESP_ERR_INVALID_SIZE: data len bigger than mtu + * - ESP_FAIL: buffer queue is full, try again later * */ -esp_err_t esp_a2d_source_register_data_callback(esp_a2d_source_data_cb_t callback); - +esp_err_t esp_a2d_source_audio_data_send(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf); /** * @@ -440,7 +635,6 @@ esp_err_t esp_a2d_source_register_data_callback(esp_a2d_source_data_cb_t callbac */ esp_err_t esp_a2d_source_connect(esp_bd_addr_t remote_bda); - /** * * @brief Disconnect from the remote A2DP sink device. This API must be called diff --git a/lib/bt/host/bluedroid/api/include/api/esp_a2dp_legacy_api.h b/lib/bt/host/bluedroid/api/include/api/esp_a2dp_legacy_api.h new file mode 100644 index 00000000..2e59d058 --- /dev/null +++ b/lib/bt/host/bluedroid/api/include/api/esp_a2dp_legacy_api.h @@ -0,0 +1,77 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Some legacy APIs of A2DP, will be removed in the future + */ + +#pragma once + +#include "esp_err.h" +#include "esp_bt_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief [Deprecated] A2DP sink data callback function + * + * @param[in] buf : pointer to the data received from A2DP source device and is PCM format decoded from SBC decoder; + * buf references to a static memory block and can be overwritten by upcoming data + * + * @param[in] len : size(in bytes) in buf + */ +typedef void (* esp_a2d_sink_data_cb_t)(const uint8_t *buf, uint32_t len); + +/** + * @brief [Deprecated] A2DP source data read callback function + * + * @param[in] buf : buffer to be filled with PCM data stream from higher layer + * + * @param[in] len : size(in bytes) of data block to be copied to buf. -1 is an indication to user + * that data buffer shall be flushed + * + * @return size of bytes read successfully, if the argument len is -1, this value is ignored. + * + */ +typedef int32_t (* esp_a2d_source_data_cb_t)(uint8_t *buf, int32_t len); + +/** + * @brief [Deprecated] Register A2DP sink data output function; For now the output is PCM data stream decoded + * from SBC format. This function should be called only after esp_bluedroid_enable() + * completes successfully, used only by A2DP sink. The callback is invoked in the context + * of A2DP sink task whose stack size is configurable through menuconfig. + * + * @param[in] callback: A2DP sink data callback function + * + * @return + * - ESP_OK: success + * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: if callback is a NULL function pointer + * + */ +esp_err_t esp_a2d_sink_register_data_callback(esp_a2d_sink_data_cb_t callback); + +/** + * @brief [Deprecated] Register A2DP source data input function. For now, the input should be PCM data stream. + * This function should be called only after esp_bluedroid_enable() completes + * successfully. The callback is invoked in the context of A2DP source task whose + * stack size is configurable through menuconfig. + * + * @param[in] callback: A2DP source data callback function + * + * @return + * - ESP_OK: success + * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: if callback is a NULL function pointer + * + */ +esp_err_t esp_a2d_source_register_data_callback(esp_a2d_source_data_cb_t callback); + +#ifdef __cplusplus +} +#endif diff --git a/lib/bt/host/bluedroid/api/include/api/esp_avrc_api.h b/lib/bt/host/bluedroid/api/include/api/esp_avrc_api.h index f226577e..6fae9c1b 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_avrc_api.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_avrc_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,6 +18,10 @@ extern "C" { #define ESP_AVRC_TRANS_LABEL_MAX 15 /*!< max transaction label */ +#define ESP_AVRC_CA_IMAGE_HANDLE_LEN 7 /* The image handle length is fixed to 7, specified by Basic Image Profile */ +#define ESP_AVRC_CA_MTU_MIN 255 /* Minimal MTU can be used in Cover Art OBEX connection */ +#define ESP_AVRC_CA_MTU_MAX 1691 /* Maximum MTU can be used in Cover Art OBEX connection */ + /// AVRC feature bit mask typedef enum { ESP_AVRC_FEAT_RCTG = 0x0001, /*!< remote control target */ @@ -30,14 +34,18 @@ typedef enum { /// AVRC supported features flag retrieved in SDP record typedef enum { + /* CT and TG common features flag */ ESP_AVRC_FEAT_FLAG_CAT1 = 0x0001, /*!< category 1 */ ESP_AVRC_FEAT_FLAG_CAT2 = 0x0002, /*!< category 2 */ ESP_AVRC_FEAT_FLAG_CAT3 = 0x0004, /*!< category 3 */ ESP_AVRC_FEAT_FLAG_CAT4 = 0x0008, /*!< category 4 */ ESP_AVRC_FEAT_FLAG_BROWSING = 0x0040, /*!< browsing */ - ESP_AVRC_FEAT_FLAG_COVER_ART_GET_IMAGE_PROP = 0x0080, /*!< Cover Art GetImageProperties */ - ESP_AVRC_FEAT_FLAG_COVER_ART_GET_IMAGE = 0x0100, /*!< Cover Art GetImage */ - ESP_AVRC_FEAT_FLAG_COVER_ART_GET_LINKED_THUMBNAIL = 0x0200, /*!< Cover Art GetLinkedThumbnail */ + /* CT only features flag */ + ESP_AVRC_FEAT_FLAG_COVER_ART_GET_IMAGE_PROP = 0x0080, /*!< CT support Cover Art GetImageProperties */ + ESP_AVRC_FEAT_FLAG_COVER_ART_GET_IMAGE = 0x0100, /*!< CT support Cover Art GetImage */ + ESP_AVRC_FEAT_FLAG_COVER_ART_GET_LINKED_THUMBNAIL = 0x0200, /*!< CT support Cover Art GetLinkedThumbnail */ + /* TG only features flag */ + ESP_AVRC_FEAT_FLAG_TG_COVER_ART = 0x0100, /*!< TG support Cover Art */ } esp_avrc_feature_flag_t; /// AVRC passthrough command code @@ -133,8 +141,11 @@ typedef enum { ESP_AVRC_CT_PLAY_STATUS_RSP_EVT = 3, /*!< play status response event */ ESP_AVRC_CT_CHANGE_NOTIFY_EVT = 4, /*!< notification event */ ESP_AVRC_CT_REMOTE_FEATURES_EVT = 5, /*!< feature of remote device indication event */ - ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT = 6, /*!< supported notification events capability of peer device */ + ESP_AVRC_CT_GET_RN_CAPABILITIES_RSP_EVT = 6, /*!< supported notification events capability of peer device */ ESP_AVRC_CT_SET_ABSOLUTE_VOLUME_RSP_EVT = 7, /*!< set absolute volume response event */ + ESP_AVRC_CT_COVER_ART_STATE_EVT = 8, /*!< cover art client connection state changed event */ + ESP_AVRC_CT_COVER_ART_DATA_EVT = 9, /*!< cover art client data event */ + ESP_AVRC_CT_PROF_STATE_EVT = 10, /*!< Indicate AVRCP controller init or deinit complete */ } esp_avrc_ct_cb_event_t; /// AVRC Target callback events @@ -145,6 +156,7 @@ typedef enum { ESP_AVRC_TG_SET_ABSOLUTE_VOLUME_CMD_EVT = 3, /*!< set absolute volume command from remote device */ ESP_AVRC_TG_REGISTER_NOTIFICATION_EVT = 4, /*!< register notification event */ ESP_AVRC_TG_SET_PLAYER_APP_VALUE_EVT = 5, /*!< set application attribute value, attribute refer to esp_avrc_ps_attr_ids_t */ + ESP_AVRC_TG_PROF_STATE_EVT = 6, /*!< Indicate AVRCP target init or deinit complete */ } esp_avrc_tg_cb_event_t; /// AVRC metadata attribute mask @@ -155,7 +167,8 @@ typedef enum { ESP_AVRC_MD_ATTR_TRACK_NUM = 0x8, /*!< track position on the album */ ESP_AVRC_MD_ATTR_NUM_TRACKS = 0x10, /*!< number of tracks on the album */ ESP_AVRC_MD_ATTR_GENRE = 0x20, /*!< track genre */ - ESP_AVRC_MD_ATTR_PLAYING_TIME = 0x40 /*!< total album playing time in miliseconds */ + ESP_AVRC_MD_ATTR_PLAYING_TIME = 0x40, /*!< total album playing time in milliseconds */ + ESP_AVRC_MD_ATTR_COVER_ART = 0x80 /*!< cover art image handle */ } esp_avrc_md_attr_mask_t; /// AVRC event notification ids @@ -261,6 +274,12 @@ typedef enum { ESP_AVRC_PLAYBACK_ERROR = 0xFF, /*!< error */ } esp_avrc_playback_stat_t; +/// AVRC Cover Art connection error code +typedef enum { + ESP_AVRC_COVER_ART_DISCONNECTED, /*!< Cover Art connection disconnected or connection failed */ + ESP_AVRC_COVER_ART_CONNECTED, /*!< Cover Art connection established */ +} esp_avrc_cover_art_conn_state_t; + /// AVRCP notification parameters typedef union { @@ -277,6 +296,27 @@ typedef struct { uint8_t attr_val; /*!< player application attribute value */ } esp_avrc_set_app_value_param_t; +/** + * @brief AVRCP profile status parameters + */ +typedef struct { + bool avrc_ct_inited; /*!< AVRCP CT initialization */ + bool avrc_tg_inited; /*!< AVRCP TG initialization */ + uint8_t ct_cover_art_conn_num; /*!< Number of cover art client connections */ +} esp_avrc_profile_status_t; + +/** + * @brief Bluetooth AVRCP Initiation states + */ +typedef enum { + ESP_AVRC_INIT_SUCCESS = 0, /*!< Indicate init successful */ + ESP_AVRC_INIT_ALREADY, /*!< Indicate init repeated */ + ESP_AVRC_INIT_FAIL, /*!< Indicate init fail */ + ESP_AVRC_DEINIT_SUCCESS, /*!< Indicate deinit successful */ + ESP_AVRC_DEINIT_ALREADY, /*!< Indicate deinit repeated */ + ESP_AVRC_DEINIT_FAIL, /*!< Indicate deinit fail */ +} esp_avrc_init_state_t; + /// AVRC controller callback parameters typedef union { /** @@ -306,6 +346,15 @@ typedef union { int attr_length; /*!< attribute character length */ } meta_rsp; /*!< metadata attributes response */ + /** + * @brief ESP_AVRC_CT_PLAY_STATUS_RSP_EVT + */ + struct avrc_ct_get_play_status_rsp_param { + uint32_t song_length; /*!< total length of the playing song in milliseconds */ + uint32_t song_position; /*!< current position of the playing song in milliseconds elapsed */ + esp_avrc_playback_stat_t play_status; /*!< current status of playing */ + } play_status_rsp; /*!< get play status command response */ + /** * @brief ESP_AVRC_CT_CHANGE_NOTIFY_EVT */ @@ -337,6 +386,32 @@ typedef union { struct avrc_ct_set_volume_rsp_param { uint8_t volume; /*!< the volume which has actually been set, range is 0 to 0x7f, means 0% to 100% */ } set_volume_rsp; /*!< set absolute volume response event */ + + /** + * @brief ESP_AVRC_CT_COVER_ART_STATE_EVT + */ + struct avrc_ct_cover_art_state_param { + esp_avrc_cover_art_conn_state_t state; /*!< indicate the Cover Art connection status */ + esp_bt_status_t reason; /*!< the disconnect reason of Cover Art connection */ + } cover_art_state; /*!< AVRC Cover Art connection state change event */ + + /** + * @brief ESP_AVRC_CT_COVER_ART_DATA_EVT + */ + struct avrc_ct_cover_art_data_param { + esp_bt_status_t status; /*!< indicate whether the get operation is success, p_data is valid only when status is ESP_BT_STATUS_SUCCESS */ + bool final; /*!< indicate whether this data event is the final one, true if we have received the entire object */ + uint16_t data_len; /*!< the data length of this data event, in bytes */ + uint8_t *p_data; /*!< pointer to data, should copy to other buff before event callback return */ + } cover_art_data; /*!< AVRC Cover Art data event */ + + /** + * @brief ESP_AVRC_CT_PROF_STATE_EVT + */ + struct avrc_ct_init_stat_param { + esp_avrc_init_state_t state; /*!< avrc ct initialization param */ + } avrc_ct_init_stat; /*!< status to indicate avrcp ct init or deinit */ + } esp_avrc_ct_cb_param_t; /// AVRC target callback parameters @@ -389,6 +464,13 @@ typedef union { esp_avrc_set_app_value_param_t *p_vals; /*!< point to the id and value of player application attribute */ } set_app_value; /*!< set player application value */ + /** + * @brief ESP_AVRC_TG_PROF_STATE_EVT + */ + struct avrc_tg_init_stat_param { + esp_avrc_init_state_t state; /*!< avrc tg initialization param */ + } avrc_tg_init_stat; /*!< status to indicate avrcp tg init or deinit */ + } esp_avrc_tg_cb_param_t; /** @@ -429,6 +511,7 @@ esp_err_t esp_avrc_ct_register_callback(esp_avrc_ct_cb_t callback); * @brief Initialize the bluetooth AVRCP controller module, This function should be called * after esp_bluedroid_enable() completes successfully. Note: AVRC cannot work independently, * AVRC should be used along with A2DP and AVRC should be initialized before A2DP. + * ESP_AVRC_CT_PROF_STATE_EVT with ESP_AVRC_INIT_SUCCESS will reported to the APP layer. * * @return * - ESP_OK: success @@ -443,6 +526,7 @@ esp_err_t esp_avrc_ct_init(void); * @brief De-initialize AVRCP controller module. This function should be called after * after esp_bluedroid_enable() completes successfully. Note: AVRC cannot work independently, * AVRC should be used along with A2DP and AVRC should be deinitialized before A2DP. + * ESP_AVRC_CT_PROF_STATE_EVT with ESP_AVRC_DEINIT_SUCCESS will reported to the APP layer. * * @return * - ESP_OK: success @@ -551,6 +635,18 @@ esp_err_t esp_avrc_ct_send_metadata_cmd(uint8_t tl, uint8_t attr_mask); */ esp_err_t esp_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code, uint8_t key_state); +/** + * @brief Send get play status command to AVRCP target. This function should be called after + * ESP_AVRC_CT_CONNECTION_STATE_EVT is received and AVRCP connection is established. + * + * @param[in] tl : transaction label, 0 to 15, consecutive commands should use different values. + * + * @return + * - ESP_OK: success + * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + */ +esp_err_t esp_avrc_ct_send_get_play_status_cmd(uint8_t tl); /** * @brief Register application callbacks to AVRCP target module. This function should be @@ -571,6 +667,7 @@ esp_err_t esp_avrc_tg_register_callback(esp_avrc_tg_cb_t callback); * @brief Initialize the bluetooth AVRCP target module, This function should be called * after esp_bluedroid_enable() completes successfully. Note: AVRC cannot work independently, * AVRC should be used along with A2DP and AVRC should be initialized before A2DP. + * ESP_AVRC_TG_PROF_STATE_EVT with ESP_AVRC_INIT_SUCCESS will reported to the APP layer. * * @return * - ESP_OK: success @@ -585,6 +682,7 @@ esp_err_t esp_avrc_tg_init(void); * @brief De-initialize AVRCP target module. This function should be called after * after esp_bluedroid_enable() completes successfully. Note: AVRC cannot work independently, * AVRC should be used along with A2DP and AVRC should be deinitialized before A2DP. + * ESP_AVRC_TG_PROF_STATE_EVT with ESP_AVRC_DEINIT_SUCCESS will reported to the APP layer. * * @return * - ESP_OK: success @@ -656,11 +754,11 @@ bool esp_avrc_psth_bit_mask_operation(esp_avrc_bit_mask_op_t op, esp_avrc_psth_b /** * - * @brief Get the requested event notification capabilies on local AVRC target. The capability is returned + * @brief Get the requested event notification capabilities on local AVRC target. The capability is returned * in a bit mask representation in evt_set. This function should be called after esp_avrc_tg_init(). * * For capability type "ESP_AVRC_RN_CAP_ALLOWED_EVT, the retrieved event set is constant and - * it covers all of the notifcation events that can possibly be supported with current + * it covers all of the notification events that can possibly be supported with current * implementation. * * For capability type ESP_AVRC_RN_CAP_SUPPORTED_EVT, the event set covers the notification @@ -729,6 +827,102 @@ bool esp_avrc_rn_evt_bit_mask_operation(esp_avrc_bit_mask_op_t op, esp_avrc_rn_e esp_err_t esp_avrc_tg_send_rn_rsp(esp_avrc_rn_event_ids_t event_id, esp_avrc_rn_rsp_t rsp, esp_avrc_rn_param_t *param); +/** + * + * @brief Start the process to establish OBEX connection used in Cover Art Client. Once the operation done, + * ESP_AVRC_CT_COVER_ART_STATE_EVT will come, operation result can be found in event param. This API + * can be used only when AVRC Cover Art feature is enabled. + * + * @param[in] mtu: MTU used in lower level connection, should not smaller than ESP_AVRC_CA_MTU_MIN or larger than + * ESP_AVRC_CA_MTU_MAX, if value is not valid, will be reset to ESP_AVRC_CA_MTU_MAX. This can limit + * the max data length in cover_art_data event. + * + * @return + * - ESP_OK: success + * - ESP_ERR_INVALID_STATE: if bluetooth stack is not enabled or AVRC CT is not initialized + * - ESP_ERR_NOT_SUPPORTED: if peer device does not support Cover Art function + * + */ +esp_err_t esp_avrc_ct_cover_art_connect(uint16_t mtu); + +/** + * + * @brief Start the process to release the OBEX connection used in Cover Art Client.Once the operation done, + * ESP_AVRC_CT_COVER_ART_STATE_EVT will come, operation result can be found in event param. This API + * can be used only when AVRC Cover Art feature is enabled. + * + * @return + * - ESP_OK: success + * - ESP_ERR_INVALID_STATE: if bluetooth stack is not enabled or AVRC CT is not initialized + * - ESP_ERR_NOT_SUPPORTED: if peer device does not support Cover Art function + * + */ +esp_err_t esp_avrc_ct_cover_art_disconnect(void); + +/** + * + * @brief Start the process to get image properties from Cover Art server. This API can be used only when AVRC + * Cover Art feature is enabled. + * + * @param[in] image_handle: pointer to image handle with a length of ESP_AVRC_CA_IMAGE_HANDLE_LEN bytes, can be freed + * after this function return + * + * @return + * - ESP_OK: success + * - ESP_ERR_INVALID_STATE: if bluetooth stack is not enabled or AVRC CT is not initialized + * - ESP_ERR_NOT_SUPPORTED: if peer device does not support Cover Art function + * + */ +esp_err_t esp_avrc_ct_cover_art_get_image_properties(uint8_t *image_handle); + +/** + * + * @brief Start the process to get image from Cover Art server. This API can be used only when AVRC Cover Art + * feature is enabled. + * + * @param[in] image_handle: pointer to image handle with a length of ESP_AVRC_CA_IMAGE_HANDLE_LEN bytes, can be freed + * after this function return + * + * @param[in] image_descriptor: pointer to image descriptor, will be cache internally by bluetooth stack, can be freed + * once this api return + * + * @param[in] image_descriptor_len: the length of image descriptor + * + * @return + * - ESP_OK: success + * - ESP_ERR_INVALID_STATE: if bluetooth stack is not enabled or AVRC CT is not initialized + * - ESP_ERR_NOT_SUPPORTED: if peer device does not support Cover Art function + * + */ +esp_err_t esp_avrc_ct_cover_art_get_image(uint8_t *image_handle, uint8_t *image_descriptor, uint16_t image_descriptor_len); + +/** + * + * @brief Start the process to get linked thumbnail from Cover Art server. This API can be used only when AVRC + * Cover Art feature is enabled. + * + * @param[in] image_handle: pointer to image handle with a length of ESP_AVRC_CA_IMAGE_HANDLE_LEN bytes, can be freed + * after this function return + * + * @return + * - ESP_OK: success + * - ESP_ERR_INVALID_STATE: if bluetooth stack is not enabled or AVRC CT is not initialized + * - ESP_ERR_NOT_SUPPORTED: if peer device does not support Cover Art function + * + */ +esp_err_t esp_avrc_ct_cover_art_get_linked_thumbnail(uint8_t *image_handle); + +/** + * @brief This function is used to get the status of AVRCP + * + * @param[out] profile_status - AVRCP status + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_avrc_get_profile_status(esp_avrc_profile_status_t *profile_status); + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/bluedroid/api/include/api/esp_ble_cte_api.h b/lib/bt/host/bluedroid/api/include/api/esp_ble_cte_api.h new file mode 100644 index 00000000..80dc5b15 --- /dev/null +++ b/lib/bt/host/bluedroid/api/include/api/esp_ble_cte_api.h @@ -0,0 +1,379 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __ESP_BLE_CTE_API_H__ +#define __ESP_BLE_CTE_API_H__ + +#include +#include + +#include "esp_err.h" +#include "esp_bt_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/// BLE CTE callback event type +typedef enum { + ESP_BLE_CTE_SET_CONNLESS_TRANS_PARAMS_CMPL_EVT = 0, /*!< When CTE set connectionless transmit parameters complete, the event comes */ + ESP_BLE_CTE_SET_CONNLESS_TRANS_ENABLE_CMPL_EVT, /*!< When CTE set connectionless transmit enable complete, the event comes */ + ESP_BLE_CTE_SET_CONNLESS_IQ_SAMPLING_ENABLE_CMPL_EVT, /*!< When CTE set connectionless IQ sampling enable complete, the event comes */ + ESP_BLE_CTE_SET_CONN_RECV_PARAMS_CMPL_EVT, /*!< When CTE set connection receive parameters complete, the event comes */ + ESP_BLE_CTE_SET_CONN_TRANS_PARAMS_CMPL_EVT, /*!< When CTE set connection transmit parameters complete, the event comes */ + ESP_BLE_CTE_SET_CONN_REQ_ENABLE_CMPL_EVT, /*!< When CTE set connection CTE request enable complete, the event comes */ + ESP_BLE_CTE_SET_CONN_RSP_ENABLE_CMPL_EVT, /*!< When CTE set connection CTE response enable complete, the event comes */ + ESP_BLE_CTE_READ_ANT_INFOR_CMPL_EVT, /*!< When CTE read antenna information complete, the event comes */ + ESP_BLE_CTE_CONNLESS_IQ_REPORT_EVT, /*!< When the device receives CTE connectionless IQ information, the event comes */ + ESP_BLE_CTE_CONN_IQ_REPORT_EVT, /*!< When the device receives CTE connection IQ information , the event comes */ + ESP_BLE_CTE_REQUEST_FAILED_EVT, /*!< When CTE request progress failed , the event comes */ + ESP_BLE_CTE_EVT_MAX, /*!< when maximum advertising event complete, the event comes */ +} esp_ble_cte_cb_event_t; + +#define ESP_BLE_CTE_SAMPLING_DISABLE (0x00) +#define ESP_BLE_CTE_SAMPLING_ENABLE (0x01) + +#define ESP_BLE_CTE_ADV_WITH_CTE_DISABLE (0x00) +#define ESP_BLE_CTE_ADV_WITH_CTE_ENABLE (0x01) + +// Constant Tone Extension length in 8 µs units +#define ESP_BLE_CTE_MIN_CTE_LENGTH (0x02) +#define ESP_BLE_CTE_MAX_CTE_LENGTH (0x14) + +#define ESP_BLE_CTE_TYPE_AOA (0x00) /*!< AoA Constant Tone Extension */ +#define ESP_BLE_CTE_TYPE_AOD_WITH_1US (0x01) /*!< AoD Constant Tone Extension with 1 µs slots */ +#define ESP_BLE_CTE_TYPE_AOD_WITH_2US (0x02) /*!< AoD Constant Tone Extension with 2 µs slots */ +typedef uint8_t esp_ble_cte_type_t; + +#define ESP_BLE_CTE_MIN_CTE_COUNT (0x01) +#define ESP_BLE_CTE_MAX_CTE_COUNT (0x10) + +#define ESP_BLE_CTE_MIN_SWITCHING_PATTERN_LENGTH (0x02) +#define ESP_BLE_CTE_MAX_SWITCHING_PATTERN_LENGTH (0x4B) + +#define ESP_BLE_CTE_SLOT_DURATION_1US (0x01) +#define ESP_BLE_CTE_SLOT_DURATION_2US (0x02) +typedef uint8_t esp_ble_cte_slot_dur_type_t; + +#define ESP_BLE_CTE_MIN_SAMPLED_CTES (0x00) +#define ESP_BLE_CTE_MAX_SAMPLED_CTES (0x10) + +#define ESP_BLE_CTE_TYPES_AOA_RESPONSE (0x01) +#define ESP_BLE_CTE_TYPES_AOD_RESPONSE_WITH_1US (0x02) +#define ESP_BLE_CTE_TYPES_AOD_RESPONSE_WITH_2US (0x04) +#define ESP_BLE_CTE_TYPES_ALL (ESP_BLE_CTE_TYPES_AOA_RESPONSE | ESP_BLE_CTE_TYPES_AOD_RESPONSE_WITH_1US | ESP_BLE_CTE_TYPES_AOD_RESPONSE_WITH_2US) +typedef uint8_t esp_ble_cte_conn_cte_types_t; + +#define ESP_BLE_CTE_REQUEST_FOR_CONNECTION_DISABLE (0x00) +#define ESP_BLE_CTE_REQUEST_FOR_CONNECTION_ENABLE (0x01) + +#define ESP_BLE_CTE_MIN_REQUESTED_CTE_LENGTH (0x02) +#define ESP_BLE_CTE_MAX_REQUESTED_CTE_LENGTH (0x14) + +#define ESP_BLE_CTE_RESPONSE_FOR_CONNECTION_DISABLE (0x00) +#define ESP_BLE_CTE_RESPONSE_FOR_CONNECTION_ENABLE (0x01) + +typedef struct { + uint8_t adv_handle; /*!< Used to identify an advertising set */ + uint8_t cte_len; /*!< Constant Tone Extension length in 8 µs units, range: 0x02 to 0x14 */ + esp_ble_cte_type_t cte_type; /*!< AoA or AoD Constant Tone Extension */ + uint8_t cte_count; /*!< The number of Constant Tone Extensions to transmit in each periodic advertising interval, range: 0x01 to 0x10 */ + uint8_t switching_pattern_len; /*!< The number of Antenna IDs in the pattern, range: 0x02 to 0x4B */ + uint8_t *antenna_ids; /*!< Antenna ID in the pattern */ +} __attribute__((packed)) esp_ble_cte_connless_trans_params_t; + +typedef struct { + uint8_t adv_handle; /*!< Identifier for the advertising set in which Constant Tone Extension is being enabled or disabled */ + uint8_t cte_enable; /*!< Advertising with Constant Tone Extension is enabled or disabled */ +} __attribute__((packed)) esp_ble_cte_trans_enable_params_t; + +typedef struct { + uint16_t sync_handle; /*!< Identifier for the periodic advertising train */ + uint8_t sampling_en; /*!< Enable or disable connectionless IQ sampling */ + esp_ble_cte_slot_dur_type_t slot_dur; /*!< Switching and sampling slots, 1 us or 2 us */ + uint8_t max_sampled_ctes; /*!< The maximum number of CTE to sample and report in each periodic advertising interval, range: 0x00 - 0x10 */ + uint8_t switching_pattern_len; /*!< The number of Antenna IDs in the pattern, range: 0x02 to 0x4B */ + uint8_t *antenna_ids; /*!< Antenna ID in the pattern */ +} __attribute__((packed)) esp_ble_cte_iq_sampling_params_t; + +typedef struct { + uint16_t conn_handle; /*!< Connection_Handle */ + uint8_t sampling_en; /*!< Enable or disable connection IQ sampling */ + esp_ble_cte_slot_dur_type_t slot_dur; /*!< Switching and sampling slots, 1 us or 2 us */ + uint8_t switching_pattern_len; /*!< The number of Antenna IDs in the pattern, range: 0x02 to 0x4B */ + uint8_t *antenna_ids; /*!< Antenna ID in the pattern */ +} __attribute__((packed)) esp_ble_cte_recv_params_params_t; + +typedef struct { + uint16_t conn_handle; /*!< Connection_Handle */ + esp_ble_cte_conn_cte_types_t cte_types; /*!< Allow AoA or AoD Constant Tone Extension Response */ + uint8_t switching_pattern_len; /*!< The number of Antenna IDs in the pattern, range: 0x02 to 0x4B */ + uint8_t *antenna_ids; /*!< Antenna ID in the pattern */ +} __attribute__((packed)) esp_ble_cte_conn_trans_params_t; + +typedef struct { + uint16_t conn_handle; /*!< Connection_Handle */ + uint8_t enable; /*!< Enable or disable Constant Tone Extension Request for the connection */ + uint16_t cte_req_interval; /*!< Requested interval for initiating the CTE Request procedure in number of underlying connection events, range: 0x0000 - 0xFFFF */ + uint8_t req_cte_len; /*!< Minimum length of the Constant Tone Extension being requested in 8 µs units, range: 0x02 - 0x14 */ + esp_ble_cte_type_t req_cte_Type; /*!< AoA or AoD Constant Tone Extension, range: 0x00 - 0x02 */ +} __attribute__((packed)) esp_ble_cte_req_en_params_t; + +typedef struct { + uint16_t conn_handle; /*!< Connection_Handle */ + uint8_t enable; /*!< Enable or disable Constant Tone Extension Response for the connection */ +} __attribute__((packed)) esp_ble_cte_rsp_en_params_t; + +/** + * @brief CTE callback parameters union + */ +typedef union { + /** + * @brief ESP_BLE_CTE_SET_CONNLESS_TRANS_PARAMS_CMPL_EVT + */ + struct ble_set_trans_params_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate setting transmit parameters status, status = (controller error code | 0x100) if status is not equal to 0 */ + } set_trans_params_cmpl; /*!< Event parameter of ESP_BLE_CTE_SET_CONNLESS_TRANS_PARAMS_CMPL_EVT */ + + /** + * @brief ESP_BLE_CTE_SET_CONNLESS_TRANS_ENABLE_CMPL_EVT + */ + struct ble_set_trans_enable_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate setting transmit enable status, status = (controller error code | 0x100) if status is not equal to 0 */ + } set_trans_enable_cmpl; /*!< Event parameter of ESP_BLE_CTE_SET_CONNLESS_TRANS_ENABLE_CMPL_EVT */ + + /** + * @brief ESP_BLE_CTE_SET_CONNLESS_IQ_SAMPLING_ENABLE_CMPL_EVT + */ + struct ble_set_iq_sampling_en_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate setting IQ sampling enable status, status = (controller error code | 0x100) if status is not equal to 0 */ + uint16_t sync_handle; /*!< Sync_Handle identifying the periodic advertising */ + } iq_sampling_enable_cmpl; /*!< Event parameter of ESP_BLE_CTE_SET_CONNLESS_IQ_SAMPLING_ENABLE_CMPL_EVT */ + + /** + * @brief ESP_BLE_CTE_SET_CONN_RECV_PARAMS_CMPL_EVT + */ + struct ble_set_conn_recv_params_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate setting received parameters status, status = (controller error code | 0x100) if status is not equal to 0 */ + uint16_t conn_handle; /*!< The connection identifier */ + } conn_recv_params_cmpl; /*!< Event parameter of ESP_BLE_CTE_SET_CONN_RECV_PARAMS_CMPL_EVT */ + + /** + * @brief ESP_BLE_CTE_SET_CONN_TRANS_PARAMS_CMPL_EVT + */ + struct ble_set_conn_trans_params_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate setting connection transmit parameters status, status = (controller error code | 0x100) if status is not equal to 0 */ + uint16_t conn_handle; /*!< The connection identifier */ + } conn_trans_params_cmpl; /*!< Event parameter of ESP_BLE_CTE_SET_CONN_TRANS_PARAMS_CMPL_EVT */ + + /** + * @brief ESP_BLE_CTE_SET_CONN_REQ_ENABLE_CMPL_EVT + */ + struct ble_set_conn_req_en_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate setting connection request enable status, status = (controller error code | 0x100) if status is not equal to 0 */ + uint16_t conn_handle; /*!< The connection identifier */ + } conn_req_en_cmpl; /*!< Event parameter of ESP_BLE_CTE_SET_CONN_REQ_ENABLE_CMPL_EVT */ + + /** + * @brief ESP_BLE_CTE_SET_CONN_RSP_ENABLE_CMPL_EVT + */ + struct ble_set_conn_rsp_en_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate setting connection response enable status, status = (controller error code | 0x100) if status is not equal to 0 */ + uint16_t conn_handle; /*!< The connection identifier */ + } conn_rsp_en_cmpl; /*!< Event parameter of ESP_BLE_CTE_SET_CONN_RSP_ENABLE_CMPL_EVT */ + + /** + * @brief ESP_BLE_CTE_READ_ANT_INFOR_CMPL_EVT + */ + struct ble_read_ant_infor_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate reading antenna information status, status = (controller error code | 0x100) if status is not equal to 0 */ + uint8_t supported_switching_sampling_rates; /*!< bit 0: 1 µs switching supported for AoD transmission + bit 1: 1 µs sampling supported for AoD reception + bit 2: 1 µs switching and sampling supported for AoA reception */ + uint8_t num_antennae; /*!< The number of antennae supported by the Controller */ + uint8_t max_switching_pattern_len; /*!< Maximum length of antenna switching pattern supported by the Controller */ + uint8_t max_cte_len; /*!< Maximum length of a transmitted Constant Tone Extension supported in 8 µs units */ + } read_ant_infor_cmpl; /*!< Event parameter of ESP_BLE_CTE_READ_ANT_INFOR_CMPL_EVT */ + + /** + * @brief ESP_BLE_CTE_CONNLESS_IQ_REPORT_EVT + */ + struct ble_cte_connless_iq_rpt_evt_param { + uint16_t sync_handle; /*!< Sync_Handle identifying the periodic advertising train */ + uint8_t channel_idx; /*!< The index of the channel on which the packet was received */ + int16_t rssi; /*!< RSSI of the packet, Range: -1270 to +200, Units: 0.1 dBm */ + uint8_t rssi_ant_id; /*!< Antenna ID */ + uint8_t cte_type; /*!< The type of Constant Tone Extension, range: 0x00 - 0x02 */ + uint8_t slot_dur; /*!< Switching and sampling slots, 1 us or 2us, range: 0x01 - 0x02 */ + uint8_t pkt_status; /*!< indicates whether the received packet had a valid CRC, range: 0x00 - 0x02 and 0xFF */ + uint16_t periodic_evt_counter; /*!< The value of paEventCounter for the reported AUX_SYNC_IND PDU */ + uint8_t sample_count; /*!< Total number of sample pairs, range: 0x00 and 0x09 - 0x52*/ + uint8_t *i_sample; /*!< I sample for the reported packet. No valid sample available if value is 0x80 */ + uint8_t *q_sample; /*!< Q sample for the reported packet. No valid sample available if value is 0x80 */ + } connless_iq_rpt; /*!< Event parameter of ESP_BLE_CTE_CONNLESS_IQ_REPORT_EVT */ + + /** + * @brief ESP_BLE_CTE_CONN_IQ_REPORT_EVT + */ + struct ble_cte_conn_iq_rpt_evt_param { + uint16_t conn_handle; /*!< Connection_Handle */ + uint8_t rx_phy; /*!< The receiver PHY for the connection, range: 0x01 - 0x02 */ + uint8_t data_channel_idx; /*!< The index of the data channel on which the Data Physical Channel PDU was received, range: 0x00 - 0x24 */ + int16_t rssi; /*!< RSSI of the packet, range: -1270 - +200, units: 0.1 dBm */ + uint8_t rssi_ant_id; /*!< ID of the antenna on which the RSSI is measured */ + uint8_t cte_type; /*!< AoA or AoD Constant Tone Extension, range: 0x00 - 0x02 */ + uint8_t slot_dur; /*!< Switching and sampling slots, range: 0x01 - 0x02 */ + uint8_t pkt_status; /*!< indicates whether the received packet had a valid CRC, range: 0x00 - 0x02 and 0xFF */ + uint16_t conn_evt_counter; /*!< The value of connEventCounter for the reported PDU */ + uint8_t sample_count; /*!< Total number of sample pairs, range: 0x00 and 0x09 - 0x52 */ + uint8_t *i_sample; /*!< I sample for the reported PDU. No valid sample available if value is 0x80 */ + uint8_t *q_sample; /*!< Q sample for the reported PDU,. No valid sample available if value is 0x80 */ + } conn_iq_rpt; /*!< Event parameter of ESP_BLE_CTE_CONN_IQ_REPORT_EVT */ + + /** + * @brief ESP_BLE_CTE_REQUEST_FAILED_EVT + */ + struct ble_cte_req_failed_evt_param{ + uint8_t reason; /*!< value: 0x00, LL_CTE_RSP PDU received successfully but without a Constant Tone Extension field; + value: 0x01 to 0xFF, Peer rejected the request, see [Vol 1] Part F controller error codes and descriptions */ + uint16_t conn_handle; /*!< Connection_Handle */ + } req_failed_evt; /*!< Event parameter of ESP_BLE_CTE_REQUEST_FAILED_EVT */ + +} esp_ble_cte_cb_param_t; + +/** + * @brief CTE callback function type + * @param event : Event type + * @param param : Point to callback parameter, currently is union type + */ +typedef void (* esp_ble_cte_cb_t)(esp_ble_cte_cb_event_t event, esp_ble_cte_cb_param_t *param); + +/** + * @brief This function is called to occur cte event + * + * @param[in] callback: callback function + * + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_cte_register_callback(esp_ble_cte_cb_t callback); + +/** + * @brief This function is called to get the current cte callback + * + * @return + * - esp_ble_cte_cb_t : callback function + * + */ +esp_ble_cte_cb_t esp_ble_cte_get_callback(void); + +/** + * @brief This function is called to set parameters for the transmission of CTE in the periodic advertising. + * + * @param[in] cte_trans_params: pointer to User defined cte_trans_params data structure. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_cte_set_connectionless_trans_params(esp_ble_cte_connless_trans_params_t *cte_trans_params); + +/** + * @brief This function is called to request that the Controller enables or disables the use of CTE in the periodic advertising. + * + * @param[in] cte_trans_enable: pointer to User defined cte_trans_enable data structure. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_cte_set_connectionless_trans_enable(esp_ble_cte_trans_enable_params_t *cte_trans_enable); + +/** + * @brief This function is called to request that the Controller enables or disables capturing IQ samples from the CTE +* of periodic advertising packets. + * + * @param[in] iq_sampling_en: pointer to User defined iq_sampling_en data structure. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_cte_set_connectionless_iq_sampling_enable(esp_ble_cte_iq_sampling_params_t *iq_sampling_en); + +/** + * @brief This function is called to enable or disable sampling received CTE fields on the connection. + * + * @param[in] cte_recv_params: pointer to User defined cte_recv_params data structure. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_cte_set_connection_receive_params(esp_ble_cte_recv_params_params_t *cte_recv_params); + +/** + * @brief This function is called to set the parameters used for transmitting CTE requested by the peer + * device on the connection. + * + * @param[in] cte_conn_trans_params: pointer to User defined cte_conn_trans_params data structure. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_cte_set_connection_transmit_params(esp_ble_cte_conn_trans_params_t *cte_conn_trans_params); + +/** + * @brief This function is called to request the Controller to start or stop initiating the CTE Request + * procedure on a connection. + * + * @param[in] cte_conn_req_en: pointer to User defined cte_conn_req_en data structure. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_cte_connection_cte_request_enable(esp_ble_cte_req_en_params_t *cte_conn_req_en); + +/** + * @brief This function is called to request the Controller to respond to LL_CTE_REQ PDUs with + * LL_CTE_RSP PDUs on the specified connection. + * + * @param[in] cte_conn_rsp_en: pointer to User defined cte_conn_rsp_en data structure. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_cte_connection_cte_response_enable(esp_ble_cte_rsp_en_params_t *cte_conn_rsp_en); + +/** + * @brief This function is called to read the parameters of a transmitted CTE supported by the Controller. + * + * @param[in] none. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_cte_read_antenna_information(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __ESP_BLE_CTE_API_H__ */ diff --git a/lib/bt/host/bluedroid/api/include/api/esp_ble_iso_api.h b/lib/bt/host/bluedroid/api/include/api/esp_ble_iso_api.h new file mode 100644 index 00000000..5531393e --- /dev/null +++ b/lib/bt/host/bluedroid/api/include/api/esp_ble_iso_api.h @@ -0,0 +1,660 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __ESP_BLE_ISO_API_H__ +#define __ESP_BLE_ISO_API_H__ + +#include +#include + +#include "esp_err.h" +#include "esp_bt_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/// ISO BLE callback event type +typedef enum { + ESP_BLE_ISO_BIG_CREATE_CMPL_EVT = 0, /*!< When BIG create complete, the event comes */ + ESP_BLE_ISO_BIG_TERMINATE_CMPL_EVT, /*!< When BIG terminate complete, the event comes */ + ESP_BLE_ISO_BIG_SYNC_ESTABLISHED_EVT, /*!< When BIG sync established, the event comes */ + ESP_BLE_ISO_BIG_SYNC_LOST_EVT, /*!< When BIG sync lost, the event comes */ + ESP_BLE_ISO_BIG_SYNC_TERMINATE_CMPL_EVT, /*!< When BIG sync terminate complete, the event comes */ + ESP_BLE_ISO_BIGINFO_ADV_REPORT_EVT, /*!< When receiving an Advertising PDU that contained a BIGInfo field, the event comes */ + ESP_BLE_ISO_ISO_DATA_PATH_UPDATE_EVT, /*!< When ISO data path update complete, the event comes */ + ESP_BLE_ISO_READ_ISO_TX_SYNC_CMPL_EVT, /*!< When reading tx sync complete, the event comes */ + ESP_BLE_ISO_READ_LINK_QUALITY_CMPL_EVT, /*!< When reading link quality complete, the event comes */ + ESP_BLE_ISO_SET_CIG_PARAMS_CMPL_EVT, /*!< When CIG parameters set complete, the event comes */ + ESP_BLE_ISO_CREATE_CIS_CMPL_EVT, /*!< When CIS create complete, the event comes */ + ESP_BLE_ISO_REMOVE_CIG_CMPL_EVT, /*!< When CIG remove complete, the event comes */ + ESP_BLE_ISO_CIS_REQUEST_EVT, /*!< When Receiving CIS request event, the event comes */ + ESP_BLE_ISO_ACCEPT_CIS_REQ_CMPL_EVT, /*!< When CIS request event accept complete, the event comes */ + ESP_BLE_ISO_REJECT_CIS_REQ_CMPL_EVT, /*!< When CIS request event reject complete, the event comes */ + ESP_BLE_ISO_CIS_ESTABLISHED_EVT, /*!< When CIS is established, the event comes */ + ESP_BLE_ISO_CIS_DISCONNECTED_EVT, /*!< When CIS is disconnected, the event comes */ + ESP_BLE_ISO_EVT_MAX, /*!< when maximum advertising event complete, the event comes */ +} esp_ble_iso_cb_event_t; + +typedef enum { + ESP_BLE_ISO_DATA_PATH_UNKNOWN = 0, + ESP_BLE_ISO_DATA_PATH_SETUP = 1, + ESP_BLE_ISO_DATA_PATH_REMOVE = 2, + ESP_BLE_ISO_DATA_PATH_MAX, +} ESP_BLE_ISO_DATA_PATH_UPDATE_TYPE; + +#define ESP_BLE_ISO_DATA_PATH_DIR_INPUT (0x00) +#define ESP_BLE_ISO_DATA_PATH_DIR_OUTPUT (0x01) + +#define ESP_BLE_ISO_DATA_PATH_DIR_INPUT_BIT_MASK (1 << 0) +#define ESP_BLE_ISO_DATA_PATH_DIR_OUTPUT_BIT_MASK (1 << 1) +#define ESP_BLE_ISO_DATA_PATH_DIR_ALL_BIT_MASK (ESP_BLE_ISO_DATA_PATH_DIR_INPUT_BIT_MASK | ESP_BLE_ISO_DATA_PATH_DIR_OUTPUT_BIT_MASK) + +#define ESP_BLE_MAX_BIS_NUM (31) +#define ESP_BLE_MAX_CIS_NUM (31) + +#define BLE_ISO_SDU_INT_MIN (0x0000FF) +#define BLE_ISO_SDU_INT_MAX (0x0FFFFF) + +#define BLE_ISO_WORST_CASE_SCA_LEVEL_500_PPM (0x00) +#define BLE_ISO_WORST_CASE_SCA_LEVEL_250_PPM (0x01) +#define BLE_ISO_WORST_CASE_SCA_LEVEL_150_PPM (0x02) +#define BLE_ISO_WORST_CASE_SCA_LEVEL_100_PPM (0x03) +#define BLE_ISO_WORST_CASE_SCA_LEVEL_75_PPM (0x04) +#define BLE_ISO_WORST_CASE_SCA_LEVEL_50_PPM (0x05) +#define BLE_ISO_WORST_CASE_SCA_LEVEL_30_PPM (0x06) +#define BLE_ISO_WORST_CASE_SCA_LEVEL_20_PPM (0x07) + +#define BLE_ISO_PACKING_SEQUENTIAL (0x00) +#define BLE_ISO_PACKING_INTERLEAVED (0x00) + +#define BLE_ISO_FRAMING_UNFRAMED_PDU (0x00) +#define BLE_ISO_FRAMING_FRAMED_PDU_SEGMENTABLE_MODE (0x01) +#define BLE_ISO_FRAMING_FRAMED_PDU_UNSEGMENTABLE_MODE (0x02) + +#define BLE_ISO_MAX_TRANSPORT_LATENCY_MIN (0x0005) +#define BLE_ISO_MAX_TRANSPORT_LATENCY_MAX (0x0FA0) + +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +typedef struct { + uint8_t big_handle; /*!< Used to identify the BIG, value 0x00 to 0xEF */ + uint8_t adv_handle; /*!< Used to identify the periodic advertising train, value 0x00 to 0xEF */ + uint8_t num_bis; /*!< Total number of BISes in the BIG, value 0x01 to 0x1F */ + uint32_t sdu_interval; /*!< The interval, in microseconds, of periodic SDUs, value 0x0000FF to 0x0FFFFF*/ + uint16_t max_sdu; /*!< Maximum size of an SDU, in octets, value 0x0001 to 0x0FFF */ + uint16_t max_transport_latency; /*!< Maximum transport latency, in milliseconds, value 0x0005 to 0x0FA0 */ + uint8_t rtn; /*!< The number of times that every BIS Data PDU should be retransmitted, value 0x00 to 0x1E */ + uint8_t phy; /*!< The transmitter PHY of packets, value bit[0, 2] */ + uint8_t packing; /*!< The preferred method of arranging subevents of multiple BISes, value 0x00 to 0x01 */ + uint8_t framing; /*!< The format of the BIS Data PDUs and the mode of framed PDUs that the Controller shall use on the specified BIG, value 0x00 to 0x02 */ + uint8_t encryption; /*!< The encryption mode of the BISes in the BIG, value 0x00 to 0x01 */ + uint8_t broadcast_code[16]; /*!< The code used to derive the session key that is used to encrypt and decrypt BIS payloads */ +} esp_ble_iso_big_creat_params_t; + +typedef struct { + uint8_t big_handle; /*!< Used to identify the BIG, value 0x00 to 0xEF */ + uint8_t adv_handle; /*!< Used to identify the periodic advertising train, value 0x00 to 0xEF */ + uint8_t num_bis; /*!< Total number of BISes in the BIG, value 0x01 to 0x1F */ + uint32_t sdu_interval; /*!< The interval, in microseconds, of periodic SDUs, value 0x0000FF to 0x0FFFFF*/ + uint16_t iso_interval; /*!< the time between two consecutive BIG anchor points, Range: 0x0004 to 0x0C80, Time = N × 1.25 ms */ + uint8_t nse; /*!< The total number of subevents in each interval of each BIS in the BIG, value 0x01 to 0x1F */ + uint16_t max_sdu; /*!< Maximum size, in octets, of an SDU */ + uint16_t max_pdu; /*!< Maximum size, in octets, of payload, value 0x0001 to 0x00FB */ + uint8_t phy; /*!< The transmitter PHY of packets */ + uint8_t packing; /*!< The preferred method of arranging subevents of multiple BISes, value 0x00 to 0x01 */ + uint8_t framing; /*!< The format of the BIS Data PDUs and the mode of framed PDUs that the Controller shall use on the specified BIG, value 0x00 to 0x02 */ + uint8_t bn; /*!< The number of new payloads in each interval for each BIS, value 0x01 to 0x07 */ + uint8_t irc; /*!< The number of times the scheduled payloads are transmitted in a given event, value 0x01 to 0x0F */ + uint8_t pto; /*!< Offset used for pre-transmissions, value 0x00 to 0x0F */ + uint8_t encryption; /*!< The encryption mode of the BISes in the BIG, value 0x00 to 0x01 */ + uint8_t broadcast_code[16]; /*!< The code used to derive the session key that is used to encrypt and decrypt BIS payloads */ +} esp_ble_iso_big_creat_test_params_t; + +#endif //#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +typedef struct { + uint8_t big_handle; /*!< Used to identify the BIG, value 0x00 to 0xEF */ + uint16_t sync_handle; /*!< Identifier of the periodic advertising train, value 0x0000 to 0x0EFF*/ + uint8_t encryption; /*!< Broadcast_Code is valid or invalid, value 0x00 to 0x01 */ + uint8_t bc_code[16]; /*!< 128-bit code used for deriving the session key for decrypting payloads of BISes in the BIG */ + uint8_t mse; /*!< Maximum number of subevents that should be used to receive data payloads in each BIS event, value 0x00 to 0x1F */ + uint16_t big_sync_timeout; /*!< Synchronization timeout for the BIG, Range: 0x000A to 0x4000, Time = N × 10 ms, Time Range: 100 ms to 163.84 s*/ + uint8_t num_bis; /*!< Total number of BISes to synchronize, value 0x01 to 0x1F */ + uint8_t bis[ESP_BLE_MAX_BIS_NUM]; /*!< Index of a BIS, value 0x01 to 0x1F */ +} esp_ble_iso_big_sync_creat_params_t; + +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + +typedef struct { + uint16_t iso_handle; /*!< Connection handle of the CIS or BIS*/ + uint8_t data_path_dir; /*!< The direction for which the data path is being configured, value 0x00 to 0x01 */ + uint8_t data_path_id; /*!< The data transport path used, value 0x00 to 0xFE */ + uint8_t coding_fmt; /*!< See Assigned Numbers for Coding Format */ + uint16_t company_id; /*!< Company ID, see Assigned Numbers for Company Identifier. Shall be ignored if coding_fmt is not 0xFF*/ + uint16_t vs_codec_id; /*!< Vendor-defined codec ID, Shall be ignored if coding_fmt is not 0xFF */ + uint32_t controller_delay; /*!< Controller delay in microseconds, range: 0x000000 to 0x3D0900, time range: 0 s to 4 s*/ + uint8_t codec_cfg_len; /*!< Length of codec configuration */ + uint8_t *codec_cfg; /*!< Codec-specific configuration data */ +} esp_ble_iso_set_data_path_params_t; + +typedef struct { + uint16_t iso_handle; /*!< Connection handle of the CIS or BIS. Range: 0x0000 to 0x0EFF */ + uint8_t data_path_dir; /*!< which directions are to have the data path removed */ +} __attribute__((packed)) esp_ble_iso_remove_data_path_params_t; + +struct ble_iso_cis_params { + uint8_t cis_id; /*!< Used to identify a CIS */ + uint16_t max_sdu_c_to_p; /*!< Maximum size, in octets, of the payload from the Central’s Host */ + uint16_t max_sdu_p_to_c; /*!< Maximum size, in octets, of the payload from the Peripheral’s Host */ + uint8_t phy_c_to_p; /*!< The transmitter PHY of packets from the Central */ + uint8_t phy_p_to_c; /*!< The transmitter PHY of packets from the Peripheral */ + uint8_t rtn_c_to_p; /*!< Number of times every CIS Data PDU should be retransmitted from the Central to the Peripheral */ + uint8_t rtn_p_to_c; /*!< Number of times every CIS Data PDU should be retransmitted from the Peripheral to the Central */ +} __attribute__((packed)); + +struct ble_iso_cis_params_test { + uint8_t cis_id; /*!< Used to identify a CIS */ + uint8_t nse; /*!< Maximum number of subevents in each CIS event */ + uint16_t max_sdu_c_to_p; /*!< Maximum size, in octets, of the payload from the Central’s Host */ + uint16_t max_sdu_p_to_c; /*!< Maximum size, in octets, of the payload from the Peripheral’s Host */ + uint16_t max_pdu_c_to_p; /*!< Maximum size, in octets, of the payload from the Central’s Link Layer to the Peripheral’s Link Layer */ + uint16_t max_pdu_p_to_c; /*!< Maximum size, in octets, of the payload from the Peripheral’s Link Layer to the Central’s Link Layer */ + uint8_t phy_c_to_p; /*!< The transmitter PHY of packets from the Central */ + uint8_t phy_p_to_c; /*!< The transmitter PHY of packets from the Peripheral */ + uint8_t bn_c_to_p; /*!< The burst number for Central to Peripheral */ + uint8_t bn_p_to_c; /*!< The burst number for Peripheral to Central */ +} __attribute__((packed)); + +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +struct esp_ble_iso_set_cig_params { + uint8_t cig_id; /*!< Used to identify the CIG */ + uint32_t sdu_int_c_to_p; /*!< The interval, in microseconds, of periodic SDUs */ + uint32_t sdu_int_p_to_c; /*!< The interval, in microseconds, of periodic SDUs */ + uint8_t worse_case_SCA; /*!< The worst-case sleep clock accuracy of all the Peripherals that will participate in the CIG */ + uint8_t packing; /*!< The preferred method of arranging subevents of multiple CISes */ + uint8_t framing; /*!< The format of the CIS Data PDUs of the specified CISes' framing mode that the Host is requesting for the CIG */ + uint16_t mtl_c_to_p; /*!< The maximum transport latency from the Central to the Peripheral, in milliseconds */ + uint16_t mtl_p_to_c; /*!< The maximum transport latency from the Peripheral to the Central, in milliseconds */ + uint8_t cis_cnt; /*!< Total number of CIS configurations in the CIG being added or modified */ + struct ble_iso_cis_params cis_params[ESP_BLE_MAX_CIS_NUM]; /*!< */ +}__attribute__((packed)); + +struct esp_ble_iso_set_cig_params_test { + uint8_t cig_id; /*!< Used to identify the CIG */ + uint32_t sdu_int_c_to_p; /*!< The interval, in microseconds, of periodic SDUs */ + uint32_t sdu_int_p_to_c; /*!< The interval, in microseconds, of periodic SDUs */ + uint8_t ft_c_to_p; /*!< The flush timeout in multiples of ISO_Interval for each payload sent from the Central to Peripheral */ + uint8_t ft_p_to_c; /*!< The flush timeout in multiples of ISO_Interval for each payload sent from the Peripheral to Central */ + uint16_t iso_interval; /*!< Time between consecutive CIS anchor points. Range: 0x0004 to 0x0C80, Time = N × 1.25 ms, Time Range: 5 ms to 4 s */ + uint8_t worse_case_SCA; /*!< The worst-case sleep clock accuracy of all the Peripherals that will participate in the CIG */ + uint8_t packing; /*!< The preferred method of arranging subevents of multiple CISes */ + uint8_t framing; /*!< The format of the CIS Data PDUs of the specified CISes' framing mode that the Host is requesting for the CIG */ + uint8_t cis_cnt; /*!< Total number of CIS configurations in the CIG being added or modified */ + struct ble_iso_cis_params_test cis_params_test[ESP_BLE_MAX_CIS_NUM]; +} __attribute__((packed)); + +struct esp_ble_gatt_cis_hdl { + uint16_t cis_hdl; /*!< Connection handle of a CIS */ + uint16_t acl_hdl; /*!< Connection handle of an ACL connection */ +}__attribute__((packed)); + +struct esp_ble_iso_create_cis_params { + uint8_t cis_count; /*!< Total number of CISes to be created */ + struct esp_ble_gatt_cis_hdl cis_hdl_info[ESP_BLE_MAX_CIS_NUM]; +}__attribute__((packed)); +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +/** + * @brief ISO callback parameters union + */ +typedef union { + /** + * @brief ESP_BLE_ISO_BIG_CREATE_CMPL_EVT + */ + struct ble_big_create_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate the BIG was successfully created */ + uint8_t big_handle; /*!< The identifier of the BIG */ + uint32_t big_sync_delay; /*!< The maximum time, in microseconds, for transmission of PDUs of all BISes in a BIG event */ + uint32_t transport_latency; /*!< The actual transport latency, in microseconds */ + uint8_t phy; /*!< The PHY used to create the BIG */ + uint8_t nse; /*!< The number of subevents in each BIS event in the BIG. The value shall be an integer multiple of BN */ + uint8_t bn; /*!< The number of new payloads in each BIS event */ + uint8_t pto; /*!< Offset used for pre-transmissions */ + uint8_t irc; /*!< The number of times a payload is transmitted in a BIS event */ + uint16_t max_pdu; /*!< Maximum size, in octets, of the payload */ + uint16_t iso_interval; /*!< The time between two consecutive BIG anchor points, Time = N × 1.25 ms */ + uint8_t num_bis; /*!< Total number of BISes in the BIG */ + uint16_t bis_handle[ESP_BLE_MAX_BIS_NUM]; /*!< Connection handle of a BIS */ + } create_big_cmpl; /*!< Event parameter of ESP_BLE_ISO_BIG_CREATE_CMPL_EVT */ + /** + * @brief ESP_BLE_ISO_BIG_TERMINATE_CMPL_EVT + */ + struct ble_big_term_cmpl_evt_param { + esp_bt_status_t status;/*!< Indicate BIG terminate complete */ + uint8_t big_handle; /*!< The identifier of the BIG */ + uint8_t reason; /*!< Reason for termination. See [Vol 1] Part F, Controller Error Codes for a list of error codes and descriptions */ + } term_big_cmpl; /*!< Event parameter of ESP_BLE_ISO_BIG_TERMINATE_CMPL_EVT */ + /** + * @brief ESP_BLE_ISO_BIG_SYNC_ESTABLISHED_EVT + */ + struct ble_big_sync_estab_evt_param { + esp_bt_status_t status; /*!< Indicate synchronization to the BIG is completed */ + uint8_t big_handle; /*!< The identifier of the BIG */ + uint32_t transport_latency; /*!< The actual transport latency, in microseconds */ + uint8_t nse; /*!< The number of subevents in each BIS event in the BIG */ + uint8_t bn; /*!< The number of new payloads in each BIS event */ + uint8_t pto; /*!< The offset in number of ISO_Intervals for pre transmissions of data packets */ + uint8_t irc; /*!< The number of times a payload is transmitted in a BIS event */ + uint16_t max_pdu; /*!< The maximum size of every BIS Data PDU for every BIS in the BIG */ + uint16_t iso_interval; /*!< The time duration between two consecutive BIG anchor points */ + uint8_t num_bis; /*!< The total number of BISes in the BIG */ + uint16_t bis_handle[ESP_BLE_MAX_BIS_NUM]; /*!< Connection handle of a BIS in the BIG */ + } big_sync_estab; /*!< Event parameter of ESP_BLE_ISO_BIG_SYNC_ESTABLISHED_EVT */ + /** + * @brief ESP_BLE_ISO_BIG_SYNC_LOST_EVT + */ + struct ble_big_sync_lost_evt_param { + uint8_t big_handle; /*!< The identifier of a BIG */ + uint8_t reason; /*!< The synchronization to BIG is terminated. See [Vol 1] Part F, Controller Error Codes for a list of error codes and descriptions */ + } big_sync_lost; /*!< Event parameter of ESP_BLE_ISO_BIG_SYNC_LOST_EVT */ + /** + * @brief ESP_BLE_ISO_BIG_SYNC_TERMINATE_CMPL_EVT + */ + struct ble_big_sync_term_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate BIG sync terminate success or not */ + uint8_t big_handle; /*!< Identifier of the BIG */ + } term_big_sync; /*!< Event parameter of ESP_BLE_ISO_BIG_SYNC_TERMINATE_CMPL_EVT */ + /** + * @brief ESP_BLE_ISO_BIGINFO_ADV_REPORT_EVT + */ + struct ble_biginfo_report_evt_param { + uint16_t sync_handle; /*!< Identify the periodic advertising train containing the BIGInfo field */ + uint8_t num_bis; /*!< The total number of BISes in the BIG */ + uint8_t nse; /*!< The total number of subevents that are used to transmit BIS Data PDUs for each BIS in a BIG event */ + uint16_t iso_interval; /*!< The time duration between two consecutive BIG anchor points */ + uint8_t bn; /*!< The number of new payloads for each BIS */ + uint8_t pto; /*!< The offset in number of ISO_Intervals for pre transmissions of data packets */ + uint8_t irc; /*!< The number of times the scheduled data packet is transmitted */ + uint16_t max_pdu; /*!< The maximum size of every BIS Data PDU for every BIS in the BIG */ + uint32_t sdu_interval; /*!< The time interval of the periodic SDUs */ + uint16_t max_sdu; /*!< The maximum size of an SDU */ + uint8_t phy; /*!< The transmitter PHY of packets */ + uint8_t framing; /*!< The format of the BIS Data PDUs and the mode of framed PDUs that the Controller used on the specified BIG */ + uint8_t encryption; /*!< The encryption mode of the BISes in the BIG */ + } biginfo_report; /*!< Event parameter of ESP_BLE_ISO_BIGINFO_ADV_REPORT_EVT */ + /** + * @brief ESP_BLE_ISO_ISO_DATA_PATH_UPDATE_EVT + */ + struct ble_iso_data_path_update_evt_param { + esp_bt_status_t status; /*!< Indicate data path update success status */ + ESP_BLE_ISO_DATA_PATH_UPDATE_TYPE op_type; /*!< data path update type, setup or remove */ + uint16_t iso_hdl; /*!< Connection handle of the CIS or BIS */ + } data_path; /*!< Event parameter of ESP_BLE_ISO_ISO_DATA_PATH_UPDATE_EVT */ + /** + * @brief ESP_BLE_ISO_READ_ISO_TX_SYNC_CMPL_EVT + */ + struct ble_iso_read_tx_sync_evt_param { + esp_bt_status_t status; /*!< Indicate tx sync read success status */ + uint16_t iso_hdl; /*!< Connection handle of the CIS or BIS */ + uint16_t pkt_seq_num; /*!< The packet sequence number of an SDU */ + uint32_t tx_time_stamp; /*!< The CIG reference point or BIG anchor point of a transmitted SDU derived using the Controller's free running reference clock (in microseconds) */ + uint32_t time_offset; /*!< The time offset, in microseconds, that is associated with a transmitted SDU */ + } read_tx_sync; /*!< Event parameter of ESP_BLE_ISO_READ_ISO_TX_SYNC_CMPL_EVT */ + /** + * @brief ESP_BLE_ISO_READ_LINK_QUALITY_CMPL_EVT + */ + struct ble_iso_read_link_quality_evt_param { + esp_bt_status_t status; /*!< Indicate link quality read success status */ + uint16_t iso_hdl; /*!< The identifier of the BIS or CIS */ + uint32_t tx_unacked_pkts; /*!< for CIS, The Link Layer does not receive an acknowledgment for a CIS Data PDU that it transmitted at least once by its flush point*/ + uint32_t tx_flushed_pkts; /*!< for CIS, The Link Layer does not transmit a specific payload by its flush point */ + uint32_t tx_last_subevt_pkts; /*!< for CIS in Peripheral role, The Link Layer transmits a CIS Data PDU in the last subevent of a CIS event */ + uint32_t retransmitted_pkts; /*!< for CIS, The Link Layer retransmits a CIS Data PDU */ + uint32_t crc_error_pkts; /*!< for CIS and BIS, The Link Layer receives a packet with a CRC error */ + uint32_t rx_unreceived_pkts; /*!< for CIS and BIS, The Link Layer does not receive a specific payload by its flush point (on a CIS) or the end of the event */ + uint32_t duplicate_pkts; /*!< for CIS, The Link Layer receives a retransmission of a CIS Data PDU */ + } read_link_quality; /*!< Event parameter of ESP_BLE_ISO_READ_LINK_QUALITY_CMPL_EVT */ + /** + * @brief ESP_BLE_ISO_SET_CIG_PARAMS_CMPL_EVT + */ + struct ble_iso_set_cig_params_evt_param { + esp_bt_status_t status; /*!< Indicate CIG parameters update success status */ + uint8_t cig_id; /*!< Used to identify a CIG */ + uint8_t cis_count; /*!< Total number of CIS configurations added or modified by this command */ + uint16_t cis_hdl[ESP_BLE_MAX_CIS_NUM]; /*!< Connection handle of the CIS in the CIG */ + } set_cig_params; /*!< Event parameter of ESP_BLE_ISO_SET_CIG_PARAMS_CMPL_EVT */ + /** + * @brief ESP_BLE_ISO_CREATE_CIS_CMPL_EVT + */ + struct ble_iso_create_cis_params_evt_param { + esp_bt_status_t status; /*!< Indicate creating cis success status */ + } create_cis; /*!< Event parameter of ESP_BLE_ISO_CREATE_CIS_CMPL_EVT */ + /** + * @brief ESP_BLE_ISO_CIS_ESTABLISHED_EVT + */ + struct ble_iso_cis_estab_evt_params{ + esp_bt_status_t status; /*!< Indicate the CIS is successfully established or not */ + uint16_t cis_handle; /*!< Connection handle of the CIS */ + uint32_t cig_sync_delay; /*!< The maximum time, in microseconds, for transmission of PDUs of all CISes in a CIG event */ + uint32_t cis_sync_delay; /*!< he maximum time, in microseconds, for transmission of PDUs of the speci-fied CIS in a CIG event */ + uint32_t trans_lat_c_to_p; /*!< The actual transport latency, in microseconds, from Central to Peripheral */ + uint32_t trans_lat_p_to_c; /*!< The actual transport latency, in microseconds, from Peripheral to Central */ + uint8_t phy_c_to_p; /*!< The transmitter PHY of packets from the Central */ + uint8_t phy_p_to_c; /*!< The transmitter PHY of packets from the Peripheral */ + uint8_t nse; /*!< Maximum number of subevents in each CIS event */ + uint8_t bn_c_to_p; /*!< The burst number for Central to Peripheral transmission */ + uint8_t bn_p_to_c; /*!< The burst number for Peripheral to Central transmission */ + uint8_t ft_c_to_p; /*!< The flush timeout, in multiples of the ISO_Interval for the CIS, for each payload sent from the Central to the Peripheral */ + uint8_t ft_p_to_c; /*!< The flush timeout, in multiples of the ISO_Interval for the CIS, for each payload sent from the Peripheral to the Central */ + uint16_t max_pdu_c_to_p; /*!< Maximum size, in octets, of the payload from Central to Peripheral */ + uint16_t max_pdu_p_to_c; /*!< Maximum size, in octets, of the payload from Peripheral to Central */ + uint16_t iso_interval; /*!< The time between two consecutive CIS anchor points, Time = N × 1.25 ms */ +#if (BLE_FEAT_ISO_60_EN == TRUE) + uint32_t sub_interval; /*!< Time, in microseconds, between the start of consecutive subevents in a CIS event */ + uint16_t max_sdu_c_to_p; /*!< Maximum size, in octets, of the payload from the Central’s Host */ + uint16_t max_sdu_p_to_c; /*!< Maximum size, in octets, of the payload from the Peripheral’s Host */ + uint32_t sdu_int_c_to_p; /*!< Time, in microseconds, between the start of consecutive SDUs sent by the Central */ + uint32_t sdu_int_p_to_c; /*!< Time, in microseconds, between the start of consecutive SDUs sent by the Peripheral */ + uint8_t framing; /*!< The format of the CIS Data PDUs and the mode of framed PDUs that the Controller used on the specified CIG */ +#endif // #if (BLE_FEAT_ISO_60_EN == TRUE) + } cis_estab; /*!< Event parameter of ESP_BLE_ISO_CIS_ESTABLISHED_EVT */ + /** + * @brief ESP_BLE_ISO_CIS_DISCONNECTED_EVT + */ + struct ble_iso_cis_dis_evt_params{ + uint16_t cis_handle; /*!< Connection handle of the CIS */ + uint8_t reason; /*!< Reason for disconnection. See [Vol 1] Part F, Controller Error Codes for error codes and descriptions */ + } cis_disconnected; /*!< Event parameter of ESP_BLE_ISO_CIS_DISCONNECTED_EVT */ + /** + * @brief ESP_BLE_ISO_CIS_REQUEST_EVT + */ + struct ble_iso_cis_request_evt_params{ + uint16_t acl_handle; /*!< Connection handle of the ACL */ + uint16_t cis_handle; /*!< Connection handle of the CIS */ + uint8_t cig_id; /*!< Identifier of the CIG */ + uint8_t cis_id; /*!< Identifier of the CIS */ + } cis_request; /*!< Event parameter of ESP_BLE_ISO_CIS_REQUEST_EVT */ + /** + * @brief ESP_BLE_ISO_REMOVE_CIG_CMPL_EVT + */ + struct ble_iso_remove_cig_params{ + esp_bt_status_t status; /*!< Indicate CIG remove succeeded or not*/ + uint8_t cig_id; /*!< Identifier of a CIG */ + } remove_cig; /*!< Event parameter of ESP_BLE_ISO_REMOVE_CIG_CMPL_EVT */ + /** + * @brief ESP_BLE_ISO_ACCEPT_CIS_REQ_CMPL_EVT + */ + struct ble_iso_accept_req_evt_params{ + esp_bt_status_t status; /*!< Indicate the CIS request is accepted successfully */ + } accept_req; /*!< Event parameter of ESP_BLE_ISO_ACCEPT_CIS_REQ_CMPL_EVT */ + /** + * @brief ESP_BLE_ISO_REJECT_CIS_REQ_CMPL_EVT + */ + struct ble_iso_reject_req_evt_params{ + esp_bt_status_t status; /*!< Indicate the CIS request is rejected successfully */ + uint16_t cis_handle; /*!< The connection handle of the CIS to be rejected */ + } reject_req; /*!< Event parameter of ESP_BLE_ISO_REJECT_CIS_REQ_CMPL_EVT */ + +} esp_ble_iso_cb_param_t; + +/** + * @brief ISO callback function type + * @param event : Event type + * @param param : Point to callback parameter, currently is union type + */ +typedef void (* esp_ble_iso_cb_t)(esp_ble_iso_cb_event_t event, esp_ble_iso_cb_param_t *param); + +/** + * @brief This function is called to occur iso event, such as scan result + * + * @param[in] callback: callback function + * + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_register_callback(esp_ble_iso_cb_t callback); + +/** + * @brief This function is called to get the current iso callback + * + * @return + * - esp_ble_iso_cb_t : callback function + * + */ +esp_ble_iso_cb_t esp_ble_iso_get_callback(void); + + + +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + +/** + * @brief This function is called to create BIG. + * + * @param[in] big_creat_param: pointer to User defined big_creat_param data structure. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_create_big(esp_ble_iso_big_creat_params_t *big_creat_param); + +/** + * @brief This function is called to create BIG test. + * + * @param[in] big_creat_test_param: pointer to User defined big_creat_test_param data structure. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_create_big_test(esp_ble_iso_big_creat_test_params_t *big_creat_test_param); + +/** + * @brief This function is called to terminate a BIG. + * + * @param[in] big_handle: Used to identify the BIG. + * @param[in] reason: indicate the reason why the BIG is to be terminated. + * + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_terminate_big(uint8_t big_handle, uint8_t reason); +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + +/** + * @brief This function is called to create BIG sync. + * + * @param[in] big_sync_create_param: pointer to User defined big_sync_create_param data structure. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_big_create_sync(esp_ble_iso_big_sync_creat_params_t *big_sync_create_param); + +/** + * @brief This function is called to terminate BIG sync. + * + * @param[in] big_handle: Identifier of the BIG. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_big_terminate_sync(uint8_t big_handle); +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + +/** + * @brief This function is called to set iso data path. + * + * @param[in] data_path_params: pointer to User defined data_path_params data structure. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_set_iso_data_path(esp_ble_iso_set_data_path_params_t *data_path_params); + +/** + * @brief This function is called to remove iso data path. + * + * @param[in] data_path_params: pointer to User defined data_path_params data structure. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_remove_iso_data_path(esp_ble_iso_remove_data_path_params_t *data_path_params); + +/** + * @brief This function is called to read tx sync. + * + * @param[in] iso_handle: Connection handle of the CIS or BIS. + + * + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_read_iso_tx_sync(uint16_t iso_handle); + +/** + * @brief This function is called to read link quality. + * + * @param[in] iso_handle: Connection handle of the CIS or BIS. + + * + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_read_link_quality(uint16_t iso_handle); + +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +/** + * @brief This function is called to accept cis request. + * + * @param[in] cis_handle: Connection handle of the CIS + + * + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_accept_cis_request(uint16_t cis_handle); + +/** + * @brief This function is called to reject cis request. + * + * @param[in] cis_handle: Connection handle of the CIS + * @param[in] reason: The reason for rejecting the CIS request + * + * + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_reject_cis_request(uint16_t cis_handle, uint8_t reason); +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +/** + * @brief This function is called to set cig parameters. + * + * @param[in] cig_params: pointer to User defined cig_params data structure. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_set_cig_parameters(struct esp_ble_iso_set_cig_params *cig_params); + +/** + * @brief This function is called to set cig test parameters. + * + * @param[in] cig_params_test: pointer to User defined cig_params_test data structure. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_set_cig_parameters_test(struct esp_ble_iso_set_cig_params_test *cig_params_test); + +/** + * @brief This function is called to create cis. + * + * @param[in] creat_cis_params: pointer to User defined creat_cis_params data structure. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_create_cis(struct esp_ble_iso_create_cis_params *creat_cis_params); + +/** + * @brief This function is called to remove CIG. + * + * @param[in] cig_id: Identifier of a CIG. + + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_remove_cig(uint8_t cig_id); +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_EN == TRUE) + +/** + * @brief This function is called to disconnect cis. + * + * @param[in] cis_handle: Connection handle of the CIS + * @param[in] reason: The reason for disconnecting the CIS. ESP_HCI_ERR_REMOTE_USER_TERM_CONN is recommended. + * + * The value of the reason is one of the following values: + * - ESP_HCI_ERR_AUTH_FAIL + * - ESP_HCI_ERR_REMOTE_USER_TERM_CONN + * - ESP_HCI_ERR_REMOTE_LOW_RESOURCES + * - ESP_HCI_ERR_REMOTE_POWER_OFF + * - ESP_HCI_ERR_UNSUPP_REMOTE_FEATURE + * - ESP_HCI_ERR_PAIRING_NOT_SUPPORTED + * - ESP_HCI_ERR_UNACCEPT_CONN_PARAM + * + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_iso_disconnect_cis(uint16_t cis_handle, uint8_t reason); +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) + +#ifdef __cplusplus +} +#endif + +#endif /* __ESP_BLE_ISO_API_H__ */ diff --git a/lib/bt/host/bluedroid/api/include/api/esp_bt_defs.h b/lib/bt/host/bluedroid/api/include/api/esp_bt_defs.h index 182f8760..d6a2718a 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_bt_defs.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_bt_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +19,83 @@ extern "C" { return ESP_ERR_INVALID_STATE; \ } -#define ESP_BT_STATUS_BASE_FOR_HCI_ERR 0X0100 /* base for converting HCI error code to ESP status */ +#define ESP_BT_STATUS_BASE_FOR_HCI_ERR 0X0100 /* base for converting HCI error code to ESP status */ + +/* See [Vol 1] Part F, Controller Error Codes for a list of error codes and descriptions */ + +#define ESP_HCI_ERR_SUCCESS 0x00 /* Success */ +#define ESP_HCI_ERR_UNKNOWN_CMD 0x01 /* Unknown HCI Command */ +#define ESP_HCI_ERR_UNKNOWN_CONN_ID 0x02 /* Unknown Connection Identifier */ +#define ESP_HCI_ERR_HW_FAILURE 0x03 /* Hardware Failure */ +#define ESP_HCI_ERR_PAGE_TIMEOUT 0x04 /* Page Timeout */ +#define ESP_HCI_ERR_AUTH_FAIL 0x05 /* Authentication Failure */ +#define ESP_HCI_ERR_PIN_OR_KEY_MISSING 0x06 /* PIN or Key Missing */ +#define ESP_HCI_ERR_MEM_CAPACITY_EXCEEDED 0x07 /* Memory Capacity Exceeded */ +#define ESP_HCI_ERR_CONN_TIMEOUT 0x08 /* Connection Timeout */ +#define ESP_HCI_ERR_CONN_LIMIT_EXCEEDED 0x09 /* Connection Limit Exceeded */ +#define ESP_HCI_ERR_SYNC_CONN_LIMIT_EXCEEDED 0x0A /* ASynchronous Connection Limit To A Device Exceeded */ +#define ESP_HCI_ERR_CONN_ALREADY_EXISTS 0x0B /* Connection Already Exists */ +#define ESP_HCI_ERR_CMD_DISALLOWED 0x0C /* Command Disallowed */ +#define ESP_HCI_ERR_INSUFFICIENT_RESOURCES 0x0D /* Connection Rejected due to Limited Resources */ +#define ESP_HCI_ERR_INSUFFICIENT_SECURITY 0x0E /* Connection Rejected Due To Security Reasons */ +#define ESP_HCI_ERR_BD_ADDR_UNACCEPTABLE 0x0F /* Connection Rejected due to Unacceptable BD_ADDR */ +#define ESP_HCI_ERR_CONN_ACCEPT_TIMEOUT 0x10 /* Connection Accept Timeout Exceeded */ +#define ESP_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL 0x11 /* Unsupported Feature or Parameter Value */ +#define ESP_HCI_ERR_INVALID_PARAM 0x12 /* Invalid HCI Command Parameters */ +#define ESP_HCI_ERR_REMOTE_USER_TERM_CONN 0x13 /* Remote User Terminated Connection */ +#define ESP_HCI_ERR_REMOTE_LOW_RESOURCES 0x14 /* Remote Device Terminated Connection due to Low Resources */ +#define ESP_HCI_ERR_REMOTE_POWER_OFF 0x15 /* Remote Device Terminated Connection due to Power Off */ +#define ESP_HCI_ERR_LOCALHOST_TERM_CONN 0x16 /* Connection Terminated By Local Host */ +#define ESP_HCI_ERR_REPEATED_ATTEMPTS 0x17 /* Repeated Attempts */ +#define ESP_HCI_ERR_PAIRING_NOT_ALLOWED 0x18 /* Pairing Not Allowed */ +#define ESP_HCI_ERR_UNKNOWN_LMP_PDU 0x19 /* Unknown LMP PDU */ +#define ESP_HCI_ERR_UNSUPP_REMOTE_FEATURE 0x1A /* Unsupported Remote Feature */ +#define ESP_HCI_ERR_SCO_OFFSET_REJECTED 0x1B /* SCO Offset Rejected */ +#define ESP_HCI_ERR_SCO_INTERVAL_REJECTED 0x1C /* SCO Interval Rejected */ +#define ESP_HCI_ERR_SCO_AIR_MODE_REJECTED 0x1D /* SCO Air Mode Rejected */ +#define ESP_HCI_ERR_INVALID_LL_PARAM 0x1E /* Invalid LMP Parameters / Invalid LL Parameters */ +#define ESP_HCI_ERR_UNSPECIFIED 0x1F /* Unspecified Error */ +#define ESP_HCI_ERR_UNSUPP_LL_PARAM_VAL 0x20 /* Unsupported LMP Parameter Value / Unsupported LL Parameter Value */ +#define ESP_HCI_ERR_ROLE_CHANGE_NOT_ALLOWED 0x21 /* Role Change Not Allowed */ +#define ESP_HCI_ERR_LL_RESP_TIMEOUT 0x22 /* LMP Response Timeout / LL Response Timeout */ +#define ESP_HCI_ERR_LL_PROC_COLLISION 0x23 /* LMP Error Transaction Collision / LL Procedure Collision */ +#define ESP_HCI_ERR_LMP_PDU_NOT_ALLOWED 0x24 /* LMP PDU Not Allowed */ +#define ESP_HCI_ERR_ENC_MODE_NOT_ACCEPTABLE 0x25 /* Encryption Mode Not Acceptable */ +#define ESP_HCI_ERR_LINK_KEY_CANNOT_BE_CHANGED 0x26 /* Link Key cannot be Changed */ +#define ESP_HCI_ERR_REQUESTED_QOS_NOT_SUPPORTED 0x27 /* Requested QoS Not Supported */ +#define ESP_HCI_ERR_INSTANT_PASSED 0x28 /* Instant Passed */ +#define ESP_HCI_ERR_PAIRING_NOT_SUPPORTED 0x29 /* Pairing With Unit Key Not Supported */ +#define ESP_HCI_ERR_DIFF_TRANS_COLLISION 0x2A /* Different Transaction Collision */ +#define ESP_HCI_ERR_UNDEFINED_0x2B 0x2B /* Reserved for future use */ +#define ESP_HCI_ERR_QOS_UNACCEPTABLE_PARAM 0x2C /* QoS Unacceptable Parameter */ +#define ESP_HCI_ERR_QOS_REJECTED 0x2D /* QoS Rejected */ +#define ESP_HCI_ERR_CHAN_ASSESS_NOT_SUPPORTED 0x2E /* Channel Classification Not Supported */ +#define ESP_HCI_ERR_INSUFF_SECURITY 0x2F /* Insufficient Security */ +#define ESP_HCI_ERR_PARAM_OUT_OF_MANDATORY_RANGE 0x30 /* Parameter Out Of Mandatory Range */ +#define ESP_HCI_ERR_UNDEFINED_0x31 0x31 /* Reserved for future use */ +#define ESP_HCI_ERR_ROLE_SWITCH_PENDING 0x32 /* Role Switch Pending */ +#define ESP_HCI_ERR_UNDEFINED_0x33 0x33 /* Reserved for future use */ +#define ESP_HCI_ERR_RESERVED_SLOT_VIOLATION 0x34 /* Reserved Slot Violation */ +#define ESP_HCI_ERR_ROLE_SWITCH_FAILED 0x35 /* Role Switch Failed */ +#define ESP_HCI_ERR_EXT_INQ_RESP_TOO_LARGE 0x36 /* Extended Inquiry Response Too Large */ +#define ESP_HCI_ERR_SIMPLE_PAIR_NOT_SUPP_BY_HOST 0x37 /* Secure Simple Pairing Not Supported By Host */ +#define ESP_HCI_ERR_HOST_BUSY_PAIRING 0x38 /* Host Busy - Pairing*/ +#define ESP_HCI_ERR_CONN_REJECTED_DUE_TO_NO_CHAN 0x39 /* Connection Rejected due to No Suitable Channel Found */ +#define ESP_HCI_ERR_CONTROLLER_BUSY 0x3A /* Controller Busy */ +#define ESP_HCI_ERR_UNACCEPT_CONN_PARAM 0x3B /* Unacceptable Connection Parameters */ +#define ESP_HCI_ERR_ADV_TIMEOUT 0x3C /* Advertising Timeout */ +#define ESP_HCI_ERR_TERM_DUE_TO_MIC_FAIL 0x3D /* Connection Terminated due to MIC Failure */ +#define ESP_HCI_ERR_CONN_FAIL_TO_ESTAB 0x3E /* Connection Failed to be Established / Synchronization Timeout */ +#define ESP_HCI_ERR_MAC_CONN_FAILED 0x3F /* Previously used */ +#define ESP_HCI_ERR_CLOCK_ADJUST_REJECTED 0x40 /* Coarse Clock Adjustment Rejected but Will Try to Adjust Using Clock Dragging */ +#define ESP_HCI_ERR_SUBMAP_NOT_DEFINED 0x41 /* Type0 Submap Not Defined */ +#define ESP_HCI_ERR_UNKNOWN_ADV_IDENTIFIER 0x42 /* Unknown Advertising Identifier */ +#define ESP_HCI_ERR_LIMIT_REACHED 0x43 /* Limit Reached */ +#define ESP_HCI_ERR_OP_CANCELLED_BY_HOST 0x44 /* Operation Cancelled by Host */ +#define ESP_HCI_ERR_PACKET_TOO_LONG 0x45 /* Packet Too Long */ +#define ESP_HCI_ERR_TOO_LATE 0x46 /* Too Late */ +#define ESP_HCI_ERR_TOO_EARLY 0x47 /* Too Early */ +#define ESP_HCI_ERR_INSUFFICIENT_CHANNELS 0x48 /* Insufficient Channels */ /* relate to BT_STATUS_xxx in bt_def.h */ /// Status Return Value @@ -110,6 +186,14 @@ typedef enum { ESP_BT_STATUS_HCI_CONN_TOUT_DUE_TO_MIC_FAILURE, ESP_BT_STATUS_HCI_CONN_FAILED_ESTABLISHMENT, ESP_BT_STATUS_HCI_MAC_CONNECTION_FAILED, + ESP_BT_STATUS_HCI_CCA_REJECTED, + ESP_BT_STATUS_HCI_TYPE0_SUBMAP_NOT_DEFINED, + ESP_BT_STATUS_HCI_UNKNOWN_ADV_ID, + ESP_BT_STATUS_HCI_LIMIT_REACHED, + ESP_BT_STATUS_HCI_OPT_CANCEL_BY_HOST, + ESP_BT_STATUS_HCI_PKT_TOO_LONG, + ESP_BT_STATUS_HCI_TOO_LATE, + ESP_BT_STATUS_HCI_TOO_EARLY, } esp_bt_status_t; @@ -137,6 +221,25 @@ typedef uint8_t esp_link_key[ESP_BT_OCTET16_LEN]; /* Link Key */ #define ESP_BLE_CONN_SUP_TOUT_MIN 0x000A /*!< relate to BTM_BLE_CONN_SUP_TOUT_MIN in stack/btm_ble_api.h */ #define ESP_BLE_CONN_SUP_TOUT_MAX 0x0C80 /*!< relate to ESP_BLE_CONN_SUP_TOUT_MAX in stack/btm_ble_api.h */ +#define ESP_BLE_PHY_1M_PREF_MASK (1 << 0) /*!< The Host prefers use the LE1M transmitter or receiver PHY */ +#define ESP_BLE_PHY_2M_PREF_MASK (1 << 1) /*!< The Host prefers use the LE2M transmitter or receiver PHY */ +#define ESP_BLE_PHY_CODED_PREF_MASK (1 << 2) /*!< The Host prefers use the LE CODED transmitter or receiver PHY */ +typedef uint8_t esp_ble_phy_mask_t; + +/** +* @brief create connection parameters +*/ +typedef struct { + uint16_t scan_interval; /*!< Initial scan interval, in units of 0.625ms, the range is 0x0004(2.5ms) to 0xFFFF(10.24s). */ + uint16_t scan_window; /*!< Initial scan window, in units of 0.625ms, the range is 0x0004(2.5ms) to 0xFFFF(10.24s). */ + uint16_t interval_min; /*!< Minimum connection interval, in units of 1.25ms, the range is 0x0006(7.5ms) to 0x0C80(4s). */ + uint16_t interval_max; /*!< Maximum connection interval, in units of 1.25ms, the range is 0x0006(7.5ms) to 0x0C80(4s). */ + uint16_t latency; /*!< Connection latency, the range is 0x0000(0) to 0x01F3(499). */ + uint16_t supervision_timeout; /*!< Connection supervision timeout, in units of 10ms, the range is from 0x000A(100ms) to 0x0C80(32s). */ + uint16_t min_ce_len; /*!< Minimum connection event length, in units of 0.625ms, setting to 0 for no preferred parameters. */ + uint16_t max_ce_len; /*!< Maximum connection event length, in units of 0.625ms, setting to 0 for no preferred parameters. */ +} esp_ble_conn_params_t; + /// Check the param is valid or not #define ESP_BLE_IS_VALID_PARAM(x, min, max) (((x) >= (min) && (x) <= (max)) ) @@ -179,8 +282,11 @@ typedef enum { /// white list address type typedef enum { - BLE_WL_ADDR_TYPE_PUBLIC = 0x00, - BLE_WL_ADDR_TYPE_RANDOM = 0x01, + BLE_WL_ADDR_TYPE_PUBLIC = 0x00, /*!< Public Device Address */ + BLE_WL_ADDR_TYPE_RANDOM = 0x01, /*!< Random Device Address */ +#if (CONFIG_BT_BLE_50_FEATURES_SUPPORTED) + BLE_WL_ADDR_TYPE_ANONYMOUS = 0xFF, /*!< Devices sending anonymous advertisements, use to enable anonymous advertising report for scanning */ +#endif // (CONFIG_BT_BLE_50_FEATURES_SUPPORTED) } esp_ble_wl_addr_type_t; /// Used to exchange the encryption key in the init key & response key @@ -201,6 +307,10 @@ typedef uint8_t esp_ble_key_mask_t; /* the key mask type */ #define ESP_BD_ADDR_STR "%02x:%02x:%02x:%02x:%02x:%02x" #define ESP_BD_ADDR_HEX(addr) addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] +#define ESP_BLE_ADV_NAME_LEN_MAX 29 + +#define ESP_INVALID_CONN_HANDLE 0xfff + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/bluedroid/api/include/api/esp_bt_device.h b/lib/bt/host/bluedroid/api/include/api/esp_bt_device.h index 6e12765c..60758f1e 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_bt_device.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_bt_device.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -128,6 +128,17 @@ esp_err_t esp_bt_dev_get_device_name(void) __attribute__((deprecated("Please use */ esp_err_t esp_bt_dev_coex_status_config(esp_bt_dev_coex_type_t type, esp_bt_dev_coex_op_t op, uint8_t status); +/** + * @brief This function is used to get the path name of the Bluetooth bond keys + * saved in the NVS module. + * @param[out] file_path: buffer to store the config file path, max length NVS_KEY_NAME_MAX_SIZE + * + * @return + * - ESP_OK: success + * + */ +esp_err_t esp_bt_config_file_path_get(char *file_path); + /** * @brief This function is used to update the path name of bluetooth bond keys saved in the NVS module * and need to be called before esp_bluedroid_init(). diff --git a/lib/bt/host/bluedroid/api/include/api/esp_bt_main.h b/lib/bt/host/bluedroid/api/include/api/esp_bt_main.h index b13ae94d..b9b60e3d 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_bt_main.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_bt_main.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,11 +30,13 @@ typedef enum { */ typedef struct { bool ssp_en; /*!< Whether SSP(secure simple pairing) or legacy pairing is used for Classic Bluetooth */ + bool sc_en; /*!< Whether secure connection host support is enabled or disabled for Classic Bluetooth */ } esp_bluedroid_config_t; #define BT_BLUEDROID_INIT_CONFIG_DEFAULT() \ { \ .ssp_en = true, \ + .sc_en = false, \ } /** @@ -55,7 +57,10 @@ esp_bluedroid_status_t esp_bluedroid_get_status(void); esp_err_t esp_bluedroid_enable(void); /** - * @brief Disable bluetooth, must prior to esp_bluedroid_deinit(). + * @brief Disable Bluetooth, must be called prior to esp_bluedroid_deinit(). + * + * @note Before calling this API, ensure that all activities related to + * the application, such as connections, scans, etc., are properly closed. * * @return * - ESP_OK : Succeed @@ -92,6 +97,11 @@ esp_err_t esp_bluedroid_init_with_cfg(esp_bluedroid_config_t *cfg); */ esp_err_t esp_bluedroid_deinit(void); +#if defined(CONFIG_EXAMPLE_CI_ID) && defined(CONFIG_EXAMPLE_CI_PIPELINE_ID) +// Only for internal used (CI example test) +char *esp_bluedroid_get_example_name(void); +#endif + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h b/lib/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h index ea52baf0..066103fa 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_gap_ble_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -229,6 +229,23 @@ typedef enum { ESP_GAP_BLE_ADD_DEV_TO_RESOLVING_LIST_COMPLETE_EVT, /*!< when add a device to the resolving list completes, the event comes*/ ESP_GAP_BLE_VENDOR_CMD_COMPLETE_EVT, /*!< When vendor hci command complete, the event comes */ ESP_GAP_BLE_SET_PRIVACY_MODE_COMPLETE_EVT, /*!< When set privacy mode complete, the event comes */ + ESP_GAP_BLE_SET_CSA_SUPPORT_COMPLETE_EVT, /*!< When set CSA support complete, the event comes */ + ESP_GAP_BLE_SET_VENDOR_EVT_MASK_COMPLETE_EVT, /*!< When set vendor event mask complete, the event comes */ + ESP_GAP_BLE_VENDOR_HCI_EVT, /*!< When BLE vendor HCI event received, the event comes */ + // BLE power control + ESP_GAP_BLE_ENH_READ_TRANS_PWR_LEVEL_EVT, /*!< When reading the current and maximum transmit power levels of the local Controller complete, the event comes */ + ESP_GAP_BLE_READ_REMOTE_TRANS_PWR_LEVEL_EVT, /*!< When reading the transmit power level used by the remote Controller on the ACL connection complete, the event comes */ + ESP_GAP_BLE_SET_PATH_LOSS_RPTING_PARAMS_EVT, /*!< when set the path loss threshold reporting parameters complete, the event comes */ + ESP_GAP_BLE_SET_PATH_LOSS_RPTING_ENABLE_EVT, /*!< when enable or disable path loss reporting complete, the event comes */ + ESP_GAP_BLE_SET_TRANS_PWR_RPTING_ENABLE_EVT, /*!< when enable or disable the reporting to the local Host of transmit power level changes complete, the event comes */ + ESP_GAP_BLE_PATH_LOSS_THRESHOLD_EVT, /*!< when receive a path loss threshold crossing, the event comes */ + ESP_GAP_BLE_TRANS_PWR_RPTING_EVT, /*!< when receive a transmit power level report, the event comes */ + // BLE connection subrating + ESP_GAP_BLE_SET_DEFAULT_SUBRATE_COMPLETE_EVT, /*!< when set default subrate complete, the event comes */ + ESP_GAP_BLE_SUBRATE_REQUEST_COMPLETE_EVT, /*!< when subrate request command complete, the event comes */ + ESP_GAP_BLE_SUBRATE_CHANGE_EVT, /*!< when Connection Subrate Update procedure has completed and some parameters of the specified connection have changed, the event comes */ + ESP_GAP_BLE_SET_HOST_FEATURE_CMPL_EVT, /*!< When host feature set complete, the event comes */ + ESP_GAP_BLE_READ_CHANNEL_MAP_COMPLETE_EVT, /*!< When BLE channel map result is received, the event comes */ ESP_GAP_BLE_EVT_MAX, /*!< when maximum advertising event complete, the event comes */ } esp_gap_ble_cb_event_t; @@ -631,6 +648,7 @@ typedef struct { esp_bd_addr_t bd_addr; /*!< peer address */ esp_ble_bond_key_info_t bond_key; /*!< the bond key information */ + esp_ble_addr_type_t bd_addr_type; /*!< peer address type */ } esp_ble_bond_dev_t; /*!< the ble bond device type */ @@ -661,21 +679,55 @@ typedef struct { esp_bt_octet16_t oob_r; /*!< the 128 bits of randomizer value */ } esp_ble_local_oob_data_t; +/** +* @brief Definition of the authentication failed reason +*/ +typedef enum { + // Failure reason defined in Bluetooth Core Spec 5.0 Vol3, Part H, 3.5.5 + ESP_AUTH_SMP_PASSKEY_FAIL = 78, /*!< The user input of passkey failed */ + ESP_AUTH_SMP_OOB_FAIL, /*!< The OOB data is not available */ + ESP_AUTH_SMP_PAIR_AUTH_FAIL, /*!< The authentication requirements cannot be met */ + ESP_AUTH_SMP_CONFIRM_VALUE_FAIL, /*!< The confirm value does not match the calculated comparison value */ + ESP_AUTH_SMP_PAIR_NOT_SUPPORT, /*!< Pairing is not supported by the device */ + ESP_AUTH_SMP_ENC_KEY_SIZE, /*!< The resultant encryption key size is not long enough */ + ESP_AUTH_SMP_INVALID_CMD, /*!< The SMP command received is not supported by this device */ + ESP_AUTH_SMP_UNKNOWN_ERR, /*!< Pairing failed due to an unspecified reason */ + ESP_AUTH_SMP_REPEATED_ATTEMPT, /*!< Pairing or authentication procedure is disallowed */ + ESP_AUTH_SMP_INVALID_PARAMETERS, /*!< The command length is invalid or that a parameter is outside the specified range */ + ESP_AUTH_SMP_DHKEY_CHK_FAIL, /*!< The DHKey Check value received doesn’t match the one calculated by the local device */ + ESP_AUTH_SMP_NUM_COMP_FAIL, /*!< The confirm values in the numeric comparison protocol do not match */ + ESP_AUTH_SMP_BR_PARING_IN_PROGR, /*!< Pairing Request sent over the BR/EDR transport is in progress */ + ESP_AUTH_SMP_XTRANS_DERIVE_NOT_ALLOW, /*!< The BR/EDR Link Key or BLE LTK cannot be used to derive */ + + // Failure reason defined in Bluedroid Host + ESP_AUTH_SMP_INTERNAL_ERR, /*!< Internal error in pairing procedure */ + ESP_AUTH_SMP_UNKNOWN_IO, /*!< Unknown IO capability, unable to decide association model */ + ESP_AUTH_SMP_INIT_FAIL, /*!< SMP pairing initiation failed */ + ESP_AUTH_SMP_CONFIRM_FAIL, /*!< The confirm value does not match */ + ESP_AUTH_SMP_BUSY, /*!< Pending security request on going */ + ESP_AUTH_SMP_ENC_FAIL, /*!< The Controller failed to start encryption */ + ESP_AUTH_SMP_STARTED, /*!< SMP pairing process started */ + ESP_AUTH_SMP_RSP_TIMEOUT, /*!< Security Manager timeout due to no SMP command being received */ + ESP_AUTH_SMP_DIV_NOT_AVAIL, /*!< Encrypted Diversifier value not available */ + ESP_AUTH_SMP_UNSPEC_ERR, /*!< Unspecified failed reason */ + ESP_AUTH_SMP_CONN_TOUT, /*!< Pairing process failed due to connection timeout */ +} esp_ble_auth_fail_rsn_t; + /** * @brief Structure associated with ESP_AUTH_CMPL_EVT */ typedef struct { - esp_bd_addr_t bd_addr; /*!< BD address peer device. */ - bool key_present; /*!< Valid link key value in key element */ - esp_link_key key; /*!< Link key associated with peer device. */ - uint8_t key_type; /*!< The type of Link Key */ - bool success; /*!< TRUE of authentication succeeded, FALSE if failed. */ - uint8_t fail_reason; /*!< The HCI reason/error code for when success=FALSE */ - esp_ble_addr_type_t addr_type; /*!< Peer device address type */ - esp_bt_dev_type_t dev_type; /*!< Device type */ - esp_ble_auth_req_t auth_mode; /*!< authentication mode */ -} esp_ble_auth_cmpl_t; /*!< The ble authentication complete cb type */ + esp_bd_addr_t bd_addr; /*!< BD address of peer device */ + bool key_present; /*!< True if the link key value is valid; false otherwise */ + esp_link_key key; /*!< Link key associated with peer device */ + uint8_t key_type; /*!< The type of link key */ + bool success; /*!< True if authentication succeeded; false otherwise */ + esp_ble_auth_fail_rsn_t fail_reason; /*!< The HCI reason/error code for failure when success is false */ + esp_ble_addr_type_t addr_type; /*!< Peer device address type */ + esp_bt_dev_type_t dev_type; /*!< Device type */ + esp_ble_auth_req_t auth_mode; /*!< Authentication mode */ +} esp_ble_auth_cmpl_t; /*!< The ble authentication complete cb type */ /** * @brief union associated with ble security @@ -846,6 +898,10 @@ typedef uint8_t esp_ble_gap_adv_type_t; /// Extend advertising tx power, range: [-127, +126] dBm #define EXT_ADV_TX_PWR_NO_PREFERENCE (127) /*!< host has no preference for tx power */ + +/// max number of advertising sets to enable or disable +#define EXT_ADV_NUM_SETS_MAX (10) /*!< max evt instance num */ + /** * @brief ext adv parameters */ @@ -926,19 +982,27 @@ typedef struct { esp_ble_gap_sync_t filter_policy; /*!< Configures the filter policy for periodic advertising sync: 0: Use Advertising SID, Advertiser Address Type, and Advertiser Address parameters to determine the advertiser to listen to. 1: Use the Periodic Advertiser List to determine the advertiser to listen to. */ - #if (CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH) +#if (CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH) esp_ble_gap_sync_t reports_disabled; /*!< Supported only by esp32c2, esp32c6, and esp32h2; can be set by menuconfig: 0: Reporting initially enabled. 1: Reporting initially disabled. */ esp_ble_gap_sync_t filter_duplicates; /*!< Supported only by esp32c2, esp32c6, and esp32h2; can be set by menuconfig: 0: Duplicate filtering initially disabled. 1: Duplicate filtering initially enabled. */ - #endif +#endif // (CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH) uint8_t sid; /*!< SID of the periodic advertising */ esp_ble_addr_type_t addr_type; /*!< Address type of the periodic advertising */ esp_bd_addr_t addr; /*!< Address of the periodic advertising */ uint16_t skip; /*!< Maximum number of periodic advertising events that can be skipped */ uint16_t sync_timeout; /*!< Synchronization timeout */ +#if (CONFIG_BT_BLE_FEAT_CTE_EN) + uint8_t sync_cte_type; /*!< Whether to only synchronize to periodic advertising with certain types of CTE (Constant Tone Extension) + bit 0: Do not sync to packets with an AoA CTE + bit 1: Do not sync to packets with an AoD CTE with 1 μs slots + bit 2: Do not sync to packets with an AoD CTE with 2 μs slots + bit 3: Do not sync to packets with a type 3 CTE (currently reserved for future use) + bit 4: Do not sync to packets without a CTE */ +#endif // BT_BLE_FEAT_CTE_EN } esp_ble_gap_periodic_adv_sync_params_t; /** @@ -970,13 +1034,20 @@ typedef struct { uint16_t sync_handle; /*!< periodic advertising train handle */ uint8_t tx_power; /*!< periodic advertising tx power*/ int8_t rssi; /*!< periodic advertising rssi */ +#if (CONFIG_BT_BLE_FEAT_CTE_EN) // #if (BLE_FEAT_CTE_EN == TRUE) + uint8_t cte_type; /*!< The type of Constant Tone Extension + 0x00: AoA Constant Tone Extension + 0x01: AoD Constant Tone Extension with 1 μs slots + 0x02: AoD Constant Tone Extension with 2 μs slots + 0xFF: No Constant Tone Extension */ +#endif // BT_BLE_FEAT_CTE_EN esp_ble_gap_ext_adv_data_status_t data_status; /*!< periodic advertising data type*/ uint8_t data_length; /*!< periodic advertising data length */ uint8_t data[251]; /*!< periodic advertising data */ } esp_ble_gap_periodic_adv_report_t; /** -* @brief perodic adv sync establish parameters +* @brief periodic adv sync establish parameters */ typedef struct { uint8_t status; /*!< periodic advertising sync status */ @@ -1031,11 +1102,123 @@ typedef struct { } esp_ble_gap_past_params_t; #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) -typedef enum{ +typedef enum { ESP_BLE_NETWORK_PRIVACY_MODE = 0X00, /*!< Network Privacy Mode for peer device (default) */ ESP_BLE_DEVICE_PRIVACY_MODE = 0X01, /*!< Device Privacy Mode for peer device */ } esp_ble_privacy_mode_t; +#define ESP_BLE_VENDOR_SCAN_REQ_RECV_EVT_MASK BIT(0) /*!< Vendor BLE legacy SCAN_REQ received event mask */ +#define ESP_BLE_VENDOR_CHMAP_UPDATE_EVT_MASK BIT(1) /*!< Vendor BLE channel map update event mask */ +#define ESP_BLE_VENDOR_SLEEP_WAKEUP_EVT_MASK BIT(3) /*!< Vendor BLE sleep wakeup event mask */ +#define ESP_BLE_VENDOR_CONN_REQ_RECV_EVT_MASK BIT(4) /*!< Vendor BLE CONNECT_IND and AUX_CONNECT_REQ received event mask */ +#define ESP_BLE_VENDOR_CONN_RSP_RECV_EVT_MASK BIT(5) /*!< Vendor BLE AUX_CONNECT_RSP received event mask */ +typedef uint32_t esp_ble_vendor_evt_mask_t; + +#define ESP_BLE_VENDOR_PDU_RECV_EVT (0) /*!< Vendor BLE specify PDU received event */ +#define ESP_BLE_VENDOR_CHAN_MAP_UPDATE_EVT (1) /*!< Vendor BLE channel map update complete event */ +#define ESP_BLE_VENDOR_SLEEP_WAKEUP_EVT (2) /*!< Vendor BLE sleep wakeup event */ +typedef uint8_t esp_ble_vendor_evt_t; + +typedef enum { + ESP_BLE_VENDOR_PDU_SCAN_REQ = 0, /*!< SCAN_REQ PDU type */ + ESP_BLE_VENDOR_PDU_CONN_REQ, /*!< CONNECT_IND and AUX_CONNECT_REQ PDU type */ + ESP_BLE_VENDOR_PDU_CONN_RSP, /*!< AUX_CONNECT_RSP PDU type */ +} esp_ble_vendor_pdu_t; + +/** + * @brief BLE vendor event parameters union + */ +typedef union { + /** + * @brief ESP_BLE_VENDOR_PDU_RECV_EVT + */ + struct ble_pdu_recv_evt_param { + esp_ble_vendor_pdu_t type; /*!< The type of LE PDU */ + uint8_t handle; /*!< The handle of advertising set */ + esp_ble_addr_type_t addr_type; /*!< The address type of peer device */ + esp_bd_addr_t peer_addr; /*!< The address of peer device */ + } pdu_recv; /*!< Event parameter of ESP_BLE_VENDOR_PDU_RECV_EVT */ + /** + * @brief ESP_BLE_VENDOR_CHAN_MAP_UPDATE_EVT + */ + struct ble_chan_map_update_evt_param { + uint8_t status; /*!< Indicate the channel map update status (HCI error code) */ + uint16_t conn_handle; /*!< The connection handle */ + esp_gap_ble_channels ch_map; /*!< The channel map after updated */ + } chan_map_update; /*!< Event parameter of ESP_BLE_VENDOR_CHAN_MAP_UPDATE_EVT */ + /** + * @brief ESP_BLE_VENDOR_SLEEP_WAKEUP_EVT + */ + struct ble_sleep_wakeup_evt_param { + // No parameters + } sleep_wakeup; /*!< Event parameter of ESP_BLE_VENDOR_SLEEP_WAKEUP_EVT */ +} esp_ble_vendor_evt_param_t; + +/** +* @brief path loss report parameters +*/ +typedef struct { + uint16_t conn_handle; /*!< Connection_Handle */ + uint8_t high_threshold; /*!< High threshold for the path loss (dB) */ + uint8_t high_hysteresis; /*!< Hysteresis value for the high threshold (dB) */ + uint8_t low_threshold; /*!< Low threshold for the path loss (dB) */ + uint8_t low_hysteresis; /*!< Hysteresis value for the low threshold (dB) */ + uint16_t min_time_spent; /*!< Minimum time in number of connection events to be observed + once the path loss crosses the threshold before an event is generated */ +} esp_ble_path_loss_rpt_params_t; + +typedef enum { + /*!< No PHY is set, should not be used */ + ESP_BLE_CONN_TX_POWER_PHY_NONE = 0, + /*!< LE 1M PHY */ + ESP_BLE_CONN_TX_POWER_PHY_1M = 0x01, + /*!< LE 2M PHY */ + ESP_BLE_CONN_TX_POWER_PHY_2M = 0x02, + /*!< LE Coded PHY using S=8 coding */ + ESP_BLE_CONN_TX_POWER_PHY_CODED_S8 = 0x03, + /*!< LE Coded PHY using S=2 coding */ + ESP_BLE_CONN_TX_POWER_PHY_CODED_S2 = 0x04, +} esp_ble_tx_power_phy_t; + +typedef enum { + /*!< Low zone entered */ + ESP_BLE_CONN_PATH_LOSS_ZONE_ENTERED_LOW = 0x00, + /*!< Middle zone entered */ + ESP_BLE_CONN_PATH_LOSS_ZONE_ENTERED_MIDDLE = 0x01, + /*!< High zone entered */ + ESP_BLE_CONN_PATH_LOSS_ZONE_ENTERED_HIGH = 0x02, +} esp_ble_path_loss_zone_t; + +/** +* @brief Connection subrating default parameters +*/ +typedef struct { + uint16_t subrate_min; /*!< Minimum subrate factor allowed in requests by a Peripheral. Range: 0x0001 to 0x01F4, default: 0x0001 */ + uint16_t subrate_max; /*!< Maximum subrate factor allowed in requests by a Peripheral. Range: 0x0001 to 0x01F4, default: 0x0001. subrate_max × (max_latency + 1) should not be greater than 500 */ + uint16_t max_latency; /*!< Maximum Peripheral latency allowed in requests by a Peripheral, in units of subrated connection intervals. + Range: 0x0000 to 0x01F3, default: 0x0000 */ + uint16_t continuation_number; /*!< Minimum number of underlying connection events to remain active after a packet containing a Link Layer + PDU with a non-zero Length field is sent or received in requests by a Peripheral. Range: 0x0000 to 0x01F3, + default: 0x0000. continuation_number should not greater than or equal to subrate_max */ + uint16_t supervision_timeout; /*!< Maximum supervision timeout allowed in requests by a Peripheral (N * 10 ms). Range: 0x000A to 0x0C80, + Time Range: 100 ms to 32 s, default: 0x0C80 (32 s) */ +} esp_ble_default_subrate_param_t; + +/** +* @brief Connection subrating request parameters +*/ +typedef struct { + uint16_t conn_handle; /*!< Connection handle of the ACL */ + uint16_t subrate_min; /*!< Minimum subrate factor to be applied to the underlying connection interval. Range: 0x0001 to 0x01F4 */ + uint16_t subrate_max; /*!< Maximum subrate factor to be applied to the underlying connection interval. Range: 0x0001 to 0x01F4 */ + uint16_t max_latency; /*!< Maximum Peripheral latency for the connection in units of subrated connection intervals. Range: 0x0000 to 0x01F3 */ + uint16_t continuation_number; /*!< Minimum number of underlying connection events to remain active after a packet containing + a Link Layer PDU with a non-zero Length field is sent or received. Range: 0x0000 to 0x01F3 */ + uint16_t supervision_timeout; /*!< Supervision timeout for this connection (N * 10 ms). Range: 0x000A to 0x0C80, Time Range: 100 ms to 32 s + The supervision_timeout, in milliseconds, shall be greater than 2 × current connection interval × subrate_max × (max_latency + 1) */ +} esp_ble_subrate_req_param_t; + + /** * @brief Gap callback parameters union */ @@ -1122,12 +1305,6 @@ typedef union { struct ble_adv_stop_cmpl_evt_param { esp_bt_status_t status; /*!< Indicate adv stop operation success status */ } adv_stop_cmpl; /*!< Event parameter of ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT */ - /** - * @brief ESP_GAP_BLE_ADV_CLEAR_COMPLETE_EVT - */ - struct ble_adv_clear_cmpl_evt_param { - esp_bt_status_t status; /*!< Indicate adv clear operation success status */ - } adv_clear_cmpl; /*!< Event parameter of ESP_GAP_BLE_ADV_CLEAR_COMPLETE_EVT */ #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) /** * @brief ESP_GAP_BLE_SET_STATIC_RAND_ADDR_EVT @@ -1141,13 +1318,13 @@ typedef union { struct ble_update_conn_params_evt_param { esp_bt_status_t status; /*!< Indicate update connection parameters success status */ esp_bd_addr_t bda; /*!< Bluetooth device address */ - uint16_t min_int; /*!< Min connection interval */ - uint16_t max_int; /*!< Max connection interval */ + uint16_t min_int; /*!< Minimum connection interval. If the master initiates the connection parameter update, this value is not applicable for the slave and will be set to zero. */ + uint16_t max_int; /*!< Maximum connection interval. If the master initiates the connection parameter update, this value is not applicable for the slave and will be set to zero. */ uint16_t latency; /*!< Slave latency for the connection in number of connection events. Range: 0x0000 to 0x01F3 */ - uint16_t conn_int; /*!< Current connection interval */ + uint16_t conn_int; /*!< Current connection interval in milliseconds, calculated as N × 1.25 ms */ uint16_t timeout; /*!< Supervision timeout for the LE Link. Range: 0x000A to 0x0C80. - Mandatory Range: 0x000A to 0x0C80 Time = N * 10 msec */ - } update_conn_params; /*!< Event parameter of ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT */ + This value is calculated as N × 10 ms */ + } update_conn_params; /*!< Event parameter for ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT */ /** * @brief ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT */ @@ -1204,6 +1381,14 @@ typedef union { if the RSSI cannot be read, the RSSI metric shall be set to 127. */ esp_bd_addr_t remote_addr; /*!< The remote device address */ } read_rssi_cmpl; /*!< Event parameter of ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT */ + /** + * @brief ESP_GAP_BLE_READ_CHANNEL_MAP_COMPLETE_EVT + */ + struct ble_read_ble_channel_map_cmpl_evt_param { + esp_bt_status_t status; /*!< Status of the read channel map operation */ + uint8_t channel_map[ESP_GAP_BLE_CHANNELS_LEN]; /*!< The BLE channel map, represented as a 5-byte array */ + esp_bd_addr_t remote_addr; /*!< The remote device address */ + } read_ble_channel_map_cmpl; /*!< Event parameter of ESP_GAP_BLE_READ_CHANNEL_MAP_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_UPDATE_WHITELIST_COMPLETE_EVT */ @@ -1251,77 +1436,93 @@ typedef union { struct ble_set_perf_phy_cmpl_evt_param { esp_bt_status_t status; /*!< Indicate perf phy set status */ } set_perf_phy; /*!< Event parameter of ESP_GAP_BLE_SET_PREFERRED_PHY_COMPLETE_EVT */ +#if (BLE_50_EXTEND_ADV_EN == TRUE) /** * @brief ESP_GAP_BLE_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT */ struct ble_ext_adv_set_rand_addr_cmpl_evt_param { esp_bt_status_t status; /*!< Indicate extend advertising random address set status */ + uint8_t instance; /*!< extend advertising handle */ } ext_adv_set_rand_addr; /*!< Event parameter of ESP_GAP_BLE_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_EXT_ADV_SET_PARAMS_COMPLETE_EVT */ struct ble_ext_adv_set_params_cmpl_evt_param { esp_bt_status_t status; /*!< Indicate extend advertising parameters set status */ + uint8_t instance; /*!< extend advertising handle */ } ext_adv_set_params; /*!< Event parameter of ESP_GAP_BLE_EXT_ADV_SET_PARAMS_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_EXT_ADV_DATA_SET_COMPLETE_EVT */ struct ble_ext_adv_data_set_cmpl_evt_param { esp_bt_status_t status; /*!< Indicate extend advertising data set status */ + uint8_t instance; /*!< extend advertising handle */ } ext_adv_data_set; /*!< Event parameter of ESP_GAP_BLE_EXT_ADV_DATA_SET_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT */ struct ble_ext_adv_scan_rsp_set_cmpl_evt_param { esp_bt_status_t status; /*!< Indicate extend advertising scan response data set status */ + uint8_t instance; /*!< extend advertising handle */ } scan_rsp_set; /*!< Event parameter of ESP_GAP_BLE_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_EXT_ADV_START_COMPLETE_EVT */ struct ble_ext_adv_start_cmpl_evt_param { esp_bt_status_t status; /*!< Indicate advertising start operation success status */ + uint8_t instance_num; /*!< extend advertising handle numble*/ + uint8_t instance[EXT_ADV_NUM_SETS_MAX]; /*!< extend advertising handle list*/ } ext_adv_start; /*!< Event parameter of ESP_GAP_BLE_EXT_ADV_START_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_EXT_ADV_STOP_COMPLETE_EVT */ struct ble_ext_adv_stop_cmpl_evt_param { esp_bt_status_t status; /*!< Indicate advertising stop operation success status */ + uint8_t instance_num; /*!< extend advertising handle numble*/ + uint8_t instance[EXT_ADV_NUM_SETS_MAX]; /*!< extend advertising handle list*/ } ext_adv_stop; /*!< Event parameter of ESP_GAP_BLE_EXT_ADV_STOP_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_EXT_ADV_SET_REMOVE_COMPLETE_EVT */ struct ble_ext_adv_set_remove_cmpl_evt_param { esp_bt_status_t status; /*!< Indicate advertising stop operation success status */ + uint8_t instance; /*!< extend advertising handle */ } ext_adv_remove; /*!< Event parameter of ESP_GAP_BLE_EXT_ADV_SET_REMOVE_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_EXT_ADV_SET_CLEAR_COMPLETE_EVT */ struct ble_ext_adv_set_clear_cmpl_evt_param { esp_bt_status_t status; /*!< Indicate advertising stop operation success status */ + uint8_t instance; /*!< extend advertising handle */ } ext_adv_clear; /*!< Event parameter of ESP_GAP_BLE_EXT_ADV_SET_CLEAR_COMPLETE_EVT */ +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) /** * @brief ESP_GAP_BLE_PERIODIC_ADV_SET_PARAMS_COMPLETE_EVT */ struct ble_periodic_adv_set_params_cmpl_param { esp_bt_status_t status; /*!< Indicate periodic advertisingparameters set status */ + uint8_t instance; /*!< extend advertising handle */ } peroid_adv_set_params; /*!< Event parameter of ESP_GAP_BLE_PERIODIC_ADV_SET_PARAMS_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_PERIODIC_ADV_DATA_SET_COMPLETE_EVT */ struct ble_periodic_adv_data_set_cmpl_param { esp_bt_status_t status; /*!< Indicate periodic advertising data set status */ + uint8_t instance; /*!< extend advertising handle */ } period_adv_data_set; /*!< Event parameter of ESP_GAP_BLE_PERIODIC_ADV_DATA_SET_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_PERIODIC_ADV_START_COMPLETE_EVT */ struct ble_periodic_adv_start_cmpl_param { esp_bt_status_t status; /*!< Indicate periodic advertising start status */ + uint8_t instance; /*!< extend advertising handle */ } period_adv_start; /*!< Event parameter of ESP_GAP_BLE_PERIODIC_ADV_START_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_PERIODIC_ADV_STOP_COMPLETE_EVT */ struct ble_periodic_adv_stop_cmpl_param { esp_bt_status_t status; /*!< Indicate periodic advertising stop status */ + uint8_t instance; /*!< extend advertising handle */ } period_adv_stop; /*!< Event parameter of ESP_GAP_BLE_PERIODIC_ADV_STOP_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_PERIODIC_ADV_CREATE_SYNC_COMPLETE_EVT @@ -1505,6 +1706,19 @@ typedef union { esp_ble_dtm_update_evt_t update_evt; /*!< DTM state change event, 0x00: DTM TX start, 0x01: DTM RX start, 0x02:DTM end */ uint16_t num_of_pkt; /*!< number of packets received, only valid if update_evt is DTM_TEST_STOP_EVT and shall be reported as 0 for a transmitter */ } dtm_state_update; /*!< Event parameter of ESP_GAP_BLE_DTM_TEST_UPDATE_EVT */ + /** + * @brief ESP_GAP_BLE_SET_PRIVACY_MODE_COMPLETE_EVT + */ + struct ble_set_privacy_mode_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate privacy mode set operation success status */ + } set_privacy_mode_cmpl; /*!< Event parameter of ESP_GAP_BLE_SET_PRIVACY_MODE_COMPLETE_EVT */ +#if (BLE_VENDOR_HCI_EN == TRUE) + /** + * @brief ESP_GAP_BLE_ADV_CLEAR_COMPLETE_EVT + */ + struct ble_adv_clear_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate adv clear operation success status */ + } adv_clear_cmpl; /*!< Event parameter of ESP_GAP_BLE_ADV_CLEAR_COMPLETE_EVT */ /** * @brief ESP_GAP_BLE_VENDOR_CMD_COMPLETE_EVT */ @@ -1514,11 +1728,136 @@ typedef union { uint8_t *p_param_buf; /*!< The point of parameter buffer */ } vendor_cmd_cmpl; /*!< Event parameter of ESP_GAP_BLE_VENDOR_CMD_COMPLETE_EVT */ /** - * @brief ESP_GAP_BLE_SET_PRIVACY_MODE_COMPLETE_EVT + * @brief ESP_GAP_BLE_SET_CSA_SUPPORT_COMPLETE_EVT + */ + struct ble_set_csa_support_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate CSA support set operation success status */ + } set_csa_support_cmpl; /*!< Event parameter of ESP_GAP_BLE_SET_CSA_SUPPORT_COMPLETE_EVT */ + /** + * @brief ESP_GAP_BLE_SET_VENDOR_EVT_MASK_COMPLETE_EVT + */ + struct ble_set_vendor_evt_mask_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate set vendor event mask operation success status */ + } set_vendor_evt_mask_cmpl; /*!< Event parameter of ESP_GAP_BLE_SET_VENDOR_EVT_MASK_COMPLETE_EVT */ + /** + * @brief ESP_GAP_BLE_VENDOR_HCI_EVT + */ + struct ble_vendor_hci_event_evt_param { + esp_ble_vendor_evt_t subevt_code; /*!< Subevent code for BLE vendor HCI event */ + esp_ble_vendor_evt_param_t param; /*!< Event parameter of BLE vendor HCI subevent */ + uint8_t param_len; /*!< The length of the event parameter buffer (for internal use only) */ + uint8_t *param_buf; /*!< The pointer of the event parameter buffer (for internal use only) */ + } vendor_hci_evt; /*!< Event parameter of ESP_GAP_BLE_VENDOR_HCI_EVT */ +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + /** + * @brief ESP_GAP_BLE_ENH_READ_TRANS_PWR_LEVEL_EVT + */ + struct ble_enh_read_trans_pwr_level_param { + esp_bt_status_t status; /*!< Indicate enhance reading transmit power level complete status, status = (controller error code | 0x100) if status is not equal to 0 */ + uint16_t conn_handle; /*!< Connection_Handle */ + uint8_t phy; /*!< 1M, 2M, Coded S2 or Coded S8 phy + 0x01: LE 1M PHY + 0x02: LE 2M PHY + 0x03: LE Coded PHY with S=8 data coding + 0x04: LE Coded PHY with S=2 data coding + */ + int8_t cur_tx_pwr_level; /*!< Current transmit power level, Range: -127 to 20, Units: dBm */ + int8_t max_tx_pwr_level; /*!< Maximum transmit power level, Range: -127 to 20, Units: dBm */ + } enh_trans_pwr_level_cmpl; /*!< Event parameter of ESP_GAP_BLE_SET_CSA_SUPPORT_COMPLETE_EVT */ + /** + * @brief ESP_GAP_BLE_READ_REMOTE_TRANS_PWR_LEVEL_EVT + */ + struct ble_read_remote_trans_pwr_level_param { + esp_bt_status_t status; /*!< Indicate reading remote transmit power level complete status, status = (controller error code | 0x100) if status is not equal to 0 */ + } read_remote_trans_pwr_level_cmpl; /*!< Event parameter of ESP_GAP_BLE_READ_REMOTE_TRANS_PWR_LEVEL_EVT */ + /** + * @brief ESP_GAP_BLE_SET_PATH_LOSS_RPTING_PARAMS_EVT + */ + struct ble_set_path_loss_rpting_param { + esp_bt_status_t status; /*!< Indicate setting path loss reporting paramwters complete status, status = (controller error code | 0x100) if status is not equal to 0 */ + uint16_t conn_handle; /*!< The ACL connection identifier */ + } set_path_loss_rpting_params; /*!< Event parameter of ESP_GAP_BLE_SET_PATH_LOSS_RPTING_PARAMS_EVT */ + /** + * @brief ESP_GAP_BLE_SET_PATH_LOSS_RPTING_ENABLE_EVT + */ + struct ble_set_path_loss_rpting_enable { + esp_bt_status_t status; /*!< Indicate setting path loss reporting enable complete status, status = (controller error code | 0x100) if status is not equal to 0 */ + uint16_t conn_handle; /*!< The ACL connection identifier */ + } set_path_loss_rpting_enable; /*!< Event parameter of ESP_GAP_BLE_SET_PATH_LOSS_RPTING_ENABLE_EVT */ + /** + * @brief ESP_GAP_BLE_SET_TRANS_PWR_RPTING_ENABLE_EVT + */ + struct ble_set_trans_pwr_rpting_enable { + esp_bt_status_t status; /*!< Indicate setting transmit power reporting enable complete status, status = (controller error code | 0x100) if status is not equal to 0 */ + uint16_t conn_handle; /*!< The ACL connection identifier */ + } set_trans_pwr_rpting_enable; /*!< Event parameter of ESP_GAP_BLE_SET_TRANS_PWR_RPTING_ENABLE_EVT */ + /** + * @brief ESP_GAP_BLE_PATH_LOSS_THRESHOLD_EVT + */ + struct ble_path_loss_thres_evt { + uint16_t conn_handle; /*!< The ACL connection identifier */ + uint8_t cur_path_loss; /*!< Current path loss (always zero or positive), Units: dB */ + esp_ble_path_loss_zone_t zone_entered; /*!< which zone was entered. If cur_path_loss is set to 0xFF then zone_entered shall be ignored */ + } path_loss_thres_evt; /*!< Event parameter of ESP_GAP_BLE_PATH_LOSS_THRESHOLD_EVT */ + /** + * @brief ESP_GAP_BLE_TRANS_PWR_RPTING_EVT + */ + struct ble_trans_power_report_evt { + esp_bt_status_t status; /*!< Indicate esp_ble_gap_read_remote_transmit_power_level() command success, status = (controller error code | 0x100) if status is not equal to 0 */ + uint16_t conn_handle; /*!< The ACL connection identifier */ + uint8_t reason; /*!< indicate why the event was sent and the device whose transmit power level is being reported + 0x00: Local transmit power changed + 0x01: Remote transmit power changed + 0x02: esp_ble_gap_read_remote_transmit_power_level() command completed, + In this case, the phy, tx_power_level, tx_power_level_flag and delta parameters shall refer to the remote device */ + esp_ble_tx_power_phy_t phy; /*!< 1M, 2M, Coded S2 or Coded S8 phy + 0x01: LE 1M PHY + 0x02: LE 2M PHY + 0x03: LE Coded PHY with S=8 data coding + 0x04: LE Coded PHY with S=2 data coding */ + int8_t tx_power_level; /*!< Transmit power level, range: -127 to 20, units: dBm + 0x7E: Remote device is not managing power levels on this PHY + 0x7F: Transmit power level is not available */ + uint8_t tx_power_level_flag; /*!< whether the transmit power level that is being reported has reached its minimum and/or maximum level */ + int8_t delta; /*!< Change in transmit power level (positive indicates increased power, negative indicates decreased power, zero indicates unchanged) Units: dB. + 0x7F: Change is not available or is out of range */ + } trans_power_report_evt; /*!< Event parameter of ESP_GAP_BLE_TRANS_PWR_RPTING_EVT */ + +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) + /** + * @brief ESP_GAP_BLE_SET_DEFAULT_SUBRATE_COMPLETE_EVT + */ + struct ble_default_subrate_evt { + esp_bt_status_t status; /*!< Indicate setting default subrate command success, status = (controller error code | 0x100) if status is not equal to 0 */ + } set_default_subrate_evt; /*!< Event parameter of ESP_GAP_BLE_SET_DEFAULT_SUBRATE_COMPLETE_EVT */ + /** + * @brief ESP_GAP_BLE_SUBRATE_REQUEST_COMPLETE_EVT + */ + struct ble_subrate_request_evt { + esp_bt_status_t status; /*!< Indicate subrate request command success, status = (controller error code | 0x100) if status is not equal to 0 */ + } subrate_req_cmpl_evt; /*!< Event parameter of ESP_GAP_BLE_SUBRATE_REQUEST_COMPLETE_EVT */ + /** + * @brief ESP_GAP_BLE_SUBRATE_CHANGE_EVT + */ + struct ble_subrate_change_evt { + esp_bt_status_t status; /*!< command succeeded or this event was generated following a request from the peer device. status = (controller error code | 0x100) if status is not equal to 0 */ + uint16_t conn_handle; /*!< connection handle */ + uint16_t subrate_factor; /*!< New subrate factor applied to the specified underlying connection interval, range 0x0001 to 0x01F4 */ + uint16_t peripheral_latency; /*!< New Peripheral latency for the connection in number of subrated connection events, range: 0x0000 to 0x01F3 */ + uint16_t continuation_number; /*!< Number of underlying connection events to remain active after a packet containing a Link Layer PDU with a non-zero Length field is sent or received, range: 0x0000 to 0x01F3 */ + uint16_t supervision_timeout; /*!< New supervision timeout for this connection(Time = N × 10 ms). Range: 0x000A to 0x0C80, Time Range: 100 ms to 32 s */ + } subrate_change_evt; /*!< Event parameter of ESP_GAP_BLE_SUBRATE_CHANGE_EVT */ +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) + /** + * @brief ESP_GAP_BLE_SET_HOST_FEATURE_CMPL_EVT */ - struct ble_set_privacy_mode_cmpl_evt_param { - esp_bt_status_t status; /*!< Indicate privacy mode set operation success status */ - } set_privacy_mode_cmpl; /*!< Event parameter of ESP_GAP_BLE_SET_PRIVACY_MODE_COMPLETE_EVT */ + struct ble_set_host_feature_evt_param { + esp_bt_status_t status; /*!< Indicate host feature update success status */ + } host_feature; /*!< Event parameter of ESP_GAP_BLE_SET_HOST_FEATURE_CMPL_EVT */ +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) } esp_ble_gap_cb_param_t; /** @@ -1533,6 +1872,8 @@ typedef void (* esp_gap_ble_cb_t)(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_p * * @param[in] callback: callback function * + * @note Avoid performing time-consuming operations within the callback functions. + * * @return * - ESP_OK : success * - other : failed @@ -1583,7 +1924,8 @@ esp_err_t esp_ble_gap_set_scan_params(esp_ble_scan_params_t *scan_params); /** * @brief This procedure keep the device scanning the peer device which advertising on the air * - * @param[in] duration: Keeping the scanning time, the unit is second. + * @param[in] duration: The scanning duration in seconds. + * Set to 0 for continuous scanning until explicitly stopped. * * @return * - ESP_OK : success @@ -1748,15 +2090,19 @@ esp_err_t esp_ble_gap_clear_rand_addr(void); esp_err_t esp_ble_gap_config_local_privacy (bool privacy_enable); /** - * @brief set local gap appearance icon + * @brief Set the local GAP appearance icon. * + * @note This API does not restrict the input icon value. + * If an undefined or incorrect icon value is used, the device icon may not display properly. * - * @param[in] icon - External appearance value, these values are defined by the Bluetooth SIG, please refer to + * For a complete list of valid appearance values, please refer to "2.6.2 Appearance Category ranges" at: * https://www.bluetooth.com/specifications/assigned-numbers/ * + * @param[in] icon - External appearance value (16-bit), as defined by the Bluetooth SIG. + * * @return - * - ESP_OK : success - * - other : failed + * - ESP_OK : Success + * - ESP_FAIL : Internal failure * */ esp_err_t esp_ble_gap_config_local_icon (uint16_t icon); @@ -1850,17 +2196,41 @@ esp_err_t esp_ble_gap_get_device_name(void); * */ esp_err_t esp_ble_gap_get_local_used_addr(esp_bd_addr_t local_used_addr, uint8_t * addr_type); + +/** + * @brief This function is called to get ADV data for a specific type. + * + * @note This is the recommended function to use for resolving ADV data by type. + * It improves upon the deprecated `esp_ble_resolve_adv_data` function by + * including an additional parameter to specify the length of the ADV data, + * thereby offering better safety and reliability. + * + * @param[in] adv_data - pointer of ADV data which to be resolved + * @param[in] adv_data_len - the length of ADV data which to be resolved. + * @param[in] type - finding ADV data type + * @param[out] length - return the length of ADV data not including type + * + * @return pointer of ADV data + * + */ +uint8_t *esp_ble_resolve_adv_data_by_type( uint8_t *adv_data, uint16_t adv_data_len, esp_ble_adv_data_type type, uint8_t *length); + /** * @brief This function is called to get ADV data for a specific type. * - * @param[in] adv_data - pointer of ADV data which to be resolved - * @param[in] type - finding ADV data type - * @param[out] length - return the length of ADV data not including type + * @note This function has been deprecated and will be removed in a future release. + * Please use `esp_ble_resolve_adv_data_by_type` instead, which provides + * better parameter validation and supports more accurate data resolution. * - * @return pointer of ADV data + * @param[in] adv_data - pointer of ADV data which to be resolved + * @param[in] type - finding ADV data type + * @param[out] length - return the length of ADV data not including type + * + * @return pointer of ADV data * */ uint8_t *esp_ble_resolve_adv_data(uint8_t *adv_data, uint8_t type, uint8_t *length); + #if (BLE_42_FEATURE_SUPPORT == TRUE) /** * @brief This function is called to set raw advertising data. User need to fill @@ -1902,6 +2272,7 @@ esp_err_t esp_ble_gap_config_scan_rsp_data_raw(uint8_t *raw_data, uint32_t raw_d * - other : failed */ esp_err_t esp_ble_gap_read_rssi(esp_bd_addr_t remote_addr); + #if (BLE_42_FEATURE_SUPPORT == TRUE) /** * @brief This function is called to add a device info into the duplicate scan exceptional list. @@ -2149,6 +2520,18 @@ esp_err_t esp_ble_get_current_conn_params(esp_bd_addr_t bd_addr, esp_gap_conn_pa */ esp_err_t esp_gap_ble_set_channels(esp_gap_ble_channels channels); +/** +* @brief This function is used to read the current channel map +* for the connection identified by remote address. +* +* @param[in] bd_addr : BD address of the peer device +* +* @return - ESP_OK : success +* - other : failed +* +*/ +esp_err_t esp_ble_gap_read_channel_map(esp_bd_addr_t bd_addr); + /** * @brief This function is called to authorized a link after Authentication(MITM protection) * @@ -2397,15 +2780,17 @@ esp_err_t esp_ble_gap_periodic_adv_stop(uint8_t instance); esp_err_t esp_ble_gap_set_ext_scan_params(const esp_ble_ext_scan_params_t *params); /** -* @brief This function is used to enable scanning. +* @brief Enables extended scanning. * -* @param[in] duration Scan duration time, where Time = N * 10 ms. Range: 0x0001 to 0xFFFF. -* @param[in] period Time interval from when the Controller started its last Scan Duration until it begins the subsequent Scan Duration. -* Time = N * 1.28 sec. Range: 0x0001 to 0xFFFF. +* @param[in] duration Scan duration in units of 10 ms. +* - Range: 0x0001 to 0xFFFF (Time = N * 10 ms). +* - 0x0000: Scan continuously until explicitly disabled. * +* @param[in] period Time interval between the start of consecutive scan durations, in units of 1.28 seconds. +* - Range: 0x0001 to 0xFFFF (Time = N * 1.28 sec). +* - 0x0000: Scan continuously. * @return - ESP_OK : success * - other : failed -* */ esp_err_t esp_ble_gap_start_ext_scan(uint32_t duration, uint16_t period); @@ -2489,6 +2874,17 @@ esp_err_t esp_ble_gap_periodic_adv_remove_dev_from_list(esp_ble_addr_type_t addr */ esp_err_t esp_ble_gap_periodic_adv_clear_dev(void); +/** + * @brief Retrieve the capacity of the periodic advertiser list in the controller. + * + * @param[out] size: Pointer to a variable where the capacity of the periodic advertiser list will be stored. + * + * @return + * - ESP_OK : Success + * - Others : Failure + */ +esp_err_t esp_ble_gap_get_periodic_list_size(uint8_t *size); + /** * @brief This function is used to set aux connection parameters * @@ -2507,7 +2903,6 @@ esp_err_t esp_ble_gap_prefer_ext_connect_params_set(esp_bd_addr_t addr, const esp_ble_gap_conn_params_t *phy_1m_conn_params, const esp_ble_gap_conn_params_t *phy_2m_conn_params, const esp_ble_gap_conn_params_t *phy_coded_conn_params); - #endif //#if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) @@ -2667,6 +3062,155 @@ esp_err_t esp_ble_gap_vendor_command_send(esp_ble_vendor_cmd_params_t *vendor_cm */ esp_err_t esp_ble_gap_set_privacy_mode(esp_ble_addr_type_t addr_type, esp_bd_addr_t addr, esp_ble_privacy_mode_t mode); +/** + * @brief This function is used to set which channel selection algorithm(CSA) is supported. + * + * @note - This function should only be used when there are BLE compatibility issues about channel hopping after connected. + * For example, if the peer device only supports CSA#1, this function can be called to make the Controller use CSA#1. + * - This function is not supported on ESP32. + * + * @param[in] csa_select: 0: Channel Selection Algorighm will be selected by Controller + * 1: Select the LE Channel Selection Algorighm #1 + * 2: Select the LE Channel Selection Algorighm #2 + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_ble_gap_set_csa_support(uint8_t csa_select); + +/** + * @brief This function is used to control which vendor events are generated by the HCI for the Host. + * + * @param[in] event_mask: The BLE vendor HCI event mask + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_ble_gap_set_vendor_event_mask(esp_ble_vendor_evt_mask_t event_mask); + +/** + * @brief This function is used to read the current and maximum transmit power levels of the local Controller. + * + * + * @param[in] conn_handle: The ACL connection identified. + * @param[in] phy: 1M, 2M, Coded S2 or Coded S8. + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_ble_gap_enhanced_read_transmit_power_level(uint16_t conn_handle, esp_ble_tx_power_phy_t phy); + +/** + * @brief This function is used to read the transmit power level used by the remote Controller on the ACL connection. + * + * + * @param[in] conn_handle: The ACL connection identifier. + * @param[in] phy: 1M, 2M, Coded S2 or Coded S8. + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_ble_gap_read_remote_transmit_power_level(uint16_t conn_handle, esp_ble_tx_power_phy_t phy); + +/** + * @brief This function is used to set the path loss threshold reporting parameters. + * + * + * @param[in] path_loss_rpt_params: The path loss threshold reporting parameters. + * + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_ble_gap_set_path_loss_reporting_params(esp_ble_path_loss_rpt_params_t *path_loss_rpt_params); + +/** + * @brief This function is used to enable or disable path loss reporting. + * + * + * @param[in] conn_handle: The ACL connection identifier. + * @param[in] enable: Reporting disabled or enabled. + * + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_ble_gap_set_path_loss_reporting_enable(uint16_t conn_handle, bool enable); + +/** + * @brief This function is used to enable or disable the reporting to the local Host of transmit power level changes in the local and remote Controllers. + * + * + * @param[in] conn_handle: The ACL connection identifier. + * @param[in] local_enable: Disable or enable local transmit power reports. + * @param[in] remote_enable: Disable or enable remote transmit power reports. + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_ble_gap_set_transmit_power_reporting_enable(uint16_t conn_handle, bool local_enable, bool remote_enable); + +/** + * @brief This function is used to set the initial values for the acceptable parameters for subrating requests, + * for all future ACL connections where the Controller is the Central. This command does not affect any + * existing connection. + * + * + * @param[in] default_subrate_params: The default subrate parameters. + * + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_ble_gap_set_default_subrate(esp_ble_default_subrate_param_t *default_subrate_params); + +/** + * @brief This function is used by a Central or a Peripheral to request a change to the subrating factor and/or other parameters + * applied to an existing connection. + * + * If this API is issued on the Central, the following rules shall apply when the Controller initiates the Connection Subrate Update procedure: + * 1. The Peripheral latency shall be less than or equal to max_latency. + * 2. The subrate factor shall be between subrate_min and subrate_max. + * 3. The continuation number shall be equal to the lesser of continuation_number and (subrate factor - 1). + * 4. The connection supervision timeout shall be equal to supervision_timeout. + * + * If this API is issued on the Peripheral, the following rules shall apply when the Controller initiates the Connection Subrate Request procedure: + * 1. The Peripheral latency shall be less than or equal to max_latency. + * 2. The minimum and maximum subrate factors shall be between subrate_min and subrate_max. + * 3. The continuation number shall be equal to the lesser of continuation_number and (maximum subrate factor - 1). + * 4.The connection supervision timeout shall be equal to supervision_timeout. + * + * + * @param[in] subrate_req_params: The subrate request parameters. + * + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_ble_gap_subrate_request(esp_ble_subrate_req_param_t *subrate_req_params); + +/** + * @brief This function is called to set host feature. + * + * @param[in] bit_num: the bit position in the FeatureSet. + * @param[in] bit_val: the feature is enabled or disabled + * + * @return + * - ESP_OK : success + * - other : failed + * + */ +esp_err_t esp_ble_gap_set_host_feature(uint16_t bit_num, uint8_t bit_val); + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h b/lib/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h index 7c75927f..1c05ffc5 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,8 +33,9 @@ typedef enum { ESP_BT_SET_COD_MAJOR_MINOR = 0x01, /*!< overwrite major, minor class */ ESP_BT_SET_COD_SERVICE_CLASS = 0x02, /*!< set the bits in the input, the current bit will remain */ ESP_BT_CLR_COD_SERVICE_CLASS = 0x04, /*!< clear the bits in the input, others will remain */ - ESP_BT_SET_COD_ALL = 0x08, /*!< overwrite major, minor, set the bits in service class */ - ESP_BT_INIT_COD = 0x0a, /*!< overwrite major, minor, and service class */ + ESP_BT_SET_COD_ALL = 0x08, /*!< overwrite major, minor, set the bits in service class, reserved_2 remain unchanged */ + ESP_BT_INIT_COD = 0x0a, /*!< overwrite major, minor, and service class, reserved_2 remain unchanged */ + ESP_BT_SET_COD_RESERVED_2 = 0x10, /*!< overwrite the two least significant bits reserved_2 whose default value is 0b00; other values of reserved_2 are invalid according to Bluetooth Core Specification 5.4 */ } esp_bt_cod_mode_t; #define ESP_BT_GAP_AFH_CHANNELS_LEN 10 @@ -209,6 +210,28 @@ typedef enum { ESP_BT_COD_MAJOR_DEV_UNCATEGORIZED = 31, /*!< Uncategorized: device not specified */ } esp_bt_cod_major_dev_t; +/// Minor device class field of Class of Device for Peripheral Major Class +typedef enum { + ESP_BT_COD_MINOR_PERIPHERAL_KEYBOARD = 0x10, /*!< Keyboard */ + ESP_BT_COD_MINOR_PERIPHERAL_POINTING = 0x20, /*!< Pointing */ + ESP_BT_COD_MINOR_PERIPHERAL_COMBO = 0x30, /*!< Combo + ESP_BT_COD_MINOR_PERIPHERAL_KEYBOARD, ESP_BT_COD_MINOR_PERIPHERAL_POINTING + and ESP_BT_COD_MINOR_PERIPHERAL_COMBO can be OR'd with one of the + following values to identify a multifunctional device. e.g. + ESP_BT_COD_MINOR_PERIPHERAL_KEYBOARD | ESP_BT_COD_MINOR_PERIPHERAL_GAMEPAD + ESP_BT_COD_MINOR_PERIPHERAL_POINTING | ESP_BT_COD_MINOR_PERIPHERAL_SENSING_DEVICE + */ + ESP_BT_COD_MINOR_PERIPHERAL_JOYSTICK = 0x01, /*!< Joystick */ + ESP_BT_COD_MINOR_PERIPHERAL_GAMEPAD = 0x02, /*!< Gamepad */ + ESP_BT_COD_MINOR_PERIPHERAL_REMOTE_CONTROL = 0x03, /*!< Remote Control */ + ESP_BT_COD_MINOR_PERIPHERAL_SENSING_DEVICE = 0x04, /*!< Sensing Device */ + ESP_BT_COD_MINOR_PERIPHERAL_DIGITIZING_TABLET = 0x05, /*!< Digitizing Tablet */ + ESP_BT_COD_MINOR_PERIPHERAL_CARD_READER = 0x06, /*!< Card Reader */ + ESP_BT_COD_MINOR_PERIPHERAL_DIGITAL_PAN = 0x07, /*!< Digital Pan */ + ESP_BT_COD_MINOR_PERIPHERAL_HAND_SCANNER = 0x08, /*!< Hand Scanner */ + ESP_BT_COD_MINOR_PERIPHERAL_HAND_GESTURAL_INPUT = 0x09, /*!< Hand Gestural Input */ +} esp_bt_cod_minor_peripheral_t; + /// Bits of major device class field #define ESP_BT_COD_MAJOR_DEV_BIT_MASK (0x1f00) /*!< Major device bit mask */ #define ESP_BT_COD_MAJOR_DEV_BIT_OFFSET (8) /*!< Major device bit offset */ @@ -290,6 +313,14 @@ typedef enum { #define ESP_BT_GAP_TPOLL_DFT (0x0028) /*!< Default poll interval, unit is 625 microseconds */ #define ESP_BT_GAP_TPOLL_MAX (0x1000) /*!< Maximum poll interval, unit is 625 microseconds */ +/** GAP status */ +typedef struct { + esp_bt_gap_discovery_state_t disc_stat; /*!< Device Discovery state */ + esp_bt_connection_mode_t conn_mode; /*!< Connection mode */ + esp_bt_discovery_mode_t disc_mode; /*!< Discovery mode */ + uint8_t bredr_acl_link_num; /*!< Number of bredr link connections */ +} esp_bt_gap_profile_status_t; + /// GAP state callback parameters typedef union { /** @@ -417,8 +448,9 @@ typedef union { * @brief ESP_BT_GAP_MODE_CHG_EVT */ struct mode_chg_param { - esp_bd_addr_t bda; /*!< remote bluetooth device address*/ - esp_bt_pm_mode_t mode; /*!< PM mode*/ + esp_bd_addr_t bda; /*!< remote bluetooth device address */ + esp_bt_pm_mode_t mode; /*!< PM mode */ + uint16_t interval; /*!< Number of baseband slots. unit is 0.625ms */ } mode_chg; /*!< mode change event parameter struct */ /** @@ -959,6 +991,17 @@ esp_err_t esp_bt_gap_set_device_name(const char *name); */ esp_err_t esp_bt_gap_get_device_name(void); +/** + * @brief Get the status of GAP + * + * @param[out] profile_status - GAP status + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_bt_gap_get_profile_status(esp_bt_gap_profile_status_t *profile_status); + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/bluedroid/api/include/api/esp_gatt_defs.h b/lib/bt/host/bluedroid/api/include/api/esp_gatt_defs.h index 77f03e8b..e8cc134c 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_gatt_defs.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_gatt_defs.h @@ -478,7 +478,7 @@ typedef uint8_t esp_gatt_char_prop_t; * * This definition specifies the maximum number of bytes that a GATT attribute can hold. */ -#define ESP_GATT_MAX_ATTR_LEN 512 /*!< As same as GATT_MAX_ATTR_LEN. */ +#define ESP_GATT_MAX_ATTR_LEN 517 /*!< As same as GATT_MAX_ATTR_LEN. */ /** * @brief Enumerates the possible sources of a GATT service discovery. @@ -682,6 +682,19 @@ typedef struct { esp_bt_uuid_t uuid; /*!< Included service UUID. */ } esp_gattc_incl_svc_elem_t; +/** @brief Represents a creat connection element. */ +typedef struct { + esp_bd_addr_t remote_bda; /*!< The Bluetooth address of the remote device */ + esp_ble_addr_type_t remote_addr_type; /*!< Address type of the remote device */ + bool is_direct; /*!< Direct connection or background auto connection(by now, background auto connection is not supported */ + bool is_aux; /*!< Set to true for BLE 5.0 or higher to enable auxiliary connections; set to false for BLE 4.2 or lower. */ + esp_ble_addr_type_t own_addr_type; /*!< Specifies the address type used in the connection request. Set to 0xFF if the address type is unknown. */ + esp_ble_phy_mask_t phy_mask; /*!< Indicates which PHY connection parameters will be used. When is_aux is false, only the connection params for 1M PHY can be specified */ + const esp_ble_conn_params_t *phy_1m_conn_params; /*!< Connection parameters for the LE 1M PHY */ + const esp_ble_conn_params_t *phy_2m_conn_params; /*!< Connection parameters for the LE 2M PHY */ + const esp_ble_conn_params_t *phy_coded_conn_params; /*!< Connection parameters for the LE Coded PHY */ +} esp_ble_gatt_creat_conn_params_t; + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/bluedroid/api/include/api/esp_gattc_api.h b/lib/bt/host/bluedroid/api/include/api/esp_gattc_api.h index 13bf16a3..0d9837a5 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_gattc_api.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_gattc_api.h @@ -15,411 +15,465 @@ extern "C" { #endif -/// GATT Client callback function events +/** + * @brief GATT Client callback function events + */ typedef enum { - ESP_GATTC_REG_EVT = 0, /*!< When GATT client is registered, the event comes */ - ESP_GATTC_UNREG_EVT = 1, /*!< When GATT client is unregistered, the event comes */ - ESP_GATTC_OPEN_EVT = 2, /*!< When GATT virtual connection is set up, the event comes */ - ESP_GATTC_READ_CHAR_EVT = 3, /*!< When GATT characteristic is read, the event comes */ - ESP_GATTC_WRITE_CHAR_EVT = 4, /*!< When GATT characteristic write operation completes, the event comes */ - ESP_GATTC_CLOSE_EVT = 5, /*!< When GATT virtual connection is closed, the event comes */ - ESP_GATTC_SEARCH_CMPL_EVT = 6, /*!< When GATT service discovery is completed, the event comes */ - ESP_GATTC_SEARCH_RES_EVT = 7, /*!< When GATT service discovery result is got, the event comes */ - ESP_GATTC_READ_DESCR_EVT = 8, /*!< When GATT characteristic descriptor read completes, the event comes */ - ESP_GATTC_WRITE_DESCR_EVT = 9, /*!< When GATT characteristic descriptor write completes, the event comes */ - ESP_GATTC_NOTIFY_EVT = 10, /*!< When GATT notification or indication arrives, the event comes */ - ESP_GATTC_PREP_WRITE_EVT = 11, /*!< When GATT prepare-write operation completes, the event comes */ - ESP_GATTC_EXEC_EVT = 12, /*!< When write execution completes, the event comes */ - ESP_GATTC_ACL_EVT = 13, /*!< When ACL connection is up, the event comes */ - ESP_GATTC_CANCEL_OPEN_EVT = 14, /*!< When GATT client ongoing connection is cancelled, the event comes */ - ESP_GATTC_SRVC_CHG_EVT = 15, /*!< When "service changed" occurs, the event comes */ - ESP_GATTC_ENC_CMPL_CB_EVT = 17, /*!< When encryption procedure completes, the event comes */ - ESP_GATTC_CFG_MTU_EVT = 18, /*!< When configuration of MTU completes, the event comes */ - ESP_GATTC_ADV_DATA_EVT = 19, /*!< When advertising of data, the event comes */ - ESP_GATTC_MULT_ADV_ENB_EVT = 20, /*!< When multi-advertising is enabled, the event comes */ - ESP_GATTC_MULT_ADV_UPD_EVT = 21, /*!< When multi-advertising parameters are updated, the event comes */ - ESP_GATTC_MULT_ADV_DATA_EVT = 22, /*!< When multi-advertising data arrives, the event comes */ - ESP_GATTC_MULT_ADV_DIS_EVT = 23, /*!< When multi-advertising is disabled, the event comes */ - ESP_GATTC_CONGEST_EVT = 24, /*!< When GATT connection congestion comes, the event comes */ - ESP_GATTC_BTH_SCAN_ENB_EVT = 25, /*!< When batch scan is enabled, the event comes */ - ESP_GATTC_BTH_SCAN_CFG_EVT = 26, /*!< When batch scan storage is configured, the event comes */ - ESP_GATTC_BTH_SCAN_RD_EVT = 27, /*!< When Batch scan read event is reported, the event comes */ - ESP_GATTC_BTH_SCAN_THR_EVT = 28, /*!< When Batch scan threshold is set, the event comes */ - ESP_GATTC_BTH_SCAN_PARAM_EVT = 29, /*!< When Batch scan parameters are set, the event comes */ - ESP_GATTC_BTH_SCAN_DIS_EVT = 30, /*!< When Batch scan is disabled, the event comes */ - ESP_GATTC_SCAN_FLT_CFG_EVT = 31, /*!< When Scan filter configuration completes, the event comes */ - ESP_GATTC_SCAN_FLT_PARAM_EVT = 32, /*!< When Scan filter parameters are set, the event comes */ - ESP_GATTC_SCAN_FLT_STATUS_EVT = 33, /*!< When Scan filter status is reported, the event comes */ - ESP_GATTC_ADV_VSC_EVT = 34, /*!< When advertising vendor spec content event is reported, the event comes */ - ESP_GATTC_REG_FOR_NOTIFY_EVT = 38, /*!< When register for notification of a service completes, the event comes */ - ESP_GATTC_UNREG_FOR_NOTIFY_EVT = 39, /*!< When unregister for notification of a service completes, the event comes */ - ESP_GATTC_CONNECT_EVT = 40, /*!< When the ble physical connection is set up, the event comes */ - ESP_GATTC_DISCONNECT_EVT = 41, /*!< When the ble physical connection disconnected, the event comes */ - ESP_GATTC_READ_MULTIPLE_EVT = 42, /*!< When the ble characteristic or descriptor multiple complete, the event comes */ - ESP_GATTC_QUEUE_FULL_EVT = 43, /*!< When the gattc command queue full, the event comes */ - ESP_GATTC_SET_ASSOC_EVT = 44, /*!< When the ble gattc set the associated address complete, the event comes */ - ESP_GATTC_GET_ADDR_LIST_EVT = 45, /*!< When the ble get gattc address list in cache finish, the event comes */ - ESP_GATTC_DIS_SRVC_CMPL_EVT = 46, /*!< When the ble discover service complete, the event comes */ - ESP_GATTC_READ_MULTI_VAR_EVT = 47, /*!< When read multiple variable characteristic complete, the event comes */ + ESP_GATTC_REG_EVT = 0, /*!< This event is triggered when a GATT Client application is registered using `esp_ble_gattc_app_register`. */ + ESP_GATTC_UNREG_EVT = 1, /*!< This event is triggered when a GATT Client application is unregistered using `esp_ble_gattc_app_unregister`. */ + ESP_GATTC_OPEN_EVT = 2, /*!< This event is triggered when a GATT virtual connection is set up using `esp_ble_gattc_open`. */ + ESP_GATTC_READ_CHAR_EVT = 3, /*!< This event is triggered upon the completion of a GATT characteristic read operation using `esp_ble_gattc_read_char`. */ + ESP_GATTC_WRITE_CHAR_EVT = 4, /*!< This event is triggered upon the completion of a GATT characteristic write operation using `esp_ble_gattc_write_char`. */ + ESP_GATTC_CLOSE_EVT = 5, /*!< This event is triggered when a GATT virtual connection is closed via `esp_ble_gattc_close`, or when the physical connection is terminated. */ + ESP_GATTC_SEARCH_CMPL_EVT = 6, /*!< This event is triggered upon the completion of a service discovery using `esp_ble_gattc_search_service`. */ + ESP_GATTC_SEARCH_RES_EVT = 7, /*!< This event is triggered each time a service result is obtained using `esp_ble_gattc_search_service`. */ + ESP_GATTC_READ_DESCR_EVT = 8, /*!< This event is triggered upon the completion of a GATT characteristic descriptor read operation using `esp_ble_gattc_read_char_descr`. */ + ESP_GATTC_WRITE_DESCR_EVT = 9, /*!< This event is triggered upon the completion of a GATT characteristic descriptor write operation using `esp_ble_gattc_write_char_descr`. */ + ESP_GATTC_NOTIFY_EVT = 10, /*!< This event is triggered when a GATT notification or indication is received from the Server. */ + ESP_GATTC_PREP_WRITE_EVT = 11, /*!< This event is triggered upon the completion of a GATT prepare-write operation using `esp_ble_gattc_prepare_write`. */ + ESP_GATTC_EXEC_EVT = 12, /*!< This event is triggered upon the completion of a GATT write execution using `esp_ble_gattc_execute_write` .*/ + ESP_GATTC_ACL_EVT = 13, /*!< Deprecated. */ + ESP_GATTC_CANCEL_OPEN_EVT = 14, /*!< Deprecated. */ + ESP_GATTC_SRVC_CHG_EVT = 15, /*!< This event is triggered when a service changed indication is received from the Server, indicating that the attribute database on the Server has been modified (e.g., services have been added, removed). */ + ESP_GATTC_ENC_CMPL_CB_EVT = 17, /*!< Deprecated. */ + ESP_GATTC_CFG_MTU_EVT = 18, /*!< This event is triggered upon the completion of the MTU configuration with `esp_ble_gattc_send_mtu_req`. */ + ESP_GATTC_ADV_DATA_EVT = 19, /*!< Deprecated. */ + ESP_GATTC_MULT_ADV_ENB_EVT = 20, /*!< Deprecated. */ + ESP_GATTC_MULT_ADV_UPD_EVT = 21, /*!< Deprecated. */ + ESP_GATTC_MULT_ADV_DATA_EVT = 22, /*!< Deprecated. */ + ESP_GATTC_MULT_ADV_DIS_EVT = 23, /*!< Deprecated. */ + ESP_GATTC_CONGEST_EVT = 24, /*!< This event is triggered when the GATT connection is congested. */ + ESP_GATTC_BTH_SCAN_ENB_EVT = 25, /*!< Deprecated. */ + ESP_GATTC_BTH_SCAN_CFG_EVT = 26, /*!< Deprecated. */ + ESP_GATTC_BTH_SCAN_RD_EVT = 27, /*!< Deprecated. */ + ESP_GATTC_BTH_SCAN_THR_EVT = 28, /*!< Deprecated. */ + ESP_GATTC_BTH_SCAN_PARAM_EVT = 29, /*!< Deprecated. */ + ESP_GATTC_BTH_SCAN_DIS_EVT = 30, /*!< Deprecated. */ + ESP_GATTC_SCAN_FLT_CFG_EVT = 31, /*!< Deprecated. */ + ESP_GATTC_SCAN_FLT_PARAM_EVT = 32, /*!< Deprecated. */ + ESP_GATTC_SCAN_FLT_STATUS_EVT = 33, /*!< Deprecated. */ + ESP_GATTC_ADV_VSC_EVT = 34, /*!< Deprecated. */ + ESP_GATTC_REG_FOR_NOTIFY_EVT = 38, /*!< This event is triggered upon the completion of a service notification registration using `esp_ble_gattc_register_for_notify`. */ + ESP_GATTC_UNREG_FOR_NOTIFY_EVT = 39, /*!< This event is triggered upon the completion of a service notification unregistration using `esp_ble_gattc_unregister_for_notify`. */ + ESP_GATTC_CONNECT_EVT = 40, /*!< This event is triggered when the physical connection is set up. */ + ESP_GATTC_DISCONNECT_EVT = 41, /*!< This event is triggered when the physical connection is terminated. */ + ESP_GATTC_READ_MULTIPLE_EVT = 42, /*!< This event is triggered when the multiple characteristic or descriptor values are retrieved using `esp_ble_gattc_read_multiple`. */ + ESP_GATTC_QUEUE_FULL_EVT = 43, /*!< This event is triggered when the GATTC command queue is full. */ + ESP_GATTC_SET_ASSOC_EVT = 44, /*!< This event is triggered when the association between the source and the remote address is added or deleted using `esp_ble_gattc_cache_assoc`. */ + ESP_GATTC_GET_ADDR_LIST_EVT = 45, /*!< This event is triggered when retrieving the address list from the GATTC cache is completed using `esp_ble_gattc_cache_get_addr_list`. */ + ESP_GATTC_DIS_SRVC_CMPL_EVT = 46, /*!< This event is triggered when the GATT service discovery is completed. */ + ESP_GATTC_READ_MULTI_VAR_EVT = 47, /*!< This event is triggered when multiple variable length characteristic values are retrieved using `esp_ble_gattc_read_multiple`. */ } esp_gattc_cb_event_t; /** - * @brief Gatt client callback parameters union + * @brief GATT Client callback parameters */ typedef union { + /** - * @brief ESP_GATTC_REG_EVT + * @brief Callback parameter for the event `ESP_GATTC_REG_EVT` */ struct gattc_reg_evt_param { esp_gatt_status_t status; /*!< Operation status */ - uint16_t app_id; /*!< Application id which input in register API */ - } reg; /*!< Gatt client callback param of ESP_GATTC_REG_EVT */ + uint16_t app_id; /*!< Application ID */ + } reg; /*!< Callback parameter for the event `ESP_GATTC_REG_EVT` */ /** - * @brief ESP_GATTC_OPEN_EVT + * @brief Callback parameter for the event `ESP_GATTC_OPEN_EVT`. */ struct gattc_open_evt_param { esp_gatt_status_t status; /*!< Operation status */ - uint16_t conn_id; /*!< Connection id */ - esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */ + uint16_t conn_id; /*!< Connection ID */ + esp_bd_addr_t remote_bda; /*!< Remote Bluetooth device address */ uint16_t mtu; /*!< MTU size */ - } open; /*!< Gatt client callback param of ESP_GATTC_OPEN_EVT */ + } open; /*!< Callback parameter for the event `ESP_GATTC_OPEN_EVT` */ /** - * @brief ESP_GATTC_CLOSE_EVT + * @brief Callback parameter for the event `ESP_GATTC_CLOSE_EVT` */ struct gattc_close_evt_param { esp_gatt_status_t status; /*!< Operation status */ - uint16_t conn_id; /*!< Connection id */ + uint16_t conn_id; /*!< Connection ID */ esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */ - esp_gatt_conn_reason_t reason; /*!< The reason of gatt connection close */ - } close; /*!< Gatt client callback param of ESP_GATTC_CLOSE_EVT */ + esp_gatt_conn_reason_t reason; /*!< The reason of GATT connection close */ + } close; /*!< Callback parameter for the event `ESP_GATTC_CLOSE_EVT` */ /** - * @brief ESP_GATTC_CFG_MTU_EVT + * @brief Callback parameter for the event `ESP_GATTC_CFG_MTU_EVT` */ struct gattc_cfg_mtu_evt_param { esp_gatt_status_t status; /*!< Operation status */ - uint16_t conn_id; /*!< Connection id */ + uint16_t conn_id; /*!< Connection ID */ uint16_t mtu; /*!< MTU size */ - } cfg_mtu; /*!< Gatt client callback param of ESP_GATTC_CFG_MTU_EVT */ + } cfg_mtu; /*!< Callback parameter for the event `ESP_GATTC_CFG_MTU_EVT` */ /** - * @brief ESP_GATTC_SEARCH_CMPL_EVT + * @brief Callback parameter for the event `ESP_GATTC_SEARCH_CMPL_EVT` */ struct gattc_search_cmpl_evt_param { esp_gatt_status_t status; /*!< Operation status */ - uint16_t conn_id; /*!< Connection id */ + uint16_t conn_id; /*!< Connection ID */ esp_service_source_t searched_service_source; /*!< The source of the service information */ - } search_cmpl; /*!< Gatt client callback param of ESP_GATTC_SEARCH_CMPL_EVT */ + } search_cmpl; /*!< Callback parameter for the event `ESP_GATTC_SEARCH_CMPL_EVT` */ /** - * @brief ESP_GATTC_SEARCH_RES_EVT + * @brief Callback parameter for the event `ESP_GATTC_SEARCH_RES_EVT` */ struct gattc_search_res_evt_param { - uint16_t conn_id; /*!< Connection id */ + uint16_t conn_id; /*!< Connection ID */ uint16_t start_handle; /*!< Service start handle */ uint16_t end_handle; /*!< Service end handle */ - esp_gatt_id_t srvc_id; /*!< Service id, include service uuid and other information */ - bool is_primary; /*!< True if this is the primary service */ - } search_res; /*!< Gatt client callback param of ESP_GATTC_SEARCH_RES_EVT */ + esp_gatt_id_t srvc_id; /*!< Service ID, including service UUID and other information */ + bool is_primary; /*!< True indicates a primary service, false otherwise */ + } search_res; /*!< Callback parameter for the event `ESP_GATTC_SEARCH_RES_EVT` */ /** - * @brief ESP_GATTC_READ_CHAR_EVT, ESP_GATTC_READ_DESCR_EVT, ESP_GATTC_READ_MULTIPLE_EVT, ESP_GATTC_READ_MULTI_VAR_EVT + * @brief Callback parameter for the events: `ESP_GATTC_READ_CHAR_EVT`, `ESP_GATTC_READ_DESCR_EVT`, + * `ESP_GATTC_READ_MULTIPLE_EVT`, `ESP_GATTC_READ_MULTI_VAR_EVT` */ struct gattc_read_char_evt_param { esp_gatt_status_t status; /*!< Operation status */ - uint16_t conn_id; /*!< Connection id */ + uint16_t conn_id; /*!< Connection ID */ uint16_t handle; /*!< Characteristic handle */ uint8_t *value; /*!< Characteristic value */ uint16_t value_len; /*!< Characteristic value length */ - } read; /*!< Gatt client callback param of ESP_GATTC_READ_CHAR_EVT */ + } read; /*!< Callback parameter for events: `ESP_GATTC_READ_CHAR_EVT`, `ESP_GATTC_READ_DESCR_EVT`, + `ESP_GATTC_READ_MULTIPLE_EVT`, `ESP_GATTC_READ_MULTI_VAR_EVT` */ /** - * @brief ESP_GATTC_WRITE_CHAR_EVT, ESP_GATTC_PREP_WRITE_EVT, ESP_GATTC_WRITE_DESCR_EVT + * @brief Callback parameter for the events: `ESP_GATTC_WRITE_CHAR_EVT`, `ESP_GATTC_PREP_WRITE_EVT`, `ESP_GATTC_WRITE_DESCR_EVT`. */ struct gattc_write_evt_param { esp_gatt_status_t status; /*!< Operation status */ - uint16_t conn_id; /*!< Connection id */ - uint16_t handle; /*!< The Characteristic or descriptor handle */ - uint16_t offset; /*!< The prepare write offset, this value is valid only when prepare write */ - } write; /*!< Gatt client callback param of ESP_GATTC_WRITE_DESCR_EVT */ + uint16_t conn_id; /*!< Connection ID */ + uint16_t handle; /*!< The characteristic or descriptor handle */ + uint16_t offset; /*!< The position offset to write. This value is valid only for prepare write operation. */ + } write; /*!< Callback parameter for the events: `ESP_GATTC_WRITE_CHAR_EVT`, `ESP_GATTC_PREP_WRITE_EVT`, `ESP_GATTC_WRITE_DESCR_EVT` */ /** - * @brief ESP_GATTC_EXEC_EVT + * @brief Callback parameter for the event `ESP_GATTC_EXEC_EVT` */ struct gattc_exec_cmpl_evt_param { esp_gatt_status_t status; /*!< Operation status */ - uint16_t conn_id; /*!< Connection id */ - } exec_cmpl; /*!< Gatt client callback param of ESP_GATTC_EXEC_EVT */ + uint16_t conn_id; /*!< Connection ID */ + } exec_cmpl; /*!< Callback parameter for the event `ESP_GATTC_EXEC_EVT` */ /** - * @brief ESP_GATTC_NOTIFY_EVT + * @brief Callback parameter for the event `ESP_GATTC_NOTIFY_EVT` */ struct gattc_notify_evt_param { - uint16_t conn_id; /*!< Connection id */ - esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */ - uint16_t handle; /*!< The Characteristic or descriptor handle */ - uint16_t value_len; /*!< Notify attribute value */ + uint16_t conn_id; /*!< Connection ID */ + esp_bd_addr_t remote_bda; /*!< Remote Bluetooth device address. */ + uint16_t handle; /*!< The characteristic or descriptor handle */ + uint16_t value_len; /*!< Notify attribute value length in bytes */ uint8_t *value; /*!< Notify attribute value */ - bool is_notify; /*!< True means notify, false means indicate */ - } notify; /*!< Gatt client callback param of ESP_GATTC_NOTIFY_EVT */ + bool is_notify; /*!< True means notification; false means indication */ + } notify; /*!< Callback parameter for the event `ESP_GATTC_NOTIFY_EVT` */ /** - * @brief ESP_GATTC_SRVC_CHG_EVT + * @brief Callback parameter for the event `ESP_GATTC_SRVC_CHG_EVT` */ struct gattc_srvc_chg_evt_param { - esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */ - } srvc_chg; /*!< Gatt client callback param of ESP_GATTC_SRVC_CHG_EVT */ + esp_bd_addr_t remote_bda; /*!< Remote Bluetooth device address */ + } srvc_chg; /*!< Callback parameter for the event `ESP_GATTC_SRVC_CHG_EVT` */ /** - * @brief ESP_GATTC_CONGEST_EVT + * @brief Callback parameter for the event `ESP_GATTC_CONGEST_EVT` */ struct gattc_congest_evt_param { - uint16_t conn_id; /*!< Connection id */ - bool congested; /*!< Congested or not */ - } congest; /*!< Gatt client callback param of ESP_GATTC_CONGEST_EVT */ + uint16_t conn_id; /*!< Connection ID */ + bool congested; /*!< True indicates that the connection is congested, false otherwise */ + } congest; /*!< Callback parameter for the event `ESP_GATTC_CONGEST_EVT` */ /** - * @brief ESP_GATTC_REG_FOR_NOTIFY_EVT + * @brief Callback parameter for the event `ESP_GATTC_REG_FOR_NOTIFY_EVT` */ struct gattc_reg_for_notify_evt_param { esp_gatt_status_t status; /*!< Operation status */ uint16_t handle; /*!< The characteristic or descriptor handle */ - } reg_for_notify; /*!< Gatt client callback param of ESP_GATTC_REG_FOR_NOTIFY_EVT */ + } reg_for_notify; /*!< Callback parameter for the event `ESP_GATTC_REG_FOR_NOTIFY_EVT` */ /** - * @brief ESP_GATTC_UNREG_FOR_NOTIFY_EVT + * @brief Callback parameter for the event `ESP_GATTC_UNREG_FOR_NOTIFY_EVT` */ struct gattc_unreg_for_notify_evt_param { esp_gatt_status_t status; /*!< Operation status */ uint16_t handle; /*!< The characteristic or descriptor handle */ - } unreg_for_notify; /*!< Gatt client callback param of ESP_GATTC_UNREG_FOR_NOTIFY_EVT */ + } unreg_for_notify; /*!< Callback parameter for the event `ESP_GATTC_UNREG_FOR_NOTIFY_EVT` */ /** - * @brief ESP_GATTC_CONNECT_EVT + * @brief Callback parameter for the event `ESP_GATTC_CONNECT_EVT` */ struct gattc_connect_evt_param { - uint16_t conn_id; /*!< Connection id */ - uint8_t link_role; /*!< Link role : master role = 0 ; slave role = 1*/ - esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */ - esp_gatt_conn_params_t conn_params; /*!< current connection parameters */ - esp_ble_addr_type_t ble_addr_type; /*!< Remote BLE device address type */ - uint16_t conn_handle; /*!< HCI connection handle */ - } connect; /*!< Gatt client callback param of ESP_GATTC_CONNECT_EVT */ + uint16_t conn_id; /*!< Connection ID */ + uint8_t link_role; /*!< Link role : master role = 0; slave role = 1 */ + esp_bd_addr_t remote_bda; /*!< Remote device address */ + esp_gatt_conn_params_t conn_params; /*!< Current connection parameters */ + esp_ble_addr_type_t ble_addr_type; /*!< Remote device address type */ + uint16_t conn_handle; /*!< HCI connection handle */ + } connect; /*!< Callback parameter for the event `ESP_GATTC_CONNECT_EVT` */ /** - * @brief ESP_GATTC_DISCONNECT_EVT + * @brief Callback parameter for the event `ESP_GATTC_DISCONNECT_EVT` */ struct gattc_disconnect_evt_param { - esp_gatt_conn_reason_t reason; /*!< disconnection reason */ - uint16_t conn_id; /*!< Connection id */ - esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */ - } disconnect; /*!< Gatt client callback param of ESP_GATTC_DISCONNECT_EVT */ + esp_gatt_conn_reason_t reason; /*!< Disconnection reason */ + uint16_t conn_id; /*!< Connection ID */ + esp_bd_addr_t remote_bda; /*!< Remote device address */ + } disconnect; /*!< Callback parameter for the event `ESP_GATTC_DISCONNECT_EVT` */ + /** - * @brief ESP_GATTC_SET_ASSOC_EVT + * @brief Callback parameter for the event `ESP_GATTC_SET_ASSOC_EVT` */ struct gattc_set_assoc_addr_cmp_evt_param { - esp_gatt_status_t status; /*!< Operation status */ - } set_assoc_cmp; /*!< Gatt client callback param of ESP_GATTC_SET_ASSOC_EVT */ + esp_gatt_status_t status; /*!< Operation status */ + } set_assoc_cmp; /*!< Callback parameter for the event `ESP_GATTC_SET_ASSOC_EVT` */ + /** - * @brief ESP_GATTC_GET_ADDR_LIST_EVT + * @brief Callback parameter for the event `ESP_GATTC_GET_ADDR_LIST_EVT` */ struct gattc_get_addr_list_evt_param { esp_gatt_status_t status; /*!< Operation status */ - uint8_t num_addr; /*!< The number of address in the gattc cache address list */ - esp_bd_addr_t *addr_list; /*!< The pointer to the address list which has been get from the gattc cache */ - } get_addr_list; /*!< Gatt client callback param of ESP_GATTC_GET_ADDR_LIST_EVT */ + uint8_t num_addr; /*!< The number of addresses in the local GATTC cache address list */ + esp_bd_addr_t *addr_list; /*!< The pointer to the address list which has been retrieved from the local GATTC cache */ + } get_addr_list; /*!< Callback parameter for the event `ESP_GATTC_GET_ADDR_LIST_EVT` */ /** - * @brief ESP_GATTC_QUEUE_FULL_EVT + * @brief Callback parameter for the event `ESP_GATTC_QUEUE_FULL_EVT` */ struct gattc_queue_full_evt_param { esp_gatt_status_t status; /*!< Operation status */ - uint16_t conn_id; /*!< Connection id */ - bool is_full; /*!< The gattc command queue is full or not */ - } queue_full; /*!< Gatt client callback param of ESP_GATTC_QUEUE_FULL_EVT */ + uint16_t conn_id; /*!< Connection ID */ + bool is_full; /*!< True indicates the GATTC command queue is full; false otherwise. */ + } queue_full; /*!< Callback parameter for the event `ESP_GATTC_QUEUE_FULL_EVT` */ /** - * @brief ESP_GATTC_DIS_SRVC_CMPL_EVT + * @brief Callback parameter for the event `ESP_GATTC_DIS_SRVC_CMPL_EVT` */ struct gattc_dis_srvc_cmpl_evt_param { esp_gatt_status_t status; /*!< Operation status */ - uint16_t conn_id; /*!< Connection id */ - } dis_srvc_cmpl; /*!< Gatt client callback param of ESP_GATTC_DIS_SRVC_CMPL_EVT */ + uint16_t conn_id; /*!< Connection ID */ + } dis_srvc_cmpl; /*!< Callback parameter for the event `ESP_GATTC_DIS_SRVC_CMPL_EVT` */ -} esp_ble_gattc_cb_param_t; /*!< GATT client callback parameter union type */ +} esp_ble_gattc_cb_param_t; /** * @brief GATT Client callback function type - * @param event : Event type - * @param gattc_if : GATT client access interface, normally - * different gattc_if correspond to different profile - * @param param : Point to callback parameter, currently is union type + * + * @param[in] event Event type + * @param[in] gattc_if GATT Client access interface + * @param[in] param The pointer to callback parameter */ typedef void (* esp_gattc_cb_t)(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param); /** - * @brief This function is called to register application callbacks - * with GATTC module. + * @brief Register GATT Client application callbacks * - * @param[in] callback : pointer to the application callback function. + * @param[in] callback The pointer to the application callback function * - * @return - * - ESP_OK: success - * - other: failed + * @note Avoid performing time-consuming operations within the callback functions. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gattc_register_callback(esp_gattc_cb_t callback); /** - * @brief This function is called to get the current application callbacks - * with BTA GATTC module. + * @brief Get the current application callbacks * * @return - * - esp_gattC_cb_t : current callback - * + * - esp_gattc_cb_t: Current callback */ esp_gattc_cb_t esp_ble_gattc_get_callback(void); /** - * @brief This function is called to register application callbacks - * with GATTC module. + * @brief Register a GATT Client application * - * @param[in] app_id : Application Identify (UUID), for different application + * @param[in] app_id The UUID for different application * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This function triggers `ESP_GATTC_REG_EVT`. + * 2. The maximum number of applications is limited to 4. * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: The input `app_id` exceeds `ESP_APP_ID_MAX` (0x7fff) defined in esp_bt_defs.h + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gattc_app_register(uint16_t app_id); - /** - * @brief This function is called to unregister an application - * from GATTC module. + * @brief Unregister a GATT Client application * - * @param[in] gattc_if: Gatt client access interface. + * @param[in] gattc_if GATT Client access interface * - * @return - * - ESP_OK: success - * - other: failed + * @note This function triggers `ESP_GATTC_UNREG_EVT`. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gattc_app_unregister(esp_gatt_if_t gattc_if); -#if (BLE_42_FEATURE_SUPPORT == TRUE) /** - * @brief Open a direct connection or add a background auto connection + * @brief Create an ACL connection * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] remote_bda: remote device bluetooth device address. - * @param[in] remote_addr_type: remote device bluetooth device the address type. - * @param[in] is_direct: direct connection or background auto connection(by now, background auto connection is not supported). + * @note + * 1. Do not enable `BT_BLE_42_FEATURES_SUPPORTED` and `BT_BLE_50_FEATURES_SUPPORTED` in the menuconfig simultaneously. + * 1. The function always triggers `ESP_GATTC_CONNECT_EVT` and `ESP_GATTC_OPEN_EVT`. + * 2. When the device acts as GATT server, besides the above two events, this function triggers `ESP_GATTS_CONNECT_EVT` as well. + * 3. This function will establish an ACL connection as a Central and a virtual connection as a GATT Client. If the ACL connection already exists, it will create a virtual connection only. + + * + * @param[in] gattc_if: GATT client access interface. + * @param[in] esp_gatt_create_conn: Pointer to the structure containing connection parameters. * * @return - * - ESP_OK: success - * - other: failed + * - ESP_OK: Success + * - others: Operation failed * */ +esp_err_t esp_ble_gattc_enh_open(esp_gatt_if_t gattc_if, esp_ble_gatt_creat_conn_params_t *esp_gatt_create_conn); + +/** + * @brief Create an ACL connection when `BT_BLE_42_FEATURES_SUPPORTED` is enabled in the menuconfig + * + * @param[in] gattc_if GATT Client access interface + * @param[in] remote_bda Remote device address + * @param[in] remote_addr_type Remote device address type + * @param[in] is_direct `True` indicates a direct connection, while `False` indicates a background auto connection. By now, background auto connection is not supported, please always pass True to this parameter. + * + * @note + * 1. The function always triggers `ESP_GATTC_CONNECT_EVT` and `ESP_GATTC_OPEN_EVT`. + * 2. When the device acts as GATT server, besides the above two events, this function triggers `ESP_GATTS_CONNECT_EVT` as well. + * 3. This function will establish an ACL connection as a Central and a virtual connection as a GATT Client. If the ACL connection already exists, it will create a virtual connection only. + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure + */ +#if (BLE_42_FEATURE_SUPPORT == TRUE) esp_err_t esp_ble_gattc_open(esp_gatt_if_t gattc_if, esp_bd_addr_t remote_bda, esp_ble_addr_type_t remote_addr_type, bool is_direct); #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) +/** + * @brief Create an ACL connection when `BT_BLE_50_FEATURES_SUPPORTED` is enabled in the menuconfig + * + * @param[in] gattc_if GATT Client access interface + * @param[in] remote_bda Remote device address + * @param[in] remote_addr_type Remote device address type + * @param[in] is_direct `True` indicates a direct connection, while `False` indicates a background auto connection. By now, background auto connection is not supported, please always pass True to this parameter. + * + * @note + * 1. The function always triggers `ESP_GATTC_CONNECT_EVT` and `ESP_GATTC_OPEN_EVT`. + * 2. When the device acts as GATT server, besides the above two events, this function triggers `ESP_GATTS_CONNECT_EVT` as well. + * 3. This function will establish an ACL connection as a Central and a virtual connection as a GATT Client. If the ACL connection already exists, it will create a virtual connection only. + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure + */ #if (BLE_50_FEATURE_SUPPORT == TRUE) esp_err_t esp_ble_gattc_aux_open(esp_gatt_if_t gattc_if, esp_bd_addr_t remote_bda, esp_ble_addr_type_t remote_addr_type, bool is_direct); #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + /** - * @brief Close the virtual connection to the GATT server. gattc may have multiple virtual GATT server connections when multiple app_id registered, - * this API only close one virtual GATT server connection. if there exist other virtual GATT server connections, - * it does not disconnect the physical connection. - * if you want to disconnect the physical connection directly, you can use esp_ble_gap_disconnect(esp_bd_addr_t remote_device). + * @brief Close the virtual GATT Client connection * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id: connection ID to be closed. + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID to be closed * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This function triggers `ESP_GATTC_CLOSE_EVT`. + * 2. There may be multiple virtual GATT server connections when multiple `app_id` got registered. + * 3. This API closes one virtual GATT server connection only, if there exist other virtual GATT server connections. It does not close the physical connection. + * 4. The API `esp_ble_gap_disconnect` can be used to disconnect the physical connection directly. + * 5. If there is only one virtual GATT connection left, this API will terminate the ACL connection in addition and triggers `ESP_GATTC_DISCONNECT_EVT`. Then there is no need to call `esp_ble_gap_disconnect` anymore. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ -esp_err_t esp_ble_gattc_close (esp_gatt_if_t gattc_if, uint16_t conn_id); - +esp_err_t esp_ble_gattc_close(esp_gatt_if_t gattc_if, uint16_t conn_id); /** - * @brief Configure the MTU size in the GATT channel. This can be done - * only once per connection. Before using, use esp_ble_gatt_set_local_mtu() - * to configure the local MTU size. + * @brief Configure the MTU size in the GATT channel * * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id: connection ID. + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This function triggers `ESP_GATTC_CFG_MTU_EVT`. + * 2. You could call `esp_ble_gatt_set_local_mtu` to set the desired MTU size locally before this API. If not set, the GATT channel uses the default MTU size (23 bytes). * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gattc_send_mtu_req (esp_gatt_if_t gattc_if, uint16_t conn_id); - /** - * @brief This function is called to get service from local cache. - * This function report service search result by a callback - * event, and followed by a service search complete event. - * Note: 128-bit base UUID will automatically be converted to a 16-bit UUID in the search results. Other types of UUID remain unchanged. + * @brief Search services from the local GATTC cache * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id: connection ID. - * @param[in] filter_uuid: a UUID of the service application is interested in. - * If Null, discover for all services. + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID + * @param[in] filter_uuid A UUID of the intended service. If NULL is passed, this API will return all services. * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This function triggers `ESP_GATTC_SEARCH_RES_EVT` each time a service is retrieved. + * 2. This function triggers `ESP_GATTC_SEARCH_CMPL_EVT` when the search is completed. + * 3. The 128-bit base UUID will be converted to a 16-bit UUID automatically in the search results. Other types of UUID remain unchanged. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gattc_search_service(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_bt_uuid_t *filter_uuid); /** - * @brief Find all the service with the given service uuid in the gattc cache, if the svc_uuid is NULL, find all the service. - * Note: It just get service from local cache, won't get from remote devices. If want to get it from remote device, need - * to used the esp_ble_gattc_cache_refresh, then call esp_ble_gattc_get_service again. + * @brief Get the service with the given service UUID in the local GATTC cache * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id: connection ID which identify the server. - * @param[in] svc_uuid: the pointer to the service uuid. - * @param[out] result: The pointer to the service which has been found in the gattc cache. - * @param[inout] count: input the number of service want to find, - * it will output the number of service has been found in the gattc cache with the given service uuid. - * @param[in] offset: Offset of the service position to get. + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID + * @param[in] svc_uuid The pointer to the service UUID. If NULL is passed, the API will retrieve all services. + * @param[out] result The pointer to the service which has been found in the local GATTC cache + * @param[inout] count The number of services to retrieve. It will be updated with the actual number of services found. + * @param[in] offset The position offset to retrieve * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This API does not trigger any event. + * 2. `esp_ble_gattc_cache_refresh` can be used to discover services again. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_gatt_status_t esp_ble_gattc_get_service(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_bt_uuid_t *svc_uuid, esp_gattc_service_elem_t *result, uint16_t *count, uint16_t offset); /** - * @brief Find all the characteristic with the given service in the gattc cache - * Note: It just get characteristic from local cache, won't get from remote devices. + * @brief Get all characteristics with the given handle range in the local GATTC cache * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id: connection ID which identify the server. - * @param[in] start_handle: the attribute start handle. - * @param[in] end_handle: the attribute end handle - * @param[out] result: The pointer to the characteristic in the service. - * @param[inout] count: input the number of characteristic want to find, - * it will output the number of characteristic has been found in the gattc cache with the given service. - * @param[in] offset: Offset of the characteristic position to get. + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID + * @param[in] start_handle The attribute start handle + * @param[in] end_handle The attribute end handle + * @param[out] result The pointer to the characteristic in the service + * @param[inout] count The number of characteristics to retrieve. It will be updated with the actual number of characteristics found. + * @param[in] offset The position offset to retrieve * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This API does not trigger any event. + * 2. `start_handle` must be greater than 0, and smaller than `end_handle`. * + * @return + * - ESP_OK: Success + * - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle` or `end_handle` + * - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0 + * - ESP_FAIL: Failure due to other reasons */ esp_gatt_status_t esp_ble_gattc_get_all_char(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -429,21 +483,24 @@ esp_gatt_status_t esp_ble_gattc_get_all_char(esp_gatt_if_t gattc_if, uint16_t *count, uint16_t offset); /** - * @brief Find all the descriptor with the given characteristic in the gattc cache - * Note: It just get descriptor from local cache, won't get from remote devices. + * @brief Get all descriptors with the given characteristic in the local GATTC cache * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id: connection ID which identify the server. - * @param[in] char_handle: the given characteristic handle - * @param[out] result: The pointer to the descriptor in the characteristic. - * @param[inout] count: input the number of descriptor want to find, - * it will output the number of descriptor has been found in the gattc cache with the given characteristic. - * @param[in] offset: Offset of the descriptor position to get. + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID which identifies the server + * @param[in] char_handle The given characteristic handle + * @param[out] result The pointer to the descriptor in the characteristic + * @param[inout] count The number of descriptors to retrieve. It will be updated with the actual number of descriptors found. + * @param[in] offset The position offset to retrieve * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This API does not trigger any event. + * 2. `char_handle` must be greater than 0. * + * @return + * - ESP_OK: Success + * - ESP_GATT_INVALID_HANDLE: Invalid GATT `char_handle` + * - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0 + * - ESP_FAIL: Failure due to other reasons */ esp_gatt_status_t esp_ble_gattc_get_all_descr(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -451,24 +508,26 @@ esp_gatt_status_t esp_ble_gattc_get_all_descr(esp_gatt_if_t gattc_if, esp_gattc_descr_elem_t *result, uint16_t *count, uint16_t offset); - /** - * @brief Find the characteristic with the given characteristic uuid in the gattc cache - * Note: It just get characteristic from local cache, won't get from remote devices. + * @brief Get the characteristic with the given characteristic UUID in the local GATTC cache * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id: connection ID which identify the server. - * @param[in] start_handle: the attribute start handle - * @param[in] end_handle: the attribute end handle - * @param[in] char_uuid: the characteristic uuid - * @param[out] result: The pointer to the characteristic in the service. - * @param[inout] count: input the number of characteristic want to find, - * it will output the number of characteristic has been found in the gattc cache with the given service. + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID + * @param[in] start_handle The attribute start handle + * @param[in] end_handle The attribute end handle + * @param[in] char_uuid The characteristic UUID + * @param[out] result The pointer to the characteristic in the service + * @param[inout] count The number of characteristics to retrieve. It will be updated with the actual number of characteristics found. * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This API does not trigger any event. + * 2. `start_handle` must be greater than 0, and smaller than `end_handle`. * + * @return + * - ESP_OK: Success + * - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle` or `end_handle` + * - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0 + * - ESP_FAIL: Failure due to other reasons */ esp_gatt_status_t esp_ble_gattc_get_char_by_uuid(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -479,23 +538,25 @@ esp_gatt_status_t esp_ble_gattc_get_char_by_uuid(esp_gatt_if_t gattc_if, uint16_t *count); /** - * @brief Find the descriptor with the given characteristic uuid in the gattc cache - * Note: It just get descriptor from local cache, won't get from remote devices. + * @brief Get the descriptor with the given characteristic UUID in the local GATTC cache * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id: connection ID which identify the server. - * @param[in] start_handle: the attribute start handle - * @param[in] end_handle: the attribute end handle - * @param[in] char_uuid: the characteristic uuid. - * @param[in] descr_uuid: the descriptor uuid. - * @param[out] result: The pointer to the descriptor in the given characteristic. - * @param[inout] count: input the number of descriptor want to find, - * it will output the number of descriptor has been found in the gattc cache with the given characteristic. + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID + * @param[in] start_handle The attribute start handle + * @param[in] end_handle The attribute end handle + * @param[in] char_uuid The characteristic UUID + * @param[in] descr_uuid The descriptor UUID. + * @param[out] result The pointer to the descriptor in the given characteristic. + * @param[inout] count The number of descriptors want to retrieve. It will be updated with the actual number of descriptors found. * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This API does not trigger any event. + * 2. `start_handle` must be greater than 0, and smaller than `end_handle`. * + * @return + * - ESP_OK: Success + * - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0 + * - ESP_FAIL: Failure due to other reasons */ esp_gatt_status_t esp_ble_gattc_get_descr_by_uuid(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -507,21 +568,24 @@ esp_gatt_status_t esp_ble_gattc_get_descr_by_uuid(esp_gatt_if_t gattc_if, uint16_t *count); /** - * @brief Find the descriptor with the given characteristic handle in the gattc cache - * Note: It just get descriptor from local cache, won't get from remote devices. + * @brief Get the descriptor with the given characteristic handle in the local GATTC cache * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id: connection ID which identify the server. - * @param[in] char_handle: the characteristic handle. - * @param[in] descr_uuid: the descriptor uuid. - * @param[out] result: The pointer to the descriptor in the given characteristic. - * @param[inout] count: input the number of descriptor want to find, - * it will output the number of descriptor has been found in the gattc cache with the given characteristic. + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID which identifies the server + * @param[in] char_handle The characteristic handle + * @param[in] descr_uuid The descriptor UUID + * @param[out] result The pointer to the descriptor in the given characteristic + * @param[inout] count The number of descriptors want to retrieve. It will be updated with the actual number of descriptors found. * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This API does not trigger any event. + * 2. `char_handle` must be greater than 0. * + * @return + * - ESP_OK: Success + * - ESP_GATT_INVALID_HANDLE: Invalid GATT `char_handle` + * - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0 + * - ESP_FAIL: Failure due to other reasons */ esp_gatt_status_t esp_ble_gattc_get_descr_by_char_handle(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -531,22 +595,24 @@ esp_gatt_status_t esp_ble_gattc_get_descr_by_char_handle(esp_gatt_if_t gattc_if, uint16_t *count); /** - * @brief Find the include service with the given service handle in the gattc cache - * Note: It just get include service from local cache, won't get from remote devices. + * @brief Get the included services with the given service handle in the local GATTC cache. * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id: connection ID which identify the server. - * @param[in] start_handle: the attribute start handle - * @param[in] end_handle: the attribute end handle - * @param[in] incl_uuid: the include service uuid - * @param[out] result: The pointer to the include service in the given service. - * @param[inout] count: input the number of include service want to find, - * it will output the number of include service has been found in the gattc cache with the given service. + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID which identifies the server + * @param[in] start_handle The attribute start handle + * @param[in] end_handle The attribute end handle + * @param[in] incl_uuid The included service UUID + * @param[out] result The pointer to the included service with the given service handle. + * @param[inout] count The number of included services to retrieve. It will be updated with the actual number of included services found. * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This API does not trigger any event. + * 2. `start_handle` must be greater than 0, and smaller than `end_handle`. * + * @return + * - ESP_OK: Success + * - ESP_GATT_INVALID_PDU: NULL pointer to `result` or NULL pointer to `count` or the count value is 0 + * - ESP_FAIL: Failure due to other reasons */ esp_gatt_status_t esp_ble_gattc_get_include_service(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -556,23 +622,27 @@ esp_gatt_status_t esp_ble_gattc_get_include_service(esp_gatt_if_t gattc_if, esp_gattc_incl_svc_elem_t *result, uint16_t *count); - /** - * @brief Find the attribute count with the given service or characteristic in the gattc cache + * @brief Get the attribute count with the given service or characteristic in the local GATTC cache * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id: connection ID which identify the server. - * @param[in] type: the attribute type. - * @param[in] start_handle: the attribute start handle, if the type is ESP_GATT_DB_DESCRIPTOR, this parameter should be ignore - * @param[in] end_handle: the attribute end handle, if the type is ESP_GATT_DB_DESCRIPTOR, this parameter should be ignore - * @param[in] char_handle: the characteristic handle, this parameter valid when the type is ESP_GATT_DB_DESCRIPTOR. If the type - * isn't ESP_GATT_DB_DESCRIPTOR, this parameter should be ignore. - * @param[out] count: output the number of attribute has been found in the gattc cache with the given attribute type. + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID + * @param[in] type The attribute type + * @param[in] start_handle The attribute start handle. If the type is `ESP_GATT_DB_DESCRIPTOR`, this parameter will be ignored. + * @param[in] end_handle The attribute end handle. If the type is `ESP_GATT_DB_DESCRIPTOR`, this parameter will be ignored. + * @param[in] char_handle The characteristic handle. This parameter is valid only if the type is `ESP_GATT_DB_DESCRIPTOR`. + * @param[out] count The number of attributes found in the local GATTC cache with the given attribute type * - * @return - * - ESP_OK: success - * - other: failed * + * @note + * 1. This API does not trigger any event. + * 2. `start_handle` must be greater than 0, and smaller than `end_handle` if the `type` is not `ESP_GATT_DB_DESCRIPTOR`. + * + * @return + * - ESP_OK: Success + * - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle`, `end_handle` + * - ESP_GATT_INVALID_PDU: NULL pointer to `count` + * - ESP_FAIL: Failure due to other reasons */ esp_gatt_status_t esp_ble_gattc_get_attr_count(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -583,38 +653,47 @@ esp_gatt_status_t esp_ble_gattc_get_attr_count(esp_gatt_if_t gattc_if, uint16_t *count); /** - * @brief This function is called to get the GATT database. - * Note: It just get attribute data base from local cache, won't get from remote devices. + * @brief Get the GATT database elements * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] start_handle: the attribute start handle - * @param[in] end_handle: the attribute end handle - * @param[in] conn_id: connection ID which identify the server. - * @param[in] db: output parameter which will contain the GATT database copy. - * Caller is responsible for freeing it. - * @param[in] count: number of elements in database. + * @param[in] gattc_if GATT Client access interface + * @param[in] start_handle The attribute start handle + * @param[in] end_handle The attribute end handle + * @param[in] conn_id Connection ID + * @param[out] db The pointer to GATT database elements + * @param[inout] count The number of elements in the database to retrieve. It will be updated with the actual number of elements found. + * + * @note + * 1. This API does not trigger any event. + * 2. `start_handle` must be greater than 0, and smaller than `end_handle`. * * @return - * - ESP_OK: success - * - other: failed + * - ESP_OK: Success + * - ESP_GATT_INVALID_HANDLE: Invalid GATT `start_handle`, `end_handle` + * - ESP_GATT_INVALID_PDU: NULL pointer to `db` or NULL pointer to `count` or the count value is 0 + * - ESP_FAIL: Failure due to other reasons * */ esp_gatt_status_t esp_ble_gattc_get_db(esp_gatt_if_t gattc_if, uint16_t conn_id, uint16_t start_handle, uint16_t end_handle, esp_gattc_db_elem_t *db, uint16_t *count); /** - * @brief This function is called to read a service's characteristics of - * the given characteristic handle + * @brief Read the characteristics value of the given characteristic handle * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id : connection ID. - * @param[in] handle : characteritic handle to read. - * @param[in] auth_req : authenticate request type + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID + * @param[in] handle Characteristic handle to read + * @param[in] auth_req Authenticate request type * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This function triggers `ESP_GATTC_READ_CHAR_EVT`. + * 2. This function should be called only after the connection has been established. + * 3. `handle` must be greater than 0. * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: The connection has not been established. + * - ESP_GATT_INVALID_HANDLE: Invalid `handle` + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -622,20 +701,25 @@ esp_err_t esp_ble_gattc_read_char (esp_gatt_if_t gattc_if, esp_gatt_auth_req_t auth_req); /** - * @brief This function is called to read a service's characteristics of - * the given characteristic UUID + * @brief Read the characteristics value of the given characteristic UUID. * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id : connection ID. - * @param[in] start_handle : the attribute start handle. - * @param[in] end_handle : the attribute end handle - * @param[in] uuid : The UUID of attribute which will be read. - * @param[in] auth_req : authenticate request type + * @param[in] gattc_if GATT Client access interface. + * @param[in] conn_id Connection ID + * @param[in] start_handle The attribute start handle + * @param[in] end_handle The attribute end handle + * @param[in] uuid The pointer to UUID of attribute to read + * @param[in] auth_req Authenticate request type * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This function triggers `ESP_GATTC_READ_CHAR_EVT`. + * 2. This function should be called only after the connection has been established. + * 3. `start_handle` must be greater than 0, and smaller than `end_handle`. * + * @return + * - ESP_OK: Success + * - ESP_GATT_ILLEGAL_PARAMETER: NULL pointer to `uuid` + * - ESP_ERR_INVALID_STATE: The connection has not been established + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gattc_read_by_type (esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -645,75 +729,92 @@ esp_err_t esp_ble_gattc_read_by_type (esp_gatt_if_t gattc_if, esp_gatt_auth_req_t auth_req); /** - * @brief This function is called to read multiple characteristic or - * characteristic descriptors. + * @brief Read multiple characteristic or descriptor values * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id : connection ID. - * @param[in] read_multi : pointer to the read multiple parameter. - * @param[in] auth_req : authenticate request type + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID which specifies the server + * @param[in] read_multi Pointer to `esp_gattc_multi_t` + * @param[in] auth_req Authenticate request type * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This function triggers `ESP_GATTC_READ_MULTIPLE_EVT`. + * 2. This function should be called only after the connection has been established. * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: The connection has not been established + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gattc_read_multiple(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_gattc_multi_t *read_multi, esp_gatt_auth_req_t auth_req); /** - * @brief This function is called to read multiple variable length characteristic or - * characteristic descriptors. + * @brief Read multiple variable length characteristic values. * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id : connection ID. - * @param[in] read_multi : pointer to the read multiple parameter. - * @param[in] auth_req : authenticate request type + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID + * @param[in] read_multi The pointer to the `esp_gattc_multi_t` + * @param[in] auth_req Authenticate request type * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This function triggers `ESP_GATTC_READ_MULTI_VAR_EVT`. + * 2. This function should be called only after the connection has been established. * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: The connection has not been established. + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gattc_read_multiple_variable(esp_gatt_if_t gattc_if, uint16_t conn_id, esp_gattc_multi_t *read_multi, esp_gatt_auth_req_t auth_req); /** - * @brief This function is called to read a characteristics descriptor. + * @brief Read a characteristics descriptor * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id : connection ID. - * @param[in] handle : descriptor handle to read. - * @param[in] auth_req : authenticate request type + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID + * @param[in] handle Descriptor handle to read + * @param[in] auth_req Authenticate request type * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This function triggers `ESP_GATTC_READ_DESCR_EVT`. + * 2. This function should be called only after the connection has been established. + * 3. `handle` must be greater than 0. * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: The connection has not been established. + * - ESP_GATT_INVALID_HANDLE:Invalid `handle` + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gattc_read_char_descr (esp_gatt_if_t gattc_if, uint16_t conn_id, uint16_t handle, esp_gatt_auth_req_t auth_req); - /** - * @brief This function is called to write characteristic value. + * @brief Write the characteristic value of a given characteristic handle * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id : connection ID. - * @param[in] handle : characteristic handle to write. - * @param[in] value_len: length of the value to be written. - * @param[in] value : the value to be written. - * @param[in] write_type : the type of attribute write operation. - * @param[in] auth_req : authentication request. + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID + * @param[in] handle The characteristic handle to write + * @param[in] value_len The length of the value to write in bytes + * @param[in] value The value to write + * @param[in] write_type The type of Attribute write operation + * @param[in] auth_req Authentication request type * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This function triggers `ESP_GATTC_WRITE_CHAR_EVT`. + * 2. This function should be called only after the connection has been established. + * 3. `handle` must be greater than 0. * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: The connection has not been established. + * - ESP_GATT_INVALID_HANDLE:Invalid `handle` + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gattc_write_char( esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -723,22 +824,27 @@ esp_err_t esp_ble_gattc_write_char( esp_gatt_if_t gattc_if, esp_gatt_write_type_t write_type, esp_gatt_auth_req_t auth_req); - /** - * @brief This function is called to write characteristic descriptor value. + * @brief Write Characteristic descriptor value of a given descriptor handle * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id : connection ID - * @param[in] handle : descriptor handle to write. - * @param[in] value_len: length of the value to be written. - * @param[in] value : the value to be written. - * @param[in] write_type : the type of attribute write operation. - * @param[in] auth_req : authentication request. + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID + * @param[in] handle The descriptor handle to write. + * @param[in] value_len The length of the value to write in bytes. + * @param[in] value The value to write + * @param[in] write_type The type of Attribute write operation + * @param[in] auth_req Authentication request type * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This function triggers `ESP_GATTC_WRITE_DESCR_EVT`. + * 2. This function should be called only after the connection has been established. + * 3. `handle` must be greater than 0. * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: The connection has not been established. + * - ESP_GATT_INVALID_HANDLE:Invalid `handle` + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -748,22 +854,29 @@ esp_err_t esp_ble_gattc_write_char_descr (esp_gatt_if_t gattc_if, esp_gatt_write_type_t write_type, esp_gatt_auth_req_t auth_req); - /** - * @brief This function is called to prepare write a characteristic value. - * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id : connection ID. - * @param[in] handle : characteristic handle to prepare write. - * @param[in] offset : offset of the write value. - * @param[in] value_len: length of the value to be written. - * @param[in] value : the value to be written. - * @param[in] auth_req : authentication request. + * @brief Prepare to write a characteristic value which is longer than the MTU size to a specified characteristic handle + * + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID + * @param[in] handle Characteristic handle to prepare to write + * @param[in] offset The position offset to write + * @param[in] value_len The length of the value to write in bytes + * @param[in] value The value to write + * @param[in] auth_req Authentication request type + * + * @note + * 1. This function should be called only after the connection has been established. + * 2. After using this API, use `esp_ble_gattc_execute_write` to write. + * 3. This function triggers `ESP_GATTC_PREP_WRITE_EVT`. + * 4. If `value_len` is less than or equal to MTU size, it is recommended to `esp_ble_gattc_write_char` to write directly. + * 5. `handle` must be greater than 0. * * @return - * - ESP_OK: success - * - other: failed - * + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: The connection has not been established. + * - ESP_GATT_INVALID_HANDLE:Invalid `handle` + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -773,22 +886,27 @@ esp_err_t esp_ble_gattc_prepare_write(esp_gatt_if_t gattc_if, uint8_t *value, esp_gatt_auth_req_t auth_req); - /** - * @brief This function is called to prepare write a characteristic descriptor value. + * @brief Prepare to write a characteristic descriptor value at a given handle * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id : connection ID. - * @param[in] handle : characteristic descriptor handle to prepare write. - * @param[in] offset : offset of the write value. - * @param[in] value_len: length of the value to be written. - * @param[in] value : the value to be written. - * @param[in] auth_req : authentication request. + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID + * @param[in] handle Characteristic descriptor handle to prepare to write + * @param[in] offset The position offset to write + * @param[in] value_len The length of the value to write in bytes + * @param[in] value The value to write + * @param[in] auth_req Authentication request type * - * @return - * - ESP_OK: success - * - other: failed + * @note + * 1. This function triggers `ESP_GATTC_WRITE_CHAR_EVT`. + * 2. This function should be called only after the connection has been established. + * 3. `handle` must be greater than 0. * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: The connection has not been established. + * - ESP_GATT_INVALID_HANDLE:Invalid `handle` + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gattc_prepare_write_char_descr(esp_gatt_if_t gattc_if, uint16_t conn_id, @@ -798,112 +916,123 @@ esp_err_t esp_ble_gattc_prepare_write_char_descr(esp_gatt_if_t gattc_if, uint8_t *value, esp_gatt_auth_req_t auth_req); - /** - * @brief This function is called to execute write a prepare write sequence. + * @brief Execute a prepared writing sequence * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] conn_id : connection ID. - * @param[in] is_execute : execute or cancel. + * @param[in] gattc_if GATT Client access interface + * @param[in] conn_id Connection ID + * @param[in] is_execute True if it is to execute the writing sequence; false if it is to cancel the writing sequence. * - * @return - * - ESP_OK: success - * - other: failed + * @note This function triggers `ESP_GATTC_EXEC_EVT`. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gattc_execute_write (esp_gatt_if_t gattc_if, uint16_t conn_id, bool is_execute); - /** - * @brief This function is called to register for notification of a service. + * @brief Register to receive notification/indication of a characteristic. * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] server_bda : target GATT server. - * @param[in] handle : GATT characteristic handle. + * @param[in] gattc_if GATT Client access interface + * @param[in] server_bda Target GATT server device address + * @param[in] handle Target GATT characteristic handle * - * @return - * - ESP_OK: registration succeeds - * - other: failed + * @note + * 1. This function triggers `ESP_GATTC_REG_FOR_NOTIFY_EVT`. + * 2. You should call `esp_ble_gattc_write_char_descr()` after this API to write Client Characteristic Configuration (CCC) descriptor to the value of 1 (Enable Notification) or 2 (Enable Indication). + * 3. `handle` must be greater than 0. * + * @return + * - ESP_OK: Success + * - ESP_GATT_INVALID_HANDLE:Invalid `handle` + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gattc_register_for_notify (esp_gatt_if_t gattc_if, esp_bd_addr_t server_bda, uint16_t handle); - /** - * @brief This function is called to de-register for notification of a service. + * @brief Unregister the notification of a service. * - * @param[in] gattc_if: Gatt client access interface. - * @param[in] server_bda : target GATT server. - * @param[in] handle : GATT characteristic handle. + * @param[in] gattc_if GATT Client access interface + * @param[in] server_bda Target GATT server device address + * @param[in] handle Target GATT characteristic handle * + * @note + * 1. This function triggers `ESP_GATTC_UNREG_FOR_NOTIFY_EVT`. + * 2. You should call `esp_ble_gattc_write_char_descr()` after this API to write Client Characteristic Configuration (CCC) descriptor value to 0. + * 3. `handle` must be greater than 0 * @return - * - ESP_OK: unregister succeeds - * - other: failed - * + * - ESP_OK: Success + * - ESP_GATT_INVALID_HANDLE:Invalid `handle` + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gattc_unregister_for_notify (esp_gatt_if_t gattc_if, esp_bd_addr_t server_bda, uint16_t handle); - /** -* @brief Refresh the server cache store in the gattc stack of the remote device. If -* the device is connected, this API will restart the discovery of service information of the remote device -* -* @param[in] remote_bda: remote device BD address. -* -* @return -* - ESP_OK: success -* - other: failed -* -*/ + * @brief Refresh the cache of the remote device + * + * @param[in] remote_bda Remote device address + * + * @note + * 1. If the device is connected, this API will restart the discovery of service information of the remote device. + * 2. This function triggers `ESP_GATTC_DIS_SRVC_CMPL_EVT` only after the ACL connection is established. Otherwise, no events will be triggered. + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure + */ esp_err_t esp_ble_gattc_cache_refresh(esp_bd_addr_t remote_bda); /** -* @brief Add or delete the associated address with the source address. -* Note: The role of this API is mainly when the client side has stored a server-side database, -* when it needs to connect another device, but the device's attribute database is the same -* as the server database stored on the client-side, calling this API can use the database -* that the device has stored used as the peer server database to reduce the attribute -* database search and discovery process and speed up the connection time. -* The associated address mains that device want to used the database has stored in the local cache. -* The source address mains that device want to share the database to the associated address device. -* -* @param[in] gattc_if: Gatt client access interface. -* @param[in] src_addr: the source address which provide the attribute table. -* @param[in] assoc_addr: the associated device address which went to share the attribute table with the source address. -* @param[in] is_assoc: true add the associated device address, false remove the associated device address. -* @return -* - ESP_OK: success -* - other: failed -* -*/ + * @brief Add or remove the association between the address in the local GATTC cache with the source address of the remote device + * + * @param[in] gattc_if GATT Client access interface + * @param[in] src_addr The source address intended to be associated to the `assoc_addr` which has been stored in the local GATTC cache + * @param[in] assoc_addr The associated device address intended to share the attribute table with the source address + * @param[in] is_assoc True if adding the association; false if removing the association. + * + * @note + * 1. This API is primarily used when the client has a stored server-side database (`assoc_addr`) and needs to connect to + * another device (`src_addr`) with the same attribute database. By invoking this API, the stored database is utilized + * as the peer server database, eliminating the need for attribute database search and discovery. This reduces + * processing time and accelerates the connection process. + * 2. The attribute table of a device with `assoc_addr` must be stored in the local GATTC cache first. + * Then, the attribute table of the device with `src_addr` must be the same as the one with `assoc_addr`. + * 3. This function triggers `ESP_GATTC_SET_ASSOC_EVT`. + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure + */ esp_err_t esp_ble_gattc_cache_assoc(esp_gatt_if_t gattc_if, esp_bd_addr_t src_addr, esp_bd_addr_t assoc_addr, bool is_assoc); + /** -* @brief Get the address list which has store the attribute table in the gattc cache. There will -* callback ESP_GATTC_GET_ADDR_LIST_EVT event when get address list complete. -* -* @param[in] gattc_if: Gatt client access interface. -* @return -* - ESP_OK: success -* - other: failed -* -*/ + * @brief Get the address list stored in the local GATTC cache + * + * @param[in] gattc_if GATT Client access interface + * + * @note This function triggers `ESP_GATTC_GET_ADDR_LIST_EVT`. + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure + */ esp_err_t esp_ble_gattc_cache_get_addr_list(esp_gatt_if_t gattc_if); /** -* @brief Clean the service cache of this device in the gattc stack, -* -* @param[in] remote_bda: remote device BD address. -* -* @return -* - ESP_OK: success -* - other: failed -* -*/ + * @brief Clean the service cache of the target device in the local GATTC cache + * + * @param[in] remote_bda Remote device address + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure + */ esp_err_t esp_ble_gattc_cache_clean(esp_bd_addr_t remote_bda); #ifdef __cplusplus diff --git a/lib/bt/host/bluedroid/api/include/api/esp_gatts_api.h b/lib/bt/host/bluedroid/api/include/api/esp_gatts_api.h index 0eb7ddd9..64222210 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_gatts_api.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_gatts_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,579 +17,606 @@ extern "C" { /// GATT Server callback function events typedef enum { - ESP_GATTS_REG_EVT = 0, /*!< When register application id, the event comes */ - ESP_GATTS_READ_EVT = 1, /*!< When gatt client request read operation, the event comes */ - ESP_GATTS_WRITE_EVT = 2, /*!< When gatt client request write operation, the event comes */ - ESP_GATTS_EXEC_WRITE_EVT = 3, /*!< When gatt client request execute write, the event comes */ - ESP_GATTS_MTU_EVT = 4, /*!< When set mtu complete, the event comes */ - ESP_GATTS_CONF_EVT = 5, /*!< When receive confirm, the event comes */ - ESP_GATTS_UNREG_EVT = 6, /*!< When unregister application id, the event comes */ - ESP_GATTS_CREATE_EVT = 7, /*!< When create service complete, the event comes */ - ESP_GATTS_ADD_INCL_SRVC_EVT = 8, /*!< When add included service complete, the event comes */ - ESP_GATTS_ADD_CHAR_EVT = 9, /*!< When add characteristic complete, the event comes */ - ESP_GATTS_ADD_CHAR_DESCR_EVT = 10, /*!< When add descriptor complete, the event comes */ - ESP_GATTS_DELETE_EVT = 11, /*!< When delete service complete, the event comes */ - ESP_GATTS_START_EVT = 12, /*!< When start service complete, the event comes */ - ESP_GATTS_STOP_EVT = 13, /*!< When stop service complete, the event comes */ - ESP_GATTS_CONNECT_EVT = 14, /*!< When gatt client connect, the event comes */ - ESP_GATTS_DISCONNECT_EVT = 15, /*!< When gatt client disconnect, the event comes */ - ESP_GATTS_OPEN_EVT = 16, /*!< When connect to peer, the event comes */ - ESP_GATTS_CANCEL_OPEN_EVT = 17, /*!< When disconnect from peer, the event comes */ - ESP_GATTS_CLOSE_EVT = 18, /*!< When gatt server close, the event comes */ - ESP_GATTS_LISTEN_EVT = 19, /*!< When gatt listen to be connected the event comes */ - ESP_GATTS_CONGEST_EVT = 20, /*!< When congest happen, the event comes */ + ESP_GATTS_REG_EVT = 0, /*!< This event is triggered when a GATT Server application is registered using `esp_ble_gatts_app_register`. */ + ESP_GATTS_READ_EVT = 1, /*!< This event is triggered when the read request from the Client is received. */ + ESP_GATTS_WRITE_EVT = 2, /*!< This event is triggered when the write request from the Client is received. */ + ESP_GATTS_EXEC_WRITE_EVT = 3, /*!< This event is triggered when the write execution request from the Client is received. */ + ESP_GATTS_MTU_EVT = 4, /*!< This event is triggered when the MTU configuration request from the Client is received. */ + ESP_GATTS_CONF_EVT = 5, /*!< This event is triggered when the confirmation from the Client is received. */ + ESP_GATTS_UNREG_EVT = 6, /*!< This event is triggered when a GATT Server application is unregistered using `esp_ble_gatts_app_unregister`. */ + ESP_GATTS_CREATE_EVT = 7, /*!< This event is triggered when a GATT Server service is created using `esp_ble_gatts_create_service`. */ + ESP_GATTS_ADD_INCL_SRVC_EVT = 8, /*!< This event is triggered when an included service is added using `esp_ble_gatts_add_included_service`. */ + ESP_GATTS_ADD_CHAR_EVT = 9, /*!< This event is triggered when a characteristic is added to the service using `esp_ble_gatts_add_char`. */ + ESP_GATTS_ADD_CHAR_DESCR_EVT = 10, /*!< This event is triggered when a characteristic descriptor is added to the service using `esp_ble_gatts_add_char_descr`. */ + ESP_GATTS_DELETE_EVT = 11, /*!< This event is triggered when the service is deleted using `esp_ble_gatts_delete_service`. */ + ESP_GATTS_START_EVT = 12, /*!< This event is triggered when the service is started using `esp_ble_gatts_start_service`. */ + ESP_GATTS_STOP_EVT = 13, /*!< This event is triggered when the service is stopped using `esp_ble_gatts_stop_service`. */ + ESP_GATTS_CONNECT_EVT = 14, /*!< This event is triggered when a physical connection is set up. */ + ESP_GATTS_DISCONNECT_EVT = 15, /*!< This event is triggered when a physical connection is terminated. */ + ESP_GATTS_OPEN_EVT = 16, /*!< This event is triggered when a virtual connection is created using `esp_ble_gatts_open`. */ + ESP_GATTS_CANCEL_OPEN_EVT = 17, /*!< Deprecated. */ + ESP_GATTS_CLOSE_EVT = 18, /*!< This event is triggered when a virtual connection is closed using `esp_ble_gatts_close`. */ + ESP_GATTS_LISTEN_EVT = 19, /*!< Deprecated. */ + ESP_GATTS_CONGEST_EVT = 20, /*!< This event is triggered when the GATT connection is congested. */ /* following is extra event */ - ESP_GATTS_RESPONSE_EVT = 21, /*!< When gatt send response complete, the event comes */ - ESP_GATTS_CREAT_ATTR_TAB_EVT = 22, /*!< When gatt create table complete, the event comes */ - ESP_GATTS_SET_ATTR_VAL_EVT = 23, /*!< When gatt set attr value complete, the event comes */ - ESP_GATTS_SEND_SERVICE_CHANGE_EVT = 24, /*!< When gatt send service change indication complete, the event comes */ + ESP_GATTS_RESPONSE_EVT = 21, /*!< This event is triggered when a response is sent to the request using `esp_ble_gatts_send_response`. */ + ESP_GATTS_CREAT_ATTR_TAB_EVT = 22, /*!< This event is triggered when a service attribute table is created using `esp_ble_gatts_create_attr_tab`. */ + ESP_GATTS_SET_ATTR_VAL_EVT = 23, /*!< This event is triggered when an attribute value is set using `esp_ble_gatts_set_attr_value`. */ + ESP_GATTS_SEND_SERVICE_CHANGE_EVT = 24, /*!< This event is triggered when a service change indication is sent using `esp_ble_gatts_send_service_change_indication`. */ } esp_gatts_cb_event_t; /** - * @brief Gatt server callback parameters union + * @brief GATT Server callback parameters */ typedef union { /** - * @brief ESP_GATTS_REG_EVT + * @brief Callback parameter for the event `ESP_GATTS_REG_EVT` */ struct gatts_reg_evt_param { esp_gatt_status_t status; /*!< Operation status */ - uint16_t app_id; /*!< Application id which input in register API */ - } reg; /*!< Gatt server callback param of ESP_GATTS_REG_EVT */ + uint16_t app_id; /*!< Application ID */ + } reg; /*!< Callback parameter for the event `ESP_GATTS_REG_EVT` */ /** - * @brief ESP_GATTS_READ_EVT + * @brief Callback parameter for the event `ESP_GATTS_READ_EVT` */ struct gatts_read_evt_param { - uint16_t conn_id; /*!< Connection id */ - uint32_t trans_id; /*!< Transfer id */ - esp_bd_addr_t bda; /*!< The bluetooth device address which been read */ + uint16_t conn_id; /*!< Connection ID */ + uint32_t trans_id; /*!< Transfer ID */ + esp_bd_addr_t bda; /*!< The device address to read */ uint16_t handle; /*!< The attribute handle */ - uint16_t offset; /*!< Offset of the value, if the value is too long */ - bool is_long; /*!< The value is too long or not */ - bool need_rsp; /*!< The read operation need to do response */ - } read; /*!< Gatt server callback param of ESP_GATTS_READ_EVT */ + uint16_t offset; /*!< The position offset to read. If the length of value is less than or equal to the MTU size, this value is 0. */ + bool is_long; /*!< True indicates that the length of value is greater than the MTU size; false otherwise. */ + bool need_rsp; /*!< True indicates that the `esp_ble_gatts_send_response` is required in the following step; false otherwise. */ + } read; /*!< Callback parameter for the event `ESP_GATTS_READ_EVT` */ /** - * @brief ESP_GATTS_WRITE_EVT + * @brief Callback parameter for the event `ESP_GATTS_WRITE_EVT` */ struct gatts_write_evt_param { - uint16_t conn_id; /*!< Connection id */ - uint32_t trans_id; /*!< Transfer id */ - esp_bd_addr_t bda; /*!< The bluetooth device address which been written */ + uint16_t conn_id; /*!< Connection ID */ + uint32_t trans_id; /*!< Transfer ID */ + esp_bd_addr_t bda; /*!< The device address to write */ uint16_t handle; /*!< The attribute handle */ - uint16_t offset; /*!< Offset of the value, if the value is too long */ - bool need_rsp; /*!< The write operation need to do response */ - bool is_prep; /*!< This write operation is prepare write */ - uint16_t len; /*!< The write attribute value length */ + uint16_t offset; /*!< The position offset to write. If the length of value is less than or equal to the MTU size, this value is 0.*/ + bool need_rsp; /*!< True indicates that the `esp_ble_gatts_send_response` is required in the following step; false otherwise. */ + bool is_prep; /*!< True indicates the write operation is a prepared write operation */ + uint16_t len; /*!< The length of the write attribute value in bytes */ uint8_t *value; /*!< The write attribute value */ - } write; /*!< Gatt server callback param of ESP_GATTS_WRITE_EVT */ + } write; /*!< Callback parameter for the event `ESP_GATTS_WRITE_EVT` */ /** - * @brief ESP_GATTS_EXEC_WRITE_EVT + * @brief Callback parameter for the event `ESP_GATTS_EXEC_WRITE_EVT` */ struct gatts_exec_write_evt_param { - uint16_t conn_id; /*!< Connection id */ - uint32_t trans_id; /*!< Transfer id */ - esp_bd_addr_t bda; /*!< The bluetooth device address which been written */ -#define ESP_GATT_PREP_WRITE_CANCEL 0x00 /*!< Prepare write flag to indicate cancel prepare write */ -#define ESP_GATT_PREP_WRITE_EXEC 0x01 /*!< Prepare write flag to indicate execute prepare write */ - uint8_t exec_write_flag; /*!< Execute write flag */ - } exec_write; /*!< Gatt server callback param of ESP_GATTS_EXEC_WRITE_EVT */ + uint16_t conn_id; /*!< Connection ID */ + uint32_t trans_id; /*!< Transfer ID */ + esp_bd_addr_t bda; /*!< The bluetooth device address to write */ + #define ESP_GATT_PREP_WRITE_CANCEL 0x00 /*!< Flag to indicate the cancellation of a prepare write operation */ + #define ESP_GATT_PREP_WRITE_EXEC 0x01 /*!< Flag to indicate the execution of a prepare write operation */ + uint8_t exec_write_flag; /*!< Execute write flag: `ESP_GATT_PREP_WRITE_CANCEL` or `ESP_GATT_PREP_WRITE_EXEC` */ + } exec_write; /*!< Callback parameter for the event `ESP_GATTS_EXEC_WRITE_EVT` */ /** - * @brief ESP_GATTS_MTU_EVT + * @brief Callback parameter for the event `ESP_GATTS_MTU_EVT` */ struct gatts_mtu_evt_param { - uint16_t conn_id; /*!< Connection id */ + uint16_t conn_id; /*!< Connection ID */ uint16_t mtu; /*!< MTU size */ - } mtu; /*!< Gatt server callback param of ESP_GATTS_MTU_EVT */ + } mtu; /*!< Callback parameter for the event `ESP_GATTS_MTU_EVT` */ /** - * @brief ESP_GATTS_CONF_EVT + * @brief Callback parameter for the event `ESP_GATTS_CONF_EVT` */ struct gatts_conf_evt_param { esp_gatt_status_t status; /*!< Operation status */ - uint16_t conn_id; /*!< Connection id */ - uint16_t handle; /*!< attribute handle */ - uint16_t len; /*!< The indication or notification value length, len is valid when send notification or indication failed */ - uint8_t *value; /*!< The indication or notification value , value is valid when send notification or indication failed */ - } conf; /*!< Gatt server callback param of ESP_GATTS_CONF_EVT (confirm) */ + uint16_t conn_id; /*!< Connection ID */ + uint16_t handle; /*!< Attribute handle */ + uint16_t len; /*!< The length of indication or notification value in bytes. The length is invalid if the notification or indication failed. */ + uint8_t *value; /*!< The indication or notification value. The value is invalid if the notification or indication failed. */ + } conf; /*!< Callback parameter for the event `ESP_GATTS_CONF_EVT` */ /** - * @brief ESP_GATTS_UNREG_EVT - */ - - /** - * @brief ESP_GATTS_CREATE_EVT + * @brief Callback parameter for the event `ESP_GATTS_CREATE_EVT` */ struct gatts_create_evt_param { esp_gatt_status_t status; /*!< Operation status */ uint16_t service_handle; /*!< Service attribute handle */ - esp_gatt_srvc_id_t service_id; /*!< Service id, include service uuid and other information */ - } create; /*!< Gatt server callback param of ESP_GATTS_CREATE_EVT */ + esp_gatt_srvc_id_t service_id; /*!< Service ID, including service UUID and other information */ + } create; /*!< Callback parameter for the event `ESP_GATTS_CREATE_EVT` */ /** - * @brief ESP_GATTS_ADD_INCL_SRVC_EVT + * @brief Callback parameter for the event `ESP_GATTS_ADD_INCL_SRVC_EVT` */ struct gatts_add_incl_srvc_evt_param { esp_gatt_status_t status; /*!< Operation status */ uint16_t attr_handle; /*!< Included service attribute handle */ uint16_t service_handle; /*!< Service attribute handle */ - } add_incl_srvc; /*!< Gatt server callback param of ESP_GATTS_ADD_INCL_SRVC_EVT */ + } add_incl_srvc; /*!< Callback parameter for the event `ESP_GATTS_ADD_INCL_SRVC_EVT` */ /** - * @brief ESP_GATTS_ADD_CHAR_EVT + * @brief Callback parameter for the event `ESP_GATTS_ADD_CHAR_EVT` */ struct gatts_add_char_evt_param { esp_gatt_status_t status; /*!< Operation status */ uint16_t attr_handle; /*!< Characteristic attribute handle */ uint16_t service_handle; /*!< Service attribute handle */ - esp_bt_uuid_t char_uuid; /*!< Characteristic uuid */ - } add_char; /*!< Gatt server callback param of ESP_GATTS_ADD_CHAR_EVT */ + esp_bt_uuid_t char_uuid; /*!< Characteristic UUID */ + } add_char; /*!< Callback parameter for the event `ESP_GATTS_ADD_CHAR_EVT` */ /** - * @brief ESP_GATTS_ADD_CHAR_DESCR_EVT + * @brief Callback parameter for the event `ESP_GATTS_ADD_CHAR_DESCR_EVT` */ struct gatts_add_char_descr_evt_param { esp_gatt_status_t status; /*!< Operation status */ uint16_t attr_handle; /*!< Descriptor attribute handle */ uint16_t service_handle; /*!< Service attribute handle */ - esp_bt_uuid_t descr_uuid; /*!< Characteristic descriptor uuid */ - } add_char_descr; /*!< Gatt server callback param of ESP_GATTS_ADD_CHAR_DESCR_EVT */ + esp_bt_uuid_t descr_uuid; /*!< Characteristic descriptor UUID */ + } add_char_descr; /*!< Callback parameter for the event `ESP_GATTS_ADD_CHAR_DESCR_EVT` */ /** - * @brief ESP_GATTS_DELETE_EVT + * @brief Callback parameter for the event `ESP_GATTS_DELETE_EVT` */ struct gatts_delete_evt_param { esp_gatt_status_t status; /*!< Operation status */ uint16_t service_handle; /*!< Service attribute handle */ - } del; /*!< Gatt server callback param of ESP_GATTS_DELETE_EVT */ + } del; /*!< Callback parameter for the event `ESP_GATTS_DELETE_EVT` */ /** - * @brief ESP_GATTS_START_EVT + * @brief Callback parameter for the event `ESP_GATTS_START_EVT` */ struct gatts_start_evt_param { esp_gatt_status_t status; /*!< Operation status */ uint16_t service_handle; /*!< Service attribute handle */ - } start; /*!< Gatt server callback param of ESP_GATTS_START_EVT */ + } start; /*!< Callback parameter for the event `ESP_GATTS_START_EVT` */ /** - * @brief ESP_GATTS_STOP_EVT + * @brief Callback parameter for the event `ESP_GATTS_STOP_EVT` */ struct gatts_stop_evt_param { esp_gatt_status_t status; /*!< Operation status */ uint16_t service_handle; /*!< Service attribute handle */ - } stop; /*!< Gatt server callback param of ESP_GATTS_STOP_EVT */ + } stop; /*!< Callback parameter for the event `ESP_GATTS_STOP_EVT` */ /** - * @brief ESP_GATTS_CONNECT_EVT + * @brief Callback parameter for the event `ESP_GATTS_CONNECT_EVT` */ struct gatts_connect_evt_param { - uint16_t conn_id; /*!< Connection id */ - uint8_t link_role; /*!< Link role : master role = 0 ; slave role = 1*/ - esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */ - esp_gatt_conn_params_t conn_params; /*!< current Connection parameters */ - esp_ble_addr_type_t ble_addr_type; /*!< Remote BLE device address type */ - uint16_t conn_handle; /*!< HCI connection handle */ - } connect; /*!< Gatt server callback param of ESP_GATTS_CONNECT_EVT */ + uint16_t conn_id; /*!< Connection ID */ + uint8_t link_role; /*!< Link role: master role = 0; slave role = 1 */ + esp_bd_addr_t remote_bda; /*!< Remote device address */ + esp_gatt_conn_params_t conn_params; /*!< Current connection parameters */ + esp_ble_addr_type_t ble_addr_type; /*!< Remote device address type */ + uint16_t conn_handle; /*!< HCI connection handle */ + } connect; /*!< Callback parameter for the event `ESP_GATTS_CONNECT_EVT` */ /** - * @brief ESP_GATTS_DISCONNECT_EVT + * @brief Callback parameter for the event `ESP_GATTS_DISCONNECT_EVT` */ struct gatts_disconnect_evt_param { - uint16_t conn_id; /*!< Connection id */ - esp_bd_addr_t remote_bda; /*!< Remote bluetooth device address */ - esp_gatt_conn_reason_t reason; /*!< Indicate the reason of disconnection */ - } disconnect; /*!< Gatt server callback param of ESP_GATTS_DISCONNECT_EVT */ + uint16_t conn_id; /*!< Connection ID */ + esp_bd_addr_t remote_bda; /*!< Remote device address */ + esp_gatt_conn_reason_t reason; /*!< The reason of disconnection */ + } disconnect; /*!< Callback parameter for the event `ESP_GATTS_DISCONNECT_EVT` */ /** - * @brief ESP_GATTS_OPEN_EVT + * @brief Callback parameter for the event `ESP_GATTS_OPEN_EVT` */ struct gatts_open_evt_param { esp_gatt_status_t status; /*!< Operation status */ - } open; /*!< Gatt server callback param of ESP_GATTS_OPEN_EVT */ + } open; /*!< Callback parameter for the event `ESP_GATTS_OPEN_EVT` */ /** - * @brief ESP_GATTS_CANCEL_OPEN_EVT + * @brief Callback parameter for the event `ESP_GATTS_CANCEL_OPEN_EVT` */ struct gatts_cancel_open_evt_param { esp_gatt_status_t status; /*!< Operation status */ - } cancel_open; /*!< Gatt server callback param of ESP_GATTS_CANCEL_OPEN_EVT */ + } cancel_open; /*!< Callback parameter for the event `ESP_GATTS_CANCEL_OPEN_EVT` */ /** - * @brief ESP_GATTS_CLOSE_EVT + * @brief Callback parameter for the event `ESP_GATTS_CLOSE_EVT` */ struct gatts_close_evt_param { esp_gatt_status_t status; /*!< Operation status */ - uint16_t conn_id; /*!< Connection id */ - } close; /*!< Gatt server callback param of ESP_GATTS_CLOSE_EVT */ + uint16_t conn_id; /*!< Connection ID */ + } close; /*!< Callback parameter for the event `ESP_GATTS_CLOSE_EVT` */ /** - * @brief ESP_GATTS_LISTEN_EVT - */ - /** - * @brief ESP_GATTS_CONGEST_EVT + * @brief Callback parameter for the event `ESP_GATTS_CONGEST_EVT` */ struct gatts_congest_evt_param { - uint16_t conn_id; /*!< Connection id */ - bool congested; /*!< Congested or not */ - } congest; /*!< Gatt server callback param of ESP_GATTS_CONGEST_EVT */ + uint16_t conn_id; /*!< Connection ID */ + bool congested; /*!< True indicates the connection is congested; false otherwise. */ + } congest; /*!< Callback parameter for the event `ESP_GATTS_CONGEST_EVT` */ /** - * @brief ESP_GATTS_RESPONSE_EVT + * @brief Callback parameter for the event `ESP_GATTS_RESPONSE_EVT` */ struct gatts_rsp_evt_param { esp_gatt_status_t status; /*!< Operation status */ - uint16_t handle; /*!< Attribute handle which send response */ - } rsp; /*!< Gatt server callback param of ESP_GATTS_RESPONSE_EVT */ + uint16_t conn_id; /*!< Connection ID */ + uint16_t handle; /*!< Attribute handle which sends the response */ + } rsp; /*!< Callback parameter for the event `ESP_GATTS_RESPONSE_EVT` */ /** - * @brief ESP_GATTS_CREAT_ATTR_TAB_EVT + * @brief Callback parameter for the event `ESP_GATTS_CREAT_ATTR_TAB_EVT` */ struct gatts_add_attr_tab_evt_param{ esp_gatt_status_t status; /*!< Operation status */ - esp_bt_uuid_t svc_uuid; /*!< Service uuid type */ - uint8_t svc_inst_id; /*!< Service id */ - uint16_t num_handle; /*!< The number of the attribute handle to be added to the gatts database */ - uint16_t *handles; /*!< The number to the handles */ - } add_attr_tab; /*!< Gatt server callback param of ESP_GATTS_CREAT_ATTR_TAB_EVT */ + esp_bt_uuid_t svc_uuid; /*!< Service UUID type */ + uint8_t svc_inst_id; /*!< Service ID */ + uint16_t num_handle; /*!< The number of the attribute handles which have been added to the GATT Service table */ + uint16_t *handles; /*!< The handles which have been added to the table */ + } add_attr_tab; /*!< Callback parameter for the event `ESP_GATTS_CREAT_ATTR_TAB_EVT` */ /** - * @brief ESP_GATTS_SET_ATTR_VAL_EVT + * @brief Callback parameter for the event `ESP_GATTS_SET_ATTR_VAL_EVT` */ struct gatts_set_attr_val_evt_param{ uint16_t srvc_handle; /*!< The service handle */ - uint16_t attr_handle; /*!< The attribute handle */ - esp_gatt_status_t status; /*!< Operation status*/ - } set_attr_val; /*!< Gatt server callback param of ESP_GATTS_SET_ATTR_VAL_EVT */ + uint16_t attr_handle; /*!< The attribute handle */ + esp_gatt_status_t status; /*!< Operation status */ + } set_attr_val; /*!< Callback parameter for the event `ESP_GATTS_SET_ATTR_VAL_EVT` */ /** - * @brief ESP_GATTS_SEND_SERVICE_CHANGE_EVT + * @brief Callback parameter for the event `ESP_GATTS_SEND_SERVICE_CHANGE_EVT` */ struct gatts_send_service_change_evt_param{ - esp_gatt_status_t status; /*!< Operation status*/ - } service_change; /*!< Gatt server callback param of ESP_GATTS_SEND_SERVICE_CHANGE_EVT */ + esp_gatt_status_t status; /*!< Operation status */ + } service_change; /*!< Callback parameter for the event `ESP_GATTS_SEND_SERVICE_CHANGE_EVT` */ } esp_ble_gatts_cb_param_t; /** * @brief GATT Server callback function type - * @param event : Event type - * @param gatts_if : GATT server access interface, normally - * different gatts_if correspond to different profile - * @param param : Point to callback parameter, currently is union type + * + * @param[in] event Event type + * @param[in] gatts_if GATT Server access interface. Typically, different `gatts_if` values correspond to different profiles. + * @param[in] param The pointer to the callback parameter, which is of a union type. */ typedef void (* esp_gatts_cb_t)(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); /** - * @brief This function is called to register application callbacks - * with BTA GATTS module. + * @brief Register GATT Server application callbacks * - * @return - * - ESP_OK : success - * - other : failed + * @param[in] callback The pointer to the application callback function + * + * @note Avoid performing time-consuming operations within the callback functions. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gatts_register_callback(esp_gatts_cb_t callback); /** - * @brief This function is called to get the current application callbacks - * with BTA GATTS module. + * @brief Get the current GATT Server application callback * * @return - * - esp_gatts_cb_t : current callback - * + * - esp_gatts_cb_t: Current callback */ esp_gatts_cb_t esp_ble_gatts_get_callback(void); /** - * @brief This function is called to register application identifier + * @brief Register GATT Server application * - * @return - * - ESP_OK : success - * - other : failed + * @param[in] app_id: The UUID for different application * + * @note + * 1. This function triggers `ESP_GATTS_REG_EVT`. + * 2. The maximum number of applications is limited to 6. + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: The input `app_id` exceeds `ESP_APP_ID_MAX` (0x7fff) defined in esp_bt_defs.h. + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gatts_app_register(uint16_t app_id); - - /** - * @brief unregister with GATT Server. + * @brief Unregister an GATT Server application * - * @param[in] gatts_if: GATT server access interface - * @return - * - ESP_OK : success - * - other : failed + * @param[in] gatts_if GATT Server access interface. + * + * @note + * 1. This function triggers `ESP_GATTS_UNREG_EVT`. + * 2. The maximum number of applications is limited to 6. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gatts_app_unregister(esp_gatt_if_t gatts_if); - /** - * @brief Create a service. When service creation is done, a callback - * event ESP_GATTS_CREATE_EVT is called to report status - * and service ID to the profile. The service ID obtained in - * the callback function needs to be used when adding included - * service and characteristics/descriptors into the service. + * @brief Create a GATT Server service * - * @param[in] gatts_if: GATT server access interface - * @param[in] service_id: service ID. - * @param[in] num_handle: number of handle requested for this service. + * @param[in] gatts_if GATT Server access interface + * @param[in] service_id The pointer to the Service ID + * @param[in] num_handle The number of handles requested for this service. * - * @return - * - ESP_OK : success - * - other : failed + * @note + * 1. This function triggers `ESP_GATTS_CREATE_EVT`. + * 2. `num_handle` should not be greater than CONFIG_BT_GATT_MAX_SR_ATTRIBUTES. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gatts_create_service(esp_gatt_if_t gatts_if, esp_gatt_srvc_id_t *service_id, uint16_t num_handle); /** - * @brief Create a service attribute tab. - * @param[in] gatts_attr_db: the pointer to the service attr tab - * @param[in] gatts_if: GATT server access interface - * @param[in] max_nb_attr: the number of attribute to be added to the service database. - * @param[in] srvc_inst_id: the instance id of the service + * @brief Create a service attribute table * - * @return - * - ESP_OK : success - * - other : failed + * @param[in] gatts_attr_db The pointer to the service attribute table + * @param[in] gatts_if GATT Server access interface + * @param[in] max_nb_attr The number of attributes to be added to the service database + * @param[in] srvc_inst_id The instance ID of the service * + * @note + * 1. This function triggers `ESP_GATTS_CREAT_ATTR_TAB_EVT`. + * 2. `max_nb_attr` should not be greater than CONFIG_BT_GATT_MAX_SR_ATTRIBUTES. + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: Invalid `max_nb_attr` + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gatts_create_attr_tab(const esp_gatts_attr_db_t *gatts_attr_db, esp_gatt_if_t gatts_if, uint16_t max_nb_attr, uint8_t srvc_inst_id); /** - * @brief This function is called to add an included service. This function have to be called between - * 'esp_ble_gatts_create_service' and 'esp_ble_gatts_add_char'. After included - * service is included, a callback event ESP_GATTS_ADD_INCL_SRVC_EVT - * is reported the included service ID. + * @brief Add an included service * - * @param[in] service_handle: service handle to which this included service is to - * be added. - * @param[in] included_service_handle: the service ID to be included. + * @param[in] service_handle Target service handle to add + * @param[in] included_service_handle The handle of included service to be added * - * @return - * - ESP_OK : success - * - other : failed + * @note + * 1. This function triggers `ESP_GATTS_ADD_INCL_SRVC_EVT`. + * 2. This function has to be called between `esp_ble_gatts_create_service` and `esp_ble_gatts_add_char`. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gatts_add_included_service(uint16_t service_handle, uint16_t included_service_handle); - - /** - * @brief This function is called to add a characteristic into a service. + * @brief Add a characteristic into a service. * - * @param[in] service_handle: service handle to which this included service is to - * be added. - * @param[in] char_uuid : Characteristic UUID. - * @param[in] perm : Characteristic value declaration attribute permission. - * @param[in] property : Characteristic Properties - * @param[in] char_val : Characteristic value - * @param[in] control : attribute response control byte + * @param[in] service_handle Target service handle to add the characteristic + * @param[in] char_uuid The pointer to the characteristic UUID + * @param[in] perm Characteristic value declaration attribute permission + * @param[in] property Characteristic Properties + * @param[in] char_val The pointer to the characteristic value + * @param[in] control The pointer to the attribute response control byte * - * @return - * - ESP_OK : success - * - other : failed + * @note + * 1. This function triggers `ESP_GATTS_ADD_CHAR_EVT`. + * 2. `control->auto_rsp` should be set to `ESP_GATT_AUTO_RSP` or `ESP_GATT_RSP_BY_APP`. + * 3. For stack respond attribute (`ESP_GATT_AUTO_RSP`), `char_val` should not be NULL and `char_val->attr_max_len` must be greater than 0. * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: Invalid arguments + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gatts_add_char(uint16_t service_handle, esp_bt_uuid_t *char_uuid, esp_gatt_perm_t perm, esp_gatt_char_prop_t property, esp_attr_value_t *char_val, esp_attr_control_t *control); - /** - * @brief This function is called to add characteristic descriptor. When - * it's done, a callback event ESP_GATTS_ADD_DESCR_EVT is called - * to report the status and an ID number for this descriptor. - * - * @param[in] service_handle: service handle to which this characteristic descriptor is to - * be added. - * @param[in] perm: descriptor access permission. - * @param[in] descr_uuid: descriptor UUID. - * @param[in] char_descr_val : Characteristic descriptor value - * @param[in] control : attribute response control byte - * @return - * - ESP_OK : success - * - other : failed + * @brief Add a characteristic descriptor + * + * @param[in] service_handle Target service handle to add the characteristic descriptor + * @param[in] descr_uuid The pointer to the descriptor UUID + * @param[in] perm Descriptor access permission + * @param[in] char_descr_val The pointer to the characteristic descriptor value + * @param[in] control The pointer to the attribute response control byte * + * @note + * 1. This function triggers `ESP_GATTS_ADD_CHAR_DESCR_EVT`. + * 2. `control->auto_rsp` should be set to `ESP_GATT_AUTO_RSP` or `ESP_GATT_RSP_BY_APP`. + * 3. For stack respond attribute (`ESP_GATT_AUTO_RSP`), `char_val` should not be NULL and `char_val->attr_max_len` must be greater than 0. + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: Invalid arguments + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gatts_add_char_descr (uint16_t service_handle, esp_bt_uuid_t *descr_uuid, esp_gatt_perm_t perm, esp_attr_value_t *char_descr_val, esp_attr_control_t *control); - - /** - * @brief This function is called to delete a service. When this is done, - * a callback event ESP_GATTS_DELETE_EVT is report with the status. + * @brief Delete a service * - * @param[in] service_handle: service_handle to be deleted. + * @param[in] service_handle Target service handle to delete * - * @return - * - ESP_OK : success - * - other : failed + * @note This function triggers `ESP_GATTS_DELETE_EVT`. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gatts_delete_service(uint16_t service_handle); - - /** - * @brief This function is called to start a service. + * @brief Start a service * - * @param[in] service_handle: the service handle to be started. + * @param[in] service_handle Target service handle to start * - * @return - * - ESP_OK : success - * - other : failed + * @note This function triggers `ESP_GATTS_START_EVT`. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gatts_start_service(uint16_t service_handle); - - /** - * @brief This function is called to stop a service. + * @brief Stop a service. * - * @param[in] service_handle - service to be topped. + * @param[in] service_handle Target service handle to stop * - * @return - * - ESP_OK : success - * - other : failed + * @note This function triggers `ESP_GATTS_STOP_EVT`. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gatts_stop_service(uint16_t service_handle); - - /** - * @brief Send indicate or notify to GATT client. - * Set param need_confirm as false will send notification, otherwise indication. - * Note: the size of indicate or notify data need less than MTU size,see "esp_ble_gattc_send_mtu_req". - * - * @param[in] gatts_if: GATT server access interface - * @param[in] conn_id - connection id to indicate. - * @param[in] attr_handle - attribute handle to indicate. - * @param[in] value_len - indicate value length. - * @param[in] value: value to indicate. - * @param[in] need_confirm - Whether a confirmation is required. - * false sends a GATT notification, true sends a GATT indication. + * @brief Send indication or notification to a GATT Client * - * @return - * - ESP_OK : success - * - other : failed + * @param[in] gatts_if GATT Server access interface + * @param[in] conn_id Connection ID + * @param[in] attr_handle Attribute handle to indicate + * @param[in] value_len Indication value length in bytes + * @param[in] value Value to indicate + * @param[in] need_confirm True if a confirmation is required, which is a GATT indication; false if the confirmation is not required, which is a GATT notification. + * + * @note + * 1. This function triggers `ESP_GATTS_CONF_EVT`. + * 2. The size of indication or notification data must be less than or equal to MTU size, see `esp_ble_gattc_send_mtu_req`. + * 3. This function should be called only after the connection has been established. * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: The connection has not been established. + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gatts_send_indicate(esp_gatt_if_t gatts_if, uint16_t conn_id, uint16_t attr_handle, uint16_t value_len, uint8_t *value, bool need_confirm); - /** - * @brief This function is called to send a response to a request. + * @brief Send a response to a request * - * @param[in] gatts_if: GATT server access interface - * @param[in] conn_id - connection identifier. - * @param[in] trans_id - transfer id - * @param[in] status - response status - * @param[in] rsp - response data. + * @param[in] gatts_if GATT Server access interface + * @param[in] conn_id Connection ID + * @param[in] trans_id Transfer ID + * @param[in] status Response status + * @param[in] rsp The pointer to the response data * - * @return - * - ESP_OK : success - * - other : failed + * @note + * 1. This function triggers `ESP_GATTS_RESPONSE_EVT`. + * 2. This function should be called only after the connection has been established. * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: The connection has not been established. + * - ESP_FAIL: Failure due to other reasons */ esp_err_t esp_ble_gatts_send_response(esp_gatt_if_t gatts_if, uint16_t conn_id, uint32_t trans_id, esp_gatt_status_t status, esp_gatt_rsp_t *rsp); - /** - * @brief This function is called to set the attribute value by the application + * @brief Set the attribute value * - * @param[in] attr_handle: the attribute handle which to be set - * @param[in] length: the value length - * @param[in] value: the pointer to the attribute value + * @param[in] attr_handle Target attribute handle to set the value + * @param[in] length The value length in bytes + * @param[in] value The pointer to the attribute value * - * @return - * - ESP_OK : success - * - other : failed + * @note This function triggers `ESP_GATTS_SET_ATTR_VAL_EVT`. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gatts_set_attr_value(uint16_t attr_handle, uint16_t length, const uint8_t *value); /** - * @brief Retrieve attribute value + * @brief Retrieve attribute value * - * @param[in] attr_handle: Attribute handle. - * @param[out] length: pointer to the attribute value length - * @param[out] value: Pointer to attribute value payload, the value cannot be modified by user + * @param[in] attr_handle Attribute handle + * @param[out] length The pointer to the attribute value length in bytes + * @param[out] value The pointer to attribute value payload. This value cannot be modified by user. * - * @return - * - ESP_GATT_OK : success - * - other : failed + * @note + * 1. This function does not trigger any event. + * 2. `attr_handle` must be greater than 0. * + * @return + * - ESP_OK: Success + * - ESP_GATT_INVALID_HANDLE: Invalid `attr_handle` + * - ESP_FAIL: Failure due to other reasons */ esp_gatt_status_t esp_ble_gatts_get_attr_value(uint16_t attr_handle, uint16_t *length, const uint8_t **value); - /** - * @brief Open a direct open connection or add a background auto connection + * @brief Create an ACL connection when `BT_BLE_42_FEATURES_SUPPORTED` is enabled in the menuconfig * - * @param[in] gatts_if: GATT server access interface - * @param[in] remote_bda: remote device bluetooth device address. - * @param[in] is_direct: direct connection or background auto connection + * @param[in] gatts_if GATT Server access interface + * @param[in] remote_bda Remote device address + * @param[in] is_direct `True` indicates a direct connection, while `False` indicates a background auto connection. Currently, background auto connection is not supported, so please always set this parameter to True. * - * @return - * - ESP_OK : success - * - other : failed + * @note + * 1. The function always triggers `ESP_GATTS_CONNECT_EVT` and `ESP_GATTS_OPEN_EVT`. + * 2. When the device acts as GATT Server, besides the above two events, this function triggers `ESP_GATTS_CONNECT_EVT` as well. + * 3. This function will establish an ACL connection as a Central and a virtual connection as a GATT Server. If the ACL connection already exists, it will create a virtual connection only. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gatts_open(esp_gatt_if_t gatts_if, esp_bd_addr_t remote_bda, bool is_direct); /** - * @brief Close a connection a remote device. + * @brief Close a connection with a remote device * - * @param[in] gatts_if: GATT server access interface - * @param[in] conn_id: connection ID to be closed. + * @param[in] gatts_if GATT Server access interface + * @param[in] conn_id Connection ID to be closed * - * @return - * - ESP_OK : success - * - other : failed + * @note + * 1. This function triggers `ESP_GATTS_CLOSE_EVT`. + * 2. There may be multiple virtual GATT server connections when multiple `app_id` got registered. + * 3. This API closes one virtual GATT server connection only, if there exist other virtual GATT server connections. It does not close the physical connection. + * 4. The API `esp_ble_gap_disconnect` can be used to disconnect the physical connection directly. + * 5. If there is only one virtual GATT connection left, this API will terminate the ACL connection in addition, and trigger `ESP_GATTS_DISCONNECT_EVT`. Then there is no need to call `esp_ble_gap_disconnect` anymore. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gatts_close(esp_gatt_if_t gatts_if, uint16_t conn_id); /** - * @brief Send service change indication + * @brief Send service change indication * - * @param[in] gatts_if: GATT server access interface - * @param[in] remote_bda: remote device bluetooth device address. + * @param[in] gatts_if GATT Server access interface + * @param[in] remote_bda Remote device address. * If remote_bda is NULL then it will send service change * indication to all the connected devices and if not then - * to a specific device + * to a specific device. * - * @return - * - ESP_OK : success - * - other : failed + * @note This function triggers `ESP_GATTS_SEND_SERVICE_CHANGE_EVT`. * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gatts_send_service_change_indication(esp_gatt_if_t gatts_if, esp_bd_addr_t remote_bda); /** - * @brief Print local database (GATT service table) + * @brief Display the Server's local attribute database. * - * @return - * - ESP_OK : success - * - other : failed + * This API prints the local attribute database of the BLE server, including details + * of all services, characteristics, and descriptors. * + * @note + * 1. This function does not trigger any event. + * 2. It is primarily intended for debugging purposes to verify the server's current configuration. + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure */ esp_err_t esp_ble_gatts_show_local_database(void); diff --git a/lib/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h b/lib/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h index 84086118..f34c52c4 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,6 +10,7 @@ #include "esp_err.h" #include "esp_bt_defs.h" #include "esp_hf_defs.h" +#include "esp_hf_ag_legacy_api.h" #ifdef __cplusplus extern "C" { @@ -63,6 +64,7 @@ typedef enum ESP_HF_WBS_RESPONSE_EVT, /*!< Codec Status */ ESP_HF_BCS_RESPONSE_EVT, /*!< Final Codec Choice */ ESP_HF_PKT_STAT_NUMS_GET_EVT, /*!< Request number of packet different status */ + ESP_HF_PROF_STATE_EVT, /*!< Indicate HF init or deinit complete */ } esp_hf_cb_event_t; /// Dial type of ESP_HF_DIAL_EVT @@ -73,6 +75,14 @@ typedef enum ESP_HF_DIAL_MEM, /*!< Dial with a memory position */ } esp_hf_dial_type_t; + +/// HFP AG profile status parameters +typedef struct { + bool hfp_ag_inited; /*!< hfp ag initialization */ + uint8_t slc_conn_num; /*!< Number of Service Level Connections */ + uint8_t sync_conn_num; /*!< Number of (e)SCO Connections */ +} esp_hf_profile_status_t; + /// HFP AG callback parameters typedef union { @@ -92,7 +102,8 @@ typedef union struct hf_audio_stat_param { esp_bd_addr_t remote_addr; /*!< Remote bluetooth device address */ esp_hf_audio_state_t state; /*!< Audio connection state */ - uint16_t sync_conn_handle; /*!< (e)SCO connection handle */ + esp_hf_sync_conn_hdl_t sync_conn_handle; /*!< (e)SCO connection handle */ + uint16_t preferred_frame_size; /*!< Valid only when Voice Over HCI is enabled, recommended frame size to send */ } audio_stat; /*!< AG callback param of ESP_HF_AUDIO_STATE_EVT */ /** @@ -223,45 +234,37 @@ typedef union uint32_t tx_discarded; /*!< the total number of packets send lost */ } pkt_nums; /*!< AG callback param of ESP_HF_PKT_STAT_NUMS_GET_EVT */ + /** + * @brief ESP_HF_PROF_STATE_EVT + */ + struct ag_prof_stat_param { + esp_hf_prof_state_t state; /*!< hf profile state param */ + } prof_stat; /*!< status to indicate hf prof init or deinit */ + } esp_hf_cb_param_t; /*!< HFP AG callback param compound*/ /** - * @brief AG incoming data callback function, the callback is useful in case of - * Voice Over HCI. + * @brief HF AG callback function type * - * @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the - * buffer is allocated inside bluetooth protocol stack and will be released after - * invoke of the callback is finished. + * @param event : Event type * - * @param[in] len : size(in bytes) in buf + * @param param : Pointer to callback parameter */ -typedef void (* esp_hf_incoming_data_cb_t)(const uint8_t *buf, uint32_t len); +typedef void (* esp_hf_cb_t) (esp_hf_cb_event_t event, esp_hf_cb_param_t *param); /** - * @brief AG outgoing data callback function, the callback is useful in case of - * Voice Over HCI. Once audio connection is set up and the application layer has - * prepared data to send, the lower layer will call this function to read data - * and then send. This callback is supposed to be implemented as non-blocking, - * and if data is not enough, return value 0 is supposed. + * @brief HFP AG incoming audio data callback function, user should copy audio_buf struct + * to other place before return. This callback is used in case of Voice Over HCI. * - * @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the - * buffer is allocated inside bluetooth protocol stack and will be released after - * invoke of the callback is finished. + * @param[in] sync_conn_hdl: (e)SCO connection handle * - * @param[in] len : size(in bytes) in buf + * @param[in] audio_buf: pointer to incoming data(payload of HCI synchronous data packet), user + * should free audio buffer by calling esp_hf_ag_audio_buff_free * - * @return length of data successfully read - */ -typedef uint32_t (* esp_hf_outgoing_data_cb_t) (uint8_t *buf, uint32_t len); - -/** - * @brief HF AG callback function type - * - * @param event : Event type + * @param[in] is_bad_frame: whether this packet is marked as bad frame by baseband * - * @param param : Pointer to callback parameter */ -typedef void (* esp_hf_cb_t) (esp_hf_cb_event_t event, esp_hf_cb_param_t *param); +typedef void (* esp_hf_ag_audio_data_cb_t)(esp_hf_sync_conn_hdl_t sync_conn_hdl, esp_hf_audio_buff_t *audio_buf, bool is_bad_frame); /************************************************************************************ ** ESP HF API @@ -284,6 +287,7 @@ esp_err_t esp_hf_ag_register_callback(esp_hf_cb_t callback); * * @brief Initialize the bluetooth HF AG module. * This function should be called after esp_bluedroid_enable() completes successfully. + * ESP_HF_PROF_STATE_EVT with ESP_HF_INIT_SUCCESS will reported to the APP layer. * * @return * - ESP_OK: if the initialization request is sent successfully @@ -297,6 +301,7 @@ esp_err_t esp_hf_ag_init(void); * * @brief De-initialize for HF AG module. * This function should be called only after esp_bluedroid_enable() completes successfully. + * ESP_HF_PROF_STATE_EVT with ESP_HF_DEINIT_SUCCESS will reported to the APP layer. * * @return * - ESP_OK: success @@ -504,13 +509,13 @@ esp_err_t esp_hf_ag_cind_response(esp_bd_addr_t remote_addr, /** * - * @brief Reponse for AT+COPS command from HF Client. + * @brief Response for AT+COPS command from HF Client. * As a precondition to use this API, Service Level Connection shall exist with HFP client. * * @param[in] remote_addr: remote bluetooth device address * @param[in] name: current operator name * @return - * - ESP_OK: reponse for AT+COPS command is sent to lower layer + * - ESP_OK: response for AT+COPS command is sent to lower layer * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled * - ESP_FAIL: others * @@ -529,7 +534,7 @@ esp_err_t esp_hf_ag_cops_response(esp_bd_addr_t remote_addr, char *name); * @param[in] mode: current call mode (voice/data/fax) * @param[in] mpty: single or multi type * @param[in] number: current call number - * @param[in] type: international type or unknow + * @param[in] type: international type or unknown * @return * - ESP_OK: response to AT+CLCC command is sent to lower layer * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled @@ -668,19 +673,58 @@ esp_err_t esp_hf_ag_end_call(esp_bd_addr_t remote_addr, int num_active, int num_ char *number, esp_hf_call_addr_type_t call_addr_type); /** - * @brief Register AG data output function. - * The callback is only used in the case that Voice Over HCI is enabled. + * @brief Register HFP AG audio data output function; the callback is only used in + * the case that Voice Over HCI is enabled. * - * @param[in] recv: HFP client incoming data callback function - * @param[in] send: HFP client outgoing data callback function + * @param[in] callback: HFP AG incoming audio data callback function * * @return * - ESP_OK: success * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled - * - ESP_FAIL: if callback is a NULL function pointer + * - ESP_FAIL: others * */ -esp_err_t esp_hf_ag_register_data_callback(esp_hf_incoming_data_cb_t recv, esp_hf_outgoing_data_cb_t send); +esp_err_t esp_hf_ag_register_audio_data_callback(esp_hf_ag_audio_data_cb_t callback); + +/** + * @brief Allocate a audio buffer to store and send audio data. This function is only + * used in the case that Voice Over HCI is enabled. + * + * @param[in] size: buffer size to allocate + * + * @return allocated audio buffer, if Bluedroid is not enabled, no memory, or size is + * zeros, will return NULL + * + */ +esp_hf_audio_buff_t *esp_hf_ag_audio_buff_alloc(uint16_t size); + +/** + * @brief Free a audio buffer allocated by esp_hf_ag_audio_buff_alloc. This function + * is only used in the case that Voice Over HCI is enabled. + * + * @param[in] audio_buf: audio buffer to free + * + */ +void esp_hf_ag_audio_buff_free(esp_hf_audio_buff_t *audio_buf); + +/** + * @brief Send audio data, the audio buffer should by allocated by esp_hf_ag_audio_buff_alloc. + * If the length of the audio data is equal to preferred_frame_size indicated by + * ESP_HF_AUDIO_STATE_EVT, then we can reduce one memory copy inside the Bluedroid stack. + * This function is only used in the case that Voice Over HCI is enabled. + * + * @param[in] sync_conn_hdl: (e)SCO connection handle + * + * @param[in] audio_buf: audio buffer that audio data stored + * + * @return + * - ESP_OK: success + * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_ERR_INVALID_ARG: invalid parameter + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_ag_audio_data_send(esp_hf_sync_conn_hdl_t sync_conn_hdl, esp_hf_audio_buff_t *audio_buf); /** * @@ -700,14 +744,15 @@ esp_err_t esp_hf_ag_register_data_callback(esp_hf_incoming_data_cb_t recv, esp_h esp_err_t esp_hf_ag_pkt_stat_nums_get(uint16_t sync_conn_handle); /** - * @brief Trigger the lower-layer to fetch and send audio data. + * @brief This function is used to get the status of hfp ag * - * This function is only used in the case that Voice Over HCI is enabled. - * As a precondition to use this API, Service Level Connection shall exist with HFP client. - * After this function is called, lower layer will invoke esp_hf_client_outgoing_data_cb_t to fetch data + * @param[out] profile_status - hfp ag status * + * @return + * - ESP_OK: success + * - other: failed */ -void esp_hf_ag_outgoing_data_ready(void); +esp_err_t esp_hf_ag_get_profile_status(esp_hf_profile_status_t *profile_status); #ifdef __cplusplus } diff --git a/lib/bt/host/bluedroid/api/include/api/esp_hf_ag_legacy_api.h b/lib/bt/host/bluedroid/api/include/api/esp_hf_ag_legacy_api.h new file mode 100644 index 00000000..7cd0769b --- /dev/null +++ b/lib/bt/host/bluedroid/api/include/api/esp_hf_ag_legacy_api.h @@ -0,0 +1,77 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Some legacy APIs of HFP AG, will be removed in the future + */ + +#pragma once + +#include "esp_err.h" +#include "esp_bt_defs.h" +#include "esp_hf_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief AG incoming data callback function, the callback is useful in case of + * Voice Over HCI. + * + * @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the + * buffer is allocated inside bluetooth protocol stack and will be released after + * invoke of the callback is finished. + * + * @param[in] len : size(in bytes) in buf + */ +typedef void (* esp_hf_incoming_data_cb_t)(const uint8_t *buf, uint32_t len); + +/** + * @brief AG outgoing data callback function, the callback is useful in case of + * Voice Over HCI. Once audio connection is set up and the application layer has + * prepared data to send, the lower layer will call this function to read data + * and then send. This callback is supposed to be implemented as non-blocking, + * and if data is not enough, return value 0 is supposed. + * + * @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the + * buffer is allocated inside bluetooth protocol stack and will be released after + * invoke of the callback is finished. + * + * @param[in] len : size(in bytes) in buf + * + * @return length of data successfully read + */ +typedef uint32_t (* esp_hf_outgoing_data_cb_t) (uint8_t *buf, uint32_t len); + +/** + * @brief Register AG data output function. + * The callback is only used in the case that Voice Over HCI is enabled. + * + * @param[in] recv: HFP client incoming data callback function + * @param[in] send: HFP client outgoing data callback function + * + * @return + * - ESP_OK: success + * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: if callback is a NULL function pointer + * + */ +esp_err_t esp_hf_ag_register_data_callback(esp_hf_incoming_data_cb_t recv, esp_hf_outgoing_data_cb_t send); + +/** + * @brief Trigger the lower-layer to fetch and send audio data. + * + * This function is only used in the case that Voice Over HCI is enabled. + * As a precondition to use this API, Service Level Connection shall exist with HFP client. + * After this function is called, lower layer will invoke esp_hf_ag_outgoing_data_cb_t to fetch data + * + */ +void esp_hf_ag_outgoing_data_ready(void); + +#ifdef __cplusplus +} +#endif diff --git a/lib/bt/host/bluedroid/api/include/api/esp_hf_client_api.h b/lib/bt/host/bluedroid/api/include/api/esp_hf_client_api.h index 9353fc03..53bf0396 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_hf_client_api.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_hf_client_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,6 +10,7 @@ #include "esp_err.h" #include "esp_bt_defs.h" #include "esp_hf_defs.h" +#include "esp_hf_client_legacy_api.h" #ifdef __cplusplus extern "C" { @@ -42,6 +43,15 @@ typedef enum { ESP_HF_CLIENT_IN_BAND_RINGTONE_PROVIDED, } esp_hf_client_in_band_ring_state_t; +/** + * @brief HF client profile status parameters + */ +typedef struct { + bool hf_client_inited; /*!< hf client initialization */ + uint8_t slc_conn_num; /*!< Number of Service Level Connections */ + uint8_t sync_conn_num; /*!< Number of (e)SCO Connections */ +} esp_hf_client_profile_status_t; + /* features masks of AG */ #define ESP_HF_CLIENT_PEER_FEAT_3WAY 0x01 /* Three-way calling */ #define ESP_HF_CLIENT_PEER_FEAT_ECNR 0x02 /* Echo cancellation and/or noise reduction */ @@ -97,6 +107,7 @@ typedef enum { ESP_HF_CLIENT_BINP_EVT, /*!< requested number of last voice tag from AG */ ESP_HF_CLIENT_RING_IND_EVT, /*!< ring indication event */ ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT, /*!< requested number of packet different status */ + ESP_HF_CLIENT_PROF_STATE_EVT, /*!< Indicate HF CLIENT init or deinit complete */ } esp_hf_client_cb_event_t; /// HFP client callback parameters @@ -117,7 +128,8 @@ typedef union { struct hf_client_audio_stat_param { esp_hf_client_audio_state_t state; /*!< audio connection state */ esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */ - uint16_t sync_conn_handle; /*!< (e)SCO connection handle */ + esp_hf_sync_conn_hdl_t sync_conn_handle; /*!< (e)SCO connection handle */ + uint16_t preferred_frame_size; /*!< valid only when Voice Over HCI is enabled, recommended frame size to send */ } audio_stat; /*!< HF callback param of ESP_HF_CLIENT_AUDIO_STATE_EVT */ /** @@ -266,35 +278,28 @@ typedef union { uint32_t tx_discarded; /*!< the total number of packets send lost */ } pkt_nums; /*!< HF callback param of ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT */ -} esp_hf_client_cb_param_t; /*!< HFP client callback parameters */ + /** + * @brief ESP_HF_CLIENT_PROF_STATE_EVT + */ + struct hf_client_prof_stat_param { + esp_hf_prof_state_t state; /*!< hf client profile state param */ + } prof_stat; /*!< status to indicate hf client prof init or deinit */ -/** - * @brief HFP client incoming data callback function, the callback is useful in case of - * Voice Over HCI. - * @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the - * buffer is allocated inside bluetooth protocol stack and will be released after - * invoke of the callback is finished. - * @param[in] len : size(in bytes) in buf - */ -typedef void (* esp_hf_client_incoming_data_cb_t)(const uint8_t *buf, uint32_t len); +} esp_hf_client_cb_param_t; /*!< HFP client callback parameters */ /** - * @brief HFP client outgoing data callback function, the callback is useful in case of - * Voice Over HCI. Once audio connection is set up and the application layer has - * prepared data to send, the lower layer will call this function to read data - * and then send. This callback is supposed to be implemented as non-blocking, - * and if data is not enough, return value 0 is supposed. + * @brief HFP client incoming audio data callback function, user should copy audio_buf struct + * to other place before return. This callback is used in case of Voice Over HCI. * - * @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the - * buffer is allocated inside bluetooth protocol stack and will be released after - * invoke of the callback is finished. + * @param[in] sync_conn_hdl: (e)SCO connection handle * - * @param[in] len : size(in bytes) in buf + * @param[in] audio_buf: pointer to incoming data(payload of HCI synchronous data packet), user + * should free audio buffer by calling esp_hf_client_audio_buff_free * - * @return length of data successfully read + * @param[in] is_bad_frame: whether this packet is marked as bad frame by baseband * */ -typedef uint32_t (* esp_hf_client_outgoing_data_cb_t)(uint8_t *buf, uint32_t len); +typedef void (* esp_hf_client_audio_data_cb_t)(esp_hf_sync_conn_hdl_t sync_conn_hdl, esp_hf_audio_buff_t *audio_buf, bool is_bad_frame); /** * @brief HFP client callback function type @@ -323,6 +328,7 @@ esp_err_t esp_hf_client_register_callback(esp_hf_client_cb_t callback); * * @brief Initialize the bluetooth HFP client module. * This function should be called after esp_bluedroid_enable() completes successfully. + * ESP_HF_CLIENT_PROF_STATE_EVT with ESP_HF_INIT_SUCCESS will reported to the APP layer. * * @return * - ESP_OK: if the initialization request is sent successfully @@ -336,6 +342,7 @@ esp_err_t esp_hf_client_init(void); * * @brief De-initialize for HFP client module. * This function should be called only after esp_bluedroid_enable() completes successfully. + * ESP_HF_CLIENT_PROF_STATE_EVT with ESP_HF_DEINIT_SUCCESS will reported to the APP layer. * * @return * - ESP_OK: success @@ -422,7 +429,7 @@ esp_err_t esp_hf_client_start_voice_recognition(void); * As a precondition to use this API, Service Level Connection shall exist with AG. * * @return - * - ESP_OK: stoping voice recognition is sent to lower layer + * - ESP_OK: stopping voice recognition is sent to lower layer * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled * - ESP_FAIL: others * @@ -652,50 +659,74 @@ esp_err_t esp_hf_client_request_last_voice_tag_number(void); */ esp_err_t esp_hf_client_send_nrec(void); - /** - * @brief Register HFP client data output function; the callback is only used in - * the case that Voice Over HCI is enabled. * - * @param[in] recv: HFP client incoming data callback function + * @brief Get the number of packets received and sent + * This function is only used in the case that Voice Over HCI is enabled and the audio state is connected. + * When the operation is completed, the callback function will be called with ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT. * - * @param[in] send: HFP client outgoing data callback function + * @param[in] sync_conn_handle: the (e)SCO connection handle * * @return - * - ESP_OK: success + * - ESP_OK: if the request is sent successfully * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled - * - ESP_FAIL: if callback is a NULL function pointer + * - ESP_FAIL: others * */ -esp_err_t esp_hf_client_register_data_callback(esp_hf_client_incoming_data_cb_t recv, - esp_hf_client_outgoing_data_cb_t send); +esp_err_t esp_hf_client_pkt_stat_nums_get(uint16_t sync_conn_handle); /** + * @brief Register HFP client audio data output function; the callback is only used in + * the case that Voice Over HCI is enabled. * - * @brief Get the number of packets received and sent - * This function is only used in the case that Voice Over HCI is enabled and the audio state is connected. - * When the operation is completed, the callback function will be called with ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT. - * - * @param[in] sync_conn_handle: the (e)SCO connection handle + * @param[in] callback: HFP client incoming audio data callback function * * @return - * - ESP_OK: if the request is sent successfully + * - ESP_OK: success * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled * - ESP_FAIL: others * */ -esp_err_t esp_hf_client_pkt_stat_nums_get(uint16_t sync_conn_handle); +esp_err_t esp_hf_client_register_audio_data_callback(esp_hf_client_audio_data_cb_t callback); /** - * @brief Trigger the lower-layer to fetch and send audio data. - * This function is only only used in the case that Voice Over HCI is enabled. After this - * function is called, lower layer will invoke esp_hf_client_outgoing_data_cb_t to fetch data. + * @brief Allocate a audio buffer to store and send audio data. This function is only + * used in the case that Voice Over HCI is enabled. * - * As a precondition to use this API, Service Level Connection shall exist with AG. + * @param[in] size: buffer size to allocate + * + * @return allocated audio buffer, if Bluedroid is not enabled, no memory, or size is + * zeros, will return NULL * */ -void esp_hf_client_outgoing_data_ready(void); +esp_hf_audio_buff_t *esp_hf_client_audio_buff_alloc(uint16_t size); +/** + * @brief Free a audio buffer allocated by esp_hf_client_audio_buff_alloc. This function + * is only used in the case that Voice Over HCI is enabled. + * + * @param[in] audio_buf: audio buffer to free + * + */ +void esp_hf_client_audio_buff_free(esp_hf_audio_buff_t *audio_buf); + +/** + * @brief Send audio data, the audio buffer should by allocated by esp_hf_client_audio_buff_alloc. + * If the length of the audio data is equal to preferred_frame_size indicated by + * ESP_HF_CLIENT_AUDIO_STATE_EVT, then we can reduce one memory copy inside the Bluedroid stack. + * This function is only used in the case that Voice Over HCI is enabled. + * + * @param[in] sync_conn_hdl: (e)SCO connection handle + * + * @param[in] audio_buf: audio buffer that audio data stored + * + * @return + * - ESP_OK: success + * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_ERR_INVALID_ARG: invalid parameter + * + */ +esp_err_t esp_hf_client_audio_data_send(esp_hf_sync_conn_hdl_t sync_conn_hdl, esp_hf_audio_buff_t *audio_buf); /** * @brief Initialize the down sampling converter. This is a utility function that can @@ -728,6 +759,17 @@ void esp_hf_client_pcm_resample_deinit(void); */ int32_t esp_hf_client_pcm_resample(void *src, uint32_t in_bytes, void *dst); +/** + * @brief This function is used to get the status of hf client + * + * @param[out] profile_status - hf client status + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_hf_client_get_profile_status(esp_hf_client_profile_status_t *profile_status); + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/bluedroid/api/include/api/esp_hf_client_legacy_api.h b/lib/bt/host/bluedroid/api/include/api/esp_hf_client_legacy_api.h new file mode 100644 index 00000000..6441bfc4 --- /dev/null +++ b/lib/bt/host/bluedroid/api/include/api/esp_hf_client_legacy_api.h @@ -0,0 +1,78 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Some legacy APIs of HFP HF, will be removed in the future + */ + +#pragma once + +#include "esp_err.h" +#include "esp_bt_defs.h" +#include "esp_hf_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief HFP client incoming data callback function, the callback is useful in case of + * Voice Over HCI. + * @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the + * buffer is allocated inside bluetooth protocol stack and will be released after + * invoke of the callback is finished. + * @param[in] len : size(in bytes) in buf + */ +typedef void (* esp_hf_client_incoming_data_cb_t)(const uint8_t *buf, uint32_t len); + +/** + * @brief HFP client outgoing data callback function, the callback is useful in case of + * Voice Over HCI. Once audio connection is set up and the application layer has + * prepared data to send, the lower layer will call this function to read data + * and then send. This callback is supposed to be implemented as non-blocking, + * and if data is not enough, return value 0 is supposed. + * + * @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the + * buffer is allocated inside bluetooth protocol stack and will be released after + * invoke of the callback is finished. + * + * @param[in] len : size(in bytes) in buf + * + * @return length of data successfully read + * + */ +typedef uint32_t (* esp_hf_client_outgoing_data_cb_t)(uint8_t *buf, uint32_t len); + +/** + * @brief Register HFP client data output function; the callback is only used in + * the case that Voice Over HCI is enabled. + * + * @param[in] recv: HFP client incoming data callback function + * + * @param[in] send: HFP client outgoing data callback function + * + * @return + * - ESP_OK: success + * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: if callback is a NULL function pointer + * + */ +esp_err_t esp_hf_client_register_data_callback(esp_hf_client_incoming_data_cb_t recv, + esp_hf_client_outgoing_data_cb_t send); + +/** + * @brief Trigger the lower-layer to fetch and send audio data. + * This function is only only used in the case that Voice Over HCI is enabled. After this + * function is called, lower layer will invoke esp_hf_client_outgoing_data_cb_t to fetch data. + * + * As a precondition to use this API, Service Level Connection shall exist with AG. + * + */ +void esp_hf_client_outgoing_data_ready(void); + +#ifdef __cplusplus +} +#endif diff --git a/lib/bt/host/bluedroid/api/include/api/esp_hf_defs.h b/lib/bt/host/bluedroid/api/include/api/esp_hf_defs.h index b7671ff1..e6ca2e70 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_hf_defs.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_hf_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,18 @@ extern "C" { #endif +typedef uint16_t esp_hf_sync_conn_hdl_t; + +/// profile states +typedef enum { + ESP_HF_INIT_SUCCESS = 0, /*!< Indicate init successful */ + ESP_HF_INIT_ALREADY, /*!< Indicate init repeated */ + ESP_HF_INIT_FAIL, /*!< Indicate init fail */ + ESP_HF_DEINIT_SUCCESS, /*!< Indicate deinit successful */ + ESP_HF_DEINIT_ALREADY, /*!< Indicate deinit repeated */ + ESP_HF_DEINIT_FAIL, /*!< Indicate deinit fail */ +} esp_hf_prof_state_t; + /// in-band ring tone state typedef enum { ESP_HF_IN_BAND_RINGTONE_NOT_PROVIDED = 0, @@ -128,7 +140,7 @@ typedef enum { /// +CLCC address type typedef enum { - ESP_HF_CALL_ADDR_TYPE_UNKNOWN = 0x81, /*!< unkown address type */ + ESP_HF_CALL_ADDR_TYPE_UNKNOWN = 0x81, /*!< unknown address type */ ESP_HF_CALL_ADDR_TYPE_INTERNATIONAL = 0x91, /*!< international address */ } esp_hf_call_addr_type_t; @@ -160,7 +172,7 @@ typedef enum ESP_HF_NREC_START } esp_hf_nrec_t; -///+CCWA resposne status +///+CCWA response status typedef enum { ESP_HF_CALL_WAITING_INACTIVE, ESP_HF_CALL_WAITING_ACTIVE, @@ -239,6 +251,25 @@ typedef enum { ESP_HF_CME_NETWORK_NOT_ALLOWED = 32, /*!< network not allowed --emergency calls only */ } esp_hf_cme_err_t; +/* Since HFP uses a fixed set of mSBC codec parameters, define it here */ +#define ESP_HF_MSBC_CHANNEL_MODE "Mono" /*!< mSBC channel mode */ +#define ESP_HF_MSBC_SAMPLING_RATE "16 kHz" /*!< mSBC sampling rate */ +#define ESP_HF_MSBC_ALLOCATION_METHOD "Loudness" /*!< mSBC allocation method */ +#define ESP_HF_MSBC_SUBBANDS 8 /*!< mSBC subbands */ +#define ESP_HF_MSBC_BLOCK_LENGTH 15 /*!< mSBC block length */ +#define ESP_HF_MSBC_BITPOOL 26 /*!< mSBC bitpool */ +/* frame size after mSBC encoded */ +#define ESP_HF_MSBC_ENCODED_FRAME_SIZE 57 /*!< mSBC frame size */ + +/** + * @brief HFP audio buffer + */ +typedef struct { + uint16_t buff_size; /*!< buffer size */ + uint16_t data_len; /*!< audio data length, data length should not greater than buffer size */ + uint8_t *data; /*!< pointer to audio data start */ +} esp_hf_audio_buff_t; /*!< struct to store audio data */ + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/bluedroid/api/include/api/esp_hidd_api.h b/lib/bt/host/bluedroid/api/include/api/esp_hidd_api.h index a2af1659..f16bbcb0 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_hidd_api.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_hidd_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 * @@ -145,6 +145,16 @@ typedef enum { ESP_HIDD_NO_CONNECTION, /*!< connection may have been closed */ } esp_hidd_status_t; +/** + * @brief HID device profile status parameters + */ +typedef struct { + bool hidd_inited; /*!< HID device initialization */ + uint8_t conn_num; /*!< Number of connections */ + uint8_t plug_vc_dev_num; /*!< Number of plugged virtual cable devices */ + uint8_t reg_app_num; /*!< Number of HID device application registrations */ +} esp_hidd_profile_status_t; + /** * @brief HID device callback parameters union */ @@ -335,6 +345,11 @@ esp_err_t esp_bt_hid_device_unregister_app(void); * called after esp_bt_hid_device_init(). When the operation is complete, the callback function will * be called with ESP_HIDD_OPEN_EVT. * + * @note The connection between the HID Host and the HID Device is established as a virtual cable by default. + * A new HID Host connection request will only be accepted after the previous HID Host has been + * explicitly unplugged. For details on disconnection and virtual cable unplugging, please refer to API + * `esp_bt_hid_device_disconnect` and `esp_bt_hid_device_virtual_cable_unplug`. + * * @param[in] bd_addr: Remote host bluetooth device address. * * @return @@ -406,6 +421,17 @@ esp_err_t esp_bt_hid_device_report_error(esp_hidd_handshake_error_t error); */ esp_err_t esp_bt_hid_device_virtual_cable_unplug(void); +/** + * @brief This function is used to get the status of hid device + * + * @param[out] profile_status - HID device status + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_device_get_profile_status(esp_hidd_profile_status_t *profile_status); + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/bluedroid/api/include/api/esp_hidh_api.h b/lib/bt/host/bluedroid/api/include/api/esp_hidh_api.h index 46f8a15b..51a0d43f 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_hidh_api.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_hidh_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 * @@ -104,7 +104,7 @@ typedef enum { typedef enum { ESP_HIDH_DEV_ATTR_VIRTUAL_CABLE = 0x0001, /*!< whether Virtual Cables is supported */ ESP_HIDH_DEV_ATTR_NORMALLY_CONNECTABLE = 0x0002, /*!< whether device is in Page Scan mode when there is no active connection */ - ESP_HIDH_DEV_ATTR_RECONNECT_INITIATE = 0x0004, /*!< whether the HID device inititates the reconnection process */ + ESP_HIDH_DEV_ATTR_RECONNECT_INITIATE = 0x0004, /*!< whether the HID device initiates the reconnection process */ } esp_hidh_dev_attr_t; /** @@ -128,11 +128,20 @@ typedef struct { int vendor_id; /*!< Device ID information: vendor ID */ int product_id; /*!< Device ID information: product ID */ int version; /*!< Device ID information: version */ - uint8_t ctry_code; /*!< SDP attrbutes of HID devices: HID country code (https://www.usb.org/sites/default/files/hid1_11.pdf) */ - int dl_len; /*!< SDP attrbutes of HID devices: HID device descriptor length */ - uint8_t dsc_list[BTHH_MAX_DSC_LEN]; /*!< SDP attrbutes of HID devices: HID device descriptor definition */ + uint8_t ctry_code; /*!< SDP attributes of HID devices: HID country code (https://www.usb.org/sites/default/files/hid1_11.pdf) */ + int dl_len; /*!< SDP attributes of HID devices: HID device descriptor length */ + uint8_t dsc_list[BTHH_MAX_DSC_LEN]; /*!< SDP attributes of HID devices: HID device descriptor definition */ } esp_hidh_hid_info_t; +/** + * @brief HID host profile status parameters + */ +typedef struct { + bool hidh_inited; /*!< HID host initialization */ + uint8_t conn_num; /*!< Number of connections */ + uint8_t plug_vc_dev_num; /*!< Number of plugged virtual cable devices*/ +} esp_hidh_profile_status_t; + /** * @brief HID host callback parameters union */ @@ -157,7 +166,7 @@ typedef union { struct hidh_open_evt_param { esp_hidh_status_t status; /*!< operation status */ esp_hidh_connection_state_t conn_status; /*!< connection status */ - bool is_orig; /*!< indicate if host intiate the connection */ + bool is_orig; /*!< indicate if host initiate the connection */ uint8_t handle; /*!< device handle */ esp_bd_addr_t bd_addr; /*!< device address */ } open; /*!< HIDH callback param of ESP_HIDH_OPEN_EVT */ @@ -475,6 +484,17 @@ esp_err_t esp_bt_hid_host_set_report(esp_bd_addr_t bd_addr, esp_hidh_report_type */ esp_err_t esp_bt_hid_host_send_data(esp_bd_addr_t bd_addr, uint8_t *data, size_t len); +/** + * @brief This function is used to get the status of hid host + * + * @param[out] profile_status - HID host status + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_hid_host_get_profile_status(esp_hidh_profile_status_t *profile_status); + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/bluedroid/api/include/api/esp_l2cap_bt_api.h b/lib/bt/host/bluedroid/api/include/api/esp_l2cap_bt_api.h index f11c932f..982cbdaa 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_l2cap_bt_api.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_l2cap_bt_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -40,6 +40,14 @@ typedef enum { #define ESP_BT_L2CAP_SEC_ENCRYPT 0x0024 /*!< Encryption required */ typedef uint32_t esp_bt_l2cap_cntl_flags_t; +/** + * @brief L2CAP status parameters + */ +typedef struct { + bool l2cap_inited; /*!< l2cap initialization */ + uint8_t conn_num; /*!< Number of connections */ +} esp_bt_l2cap_protocol_status_t; + /** * @brief L2CAP callback function events */ @@ -51,6 +59,8 @@ typedef enum { ESP_BT_L2CAP_START_EVT = 18, /*!< When L2CAP server started, the event comes */ ESP_BT_L2CAP_CL_INIT_EVT = 19, /*!< When L2CAP client initiated a connection, the event comes */ ESP_BT_L2CAP_SRV_STOP_EVT = 36, /*!< When L2CAP server stopped, the event comes */ + ESP_BT_L2CAP_VFS_REGISTER_EVT = 38, /*!< When L2CAP VFS register, the event comes */ + ESP_BT_L2CAP_VFS_UNREGISTER_EVT = 39, /*!< When L2CAP VFS unregister, the event comes */ } esp_bt_l2cap_cb_event_t; /** @@ -114,9 +124,23 @@ typedef union { */ struct l2cap_srv_stop_evt_param { esp_bt_l2cap_status_t status; /*!< status */ - uint8_t psm; /*!< local psm */ + uint16_t psm; /*!< local psm */ } srv_stop; /*!< L2CAP callback param of ESP_BT_L2CAP_SRV_STOP_EVT */ + /** + * @brief ESP_BT_L2CAP_VFS_REGISTER_EVT + */ + struct l2cap_vfs_register_evt_param { + esp_bt_l2cap_status_t status; /*!< status */ + } vfs_register; /*!< L2CAP callback param of ESP_BT_L2CAP_VFS_REGISTER_EVT */ + + /** + * @brief ESP_BT_L2CAP_VFS_UNREGISTER_EVT + */ + struct l2cap_vfs_unregister_evt_param { + esp_bt_l2cap_status_t status; /*!< status */ + } vfs_unregister; /*!< L2CAP callback param of ESP_BT_L2CAP_VFS_UNREGISTER_EVT */ + } esp_bt_l2cap_cb_param_t; /** @@ -226,6 +250,7 @@ esp_err_t esp_bt_l2cap_stop_srv(uint16_t local_psm); /** * @brief This function is used to register VFS. * Only supports write, read and close. + * When the operation is completed, the callback function will be called with ESP_BT_L2CAP_VFS_REGISTER_EVT. * This function must be called after esp_bt_l2cap_init() successful and before esp_bt_l2cap_deinit(). * * @return @@ -236,6 +261,7 @@ esp_err_t esp_bt_l2cap_vfs_register(void); /** * @brief This function is used to unregister VFS. + * When the operation is completed, the callback function will be called with ESP_BT_L2CAP_VFS_UNREGISTER_EVT. * This function must be called after esp_bt_l2cap_init() successful and before esp_bt_l2cap_deinit(). * * @return @@ -244,6 +270,17 @@ esp_err_t esp_bt_l2cap_vfs_register(void); */ esp_err_t esp_bt_l2cap_vfs_unregister(void); +/** + * @brief This function is used to get the status of L2CAP + * + * @param[out] status - l2cap status + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_bt_l2cap_get_protocol_status(esp_bt_l2cap_protocol_status_t *status); + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/bluedroid/api/include/api/esp_pba_defs.h b/lib/bt/host/bluedroid/api/include/api/esp_pba_defs.h new file mode 100644 index 00000000..c3a6f510 --- /dev/null +++ b/lib/bt/host/bluedroid/api/include/api/esp_pba_defs.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_bt_defs.h" + +/* Supported repositories bit mask */ +#define ESP_PBA_SUPPORTED_REPO_LOCAL_PHONE_BOOK 0x01 +#define ESP_PBA_SUPPORTED_REPO_SIM_CARD 0x02 +#define ESP_PBA_SUPPORTED_REPO_SPEED_DIAL 0x04 +#define ESP_PBA_SUPPORTED_REPO_FAVORITES 0x08 + +/* Supported features bit mask */ +#define ESP_PBA_SUPPORTED_FEAT_DOWNLOAD 0x0001 +#define ESP_PBA_SUPPORTED_FEAT_BROWSING 0x0002 +#define ESP_PBA_SUPPORTED_FEAT_DATABASE_IDENTIFIER 0x0004 +#define ESP_PBA_SUPPORTED_FEAT_FOLDER_VERSION_COUNTERS 0x0008 +#define ESP_PBA_SUPPORTED_FEAT_VCARD_SELECTING 0x0010 +#define ESP_PBA_SUPPORTED_FEAT_ENHANCED_MISSED_CALLS 0x0020 +#define ESP_PBA_SUPPORTED_FEAT_X_BT_UCI_VCARD_PROPERTY 0x0040 +#define ESP_PBA_SUPPORTED_FEAT_X_BT_UID_VCARD_PROPERTY 0x0080 +#define ESP_PBA_SUPPORTED_FEAT_CONTACT_REFERENCING 0x0100 +#define ESP_PBA_SUPPORTED_FEAT_DEFAULT_CONTACT_IMAGE_FORMAT 0x0200 diff --git a/lib/bt/host/bluedroid/api/include/api/esp_pbac_api.h b/lib/bt/host/bluedroid/api/include/api/esp_pbac_api.h new file mode 100644 index 00000000..131d53f8 --- /dev/null +++ b/lib/bt/host/bluedroid/api/include/api/esp_pbac_api.h @@ -0,0 +1,340 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_err.h" +#include "esp_bt_defs.h" +#include "esp_pba_defs.h" + +#define ESP_PBAC_INVALID_HANDLE 0 /*!< invalid handle value */ + +typedef uint16_t esp_pbac_conn_hdl_t; + +/** + * @brief PBA client callback events + */ +typedef enum { + ESP_PBAC_INIT_EVT, /*!< PBA client initialized event */ + ESP_PBAC_DEINIT_EVT, /*!< PBA client de-initialized event */ + ESP_PBAC_CONNECTION_STATE_EVT, /*!< PBA client connection state changed event */ + ESP_PBAC_PULL_PHONE_BOOK_RESPONSE_EVT, /*!< Response of pull phone book */ + ESP_PBAC_SET_PHONE_BOOK_RESPONSE_EVT, /*!< Response of set phone book */ + ESP_PBAC_PULL_VCARD_LISTING_RESPONSE_EVT, /*!< Response of pull vCard listing */ + ESP_PBAC_PULL_VCARD_ENTRY_RESPONSE_EVT, /*!< Response of pull vCard entry */ +} esp_pbac_event_t; + +/** + * @brief PBA client status code + */ +typedef enum { + ESP_PBAC_SUCCESS = 0, /*!< Operation success */ + ESP_PBAC_FAILURE, /*!< Generic failure */ + ESP_PBAC_ALREADY_CONN, /*!< Connection to peer device already exist */ + ESP_PBAC_NO_RESOURCE, /*!< No more resource */ + ESP_PBAC_SDP_FAIL, /*!< Connection failed in SDP */ + ESP_PBAC_GOEP_FAIL, /*!< Operation failed in GOEP */ + ESP_PBAC_AUTH_FAIL, /*!< Connection failed in OBEX authentication */ + ESP_PBAC_DEINIT, /*!< Connection closed due to pba client is deinit */ + + /* these error code is related to OBEX */ + ESP_PBAC_BAD_REQUEST = 0xC0, /*!< Server couldn't understand request */ + ESP_PBAC_UNAUTHORIZED = 0xC1, /*!< Unauthorized */ + ESP_PBAC_FORBIDDEN = 0xC3, /*!< Operation is understood but refused */ + ESP_PBAC_NOT_FOUND = 0xC4, /*!< Not found */ + ESP_PBAC_NOT_ACCEPTABLE = 0xC6, /*!< Not Acceptable */ + ESP_PBAC_PRECONDITION_FAILED = 0xCC, /*!< Precondition failed */ + ESP_PBAC_NOT_IMPLEMENTED = 0xD1, /*!< Not implemented */ + ESP_PBAC_SERVICE_UNAVAILABLE = 0xD3, /*!< Service unavailable */ +} esp_pbac_status_t; + +/** + * @brief PBA client set phone book flags + */ +typedef enum { + ESP_PBAC_SET_PHONE_BOOK_FLAGS_ROOT = 0x02, /*!< Go back to root, name should set to empty string, not NULL */ + ESP_PBAC_SET_PHONE_BOOK_FLAGS_DOWN = 0x02, /*!< Go down 1 level, name should set to child folder */ + ESP_PBAC_SET_PHONE_BOOK_FLAGS_UP = 0x03, /*!< Go up 1 level, name is optional */ +} esp_pbac_set_phone_book_flags_t; + +/** + * @brief PBA client pull phone book optional application parameter + */ +typedef struct { + uint8_t include_property_selector : 1; /*!< 1 if app param include property_selector */ + uint8_t include_format : 1; /*!< 1 if app param include format */ + uint8_t include_max_list_count : 1; /*!< 1 if app param include max_list_count */ + uint8_t include_list_start_offset : 1; /*!< 1 if app param include list_start_offset */ + uint8_t include_reset_new_missed_calls : 1; /*!< 1 if app param include reset_new_missed_calls */ + uint8_t include_vcard_selector : 1; /*!< 1 if app param include vcard_selector */ + uint8_t include_vcard_selector_operator : 1; /*!< 1 if app param include vcard_selector_operator */ + uint8_t format; /*!< 0x00 = 2.1, 0x01 = 3.0 */ + uint8_t reset_new_missed_calls; /*!< 0x01 = Reset */ + uint8_t vcard_selector_operator; /*!< 0x00 = OR, 0x01 = AND */ + uint16_t max_list_count; /*!< 0x0000 to 0xFFFF */ + uint16_t list_start_offset; /*!< 0x0000 to 0xFFFF */ + uint64_t property_selector; /*!< 64 bits mask */ + uint64_t vcard_selector; /*!< 64 bits mask */ +} esp_pbac_pull_phone_book_app_param_t; + +/** + * @brief PBA client pull vCard listing optional application parameter + */ +typedef struct { + uint8_t include_order : 1; /*!< 1 if app param include order */ + uint8_t include_search_value : 1; /*!< 1 if app param include search_value */ + uint8_t include_search_property : 1; /*!< 1 if app param include search_property */ + uint8_t include_max_list_count : 1; /*!< 1 if app param include max_list_count */ + uint8_t include_list_start_offset : 1; /*!< 1 if app param include list_start_offset */ + uint8_t include_reset_new_missed_calls : 1; /*!< 1 if app param include reset_new_missed_calls */ + uint8_t include_vcard_selector : 1; /*!< 1 if app param include vcard_selector */ + uint8_t include_vcard_selector_operator : 1; /*!< 1 if app param include vcard_selector_operator */ + uint8_t order; /*!< 0x00 = indexed, 0x01 = alphanumeric */ + uint8_t search_property; /*!< 0x00 = Name, 0x01 = Number, 0x02 = Sound */ + uint8_t reset_new_missed_calls; /*!< 0x01 = Reset */ + uint8_t vcard_selector_operator; /*!< 0x00 = OR, 0x01 = AND */ + uint16_t max_list_count; /*!< 0x0000 to 0xFFFF */ + uint16_t list_start_offset; /*!< 0x0000 to 0xFFFF */ + char *search_value; /*!< Text */ + uint64_t vcard_selector; /*!< 64 bits mask */ +} esp_pbac_pull_vcard_listing_app_param_t; + +/** + * @brief PBA client pull vCard entry optional application parameter + */ +typedef struct { + uint8_t include_property_selector : 1; /*!< 1 if app param include property_selector */ + uint8_t include_format : 1; /*!< 1 if app param include format */ + uint8_t format; /*!< 0x00 = 2.1, 0x01 = 3.0 */ + uint64_t property_selector; /*!< 64 bits mask */ +} esp_pbac_pull_vcard_entry_app_param_t; + +/** + * @brief PBA client callback parameters + */ +typedef union { + /** + * @brief ESP_PBAC_CONNECTION_STATE_EVT + */ + struct pbac_conn_stat_param { + bool connected; /*!< whether pba client is connected to server */ + esp_pbac_conn_hdl_t handle; /*!< connection handle, non zeros if exist */ + uint8_t peer_supported_repo; /*!< peer supported repositories */ + uint32_t peer_supported_feat; /*!< peer supported features */ + esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */ + esp_pbac_status_t reason; /*!< reason if disconnect */ + } conn_stat; /*!< PBA client connection status */ + + /** + * @brief ESP_PBAC_PULL_PHONE_BOOK_RESPONSE_EVT + */ + struct pbac_pull_phone_book_rsp_param { + esp_pbac_conn_hdl_t handle; /*!< PBA client connection handle */ + esp_pbac_status_t result; /*!< operation result, ESP_PBAC_SUCCESS if success */ + bool final; /*!< whether this is the final response packet */ + uint8_t *data; /*!< response data */ + uint16_t data_len; /*!< response data len */ + /* The following are the application parameters */ + uint8_t include_phone_book_size : 1; /*!< 1 if app param include phone_book_size */ + uint8_t include_new_missed_calls : 1; /*!< 1 if app param include new_missed_calls */ + uint8_t include_primary_folder_version : 1; /*!< 1 if app param include primary_folder_version */ + uint8_t include_secondary_folder_version : 1; /*!< 1 if app param include secondary_folder_version */ + uint8_t include_database_identifier : 1; /*!< 1 if app param include database_identifier */ + uint8_t new_missed_calls; /*!< 0x00 to 0xFF */ + uint16_t phone_book_size; /*!< 0x0000 to 0xFFFF */ + uint8_t *primary_folder_version; /*!< 0 to (2^128 -1) */ + uint8_t *secondary_folder_version; /*!< 0 to (2^128 -1) */ + uint8_t *database_identifier; /*!< 0 to (2^128 -1) */ + } pull_phone_book_rsp; /*!< pull phone book response */ + + /** + * @brief ESP_PBAC_SET_PHONE_BOOK_RESPONSE_EVT + */ + struct pbac_set_phone_book_rsp_param { + esp_pbac_conn_hdl_t handle; /*!< PBA client connection handle */ + esp_pbac_status_t result; /*!< operation result, ESP_PBAC_SUCCESS if success */ + } set_phone_book_rsp; /*!< set phone book response, always the final response */ + + /** + * @brief ESP_PBAC_PULL_VCARD_LISTING_RESPONSE_EVT + */ + struct pbac_pull_vcard_listing_rsp_param { + esp_pbac_conn_hdl_t handle; /*!< PBA client connection handle */ + esp_pbac_status_t result; /*!< operation result, ESP_PBAC_SUCCESS if success */ + bool final; /*!< whether this is the final response packet */ + uint8_t *data; /*!< response data */ + uint16_t data_len; /*!< response data len */ + /* The following are the application parameters */ + uint8_t include_phone_book_size : 1; /*!< 1 if app param include phone_book_size */ + uint8_t include_new_missed_calls : 1; /*!< 1 if app param include new_missed_calls */ + uint8_t include_primary_folder_version : 1; /*!< 1 if app param include primary_folder_version */ + uint8_t include_secondary_folder_version : 1; /*!< 1 if app param include secondary_folder_version */ + uint8_t include_database_identifier : 1; /*!< 1 if app param include database_identifier */ + uint8_t new_missed_calls; /*!< 0x00 to 0xFF */ + uint16_t phone_book_size; /*!< 0x0000 to 0xFFFF */ + uint8_t *primary_folder_version; /*!< 0 to (2^128 -1) */ + uint8_t *secondary_folder_version; /*!< 0 to (2^128 -1) */ + uint8_t *database_identifier; /*!< 0 to (2^128 -1) */ + } pull_vcard_listing_rsp; /*!< pull vcard listing response */ + + /** + * @brief ESP_PBAC_PULL_VCARD_ENTRY_RESPONSE_EVT + */ + struct pbac_pull_vcard_entry_rsp_param { + esp_pbac_conn_hdl_t handle; /*!< PBA client connection handle */ + esp_pbac_status_t result; /*!< operation result, ESP_PBAC_SUCCESS if success */ + bool final; /*!< whether this is the final response packet */ + uint8_t *data; /*!< response data */ + uint16_t data_len; /*!< response data len */ + /* The following are the application parameters */ + uint8_t include_database_identifier : 1; /*!< 1 if app param include database_identifier */ + uint8_t *database_identifier; /*!< 0 to (2^128 -1) */ + } pull_vcard_entry_rsp; /*!< pull vcard listing response */ +} esp_pbac_param_t; + +/** + * @brief PBA client callback function type + * + * @param event : Event type + * + * @param param : Pointer to callback parameter + */ +typedef void (*esp_pbac_callback_t)(esp_pbac_event_t event, esp_pbac_param_t *param); + + +/** + * @brief This function is called to register a user callbacks in PBA client. + * + * @param[in] callback: pointer to the user callback function. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_pbac_register_callback(esp_pbac_callback_t callback); + +/** + * @brief Initializes PBA client interface. This function should be called after bluedroid + * enable successfully, and should be called after esp_pbac_register_callback. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_pbac_init(void); + +/** + * @brief De-initializes PBA client interface. This will close all PBA client connection. + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_pbac_deinit(void); + +/** + * @brief Start the process to establish a connection to PBA server. + * + * @param[in] bd_addr: peer bluetooth device address + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_pbac_connect(esp_bd_addr_t bd_addr); + +/** + * @brief Disconnects from the current connected PBA server. + * + * @param[in] handle: connection handle retrieved from ESP_PBAC_CONNECTION_STATE_EVT + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_pbac_disconnect(esp_pbac_conn_hdl_t handle); + +/** + * @brief Send a request to pull phone book. + * + * @param[in] handle: connection handle retrieved from ESP_PBAC_CONNECTION_STATE_EVT + * + * @param[in] name: phone book object path and name, shall contain the absolute path + * in the virtual folder architecture + * + * @param[in] app_param: optional application parameter + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_pbac_pull_phone_book(esp_pbac_conn_hdl_t handle, const char *name, esp_pbac_pull_phone_book_app_param_t *app_param); + +/** + * @brief Send a request to set the current folder in the virtual folder architecture. + * + * @param[in] handle: connection handle retrieved from ESP_PBAC_CONNECTION_STATE_EVT + * + * @param[in] flags: operation flags, one of ESP_PBAC_SET_PHONE_BOOK_FLAGS_XXX + * + * @param[in] name: folder name, if flags is set to ROOT, name should be empty string (""), + * if flags is set to UP, name is optional, if flags is set to DOWN, name + * is mandatory + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_pbac_set_phone_book(esp_pbac_conn_hdl_t handle, esp_pbac_set_phone_book_flags_t flags, const char *name); + +/** + * @brief Set the current folder in the virtual folder architecture, use absolute path. + * + * @param[in] handle: connection handle retrieved from ESP_PBAC_CONNECTION_STATE_EVT + * + * @param[in] path: absolute path of the folder intend to set. NULL or empty string will + * set to ROOT + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_pbac_set_phone_book2(esp_pbac_conn_hdl_t handle, const char *path); + +/** + * @brief Send a request to pull vCard listing. + * + * @param[in] handle: connection handle retrieved from ESP_PBAC_CONNECTION_STATE_EVT + * + * @param[in] name: specifies the name of the folder to be retrieved, uses relative paths, + * shall not include any path information. An empty name (empty string "") + * may be sent to retrieve the vCard Listing object of the current folder. + * However, it is illegal to issue a pull vCard listing request with an + * empty name header from the ‘telecom/’ folder + * + * @param[in] app_param: optional application parameter + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_pbac_pull_vcard_listing(esp_pbac_conn_hdl_t handle, const char *name, esp_pbac_pull_vcard_listing_app_param_t *app_param); + +/** + * @brief Send a request to pull vCard entry. + * + * @param[in] handle: connection handle retrieved from ESP_PBAC_CONNECTION_STATE_EVT + * + * @param[in] name: vCard name or, if supported, the X-BT-UID of the object to be retrieved. + * uses relative paths,shall not include any path information + * + * @param[in] app_param: optional application parameter + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_pbac_pull_vcard_entry(esp_pbac_conn_hdl_t handle, const char *name, esp_pbac_pull_vcard_entry_app_param_t *app_param); diff --git a/lib/bt/host/bluedroid/api/include/api/esp_sdp_api.h b/lib/bt/host/bluedroid/api/include/api/esp_sdp_api.h index 14741e74..956af037 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_sdp_api.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_sdp_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,123 +14,173 @@ extern "C" { #endif -#define ESP_SDP_SERVER_NAME_MAX 32 /*!< Service name max length */ -#define SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH 15 /*!< OPP supported format list maximum length */ +#define ESP_SDP_SERVER_NAME_MAX 32 /*!< Service name max length */ +#define SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH 15 /*!< OPP supported format list maximum length */ + +#define ESP_SDP_UUID_MAP_MAS 0x1132 /*!< Message Access Service UUID */ +#define ESP_SDP_UUID_MAP_MNS 0x1133 /*!< Message Notification Service UUID */ +#define ESP_SDP_UUID_PBAP_PSE 0x112F /*!< Phone Book Server Equipment UUID */ +#define ESP_SDP_UUID_PBAP_PCE 0x112E /*!< Phone Book Client Equipment UUID */ +#define ESP_SDP_UUID_OPP 0x1105 /*!< Object Push Profile UUID */ +#define ESP_SDP_UUID_SAP 0x112D /*!< SIM Access Profile UUID */ +#define ESP_SDP_UUID_DIP 0x1200 /*!< Device Identification Profile UUID */ + +#define ESP_SDP_BUILD_BT_UUID16(uuid16_val) \ + (esp_bt_uuid_t) { .len = ESP_UUID_LEN_16, .uuid = {.uuid16 = (uint16_t)(uuid16_val),}, } typedef enum { - ESP_SDP_SUCCESS = 0, /*!< Successful operation. */ - ESP_SDP_FAILURE, /*!< Generic failure. */ - ESP_SDP_NO_RESOURCE, /*!< No more resource */ - ESP_SDP_NEED_INIT, /*!< SDP module shall init first */ - ESP_SDP_NEED_DEINIT, /*!< SDP module shall deinit first */ - ESP_SDP_NO_CREATE_RECORD, /*!< No record created */ + ESP_SDP_SUCCESS = 0, /*!< Successful operation. */ + ESP_SDP_FAILURE, /*!< Generic failure. */ + ESP_SDP_NO_RESOURCE, /*!< No more resource */ + ESP_SDP_NEED_INIT, /*!< SDP module shall init first */ + ESP_SDP_NEED_DEINIT, /*!< SDP module shall deinit first */ + ESP_SDP_NO_CREATE_RECORD, /*!< No record created */ } esp_sdp_status_t; +/** + * @brief SDP protocol status parameters + */ +typedef struct { + bool sdp_inited; /*!< SDP initialization */ + uint8_t records_num; /*!< Number of created records */ +} esp_sdp_protocol_status_t; + /** * @brief SDP callback function events */ typedef enum { - ESP_SDP_INIT_EVT = 0, /*!< When SDP is initialized, the event comes */ - ESP_SDP_DEINIT_EVT = 1, /*!< When SDP is deinitialized, the event comes */ - ESP_SDP_SEARCH_COMP_EVT = 2, /*!< When SDP search complete, the event comes */ - ESP_SDP_CREATE_RECORD_COMP_EVT = 3, /*!< When create SDP records complete, the event comes */ - ESP_SDP_REMOVE_RECORD_COMP_EVT = 4, /*!< When remove a SDP record complete, the event comes */ + ESP_SDP_INIT_EVT = 0, /*!< When SDP is initialized, the event comes */ + ESP_SDP_DEINIT_EVT = 1, /*!< When SDP is de-initialized, the event comes */ + ESP_SDP_SEARCH_COMP_EVT = 2, /*!< When SDP search complete, the event comes */ + ESP_SDP_CREATE_RECORD_COMP_EVT = 3, /*!< When create SDP records complete, the event comes */ + ESP_SDP_REMOVE_RECORD_COMP_EVT = 4, /*!< When remove a SDP record complete, the event comes */ } esp_sdp_cb_event_t; /** * @brief SDP record type */ typedef enum { - ESP_SDP_TYPE_RAW, /*!< Used to carry raw SDP search data for unknown UUIDs */ - ESP_SDP_TYPE_MAP_MAS, /*!< Message Access Profile - Server */ - ESP_SDP_TYPE_MAP_MNS, /*!< Message Access Profile - Client (Notification Server) */ - ESP_SDP_TYPE_PBAP_PSE, /*!< Phone Book Profile - Server */ - ESP_SDP_TYPE_PBAP_PCE, /*!< Phone Book Profile - Client */ - ESP_SDP_TYPE_OPP_SERVER, /*!< Object Push Profile */ - ESP_SDP_TYPE_SAP_SERVER /*!< SIM Access Profile */ + ESP_SDP_TYPE_RAW, /*!< Used to carry raw SDP search data for unknown UUIDs */ + ESP_SDP_TYPE_MAP_MAS, /*!< Message Access Profile - Server */ + ESP_SDP_TYPE_MAP_MNS, /*!< Message Access Profile - Client (Notification Server) */ + ESP_SDP_TYPE_PBAP_PSE, /*!< Phone Book Profile - Server */ + ESP_SDP_TYPE_PBAP_PCE, /*!< Phone Book Profile - Client */ + ESP_SDP_TYPE_OPP_SERVER, /*!< Object Push Profile */ + ESP_SDP_TYPE_SAP_SERVER, /*!< SIM Access Profile */ + ESP_SDP_TYPE_DIP_SERVER, /*!< Device Identification Profile */ } esp_bluetooth_sdp_types_t; /** - * @brief Some signals need additional pointers, hence we introduce a - * generic way to handle these pointers. + * @brief SDP header structure */ typedef struct bluetooth_sdp_hdr_overlay { - esp_bluetooth_sdp_types_t type; /*!< SDP type */ - esp_bt_uuid_t uuid; /*!< UUID type, include uuid and uuid length */ - uint32_t service_name_length; /*!< Service name length */ - char *service_name; /*!< service name */ - int32_t rfcomm_channel_number; /*!< rfcomm channel number, if not used set to -1*/ - int32_t l2cap_psm; /*!< l2cap psm, if not used set to -1 */ - int32_t profile_version; /*!< profile version */ - - // User pointers, only used for some signals - see esp_bluetooth_sdp_ops_record_t - int user1_ptr_len; /*!< see esp_bluetooth_sdp_ops_record_t */ - uint8_t *user1_ptr; /*!< see esp_bluetooth_sdp_ops_record_t */ - int user2_ptr_len; /*!< see esp_bluetooth_sdp_ops_record_t */ - uint8_t *user2_ptr; /*!< see esp_bluetooth_sdp_ops_record_t */ + esp_bluetooth_sdp_types_t type; /*!< SDP type */ + esp_bt_uuid_t uuid; /*!< UUID type, include uuid and uuid length, only needed to be set for RAW record creation */ + uint32_t service_name_length; /*!< Service name length */ + char *service_name; /*!< Service name */ + int32_t rfcomm_channel_number; /*!< RFCOMM channel number, if not used set to -1*/ + int32_t l2cap_psm; /*!< L2CAP psm, if not used set to -1 */ + int32_t profile_version; /*!< Profile version */ + int user1_ptr_len; /*!< User data1 length, only used for searching RAW record */ + uint8_t *user1_ptr; /*!< User data1 pointer to the raw SDP response data, only used for searching RAW record */ + int user2_ptr_len __attribute__((deprecated)); /*!< User data2 length, only used for searching RAW record */ + uint8_t *user2_ptr __attribute__((deprecated)); /*!< User data2 pointer, only used for searching RAW record */ } esp_bluetooth_sdp_hdr_overlay_t; +/** + * @brief Raw SDP record + */ +typedef struct bluetooth_sdp_raw_record { + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ +} esp_bluetooth_sdp_raw_record_t; + /** * @brief Message Access Profile - Server parameters */ typedef struct bluetooth_sdp_mas_record { - esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ - uint32_t mas_instance_id; /*!< MAS Instance ID */ - uint32_t supported_features; /*!< Map supported features */ - uint32_t supported_message_types; /*!< Supported message types */ + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ + uint32_t mas_instance_id; /*!< MAS Instance ID */ + uint32_t supported_features; /*!< Map supported features */ + uint32_t supported_message_types; /*!< Supported message types */ } esp_bluetooth_sdp_mas_record_t; /** * @brief Message Access Profile - Client (Notification Server) parameters */ typedef struct bluetooth_sdp_mns_record { - esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ - uint32_t supported_features; /*!< Supported features */ + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ + uint32_t supported_features; /*!< Supported features */ } esp_bluetooth_sdp_mns_record_t; /** * @brief Phone Book Profile - Server parameters */ typedef struct bluetooth_sdp_pse_record { - esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ - uint32_t supported_features; /*!< Pbap Supported Features */ - uint32_t supported_repositories; /*!< Supported Repositories */ + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ + uint32_t supported_features; /*!< PBAP Supported Features */ + uint32_t supported_repositories; /*!< Supported Repositories */ } esp_bluetooth_sdp_pse_record_t; /** * @brief Phone Book Profile - Client parameters */ typedef struct bluetooth_sdp_pce_record { - esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ } esp_bluetooth_sdp_pce_record_t; /** * @brief Object Push Profile parameters */ typedef struct bluetooth_sdp_ops_record { - esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ - int supported_formats_list_len; /*!< Supported formats list length */ - uint8_t supported_formats_list[SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH]; /*!< Supported formats list */ + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ + int supported_formats_list_len; /*!< Supported formats list length */ + uint8_t supported_formats_list[SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH]; /*!< Supported formats list */ } esp_bluetooth_sdp_ops_record_t; /** * @brief SIM Access Profile parameters */ typedef struct bluetooth_sdp_sap_record { - esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ } esp_bluetooth_sdp_sap_record_t; +/** + * @brief Vendor ID source + */ +typedef enum { + ESP_SDP_VENDOR_ID_SRC_BT = 1, /*!< Bluetooth assigned vendor id source */ + ESP_SDP_VENDOR_ID_SRC_USB = 2, /*!< USB assigned vendor id source */ +} esp_sdp_vendor_id_source_t; + +/** + * @brief Device Identification Profile parameters + * + * @note Only one primary Device Identification service record can be added in the SDP database. If primary + * Device Identification service is created multiple times, only the last one will take effect. + */ +typedef struct bluetooth_sdp_dip_record { + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ + uint16_t vendor; /*!< Vendor ID */ + uint16_t vendor_id_source; /*!< Vendor ID source, 0x0001 for Bluetooth, 0x0002 for USB, other values reserved, see `esp_sdp_vendor_id_source_t` */ + uint16_t product; /*!< Product ID */ + uint16_t version; /*!< Release version in format 0xJJMN(JJ – major number, M – minor number, N – sub-minor number) */ + bool primary_record; /*!< Indicate if the record is primary, shall set to true if there is a only single device + record, others shall be set to false */ +} esp_bluetooth_sdp_dip_record_t; + /** * @brief SDP record parameters union */ typedef union { - esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ - esp_bluetooth_sdp_mas_record_t mas; /*!< Message Access Profile - Server */ - esp_bluetooth_sdp_mns_record_t mns; /*!< Message Access Profile - Client (Notification Server) */ - esp_bluetooth_sdp_pse_record_t pse; /*!< Phone Book Profile - Server */ - esp_bluetooth_sdp_pce_record_t pce; /*!< Phone Book Profile - Client */ - esp_bluetooth_sdp_ops_record_t ops; /*!< Object Push Profile */ - esp_bluetooth_sdp_sap_record_t sap; /*!< SIM Access Profile */ + esp_bluetooth_sdp_hdr_overlay_t hdr; /*!< General info */ + esp_bluetooth_sdp_raw_record_t raw; /*!< Raw SDP search data for unknown UUIDs */ + esp_bluetooth_sdp_mas_record_t mas; /*!< Message Access Profile - Server */ + esp_bluetooth_sdp_mns_record_t mns; /*!< Message Access Profile - Client (Notification Server) */ + esp_bluetooth_sdp_pse_record_t pse; /*!< Phone Book Profile - Server */ + esp_bluetooth_sdp_pce_record_t pce; /*!< Phone Book Profile - Client */ + esp_bluetooth_sdp_ops_record_t ops; /*!< Object Push Profile */ + esp_bluetooth_sdp_sap_record_t sap; /*!< SIM Access Profile */ + esp_bluetooth_sdp_dip_record_t dip; /*!< Device Identification Profile */ } esp_bluetooth_sdp_record_t; /** @@ -141,44 +191,43 @@ typedef union { * @brief ESP_SDP_INIT_EVT */ struct sdp_init_evt_param { - esp_sdp_status_t status; /*!< status */ - } init; /*!< SDP callback param of ESP_SDP_INIT_EVT */ + esp_sdp_status_t status; /*!< Status */ + } init; /*!< SDP callback param of ESP_SDP_INIT_EVT */ /** * @brief ESP_SDP_DEINIT_EVT */ struct sdp_deinit_evt_param { - esp_sdp_status_t status; /*!< status */ - } deinit; /*!< SDP callback param of ESP_SDP_DEINIT_EVT */ + esp_sdp_status_t status; /*!< Status */ + } deinit; /*!< SDP callback param of ESP_SDP_DEINIT_EVT */ /** * @brief ESP_SDP_SEARCH_COMP_EVT */ struct sdp_search_evt_param { - esp_sdp_status_t status; /*!< status */ - esp_bd_addr_t remote_addr; /*!< remote device address */ - esp_bt_uuid_t sdp_uuid; /*!< service uuid */ - int record_count; /*!< Number of SDP records */ - esp_bluetooth_sdp_record_t *records;/*!< SDP records */ - } search; /*!< SDP callback param of ESP_SDP_SEARCH_COMP_EVT */ + esp_sdp_status_t status; /*!< Status */ + esp_bd_addr_t remote_addr; /*!< Remote device address */ + esp_bt_uuid_t sdp_uuid; /*!< Service uuid */ + int record_count; /*!< Number of SDP records */ + esp_bluetooth_sdp_record_t *records; /*!< SDP records */ + } search; /*!< SDP callback param of ESP_SDP_SEARCH_COMP_EVT */ /** * @brief ESP_SDP_CREATE_RECORD_COMP_EVT */ - struct sdp_crate_record_evt_param { - esp_sdp_status_t status; /*!< status */ - int record_handle; /*!< SDP record handle */ - } create_record; /*!< SDP callback param of ESP_SDP_CREATE_RECORD_COMP_EVT */ + struct sdp_create_record_evt_param { + esp_sdp_status_t status; /*!< Status */ + int record_handle; /*!< SDP record handle */ + } create_record; /*!< SDP callback param of ESP_SDP_CREATE_RECORD_COMP_EVT */ /** * @brief ESP_SDP_REMOVE_RECORD_COMP_EVT */ struct sdp_remove_record_evt_param { - esp_sdp_status_t status; /*!< status */ - } remove_record; /*!< SDP callback param of ESP_SDP_REMOVE_RECORD_COMP_EVT */ - -} esp_sdp_cb_param_t; /*!< SDP callback parameter union type */ + esp_sdp_status_t status; /*!< Status */ + } remove_record; /*!< SDP callback param of ESP_SDP_REMOVE_RECORD_COMP_EVT */ +} esp_sdp_cb_param_t; /** * @brief SDP callback function type. @@ -264,6 +313,17 @@ esp_err_t esp_sdp_create_record(esp_bluetooth_sdp_record_t *record); */ esp_err_t esp_sdp_remove_record(int record_handle); +/** + * @brief This function is used to get the status of SDP + * + * @param[out] status - sdp status + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_sdp_get_protocol_status(esp_sdp_protocol_status_t *status); + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/bluedroid/api/include/api/esp_spp_api.h b/lib/bt/host/bluedroid/api/include/api/esp_spp_api.h index d2a0e090..40788667 100644 --- a/lib/bt/host/bluedroid/api/include/api/esp_spp_api.h +++ b/lib/bt/host/bluedroid/api/include/api/esp_spp_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -102,6 +102,13 @@ typedef enum { ESP_SPP_VFS_UNREGISTER_EVT = 37, /*!< When SPP VFS unregister, the event comes */ } esp_spp_cb_event_t; +/** + * @brief SPP profile status parameters + */ +typedef struct { + bool spp_inited; /*!< spp initialization */ + uint8_t conn_num; /*!< Number of connections */ +} esp_spp_profile_status_t; /** * @brief SPP callback parameters union @@ -432,6 +439,17 @@ esp_err_t esp_spp_vfs_register(void); */ esp_err_t esp_spp_vfs_unregister(void); +/** + * @brief This function is used to get the status of SPP + * + * @param[out] profile_status - SPP status + * + * @return + * - ESP_OK: success + * - other: failed + */ +esp_err_t esp_spp_get_profile_status(esp_spp_profile_status_t *profile_status); + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/bluedroid/bta/av/bta_av_aact.c b/lib/bt/host/bluedroid/bta/av/bta_av_aact.c index 26a23958..e75fe818 100644 --- a/lib/bt/host/bluedroid/bta/av/bta_av_aact.c +++ b/lib/bt/host/bluedroid/bta/av/bta_av_aact.c @@ -57,7 +57,7 @@ #define BTA_AV_CLOSE_REQ_TIME_VAL 4000 #endif -/* number to retry on reconfigure failure - some headsets requirs this number to be more than 1 */ +/* number to retry on reconfigure failure - some headsets requires this number to be more than 1 */ #ifndef BTA_AV_RECONFIG_RETRY #define BTA_AV_RECONFIG_RETRY 6 #endif @@ -239,7 +239,7 @@ static UINT8 bta_av_get_scb_handle(tBTA_AV_SCB *p_scb, UINT8 local_sep) return (p_scb->seps[xx].av_handle); } } - APPL_TRACE_DEBUG(" bta_av_get_scb_handle appropiate sep_type not found") + APPL_TRACE_DEBUG(" bta_av_get_scb_handle appropriate sep_type not found") return 0; /* return invalid handle */ } @@ -260,7 +260,7 @@ static UINT8 bta_av_get_scb_sep_type(tBTA_AV_SCB *p_scb, UINT8 tavdt_handle) return (p_scb->seps[xx].tsep); } } - APPL_TRACE_DEBUG(" bta_av_get_scb_sep_type appropiate handle not found") + APPL_TRACE_DEBUG(" bta_av_get_scb_sep_type appropriate handle not found") return 3; /* return invalid sep type */ } @@ -586,9 +586,18 @@ void bta_av_stream_data_cback(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UI osi_free(p_pkt); return; } + + if (p_pkt->offset >= 4) { + /* The offset of avdt packet will always greater than 4, it is safe to add timestamp here */ + *((UINT32 *) (p_pkt + 1)) = time_stamp; + } + else { + APPL_TRACE_WARNING("bta_av_stream_data_cback avdt packet offset small than 4"); + } + p_pkt->event = BTA_AV_MEDIA_DATA_EVT; p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_DATA_EVT, (tBTA_AV_MEDIA *)p_pkt); - osi_free(p_pkt); /* a copy of packet had been delivered, we free this buffer */ + /* packet will be free by upper */ } /******************************************************************************* @@ -843,7 +852,7 @@ void bta_av_role_res (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) bdcpy(av_open.bd_addr, p_scb->peer_addr); av_open.chnl = p_scb->chnl; av_open.hndl = p_scb->hndl; - start.status = BTA_AV_FAIL_ROLE; + av_open.status = BTA_AV_FAIL_ROLE; if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SRC ) { av_open.sep = AVDT_TSEP_SNK; } else if (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK ) { @@ -1138,7 +1147,7 @@ void bta_av_config_ind (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) p_info->media_type = p_scb->media_type; p_info->seid = p_data->str_msg.msg.config_ind.int_seid; - /* Sep type of Peer will be oppsite role to our local sep */ + /* Sep type of Peer will be opposite role to our local sep */ if (local_sep == AVDT_TSEP_SRC) { p_info->tsep = AVDT_TSEP_SNK; } else if (local_sep == AVDT_TSEP_SNK) { @@ -1271,7 +1280,7 @@ void bta_av_setconfig_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) if (AVDT_TSEP_SNK == local_sep) { if ((p_data->ci_setconfig.err_code == AVDT_SUCCESS) && (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL)) { - p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_SINK_CFG_EVT, + p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_CFG_EVT, (tBTA_AV_MEDIA *)p_scb->cfg.codec_info); } if (p_scb->cur_psc_mask & AVDT_PSC_DELAY_RPT) { @@ -1384,7 +1393,7 @@ void bta_av_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) { /* TODO check if other audio channel is open. * If yes, check if reconfig is needed - * Rigt now we do not do this kind of checking. + * Right now we do not do this kind of checking. * BTA-AV is INT for 2nd audio connection. * The application needs to make sure the current codec_info is proper. * If one audio connection is open and another SNK attempts to connect to AV, @@ -1397,6 +1406,7 @@ void bta_av_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) open.status = BTA_AV_SUCCESS; open.starting = bta_av_chk_start(p_scb); open.edr = 0; + open.mtu = mtu; if ( NULL != (p = BTM_ReadRemoteFeatures(p_scb->peer_addr))) { if (HCI_EDR_ACL_2MPS_SUPPORTED(p)) { open.edr |= BTA_AV_EDR_2MBPS; @@ -1533,7 +1543,7 @@ void bta_av_do_close (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL); AVDT_CloseReq(p_scb->avdt_handle); - /* just in case that the link is congested, link is flow controled by peer or + /* just in case that the link is congested, link is flow controlled by peer or * for whatever reason the the close request can not be sent in time. * when this timer expires, AVDT_DisconnectReq will be called to disconnect the link */ @@ -1814,7 +1824,7 @@ void bta_av_open_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) } - /* if there is already an active AV connnection with the same bd_addr, + /* if there is already an active AV connection with the same bd_addr, don't send disconnect req, just report the open event with BTA_AV_FAIL_GET_CAP status */ if (is_av_opened == TRUE) { bdcpy(open.bd_addr, p_scb->peer_addr); @@ -1856,7 +1866,7 @@ void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) tAVDT_CFG cfg; UINT8 media_type; tAVDT_SEP_INFO *p_info = &p_scb->sep_info[p_scb->sep_info_idx]; - UINT16 uuid_int; /* UUID for which connection was initiatied */ + UINT16 uuid_int; /* UUID for which connection was initiated */ tBTA_AV_SNK_PSC_CFG psc_cfg = {0}; memcpy(&cfg, &p_scb->cfg, sizeof(tAVDT_CFG)); @@ -1899,9 +1909,9 @@ void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) p_scb->cur_psc_mask = cfg.psc_mask; if (uuid_int == UUID_SERVCLASS_AUDIO_SINK) { - if (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL) { + if (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL) { APPL_TRACE_DEBUG(" Configure Deoder for Sink Connection "); - p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_SINK_CFG_EVT, + p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_CFG_EVT, (tBTA_AV_MEDIA *)p_scb->cfg.codec_info); } if (p_scb->cur_psc_mask & AVDT_PSC_DELAY_RPT) { @@ -1909,6 +1919,13 @@ void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) } (*bta_av_cb.p_cback)(BTA_AV_SNK_PSC_CFG_EVT, (tBTA_AV *)&psc_cfg); } + else { + /* UUID_SERVCLASS_AUDIO_SOURCE */ + if (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL) { + p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_CFG_EVT, + (tBTA_AV_MEDIA *)p_scb->cfg.codec_info); + } + } /* open the stream */ AVDT_OpenReq(p_scb->seps[p_scb->sep_idx].av_handle, p_scb->peer_addr, @@ -2387,7 +2404,7 @@ void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) { /* If sink starts stream, disable sniff mode here */ if (!initiator) { - /* If souce is the master role, disable role switch during streaming. + /* If source is the master role, disable role switch during streaming. * Otherwise allow role switch, if source is slave. * Because it would not hurt source, if the peer device wants source to be master */ if ((BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS) && @@ -2502,7 +2519,7 @@ void bta_av_str_closed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) bta_av_str_stopped(p_scb, NULL); } - /* Update common mtu shared by remaining connectons */ + /* Update common mtu shared by remaining connections */ mtu = bta_av_chk_mtu(p_scb, BTA_AV_MAX_A2DP_MTU); { diff --git a/lib/bt/host/bluedroid/bta/av/bta_av_act.c b/lib/bt/host/bluedroid/bta/av/bta_av_act.c index 13a57507..1fd59a04 100644 --- a/lib/bt/host/bluedroid/bta/av/bta_av_act.c +++ b/lib/bt/host/bluedroid/bta/av/bta_av_act.c @@ -37,6 +37,10 @@ #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE) #include "bta/bta_ar_api.h" #endif +#if BTA_AV_CA_INCLUDED +#include "stack/goep_common.h" +#include "stack/goepc_api.h" +#endif #define LOG_TAG "bt_bta_av" // #include "osi/include/log.h" @@ -98,6 +102,10 @@ void bta_av_del_rc(tBTA_AV_RCB *p_rcb) p_scb = NULL; if (p_rcb->handle != BTA_AV_RC_HANDLE_NONE) { +#if BTA_AV_CA_INCLUDED + /* reset cover art state */ + bta_av_ca_reset(p_rcb); +#endif if (p_rcb->shdl) { /* Validate array index*/ if ((p_rcb->shdl - 1) < BTA_AV_NUM_STRS) { @@ -127,9 +135,6 @@ void bta_av_del_rc(tBTA_AV_RCB *p_rcb) } /* else ACP && connected. do not clear the handle yet */ AVRC_Close(rc_handle); - if (rc_handle == bta_av_cb.rc_acp_handle) { - bta_av_cb.rc_acp_handle = BTA_AV_RC_HANDLE_NONE; - } APPL_TRACE_EVENT("end del_rc handle: %d status=0x%x, rc_acp_handle:%d, lidx:%d", p_rcb->handle, p_rcb->status, bta_av_cb.rc_acp_handle, p_rcb->lidx); } @@ -302,7 +307,7 @@ UINT8 bta_av_rc_create(tBTA_AV_CB *p_cb, UINT8 role, UINT8 shdl, UINT8 lidx) bda = p_scb->peer_addr; status = BTA_AV_RC_ROLE_INT; } else { - if ((p_rcb = bta_av_get_rcb_by_shdl(shdl)) != NULL ) { + if (shdl != 0 && ((p_rcb = bta_av_get_rcb_by_shdl(shdl)) != NULL)) { APPL_TRACE_ERROR("bta_av_rc_create ACP handle exist for shdl:%d", shdl); return p_rcb->handle; } @@ -1143,7 +1148,7 @@ void bta_av_conn_chg(tBTA_AV_DATA *p_data) p_data->conn_chg.peer_addr[5]); if (p_lcb_rc->conn_msk && bdcmp(p_lcb_rc->addr, p_data->conn_chg.peer_addr) == 0) { /* AVRCP is already connected. - * need to update the association betwen SCB and RCB */ + * need to update the association between SCB and RCB */ p_lcb_rc->conn_msk = 0; /* indicate RC ONLY is not connected */ p_lcb_rc->lidx = 0; p_scb->rc_handle = p_cb->rc_acp_handle; @@ -1484,6 +1489,51 @@ static void bta_av_acp_sig_timer_cback (TIMER_LIST_ENT *p_tle) } } +#if BTA_AV_CA_INCLUDED + +/******************************************************************************* +** +** Function bta_av_extra_tg_cover_art_l2cap_psm +** +** Description Extra the AVRC Cover Art L2CAP PSM of peer device from the +** SDP record +** +** Returns void +** +*******************************************************************************/ +static UINT16 bta_av_extra_tg_cover_art_l2cap_psm(void) +{ + tBTA_AV_CB *p_cb = &bta_av_cb; + tSDP_DISC_REC *p_rec = NULL; + tSDP_DISC_ATTR *p_add_prot_desc, *p_prot_desc; + tSDP_PROTOCOL_ELEM elem_l2cap, elem_obex; + UINT16 l2cap_psm = 0; + + while (TRUE) { + /* get next record; if none found, we're done */ + if ((p_rec = SDP_FindServiceInDb(p_cb->p_disc_db, UUID_SERVCLASS_AV_REM_CTRL_TARGET, p_rec)) == NULL) { + break; + } + + p_add_prot_desc = SDP_FindAttributeInRec(p_rec, ATTR_ID_ADDITION_PROTO_DESC_LISTS); + if ((p_add_prot_desc != NULL) && (SDP_DISC_ATTR_TYPE(p_add_prot_desc->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE)) { + /* Walk through all protocol descriptor list */ + for (p_prot_desc = p_add_prot_desc->attr_value.v.p_sub_attr; p_prot_desc; p_prot_desc = p_prot_desc->p_next_attr) { + if(SDP_FindProtocolListElem(p_prot_desc, UUID_PROTOCOL_L2CAP, &elem_l2cap) + && SDP_FindProtocolListElem(p_prot_desc, UUID_PROTOCOL_OBEX, &elem_obex)) + { + /* found */ + l2cap_psm = elem_l2cap.params[0]; + break; + } + } + } + } + return l2cap_psm; +} + +#endif /* BTA_AV_CA_INCLUDED */ + /******************************************************************************* ** ** Function bta_av_check_peer_rc_features @@ -1539,6 +1589,10 @@ tBTA_AV_FEAT bta_av_check_peer_rc_features (UINT16 service_uuid, UINT16 *rc_feat if (categories & AVRC_SUPF_CT_BROWSE) { peer_features |= (BTA_AV_FEAT_BROWSE); } + if ((service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET) && (categories & AVRC_SUPF_TG_COVER_ART)) { + /* remote target support cover art */ + peer_features |= BTA_AV_FEAT_COVER_ART; + } } } } @@ -1573,6 +1627,9 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data) tBTA_AV_FEAT peer_features; /* peer features mask */ UINT16 peer_ct_features; /* peer features mask as controller */ UINT16 peer_tg_features; /* peer features mask as target */ +#if BTA_AV_CA_INCLUDED + UINT16 obex_l2cap_psm = 0; /* target obex l2cap psm */ +#endif UNUSED(p_data); APPL_TRACE_DEBUG("bta_av_rc_disc_done disc:x%x", p_cb->disc); @@ -1600,7 +1657,11 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data) /* check peer version and whether support CT and TG role */ peer_features = bta_av_check_peer_rc_features (UUID_SERVCLASS_AV_REMOTE_CONTROL, &peer_ct_features); peer_features |= bta_av_check_peer_rc_features (UUID_SERVCLASS_AV_REM_CTRL_TARGET, &peer_tg_features); - +#if BTA_AV_CA_INCLUDED + if (peer_features & BTA_AV_FEAT_COVER_ART) { + obex_l2cap_psm = bta_av_extra_tg_cover_art_l2cap_psm(); + } +#endif p_cb->disc = 0; utl_freebuf((void **) &p_cb->p_disc_db); @@ -1618,6 +1679,9 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data) p_cb->rcb[rc_handle].peer_features = peer_features; p_cb->rcb[rc_handle].peer_ct_features = peer_ct_features; p_cb->rcb[rc_handle].peer_tg_features = peer_tg_features; +#if BTA_AV_CA_INCLUDED + p_cb->rcb[rc_handle].cover_art_l2cap_psm = obex_l2cap_psm; +#endif } #if (BT_USE_TRACES == TRUE || BT_TRACE_APPL == TRUE) else { @@ -1636,6 +1700,11 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data) } } else { p_cb->rcb[rc_handle].peer_features = peer_features; + p_cb->rcb[rc_handle].peer_ct_features = peer_ct_features; + p_cb->rcb[rc_handle].peer_tg_features = peer_tg_features; +#if BTA_AV_CA_INCLUDED + p_cb->rcb[rc_handle].cover_art_l2cap_psm = obex_l2cap_psm; +#endif rc_feat.rc_handle = rc_handle; rc_feat.peer_features = peer_features; rc_feat.peer_ct_features = peer_ct_features; @@ -1676,6 +1745,10 @@ void bta_av_rc_closed(tBTA_AV_DATA *p_data) p_rcb->peer_features = 0; p_rcb->peer_ct_features = 0; p_rcb->peer_tg_features = 0; +#if BTA_AV_CA_INCLUDED + /* reset cover art state */ + bta_av_ca_reset(p_rcb); +#endif APPL_TRACE_DEBUG(" shdl:%d, lidx:%d", p_rcb->shdl, p_rcb->lidx); if (p_rcb->shdl) { if ((p_rcb->shdl - 1) < BTA_AV_NUM_STRS) { @@ -1711,7 +1784,8 @@ void bta_av_rc_closed(tBTA_AV_DATA *p_data) bta_av_del_rc(p_rcb); /* if the AVRCP is no longer listening, create the listening channel */ - if (bta_av_cb.rc_acp_handle == BTA_AV_RC_HANDLE_NONE && bta_av_cb.features & BTA_AV_FEAT_RCTG) { + if (bta_av_cb.rc_acp_handle == p_msg->handle && bta_av_cb.features & BTA_AV_FEAT_RCTG) { + bta_av_cb.rc_acp_handle = BTA_AV_RC_HANDLE_NONE; bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1); } } @@ -1748,6 +1822,7 @@ void bta_av_rc_disc(UINT8 disc) tAVRC_SDP_DB_PARAMS db_params; UINT16 attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST, ATTR_ID_BT_PROFILE_DESC_LIST, + ATTR_ID_ADDITION_PROTO_DESC_LISTS, ATTR_ID_SUPPORTED_FEATURES }; UINT8 hdi; @@ -1785,7 +1860,7 @@ void bta_av_rc_disc(UINT8 disc) if (p_cb->p_disc_db) { /* set up parameters */ db_params.db_len = BTA_AV_DISC_BUF_SIZE; - db_params.num_attr = 3; + db_params.num_attr = 4; db_params.p_db = p_cb->p_disc_db; db_params.p_attrs = attr_list; diff --git a/lib/bt/host/bluedroid/bta/av/bta_av_api.c b/lib/bt/host/bluedroid/bta/av/bta_av_api.c index 01993eec..f62d9efe 100644 --- a/lib/bt/host/bluedroid/bta/av/bta_av_api.c +++ b/lib/bt/host/bluedroid/bta/av/bta_av_api.c @@ -129,6 +129,23 @@ void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name, UINT8 app_id, } } +void BTA_AvRegSEP(tBTA_AV_CHNL chnl, UINT8 seid, UINT8 tsep, tBTA_AV_CODEC codec_type, UINT8 *p_codec_info, tBTA_AV_DATA_CBACK *p_data_cback) +{ + tBTA_AV_API_REG_SEP *p_buf; + + if ((p_buf = (tBTA_AV_API_REG_SEP *) osi_malloc(sizeof(tBTA_AV_API_REG_SEP))) != NULL) { + p_buf->hdr.layer_specific = chnl; + p_buf->hdr.event = BTA_AV_API_REG_SEP_EVT; + + p_buf->seid = seid; + p_buf->tsep = tsep; + p_buf->codec_type = codec_type; + memcpy(p_buf->codec_info, p_codec_info, AVDT_CODEC_SIZE); + p_buf->p_data_cback = p_data_cback; + bta_sys_sendmsg(p_buf); + } +} + /******************************************************************************* ** ** Function BTA_AvDeregister @@ -613,4 +630,77 @@ void BTA_AvMetaCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CMD cmd_code, BT_HDR *p } } +#if BTA_AV_CA_INCLUDED + +/******************************************************************************* +** +** Function BTA_AvCaOpen +** +** Description Open a Cover Art OBEX connection to peer device. This function +** can only be used if peer device TG support Cover Art feature and +** AV is enabled with feature BTA_AV_FEAT_METADATA. +** +** Returns void +** +*******************************************************************************/ +void BTA_AvCaOpen(UINT8 rc_handle, UINT16 mtu) +{ + tBTA_AV_API_CA_OPEN *p_buf; + + if ((p_buf = (tBTA_AV_API_CA_OPEN *) osi_malloc(sizeof(tBTA_AV_API_CA_OPEN))) != NULL) { + p_buf->hdr.event = BTA_AV_API_CA_OPEN_EVT; + p_buf->hdr.layer_specific = rc_handle; + p_buf->mtu = mtu; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_AvCaClose +** +** Description Close a Cover Art OBEX connection. +** +** Returns void +** +*******************************************************************************/ +void BTA_AvCaClose(UINT8 rc_handle) +{ + tBTA_AV_API_CA_CLOSE *p_buf; + + if ((p_buf = (tBTA_AV_API_CA_CLOSE *) osi_malloc(sizeof(tBTA_AV_API_CA_CLOSE))) != NULL) { + p_buf->hdr.event = BTA_AV_API_CA_CLOSE_EVT; + p_buf->hdr.layer_specific = rc_handle; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_AvCaGet +** +** Description Start the process to get image properties, get image or get +** linked thumbnail. This function can only be used if Cover Art +** OBEX connection is established. +** +** Returns void +** +*******************************************************************************/ +void BTA_AvCaGet(UINT8 rc_handle, tBTA_AV_GET_TYPE type, UINT8 *image_handle, UINT8 *image_descriptor, UINT16 image_descriptor_len) +{ + tBTA_AV_API_CA_GET *p_buf; + + if ((p_buf = (tBTA_AV_API_CA_GET *) osi_malloc(sizeof(tBTA_AV_API_CA_GET))) != NULL) { + p_buf->hdr.event = BTA_AV_API_CA_GET_EVT; + p_buf->hdr.layer_specific = rc_handle; + p_buf->type = type; + memcpy(p_buf->image_handle, image_handle, BTA_AV_CA_IMG_HDL_LEN); + p_buf->image_descriptor = image_descriptor; + p_buf->image_descriptor_len = image_descriptor_len; + bta_sys_sendmsg(p_buf); + } +} + +#endif /* BTA_AV_CA_INCLUDED */ + #endif /* BTA_AV_INCLUDED */ diff --git a/lib/bt/host/bluedroid/bta/av/bta_av_ca_act.c b/lib/bt/host/bluedroid/bta/av/bta_av_ca_act.c new file mode 100644 index 00000000..d886f593 --- /dev/null +++ b/lib/bt/host/bluedroid/bta/av/bta_av_ca_act.c @@ -0,0 +1,496 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "common/bt_target.h" +#if BTA_AV_CA_INCLUDED + +#include +#include "bta/bta_av_api.h" +#include "bta_av_int.h" +#include "stack/avdt_api.h" +#include "bta/utl.h" +#include "stack/l2c_api.h" +#include "osi/allocator.h" +#include "osi/list.h" +#include "stack/goep_common.h" +#include "stack/goepc_api.h" +#include "stack/obex_api.h" +#include "common/bt_trace.h" + +#define COVER_ART_HEADER_ID_IMG_HANDLE 0x30 +#define COVER_ART_HEADER_ID_IMG_DESCRIPTOR 0x71 +static const UINT8 cover_art_uuid[16] = {0x71, 0x63, 0xDD, 0x54, 0x4A, 0x7E, 0x11, 0xE2, 0xB4, 0x7C, 0x00, 0x50, 0xC2, 0x49, 0x00, 0x48}; +static const char *cover_art_img_type_img = "x-bt/img-img"; +static const char *cover_art_img_type_thm = "x-bt/img-thm"; +static const char *cover_art_img_type_prop = "x-bt/img-properties"; + +#define COVER_ART_IMG_TYPE_IMG_LEN 13 +#define COVER_ART_IMG_TYPE_THM_LEN 13 +#define COVER_ART_IMG_TYPE_PROP_LEN 20 + + +static BOOLEAN find_rcb_idx_by_goep_handle(UINT16 handle, UINT16 *out_idx) +{ + for (UINT16 i = 0; i < BTA_AV_NUM_RCB; ++i) { + if (bta_av_cb.rcb[i].handle != BTA_AV_RC_HANDLE_NONE && bta_av_cb.rcb[i].cover_art_goep_hdl == handle) { + *out_idx = i; + return TRUE; + } + } + return FALSE; +} + +static UINT8 get_rcb_idx(tBTA_AV_RCB *p_rcb) +{ + return (p_rcb - &bta_av_cb.rcb[0]); +} + +static void get_peer_bd_addr(tBTA_AV_RCB *p_rcb, BD_ADDR out_addr) +{ + /* check if this rcb is related to a scb */ + if (p_rcb->shdl && p_rcb->shdl <= BTA_AV_NUM_STRS) { + tBTA_AV_SCB *p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1]; + bdcpy(out_addr, p_scb->peer_addr); + } + /* else, try get peer addr from lcb */ + else if (p_rcb->lidx && p_rcb->lidx <= BTA_AV_NUM_LINKS + 1) + { + bdcpy(out_addr, bta_av_cb.lcb[p_rcb->lidx-1].addr); + } +} + +static void report_data_event(BT_HDR *pkt, UINT8 *p_data, UINT16 data_len, BOOLEAN final) +{ + tBTA_AV_CA_DATA ca_data; + ca_data.status = BT_STATUS_SUCCESS; + ca_data.final = final; + ca_data.data_len = data_len; + ca_data.p_data = p_data; + ca_data.p_hdr = pkt; + (*bta_av_cb.p_cback)(BTA_AV_CA_DATA_EVT, (tBTA_AV *) &ca_data); +} + +static void report_error_data_event(UINT16 status) +{ + tBTA_AV_CA_DATA ca_data; + ca_data.status = status; + ca_data.final = TRUE; + ca_data.data_len = 0; + ca_data.p_data = NULL; + ca_data.p_hdr = NULL; + (*bta_av_cb.p_cback)(BTA_AV_CA_DATA_EVT, (tBTA_AV *) &ca_data); +} + +static void build_and_send_connect_req(tBTA_AV_RCB *p_rcb) +{ + tOBEX_PARSE_INFO info = {0}; + info.opcode = OBEX_OPCODE_CONNECT; + info.obex_version_number = 0x15; + info.max_packet_length = p_rcb->cover_art_max_rx; + /* before OBEX connect response, we dont know cover_art_max_tx, use BT_SMALL_BUFFER_SIZE as tx buff size */ + if (GOEPC_PrepareRequest(p_rcb->cover_art_goep_hdl, &info, BT_SMALL_BUFFER_SIZE) == GOEP_SUCCESS) { + GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, OBEX_HEADER_ID_TARGET, (UINT8 *)cover_art_uuid, 16); + GOEPC_SendRequest(p_rcb->cover_art_goep_hdl); + } +} + +static void build_and_send_disconnect_req(tBTA_AV_RCB *p_rcb) +{ + tOBEX_PARSE_INFO info = {0}; + info.opcode = OBEX_OPCODE_DISCONNECT; + if (GOEPC_PrepareRequest(p_rcb->cover_art_goep_hdl, &info, BT_SMALL_BUFFER_SIZE) == GOEP_SUCCESS) { + GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, OBEX_HEADER_ID_CONNECTION_ID, (UINT8 *)(&p_rcb->cover_art_cid), 4); + GOEPC_SendRequest(p_rcb->cover_art_goep_hdl); + } +} + +static void build_and_send_empty_get_req(tBTA_AV_RCB *p_rcb) +{ + tOBEX_PARSE_INFO info = {0}; + info.opcode = OBEX_OPCODE_GET_FINAL; + /* empty get request, use a small buff size */ + UINT16 tx_buff_size = BT_SMALL_BUFFER_SIZE < p_rcb->cover_art_max_tx ? BT_SMALL_BUFFER_SIZE : p_rcb->cover_art_max_tx; + if (GOEPC_PrepareRequest(p_rcb->cover_art_goep_hdl, &info, tx_buff_size) == GOEP_SUCCESS) { + GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, OBEX_HEADER_ID_CONNECTION_ID, (UINT8 *)(&p_rcb->cover_art_cid), 4); + GOEPC_SendRequest(p_rcb->cover_art_goep_hdl); + } +} + +static void close_goepc_and_disconnect(tBTA_AV_RCB *p_rcb) +{ + if (p_rcb->cover_art_goep_hdl) { + GOEPC_Close(p_rcb->cover_art_goep_hdl); + } + p_rcb->cover_art_goep_hdl = 0; + p_rcb->cover_art_cid = 0; + p_rcb->cover_art_max_tx = 0; + p_rcb->cover_art_max_rx = 0; + + tBTA_AV_DATA *p_data = (tBTA_AV_DATA *) osi_malloc(sizeof(tBTA_AV_DATA)); + if (p_data == NULL) { + assert(0); + } + p_data->hdr.event = BTA_AV_CA_GOEP_DISCONNECT_EVT; + p_data->hdr.layer_specific = get_rcb_idx(p_rcb); + p_data->ca_disconnect.reason = BT_STATUS_FAIL; + bta_sys_sendmsg(p_data); +} + +static void image_handle_to_utf16(const UINT8 *image_handle, UINT8 *buffer) +{ + UINT8 pos = 0; + for (int i = 0 ; i < BTA_AV_CA_IMG_HDL_LEN ; i++){ + buffer[pos++] = 0; + buffer[pos++] = image_handle[i]; + } + buffer[pos++] = 0; + buffer[pos++] = 0; +} + +void bta_av_ca_goep_event_handler(UINT16 handle, UINT8 event, tGOEPC_MSG *p_msg) +{ + tBTA_AV_DATA *p_data = NULL; + UINT16 rcb_idx; + if (!find_rcb_idx_by_goep_handle(handle, &rcb_idx)) { + /* can not find a rcb, go error */ + goto error; + } + + if (event == GOEPC_RESPONSE_EVT || event == GOEPC_OPENED_EVT || event == GOEPC_CLOSED_EVT) { + p_data = (tBTA_AV_DATA *) osi_malloc(sizeof(tBTA_AV_DATA)); + assert(p_data != NULL); + } + + switch (event) + { + case GOEPC_OPENED_EVT: + p_data->hdr.layer_specific = rcb_idx; + p_data->hdr.event = BTA_AV_CA_GOEP_CONNECT_EVT; + p_data->ca_connect.max_rx = p_msg->opened.our_mtu; + break; + case GOEPC_CLOSED_EVT: + p_data->hdr.layer_specific = rcb_idx; + p_data->hdr.event = BTA_AV_CA_GOEP_DISCONNECT_EVT; + p_data->ca_disconnect.reason = BT_STATUS_FAIL; + break; + case GOEPC_RESPONSE_EVT: + p_data->hdr.layer_specific = rcb_idx; + p_data->ca_response.pkt = p_msg->response.pkt; + p_data->ca_response.opcode = p_msg->response.opcode; + p_data->ca_response.srm_en = p_msg->response.srm_en; + p_data->ca_response.srm_wait = p_msg->response.srm_wait; + if (p_msg->response.final) { + p_data->hdr.event = BTA_AV_CA_RESPONSE_FINAL_EVT; + } + else { + p_data->hdr.event = BTA_AV_CA_RESPONSE_EVT; + } + break; + case GOEPC_MTU_CHANGED_EVT: + case GOEPC_CONGEST_EVT: + case GOEPC_UNCONGEST_EVT: + /* ignore these event */ + break; + default: + goto error; + break; + } + if (p_data) { + bta_sys_sendmsg(p_data); + } + return; + +error: + /* can not find rcb, just free resource and disconnect */ + if (p_data != NULL) { + osi_free(p_data); + } + if (event == GOEPC_RESPONSE_EVT && p_msg->response.pkt != NULL) { + osi_free(p_msg->response.pkt); + } + if (event != GOEPC_CLOSED_EVT) { + GOEPC_Close(handle); + } +} + +void bta_av_ca_api_open(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data) +{ + tOBEX_SVR_INFO svr = {0}; + svr.tl = OBEX_OVER_L2CAP; + svr.l2cap.psm = p_rcb->cover_art_l2cap_psm; + svr.l2cap.pref_mtu = p_data->api_ca_open.mtu; + /* reuse the security mask store in bta_av_cb, when support multi connection, this may need change */ + svr.l2cap.sec_mask = bta_av_cb.sec_mask; + p_rcb->cover_art_max_rx = p_data->api_ca_open.mtu; + get_peer_bd_addr(p_rcb, svr.l2cap.addr); + + if (GOEPC_Open(&svr, bta_av_ca_goep_event_handler, &p_rcb->cover_art_goep_hdl) != GOEP_SUCCESS) { + /* open failed */ + if ((p_data = (tBTA_AV_DATA *) osi_malloc(sizeof(tBTA_AV_DATA))) == NULL) { + assert(0); + } + p_data->hdr.event = BTA_AV_CA_GOEP_DISCONNECT_EVT; + p_data->hdr.layer_specific = get_rcb_idx(p_rcb); + p_data->ca_disconnect.reason = BT_STATUS_FAIL; + bta_sys_sendmsg(p_data); + } +} + +void bta_av_ca_api_close(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data) +{ + /* this is a normal disconnect, just build and send OBEX disconnect request */ + build_and_send_disconnect_req(p_rcb); +} + +void bta_av_ca_api_get(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data) +{ + tOBEX_PARSE_INFO info = {0}; + UINT8 image_handle_utf16[BTA_AV_CA_IMG_HDL_UTF16_LEN]; + info.opcode = OBEX_OPCODE_GET_FINAL; + /* limit the tx buff size to BT_DEFAULT_BUFFER_SIZE */ + UINT16 tx_buff_size = BT_DEFAULT_BUFFER_SIZE < p_rcb->cover_art_max_tx ? BT_DEFAULT_BUFFER_SIZE : p_rcb->cover_art_max_tx; + if (GOEPC_PrepareRequest(p_rcb->cover_art_goep_hdl, &info, tx_buff_size) != GOEP_SUCCESS) { + /* something error */ + goto error; + } + + GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, OBEX_HEADER_ID_CONNECTION_ID, (UINT8 *)(&p_rcb->cover_art_cid), 4); + switch (p_data->api_ca_get.type) + { + case BTA_AV_CA_GET_IMAGE_PROPERTIES: + GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, OBEX_HEADER_ID_TYPE, (const UINT8 *)cover_art_img_type_prop, COVER_ART_IMG_TYPE_PROP_LEN); + break; + case BTA_AV_CA_GET_IMAGE: + GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, OBEX_HEADER_ID_TYPE, (const UINT8 *)cover_art_img_type_img, COVER_ART_IMG_TYPE_IMG_LEN); + break; + case BTA_AV_CA_GET_LINKED_THUMBNAIL: + GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, OBEX_HEADER_ID_TYPE, (const UINT8 *)cover_art_img_type_thm, COVER_ART_IMG_TYPE_THM_LEN); + break; + default: + /* should not go here */ + assert(0); + break; + } + image_handle_to_utf16(p_data->api_ca_get.image_handle, image_handle_utf16); + GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, COVER_ART_HEADER_ID_IMG_HANDLE, (UINT8 *)image_handle_utf16, BTA_AV_CA_IMG_HDL_UTF16_LEN); + if (p_data->api_ca_get.type == BTA_AV_CA_GET_IMAGE) { + GOEPC_RequestAddHeader(p_rcb->cover_art_goep_hdl, COVER_ART_HEADER_ID_IMG_DESCRIPTOR, (UINT8 *)p_data->api_ca_get.image_descriptor, p_data->api_ca_get.image_descriptor_len); + osi_free(p_data->api_ca_get.image_descriptor); + } + /* always request to enable srm */ + GOEPC_RequestSetSRM(p_rcb->cover_art_goep_hdl, TRUE, FALSE); + + if (GOEPC_SendRequest(p_rcb->cover_art_goep_hdl) != GOEP_SUCCESS) { + goto error; + } + return; +error: + close_goepc_and_disconnect(p_rcb); +} + +void bta_av_ca_response(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data) +{ + tOBEX_PARSE_INFO info; + OBEX_ParseResponse(p_data->ca_response.pkt, p_data->ca_response.opcode, &info); + /* we always use a final get */ + if (p_data->ca_response.opcode == OBEX_OPCODE_GET_FINAL + && (info.response_code == OBEX_RESPONSE_CODE_CONTINUE || info.response_code == (OBEX_RESPONSE_CODE_CONTINUE | OBEX_FINAL_BIT_MASK))) + { + UINT8 *header = NULL; + UINT8 *body_data = NULL; + UINT16 body_data_len = 0; + while((header = OBEX_GetNextHeader(p_data->ca_response.pkt, &info)) != NULL) { + switch (*header) + { + case OBEX_HEADER_ID_BODY: + /* actually,END_OF_BODY should not in this continue response */ + case OBEX_HEADER_ID_END_OF_BODY: + if (body_data == NULL) { + /* first body header */ + body_data = header + 3; /* skip opcode, length */ + body_data_len = OBEX_GetHeaderLength(header) - 3; + } + else { + /* another body header found */ + report_data_event(NULL, body_data, body_data_len, FALSE); + body_data = header + 3; /* skip opcode, length */ + body_data_len = OBEX_GetHeaderLength(header) - 3; + } + break; + default: + break; + } + } + if (body_data != NULL) { + /* the only one or the last body data */ + report_data_event(p_data->ca_response.pkt, body_data, body_data_len, FALSE); + } + else { + /* not any body data */ + osi_free(p_data->ca_response.pkt); + } + + /* if SRM not enable, we need to send a empty get request */ + if (!p_data->ca_response.srm_en || p_data->ca_response.srm_wait) { + build_and_send_empty_get_req(p_rcb); + } + } + else { + osi_free(p_data->ca_response.pkt); + goto error; + } + return; + +error: + close_goepc_and_disconnect(p_rcb); +} + +void bta_av_ca_response_final(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data) +{ + tOBEX_PARSE_INFO info; + OBEX_ParseResponse(p_data->ca_response.pkt, p_data->ca_response.opcode, &info); + UINT8 *header = NULL; + if (p_data->ca_response.opcode == OBEX_OPCODE_CONNECT) { + /* we expect a success response code with final bit set */ + if (info.response_code == (OBEX_RESPONSE_CODE_OK | OBEX_FINAL_BIT_MASK)) { + if (info.max_packet_length < 255) { + p_rcb->cover_art_max_tx = 255; + } + else { + p_rcb->cover_art_max_tx = info.max_packet_length; + } + BOOLEAN cid_found = false; + while((header = OBEX_GetNextHeader(p_data->ca_response.pkt, &info)) != NULL) { + if (*header == OBEX_HEADER_ID_CONNECTION_ID) { + cid_found = true; + memcpy((UINT8 *)(&p_rcb->cover_art_cid), header + 1, 4); + break; + } + } + if (!cid_found) { + goto error; + } + tBTA_AV_CA_STATUS ca_status; + ca_status.connected = TRUE; + ca_status.reason = BT_STATUS_SUCCESS; + (*bta_av_cb.p_cback)(BTA_AV_CA_STATUS_EVT, (tBTA_AV *) &ca_status); + /* done, free response packet */ + osi_free(p_data->ca_response.pkt); + } + else { + osi_free(p_data->ca_response.pkt); + goto error; + } + } + else if (p_data->ca_response.opcode == OBEX_OPCODE_GET_FINAL) { + UINT8 *body_data = NULL; + UINT16 body_data_len = 0; + /* check response code is success */ + if (info.response_code == (OBEX_RESPONSE_CODE_OK | OBEX_FINAL_BIT_MASK)) { + while((header = OBEX_GetNextHeader(p_data->ca_response.pkt, &info)) != NULL) { + switch (*header) + { + /* actually, BODY should not in this final response */ + case OBEX_HEADER_ID_BODY: + case OBEX_HEADER_ID_END_OF_BODY: + if (body_data == NULL) { + /* first body header */ + body_data = header + 3; /* skip opcode, length */ + body_data_len = OBEX_GetHeaderLength(header) - 3; + } + else { + /* another body header found */ + report_data_event(NULL, body_data, body_data_len, FALSE); + body_data = header + 3; /* skip opcode, length */ + body_data_len = OBEX_GetHeaderLength(header) - 3; + } + break; + default: + break; + } + } + if (body_data != NULL) { + /* the only one or the last body data, packet will be free by upper layer */ + report_data_event(p_data->ca_response.pkt, body_data, body_data_len, TRUE); + } + else { + /* not any body data */ + osi_free(p_data->ca_response.pkt); + } + } + else { + report_error_data_event(BT_STATUS_FAIL); + osi_free(p_data->ca_response.pkt); + } + } + else if (p_data->ca_response.opcode == OBEX_OPCODE_DISCONNECT) { + /* received disconnect response, close l2cap channel and reset cover art value */ + bta_av_ca_force_disconnect(p_rcb, p_data); + osi_free(p_data->ca_response.pkt); + } + else { + osi_free(p_data->ca_response.pkt); + goto error; + } + return; + +error: + close_goepc_and_disconnect(p_rcb); +} + +void bta_av_ca_goep_connect(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data) +{ + /* goep connection open, use a smaller value as max_rx */ + if (p_rcb->cover_art_max_rx > p_data->ca_connect.max_rx) { + p_rcb->cover_art_max_rx = p_data->ca_connect.max_rx; + } + build_and_send_connect_req(p_rcb); +} + +void bta_av_ca_goep_disconnect(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data) +{ + p_rcb->cover_art_goep_hdl = 0; + p_rcb->cover_art_max_rx = 0; + p_rcb->cover_art_max_tx = 0; + p_rcb->cover_art_cid = 0; + + tBTA_AV_CA_STATUS ca_status; + ca_status.connected = FALSE; + ca_status.reason = p_data->ca_disconnect.reason; + (*bta_av_cb.p_cback)(BTA_AV_CA_STATUS_EVT, (tBTA_AV *) &ca_status); +} + +void bta_av_ca_force_disconnect(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data) +{ + if (p_rcb->cover_art_goep_hdl) { + GOEPC_Close(p_rcb->cover_art_goep_hdl); + } + /* dont reset p_rcb->cover_art_l2cap_psm */ + p_rcb->cover_art_goep_hdl = 0; + p_rcb->cover_art_cid = 0; + p_rcb->cover_art_max_tx = 0; + p_rcb->cover_art_max_rx = 0; + tBTA_AV_CA_STATUS ca_status; + ca_status.connected = FALSE; + /* force disconnect by upper, set reason to success */ + ca_status.reason = BT_STATUS_SUCCESS; + (*bta_av_cb.p_cback)(BTA_AV_CA_STATUS_EVT, (tBTA_AV *) &ca_status); +} + +void bta_av_ca_reset(tBTA_AV_RCB *p_rcb) +{ + if (p_rcb->cover_art_goep_hdl) { + GOEPC_Close(p_rcb->cover_art_goep_hdl); + } + p_rcb->cover_art_l2cap_psm = 0; + p_rcb->cover_art_goep_hdl = 0; + p_rcb->cover_art_state = 0; + p_rcb->cover_art_cid = 0; + p_rcb->cover_art_max_tx = 0; + p_rcb->cover_art_max_rx = 0; +} + +#endif /* BTA_AV_CA_INCLUDED */ diff --git a/lib/bt/host/bluedroid/bta/av/bta_av_ca_sm.c b/lib/bt/host/bluedroid/bta/av/bta_av_ca_sm.c new file mode 100644 index 00000000..4a9d4e7c --- /dev/null +++ b/lib/bt/host/bluedroid/bta/av/bta_av_ca_sm.c @@ -0,0 +1,170 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "common/bt_target.h" +#if BTA_AV_CA_INCLUDED + +#include +#include "bta/bta_av_api.h" +#include "bta_av_int.h" +#include "stack/avdt_api.h" +#include "bta/utl.h" +#include "stack/l2c_api.h" +#include "osi/allocator.h" +#include "osi/list.h" + +#include "common/bt_trace.h" + +/* state machine states */ +enum { + BTA_AV_CA_INIT_ST, + BTA_AV_CA_OPENING_ST, + BTA_AV_CA_CONNECTING_ST, + BTA_AV_CA_CONNECTED_ST, + BTA_AV_CA_GETTING_ST, + BTA_AV_CA_CLOSING_ST +}; + +/* state machine action enumeration list */ +enum { + BTA_AV_API_CA_OPEN, + BTA_AV_API_CA_CLOSE, + BTA_AV_API_CA_GET, + BTA_AV_CA_RESPONSE, + BTA_AV_CA_RESPONSE_FINAL, + BTA_AV_CA_GOEP_CONNECT, + BTA_AV_CA_GOEP_DISCONNECT, + BTA_AV_CA_FORCE_DISCONNECT, + BTA_AV_CA_NUM_ACTIONS +}; + +#define BTA_AV_CA_IGNORE BTA_AV_CA_NUM_ACTIONS + +/* type for action functions */ +typedef void (*tBTA_AV_CA_ACTION)(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data); + +/* action functions */ +const tBTA_AV_CA_ACTION bta_av_ca_action[] = { + bta_av_ca_api_open, + bta_av_ca_api_close, + bta_av_ca_api_get, + bta_av_ca_response, + bta_av_ca_response_final, + bta_av_ca_goep_connect, + bta_av_ca_goep_disconnect, + bta_av_ca_force_disconnect, + NULL +}; + +/* state table information */ +#define BTA_AV_CA_ACTION_COL 0 /* position of actions */ +#define BTA_AV_CA_NEXT_STATE 1 /* position of next state */ +#define BTA_AV_CA_NUM_COLS 2 /* number of columns in state tables */ + +/* state table for init state */ +static const UINT8 bta_av_ca_st_init[][BTA_AV_CA_NUM_COLS] = { + /* Event Action 1 Next state */ + /* API_CA_OPEN_EVT */ {BTA_AV_API_CA_OPEN, BTA_AV_CA_OPENING_ST }, + /* API_CA_CLOSE_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_INIT_ST }, + /* API_CA_GET_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_INIT_ST }, + /* CA_RESPONSE_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_INIT_ST }, + /* CA_RESPONSE_FINAL_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_INIT_ST }, + /* CA_GOEP_CONNECT_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_INIT_ST }, + /* CA_GOEP_DISCONNECT_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_INIT_ST }, +}; + +/* state table for opening state */ +static const UINT8 bta_av_ca_st_opening[][BTA_AV_CA_NUM_COLS] = { + /* Event Action 1 Next state */ + /* API_CA_OPEN_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_OPENING_ST }, + /* API_CA_CLOSE_EVT */ {BTA_AV_CA_FORCE_DISCONNECT, BTA_AV_CA_INIT_ST }, + /* API_CA_GET_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_OPENING_ST }, + /* CA_RESPONSE_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_OPENING_ST }, + /* CA_RESPONSE_FINAL_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_OPENING_ST }, + /* CA_GOEP_CONNECT_EVT */ {BTA_AV_CA_GOEP_CONNECT, BTA_AV_CA_CONNECTING_ST }, + /* CA_GOEP_DISCONNECT_EVT */ {BTA_AV_CA_GOEP_DISCONNECT, BTA_AV_CA_INIT_ST }, +}; + +/* state table for connecting state */ +static const UINT8 bta_av_ca_st_connecting[][BTA_AV_CA_NUM_COLS] = { + /* Event Action 1 Next state */ + /* API_CA_OPEN_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTING_ST }, + /* API_CA_CLOSE_EVT */ {BTA_AV_CA_FORCE_DISCONNECT, BTA_AV_CA_INIT_ST }, + /* API_CA_GET_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTING_ST }, + /* CA_RESPONSE_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTING_ST }, + /* CA_RESPONSE_FINAL_EVT */ {BTA_AV_CA_RESPONSE_FINAL, BTA_AV_CA_CONNECTED_ST }, + /* CA_GOEP_CONNECT_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTING_ST }, + /* CA_GOEP_DISCONNECT_EVT */ {BTA_AV_CA_GOEP_DISCONNECT, BTA_AV_CA_INIT_ST }, +}; + +/* state table for connected state */ +static const UINT8 bta_av_ca_st_connected[][BTA_AV_CA_NUM_COLS] = { + /* Event Action 1 Next state */ + /* API_CA_OPEN_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTED_ST }, + /* API_CA_CLOSE_EVT */ {BTA_AV_API_CA_CLOSE, BTA_AV_CA_CLOSING_ST }, + /* API_CA_GET_EVT */ {BTA_AV_API_CA_GET, BTA_AV_CA_GETTING_ST }, + /* CA_RESPONSE_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTED_ST }, + /* CA_RESPONSE_FINAL_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTED_ST }, + /* CA_GOEP_CONNECT_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CONNECTED_ST }, + /* CA_GOEP_DISCONNECT_EVT */ {BTA_AV_CA_GOEP_DISCONNECT, BTA_AV_CA_INIT_ST }, +}; + +/* state table for getting state */ +static const UINT8 bta_av_ca_st_getting[][BTA_AV_CA_NUM_COLS] = { + /* Event Action 1 Next state */ + /* API_CA_OPEN_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_GETTING_ST }, + /* API_CA_CLOSE_EVT */ {BTA_AV_CA_FORCE_DISCONNECT, BTA_AV_CA_INIT_ST }, + /* API_CA_GET_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_GETTING_ST }, + /* CA_RESPONSE_EVT */ {BTA_AV_CA_RESPONSE, BTA_AV_CA_GETTING_ST }, + /* CA_RESPONSE_FINAL_EVT */ {BTA_AV_CA_RESPONSE_FINAL, BTA_AV_CA_CONNECTED_ST }, + /* CA_GOEP_CONNECT_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_GETTING_ST }, + /* CA_GOEP_DISCONNECT_EVT */ {BTA_AV_CA_GOEP_DISCONNECT, BTA_AV_CA_INIT_ST }, +}; + +/* state table for closing state */ +static const UINT8 bta_av_ca_st_closing[][BTA_AV_CA_NUM_COLS] = { + /* Event Action 1 Next state */ + /* API_CA_OPEN_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CLOSING_ST }, + /* API_CA_CLOSE_EVT */ {BTA_AV_CA_FORCE_DISCONNECT, BTA_AV_CA_INIT_ST }, + /* API_CA_GET_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CLOSING_ST }, + /* CA_RESPONSE_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CLOSING_ST }, + /* CA_RESPONSE_FINAL_EVT */ {BTA_AV_CA_RESPONSE_FINAL, BTA_AV_CA_INIT_ST }, + /* CA_GOEP_CONNECT_EVT */ {BTA_AV_CA_IGNORE, BTA_AV_CA_CLOSING_ST }, + /* CA_GOEP_DISCONNECT_EVT */ {BTA_AV_CA_GOEP_DISCONNECT, BTA_AV_CA_INIT_ST }, +}; + +/* type for state table */ +typedef const UINT8 (*tBTA_AV_CA_ST_TBL)[BTA_AV_CA_NUM_COLS]; + +/* state table */ +static const tBTA_AV_CA_ST_TBL bta_av_ca_st_tbl[] = { + bta_av_ca_st_init, + bta_av_ca_st_opening, + bta_av_ca_st_connecting, + bta_av_ca_st_connected, + bta_av_ca_st_getting, + bta_av_ca_st_closing +}; + +void bta_av_ca_sm_execute(tBTA_AV_RCB *p_rcb, UINT16 event, tBTA_AV_DATA *p_data) +{ + tBTA_AV_CA_ST_TBL state_table; + UINT8 action; + /* look up the state table for the current state */ + state_table = bta_av_ca_st_tbl[p_rcb->cover_art_state]; + + event -= BTA_AV_CA_FIRST_SM_EVT; + + /* set next state */ + p_rcb->cover_art_state = state_table[event][BTA_AV_CA_NEXT_STATE]; + + /* execute action functions */ + if ((action = state_table[event][BTA_AV_CA_ACTION_COL]) != BTA_AV_CA_IGNORE) { + (*bta_av_ca_action[action])(p_rcb, p_data); + } +} + +#endif /* BTA_AV_CA_INCLUDED */ diff --git a/lib/bt/host/bluedroid/bta/av/bta_av_main.c b/lib/bt/host/bluedroid/bta/av/bta_av_main.c index 2fde06f6..7ccd3423 100644 --- a/lib/bt/host/bluedroid/bta/av/bta_av_main.c +++ b/lib/bt/host/bluedroid/bta/av/bta_av_main.c @@ -151,6 +151,7 @@ static const tBTA_AV_ST_TBL bta_av_st_tbl[] = { typedef void (*tBTA_AV_NSM_ACT)(tBTA_AV_DATA *p_data); static void bta_av_api_enable(tBTA_AV_DATA *p_data); static void bta_av_api_register(tBTA_AV_DATA *p_data); +static void bta_av_api_reg_sep(tBTA_AV_DATA *p_data); #if (BTA_AV_SINK_INCLUDED == TRUE) static void bta_av_api_sink_enable(tBTA_AV_DATA *p_data); static void bta_av_api_get_delay_value(tBTA_AV_DATA *p_data); @@ -170,6 +171,7 @@ static void bta_av_sys_rs_cback (tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 ap const tBTA_AV_NSM_ACT bta_av_nsm_act[] = { bta_av_api_enable, /* BTA_AV_API_ENABLE_EVT */ bta_av_api_register, /* BTA_AV_API_REGISTER_EVT */ + bta_av_api_reg_sep, /* BTA_AV_API_REG_SEP_EVT */ bta_av_api_deregister, /* BTA_AV_API_DEREGISTER_EVT */ bta_av_api_disconnect, /* BTA_AV_API_DISCONNECT_EVT */ bta_av_ci_data, /* BTA_AV_CI_SRC_DATA_READY_EVT */ @@ -461,7 +463,7 @@ static void bta_av_a2dp_report_cback(UINT8 handle, AVDT_REPORT_TYPE type, ** ** Function bta_av_api_sink_enable ** -** Description activate, deactive A2DP Sink, +** Description activate, deactivate A2DP Sink, ** ** Returns void ** @@ -533,9 +535,11 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data) tAVDT_REG reg; tAVDT_CS cs; char *p_service_name; - tBTA_AV_CODEC codec_type; tBTA_UTL_COD cod; +#if (BTA_AV_EXT_CODEC == FALSE) + tBTA_AV_CODEC codec_type; UINT8 index = 0; +#endif char p_avk_service_name[BTA_SERVICE_NAME_LEN + 1]; BCM_STRNCPY_S(p_avk_service_name, BTIF_AVK_SERVICE_NAME, BTA_SERVICE_NAME_LEN); p_avk_service_name[BTA_SERVICE_NAME_LEN] = '\0'; @@ -593,7 +597,7 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data) #endif } - /* Set the Calss of Device (Audio & Capturing/Rendering service class bit) */ + /* Set the Class of Device (Audio & Capturing/Rendering service class bit) */ if (p_data->api_reg.tsep == AVDT_TSEP_SRC) { cod.service = BTM_COD_SERVICE_CAPTURING | BTM_COD_SERVICE_AUDIO; cod.major = BTM_COD_MAJOR_AUDIO; @@ -658,6 +662,7 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data) /* keep the configuration in the stream control block */ memcpy(&p_scb->cfg, &cs.cfg, sizeof(tAVDT_CFG)); +#if (BTA_AV_EXT_CODEC == FALSE) while (index < BTA_AV_MAX_SEPS && (p_scb->p_cos->init)(&codec_type, cs.cfg.codec_info, &cs.cfg.num_protect, cs.cfg.protect_info, p_data->api_reg.tsep) == TRUE) { @@ -673,12 +678,13 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data) #if (BTA_AV_SINK_INCLUDED == TRUE) p_scb->seps[index].tsep = cs.tsep; - if (cs.tsep == AVDT_TSEP_SNK) { - p_scb->seps[index].p_app_data_cback = p_data->api_reg.p_app_data_cback; - } else { - p_scb->seps[index].p_app_data_cback = NULL; /* In case of A2DP SOURCE we don't need a callback to handle media packets */ - } + // if (cs.tsep == AVDT_TSEP_SNK) { + // p_scb->seps[index].p_app_data_cback = p_data->api_reg.p_app_data_cback; + // } else { + // p_scb->seps[index].p_app_data_cback = NULL; /* In case of A2DP SOURCE we don't need a callback to handle media packets */ + // } #endif + p_scb->seps[index].p_app_data_cback = p_data->api_reg.p_app_data_cback; APPL_TRACE_DEBUG("audio[%d] av_handle: %d codec_type: %d\n", index, p_scb->seps[index].av_handle, p_scb->seps[index].codec_type); @@ -687,6 +693,7 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data) break; } } +#endif if (!bta_av_cb.reg_audio) { if (p_data->api_reg.tsep == AVDT_TSEP_SRC) { @@ -744,6 +751,86 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data) (*bta_av_cb.p_cback)(BTA_AV_REGISTER_EVT, (tBTA_AV *)®istr); } +static void bta_av_api_reg_sep(tBTA_AV_DATA *p_data) +{ + UNUSED(p_data); +#if (BTA_AV_EXT_CODEC == TRUE) + tAVDT_CS cs; + tBTA_AV_CODEC codec_type; + UINT8 index = p_data->api_reg_sep.seid; + tBTA_AV_SEP_REG sep_reg; + + sep_reg.seid = p_data->api_reg_sep.seid; + sep_reg.reg_state = BTA_AV_FAIL; + + if (index > BTA_AV_MAX_SEPS || p_data->hdr.layer_specific != BTA_AV_CHNL_AUDIO) { + (*bta_av_cb.p_cback)(BTA_AV_SEP_REG_EVT, (tBTA_AV *)&sep_reg); + APPL_TRACE_WARNING("%s invalid parameter: seid %d, ch %d", __FUNCTION__, index, p_data->hdr.layer_specific); + return; + } + + memset(&cs, 0, sizeof(tAVDT_CS)); + cs.cfg.num_codec = 1; + cs.tsep = p_data->api_reg_sep.tsep; + cs.nsc_mask = AVDT_NSC_RECONFIG | ((bta_av_cb.features & BTA_AV_FEAT_PROTECT) ? 0 : AVDT_NSC_SECURITY); + + for (int xx = 0; xx < BTA_AV_NUM_STRS; xx++) { + if (bta_av_cb.p_scb[xx] != NULL && bta_av_cb.p_scb[xx]->chnl == BTA_AV_CHNL_AUDIO) { + tBTA_AV_SCB *p_scb = bta_av_cb.p_scb[xx]; + cs.p_ctrl_cback = bta_av_dt_cback[p_scb->hdi]; + cs.cfg.psc_mask = AVDT_PSC_TRANS; + cs.media_type = AVDT_MEDIA_AUDIO; + cs.mtu = p_bta_av_cfg->audio_mtu; + cs.flush_to = L2CAP_DEFAULT_FLUSH_TO; + +#if AVDT_REPORTING == TRUE + if (bta_av_cb.features & BTA_AV_FEAT_REPORT) { + cs.cfg.psc_mask |= AVDT_PSC_REPORT; + cs.p_report_cback = bta_av_a2dp_report_cback; +#if AVDT_MULTIPLEXING == TRUE + cs.cfg.mux_tsid_report = 2; +#endif + } +#endif + if (bta_av_cb.features & BTA_AV_FEAT_DELAY_RPT) { + cs.cfg.psc_mask |= AVDT_PSC_DELAY_RPT; + } + /* todo: check whether this memcpy is necessary */ + memcpy(&p_scb->cfg, &cs.cfg, sizeof(tAVDT_CFG)); + + codec_type = p_data->api_reg_sep.codec_type; + memcpy(cs.cfg.codec_info, p_data->api_reg_sep.codec_info, AVDT_CODEC_SIZE); + if ((p_scb->p_cos->init)(&codec_type, cs.cfg.codec_info, + &cs.cfg.num_protect, cs.cfg.protect_info, p_data->api_reg_sep.tsep) == TRUE) { + +#if (BTA_AV_SINK_INCLUDED == TRUE) + if (p_data->api_reg_sep.tsep == AVDT_TSEP_SNK) { + cs.p_data_cback = bta_av_stream_data_cback; + } +#endif + if ((p_scb->seps[index].av_handle != 0) && (AVDT_RemoveStream(p_scb->seps[index].av_handle) != AVDT_SUCCESS)) { + APPL_TRACE_WARNING("%s fail to remove exist sep", __FUNCTION__); + } + if (AVDT_CreateStream(&p_scb->seps[index].av_handle, &cs) == AVDT_SUCCESS) { + p_scb->seps[index].codec_type = codec_type; + p_scb->seps[index].tsep = cs.tsep; + p_scb->seps[index].p_app_data_cback = p_data->api_reg_sep.p_data_cback; + } else { + APPL_TRACE_WARNING("%s fail to create sep", __FUNCTION__); + break; + } + } + else { + APPL_TRACE_WARNING("%s invalid codec capability", __FUNCTION__); + } + } + } + + sep_reg.reg_state = BTA_AV_SUCCESS; + (*bta_av_cb.p_cback)(BTA_AV_SEP_REG_EVT, (tBTA_AV *)&sep_reg); +#endif +} + /******************************************************************************* ** ** Function bta_av_api_deregister @@ -1248,6 +1335,13 @@ BOOLEAN bta_av_hdl_event(BT_HDR *p_msg) APPL_TRACE_VERBOSE("AV sm event=0x%x(%s)\n", event, bta_av_evt_code(event)); /* state machine events */ bta_av_sm_execute(&bta_av_cb, p_msg->event, (tBTA_AV_DATA *) p_msg); +#if BTA_AV_CA_INCLUDED + } else if (event >= BTA_AV_CA_FIRST_SM_EVT && event <= BTA_AV_CA_LAST_SM_EVT) { + if (p_msg->layer_specific < BTA_AV_NUM_RCB) { + tBTA_AV_RCB *p_rcb = &bta_av_cb.rcb[p_msg->layer_specific]; + bta_av_ca_sm_execute(p_rcb, p_msg->event, (tBTA_AV_DATA *) p_msg); + } +#endif } else { APPL_TRACE_VERBOSE("handle=0x%x\n", p_msg->layer_specific); tBTA_AV_SCB *p_scb = bta_av_hndl_to_scb(p_msg->layer_specific); @@ -1408,7 +1502,8 @@ char *bta_av_action_code(UINT16 action_code) case 46: return "BTA_AV_DELAY_CO"; case 47: return "BTA_AV_OPEN_AT_INC"; case 48: return "BTA_AV_OPEN_FAIL_SDP"; - case 49: return "NULL"; + case 49: return "BTA_AV_SET_DELAY_VALUE"; + case 50: return "NULL"; default: return "unknown"; } } diff --git a/lib/bt/host/bluedroid/bta/av/bta_av_sbc.c b/lib/bt/host/bluedroid/bta/av/bta_av_sbc.c index 4e034c42..3fd3d94b 100644 --- a/lib/bt/host/bluedroid/bta/av/bta_av_sbc.c +++ b/lib/bt/host/bluedroid/bta/av/bta_av_sbc.c @@ -581,6 +581,64 @@ UINT8 bta_av_sbc_cfg_in_cap(UINT8 *p_cfg, tA2D_SBC_CIE *p_cap) return status; } +/******************************************************************************* +** +** Function bta_av_sbc_cfg_in_external_codec_cap +** +** Description This function checks whether an SBC codec configuration +** is allowable for the given external codec capabilities. +** +** Returns 0 if ok, nonzero if error. +** +*******************************************************************************/ +UINT8 bta_av_sbc_cfg_in_external_codec_cap(UINT8 *p_cfg, UINT8 *p_cap) +{ + UINT8 status = 0; + tA2D_SBC_CIE cfg_cie; + tA2D_SBC_CIE cap_cie; + + /* parse configuration */ + if ((status = A2D_ParsSbcInfo(&cfg_cie, p_cfg, FALSE)) != 0) { + return status; + } + /* parse capability */ + if ((status = A2D_ParsSbcInfo(&cap_cie, p_cap, TRUE)) != 0) { + return status; + } + + /* verify that each parameter is in range */ + + /* sampling frequency */ + if ((cfg_cie.samp_freq & cap_cie.samp_freq) == 0) { + status = A2D_NS_SAMP_FREQ; + } + /* channel mode */ + else if ((cfg_cie.ch_mode & cap_cie.ch_mode) == 0) { + status = A2D_NS_CH_MODE; + } + /* block length */ + else if ((cfg_cie.block_len & cap_cie.block_len) == 0) { + status = A2D_BAD_BLOCK_LEN; + } + /* subbands */ + else if ((cfg_cie.num_subbands & cap_cie.num_subbands) == 0) { + status = A2D_NS_SUBBANDS; + } + /* allocation method */ + else if ((cfg_cie.alloc_mthd & cap_cie.alloc_mthd) == 0) { + status = A2D_NS_ALLOC_MTHD; + } + /* max bitpool */ + else if (cfg_cie.max_bitpool > cap_cie.max_bitpool) { + status = A2D_NS_MAX_BITPOOL; + } + /* min bitpool */ + else if (cfg_cie.min_bitpool < cap_cie.min_bitpool) { + status = A2D_NS_MIN_BITPOOL; + } + return status; +} + /******************************************************************************* ** ** Function bta_av_sbc_bld_hdr diff --git a/lib/bt/host/bluedroid/bta/av/include/bta_av_int.h b/lib/bt/host/bluedroid/bta/av/include/bta_av_int.h index 8c255456..9d8e6dfd 100644 --- a/lib/bt/host/bluedroid/bta/av/include/bta_av_int.h +++ b/lib/bt/host/bluedroid/bta/av/include/bta_av_int.h @@ -85,10 +85,20 @@ enum { BTA_AV_ROLE_CHANGE_EVT, BTA_AV_AVDT_DELAY_RPT_EVT, BTA_AV_ACP_CONNECT_EVT, - +#if BTA_AV_CA_INCLUDED + /* these events are handled by the Cover Art Client state machine */ + BTA_AV_API_CA_OPEN_EVT, + BTA_AV_API_CA_CLOSE_EVT, + BTA_AV_API_CA_GET_EVT, + BTA_AV_CA_RESPONSE_EVT, + BTA_AV_CA_RESPONSE_FINAL_EVT, + BTA_AV_CA_GOEP_CONNECT_EVT, + BTA_AV_CA_GOEP_DISCONNECT_EVT, +#endif /* these events are handled outside of the state machine */ BTA_AV_API_ENABLE_EVT, BTA_AV_API_REGISTER_EVT, + BTA_AV_API_REG_SEP_EVT, BTA_AV_API_DEREGISTER_EVT, BTA_AV_API_DISCONNECT_EVT, BTA_AV_CI_SRC_DATA_READY_EVT, @@ -115,6 +125,12 @@ enum { #define BTA_AV_FIRST_SM_EVT BTA_AV_API_DISABLE_EVT #define BTA_AV_LAST_SM_EVT BTA_AV_AVRC_NONE_EVT +#if BTA_AV_CA_INCLUDED +/* events for AVRC Cover Art state machine */ +#define BTA_AV_CA_FIRST_SM_EVT BTA_AV_API_CA_OPEN_EVT +#define BTA_AV_CA_LAST_SM_EVT BTA_AV_CA_GOEP_DISCONNECT_EVT +#endif + /* events for AV stream control block state machine */ #define BTA_AV_FIRST_SSM_EVT BTA_AV_API_OPEN_EVT @@ -180,6 +196,15 @@ typedef struct { tBTA_AVRC_CO_FUNCTS *bta_avrc_cos; } tBTA_AV_API_REG; +/* data type for BTA_AV_API_REG_SEP_EVT */ +typedef struct { + BT_HDR hdr; + UINT8 seid; + UINT8 tsep; + tBTA_AV_CODEC codec_type; + UINT8 codec_info[AVDT_CODEC_SIZE]; + tBTA_AV_DATA_CBACK *p_data_cback; +} tBTA_AV_API_REG_SEP; enum { BTA_AV_RS_NONE, /* straight API call */ @@ -348,6 +373,52 @@ typedef struct { BT_HDR hdr; } tBTA_AV_API_GET_DELAY_VALUE; +#if BTA_AV_CA_INCLUDED + +/* data type for BTA_AV_API_CA_OPEN_EVT */ +typedef struct { + BT_HDR hdr; + UINT16 mtu; +} tBTA_AV_API_CA_OPEN; + +/* data type for BTA_AV_API_CA_CLOSE_EVT */ +typedef struct { + BT_HDR hdr; +} tBTA_AV_API_CA_CLOSE; + +/* data type for BTA_AV_API_CA_GET_EVT */ +typedef struct { + BT_HDR hdr; + tBTA_AV_GET_TYPE type; + UINT8 image_handle[7]; + /* Image descriptor used in get image function */ + UINT16 image_descriptor_len; + UINT8 *image_descriptor; +} tBTA_AV_API_CA_GET; + +/* data type for BTA_AV_CA_RESPONSE_EVT and BTA_AV_CA_RESPONSE_FINAL_EVT */ +typedef struct { + BT_HDR hdr; + BT_HDR *pkt; + UINT8 opcode; + BOOLEAN srm_en; + BOOLEAN srm_wait; +} tBTA_AV_CA_RESPONSE; + +/* data type for BTA_AV_CA_CONNECT_EVT */ +typedef struct { + BT_HDR hdr; + UINT16 max_rx; +} tBTA_AV_CA_CONNECT; + +/* data type for BTA_AV_CA_DISCONNECT_EVT */ +typedef struct { + BT_HDR hdr; + UINT16 reason; +} tBTA_AV_CA_DISCONNECT; + +#endif /* BTA_AV_CA_INCLUDED */ + /* initiator/acceptor role for adaption */ #define BTA_AV_ROLE_AD_INT 0x00 /* initiator */ #define BTA_AV_ROLE_AD_ACP 0x01 /* acceptor */ @@ -364,6 +435,7 @@ typedef union { BT_HDR hdr; tBTA_AV_API_ENABLE api_enable; tBTA_AV_API_REG api_reg; + tBTA_AV_API_REG_SEP api_reg_sep; tBTA_AV_API_OPEN api_open; tBTA_AV_API_STOP api_stop; tBTA_AV_API_DISCNT api_discnt; @@ -382,6 +454,14 @@ typedef union { tBTA_AV_API_META_RSP api_meta_rsp; tBTA_AV_API_SET_DELAY_VALUE api_set_delay_vlaue; tBTA_AV_API_GET_DELAY_VALUE api_get_delay_value; +#if BTA_AV_CA_INCLUDED + tBTA_AV_API_CA_OPEN api_ca_open; + tBTA_AV_API_CA_CLOSE api_ca_close; + tBTA_AV_API_CA_GET api_ca_get; + tBTA_AV_CA_RESPONSE ca_response; + tBTA_AV_CA_CONNECT ca_connect; + tBTA_AV_CA_DISCONNECT ca_disconnect; +#endif } tBTA_AV_DATA; typedef void (tBTA_AV_VDP_DATA_ACT)(void *p_scb); @@ -405,8 +485,8 @@ typedef union { #define BTA_AV_Q_TAG_START 0x02 /* before start sending media packets */ #define BTA_AV_Q_TAG_STREAM 0x03 /* during streaming */ -#define BTA_AV_WAIT_ACP_CAPS_ON 0x01 /* retriving the peer capabilities */ -#define BTA_AV_WAIT_ACP_CAPS_STARTED 0x02 /* started while retriving peer capabilities */ +#define BTA_AV_WAIT_ACP_CAPS_ON 0x01 /* retrieving the peer capabilities */ +#define BTA_AV_WAIT_ACP_CAPS_STARTED 0x02 /* started while retrieving peer capabilities */ #define BTA_AV_WAIT_ROLE_SW_RES_OPEN 0x04 /* waiting for role switch result after API_OPEN, before STR_OPENED */ #define BTA_AV_WAIT_ROLE_SW_RES_START 0x08 /* waiting for role switch result before streaming */ #define BTA_AV_WAIT_ROLE_SW_STARTED 0x10 /* started while waiting for role switch result */ @@ -462,7 +542,7 @@ typedef struct { BOOLEAN use_rc; /* TRUE if AVRCP is allowed */ BOOLEAN started; /* TRUE if stream started */ UINT8 co_started; /* non-zero, if stream started from call-out perspective */ - BOOLEAN recfg_sup; /* TRUE if the first attempt to reconfigure the stream was successfull, else False if command fails */ + BOOLEAN recfg_sup; /* TRUE if the first attempt to reconfigure the stream was successful, else False if command fails */ BOOLEAN suspend_sup; /* TRUE if Suspend stream is supported, else FALSE if suspend command fails */ BOOLEAN deregistring; /* TRUE if deregistering */ BOOLEAN sco_suspend; /* TRUE if SUSPEND is issued automatically for SCO */ @@ -471,7 +551,7 @@ typedef struct { UINT8 wait; /* set 0x1, when getting Caps as ACP, set 0x2, when started */ UINT8 q_tag; /* identify the associated q_info union member */ BOOLEAN no_rtp_hdr; /* TRUE if add no RTP header*/ - UINT8 disc_rsn; /* disconenction reason */ + UINT8 disc_rsn; /* disconnection reason */ UINT16 uuid_int; /*intended UUID of Initiator to connect to */ } tBTA_AV_SCB; @@ -481,6 +561,13 @@ typedef struct { #define BTA_AV_RC_CONN_MASK 0x20 +#define BTA_AV_CA_IMG_HDL_UTF16_LEN 16 /* Cover Art image handle in utf-16 format, fixed to 16 */ + +#define BTA_AV_CA_SRM_DISABLE 0x00 +#define BTA_AV_CA_SRM_ENABLE_REQ 0x01 +#define BTA_AV_CA_SRM_WAIT 0x02 +#define BTA_AV_CA_SRM_ENABLE 0x03 + /* type for AV RCP control block */ /* index to this control block is the rc handle */ typedef struct { @@ -491,6 +578,14 @@ typedef struct { tBTA_AV_FEAT peer_features; /* peer features mask */ UINT16 peer_ct_features; UINT16 peer_tg_features; +#if BTA_AV_CA_INCLUDED + UINT16 cover_art_l2cap_psm; /* OBEX over L2CAP PSM */ + UINT16 cover_art_goep_hdl; /* Cover Art client GOEP connection handle */ + UINT8 cover_art_state; /* Cover Art client state machine */ + UINT32 cover_art_cid; /* Cover Art client connection id */ + UINT16 cover_art_max_tx; /* max packet length peer device can receive */ + UINT16 cover_art_max_rx; /* max packet length we can receive */ +#endif } tBTA_AV_RCB; #define BTA_AV_NUM_RCB (BTA_AV_NUM_STRS + 2) @@ -705,6 +800,19 @@ extern void bta_av_do_disc_vdp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data); extern void bta_av_vdp_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data); extern void bta_av_reg_vdp (tAVDT_CS *p_cs, char *p_service_name, void *p_data); +#if BTA_AV_CA_INCLUDED +extern void bta_av_ca_api_open(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data); +extern void bta_av_ca_api_close(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data); +extern void bta_av_ca_api_get(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data); +extern void bta_av_ca_response(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data); +extern void bta_av_ca_response_final(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data); +extern void bta_av_ca_goep_connect(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data); +extern void bta_av_ca_goep_disconnect(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data); +extern void bta_av_ca_force_disconnect(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data); +extern void bta_av_ca_sm_execute(tBTA_AV_RCB *p_rcb, UINT16 event, tBTA_AV_DATA *p_data); +extern void bta_av_ca_reset(tBTA_AV_RCB *p_rcb); +#endif + #endif ///BTA_AV_INCLUDED == TRUE #endif /* BTA_AV_INT_H */ diff --git a/lib/bt/host/bluedroid/bta/dm/bta_dm_act.c b/lib/bt/host/bluedroid/bta/dm/bta_dm_act.c index ba5e8f02..3ec7ae2a 100644 --- a/lib/bt/host/bluedroid/bta/dm/bta_dm_act.c +++ b/lib/bt/host/bluedroid/bta/dm/bta_dm_act.c @@ -616,8 +616,10 @@ void bta_dm_disable (tBTA_DM_MSG *p_data) #endif #if BLE_INCLUDED == TRUE +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) // btm_ble_multi_adv_init is called when the host is enabled, so btm_ble_multi_adv_cleanup is called when the host is disabled. btm_ble_multi_adv_cleanup(); +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) #endif } @@ -731,6 +733,7 @@ void bta_dm_cfg_coex_status (tBTA_DM_MSG *p_data) } #endif +#if (BLE_VENDOR_HCI_EN == TRUE) void bta_dm_send_vendor_hci(tBTA_DM_MSG *p_data) { BTM_VendorSpecificCommand(p_data->vendor_hci_cmd.opcode, @@ -739,6 +742,28 @@ void bta_dm_send_vendor_hci(tBTA_DM_MSG *p_data) p_data->vendor_hci_cmd.vendor_hci_cb); } +void bta_dm_ble_gap_clear_adv(tBTA_DM_MSG *p_data) +{ + if (BTM_BleClearAdv(p_data->ble_clear_adv.p_clear_adv_cback) == FALSE) { + if (p_data->ble_clear_adv.p_clear_adv_cback) { + (*p_data->ble_clear_adv.p_clear_adv_cback)(BTA_FAILURE); + } + } +} + +void bta_dm_ble_gap_set_csa_support(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s, csa_select = %d", __func__, p_data->ble_set_csa_support.csa_select); + BTM_BleSetCsaSupport(p_data->ble_set_csa_support.csa_select, p_data->ble_set_csa_support.p_cback); +} + +void bta_dm_ble_gap_set_vendor_evt_mask(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s, evt_mask = %d", __func__, p_data->ble_set_vendor_evt_mask.evt_mask); + BTM_BleSetVendorEventMask(p_data->ble_set_vendor_evt_mask.evt_mask, p_data->ble_set_vendor_evt_mask.p_cback); +} +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) + /******************************************************************************* ** ** Function bta_dm_set_afh_channels @@ -970,7 +995,7 @@ void bta_dm_clear_white_list(tBTA_DM_MSG *p_data) BTM_BleClearWhitelist(p_data->white_list.update_wl_cb); #endif } - +#if (BLE_HOST_READ_TX_POWER_EN == TRUE) void bta_dm_ble_read_adv_tx_power(tBTA_DM_MSG *p_data) { #if (BLE_INCLUDED == TRUE) @@ -981,6 +1006,7 @@ void bta_dm_ble_read_adv_tx_power(tBTA_DM_MSG *p_data) } #endif ///BLE_INCLUDED == TRUE } +#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) void bta_dm_read_rssi(tBTA_DM_MSG *p_data) { @@ -991,6 +1017,7 @@ void bta_dm_read_rssi(tBTA_DM_MSG *p_data) } } +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function bta_dm_set_visibility @@ -1080,6 +1107,7 @@ void bta_dm_set_visibility(tBTA_DM_MSG *p_data) } } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -1211,6 +1239,7 @@ void bta_dm_add_device (tBTA_DM_MSG *p_data) } } +#if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_close_acl @@ -1256,7 +1285,9 @@ void bta_dm_close_acl(tBTA_DM_MSG *p_data) /* otherwise, no action needed */ } +#endif // #if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) +#if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_remove_all_acl @@ -1285,7 +1316,7 @@ void bta_dm_remove_all_acl(tBTA_DM_MSG *p_data) } } } - +#endif // #if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) /******************************************************************************* ** @@ -2385,7 +2416,12 @@ void bta_dm_queue_search (tBTA_DM_MSG *p_data) osi_free(bta_dm_search_cb.p_search_queue); } - bta_dm_search_cb.p_search_queue = (tBTA_DM_MSG *)osi_malloc(sizeof(tBTA_DM_API_SEARCH)); + tBTA_DM_API_SEARCH *search_queue = osi_malloc(sizeof(tBTA_DM_API_SEARCH)); + if (search_queue == NULL) { + APPL_TRACE_ERROR("%s: couldn't allocate memory", __func__); + return; + } + bta_dm_search_cb.p_search_queue = (tBTA_DM_MSG *) search_queue; memcpy(bta_dm_search_cb.p_search_queue, p_data, sizeof(tBTA_DM_API_SEARCH)); } @@ -2406,7 +2442,12 @@ void bta_dm_queue_disc (tBTA_DM_MSG *p_data) osi_free(bta_dm_search_cb.p_search_queue); } - bta_dm_search_cb.p_search_queue = (tBTA_DM_MSG *)osi_malloc(sizeof(tBTA_DM_API_DISCOVER)); + tBTA_DM_API_DISCOVER *search_queue = osi_malloc(sizeof(tBTA_DM_API_DISCOVER)); + if (search_queue == NULL) { + APPL_TRACE_ERROR("%s: couldn't allocate memory", __func__); + return; + } + bta_dm_search_cb.p_search_queue = (tBTA_DM_MSG *)search_queue; memcpy(bta_dm_search_cb.p_search_queue, p_data, sizeof(tBTA_DM_API_DISCOVER)); } #endif ///SDP_INCLUDED == TRUE @@ -4589,6 +4630,7 @@ void bta_dm_eir_update_uuid(tBT_UUID uuid, BOOLEAN adding) } #endif +#if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_enable_test_mode @@ -4620,7 +4662,9 @@ void bta_dm_disable_test_mode(tBTA_DM_MSG *p_data) UNUSED(p_data); BTM_DeviceReset(NULL); } +#endif // #if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) +#if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_execute_callback @@ -4640,6 +4684,7 @@ void bta_dm_execute_callback(tBTA_DM_MSG *p_data) p_data->exec_cback.p_exec_cback(p_data->exec_cback.p_param); } +#endif // #if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) /******************************************************************************* ** @@ -4962,7 +5007,9 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D if (p_data->complt.reason != 0) { sec_event.auth_cmpl.fail_reason = BTA_DM_AUTH_CONVERT_SMP_CODE(((UINT8)p_data->complt.reason)); /* delete this device entry from Sec Dev DB */ - bta_dm_remove_sec_dev_entry (bda); + APPL_TRACE_WARNING("%s remove bond,rsn %d, BDA:0x%02X%02X%02X%02X%02X%02X", __func__, sec_event.auth_cmpl.fail_reason, + bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + bta_dm_remove_sec_dev_entry(bda); } else { sec_event.auth_cmpl.success = TRUE; if (!p_data->complt.smp_over_br) { @@ -5162,6 +5209,7 @@ void bta_dm_ble_set_conn_params (tBTA_DM_MSG *p_data) p_data->ble_set_conn_params.slave_latency, p_data->ble_set_conn_params.supervision_tout); } +#if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) /******************************************************************************* ** ** Function bta_dm_ble_set_conn_scan_params @@ -5179,7 +5227,9 @@ void bta_dm_ble_set_scan_params(tBTA_DM_MSG *p_data) p_data->ble_set_scan_params.scan_mode, p_data->ble_set_scan_params.scan_param_setup_cback); } +#endif // #if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) +#if (BLE_42_SCAN_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_ble_set_scan_fil_params @@ -5211,8 +5261,9 @@ void bta_dm_ble_set_scan_fil_params(tBTA_DM_MSG *p_data) } } +#endif // #if (BLE_42_SCAN_EN == TRUE) - +#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_ble_set_conn_scan_params @@ -5227,6 +5278,8 @@ void bta_dm_ble_set_conn_scan_params (tBTA_DM_MSG *p_data) BTM_BleSetConnScanParams(p_data->ble_set_conn_scan_params.scan_int, p_data->ble_set_conn_scan_params.scan_window); } +#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) + /******************************************************************************* ** ** Function bta_dm_ble_update_conn_params @@ -5293,6 +5346,7 @@ void bta_dm_ble_clear_rand_address(tBTA_DM_MSG *p_data) BTM_BleClearRandAddress(); } +#if (BLE_HOST_STOP_ADV_UNUSED == TRUE) /******************************************************************************* ** ** Function bta_dm_ble_stop_advertising @@ -5307,10 +5361,11 @@ void bta_dm_ble_stop_advertising(tBTA_DM_MSG *p_data) if (p_data->hdr.event != BTA_DM_API_BLE_STOP_ADV_EVT) { APPL_TRACE_ERROR("Invalid BTA event,can't stop the BLE adverting\n"); } - +#if (BLE_42_ADV_EN == TRUE) btm_ble_stop_adv(); +#endif // #if (BLE_42_ADV_EN == TRUE) } - +#endif // #if (BLE_HOST_STOP_ADV_UNUSED == TRUE) #if BLE_PRIVACY_SPT == TRUE @@ -5342,6 +5397,7 @@ void bta_dm_ble_config_local_icon (tBTA_DM_MSG *p_data) BTM_BleConfigLocalIcon (p_data->ble_local_icon.icon); } +#if (BLE_HOST_BLE_OBSERVE_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_ble_observe @@ -5381,6 +5437,7 @@ void bta_dm_ble_observe (tBTA_DM_MSG *p_data) } } } +#endif // #if (BLE_HOST_BLE_OBSERVE_EN == TRUE) /******************************************************************************* ** @@ -5419,26 +5476,14 @@ void bta_dm_ble_scan (tBTA_DM_MSG *p_data) status = (status == BTM_CMD_STARTED ? BTA_SUCCESS : BTA_FAILURE); p_data->ble_scan.p_stop_scan_cback(status); } - } -} -/******************************************************************************* -** -** Function bta_dm_ble_set_adv_params -** -** Description This function set the adv parameters. -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_ble_set_adv_params (tBTA_DM_MSG *p_data) -{ - BTM_BleSetAdvParams(p_data->ble_set_adv_params.adv_int_min, - p_data->ble_set_adv_params.adv_int_max, - p_data->ble_set_adv_params.p_dir_bda, - BTA_DM_BLE_ADV_CHNL_MAP); + // reset BLE scan link state when stop scan + btm_ble_clear_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT); + btm_ble_clear_topology_mask(BTM_BLE_STATE_PASSIVE_SCAN_BIT); + } } +#if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_ble_set_adv_params_all @@ -5476,6 +5521,7 @@ void bta_dm_ble_set_adv_params_all (tBTA_DM_MSG *p_data) (*p_data->ble_set_adv_params_all.p_start_adv_cback)(status); } } +#endif // #if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** @@ -5493,6 +5539,7 @@ void bta_dm_ble_update_duplicate_exceptional_list(tBTA_DM_MSG *p_data) p_data->ble_duplicate_exceptional_list.exceptional_list_cb); } +#if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_ble_set_adv_config @@ -5516,29 +5563,6 @@ void bta_dm_ble_set_adv_config (tBTA_DM_MSG *p_data) } } -/******************************************************************************* -** -** Function bta_dm_ble_set_long_adv -** -** Description This function set the long ADV data -** -** Parameters: -** -*******************************************************************************/ -void bta_dm_ble_set_long_adv (tBTA_DM_MSG *p_data) -{ - tBTA_STATUS status = BTA_FAILURE; - - if (BTM_BleWriteLongAdvData(p_data->ble_set_long_adv_data.adv_data, - p_data->ble_set_long_adv_data.adv_data_len) == BTM_SUCCESS) { - status = BTA_SUCCESS; - } - - if (p_data->ble_set_adv_data.p_adv_data_cback) { - (*p_data->ble_set_adv_data.p_adv_data_cback)(status); - } -} - /******************************************************************************* ** ** Function bta_dm_ble_set_adv_config_raw @@ -5562,7 +5586,6 @@ void bta_dm_ble_set_adv_config_raw (tBTA_DM_MSG *p_data) } } - /******************************************************************************* ** ** Function bta_dm_ble_set_scan_rsp @@ -5608,7 +5631,7 @@ void bta_dm_ble_set_scan_rsp_raw (tBTA_DM_MSG *p_data) (*p_data->ble_set_adv_data_raw.p_adv_data_cback)(status); } } - +#endif // #if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_ble_set_data_length @@ -5665,6 +5688,7 @@ void bta_dm_ble_set_data_length(tBTA_DM_MSG *p_data) } +#if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_ble_broadcast @@ -5690,7 +5714,9 @@ void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data) } } +#endif // #if (BLE_42_ADV_EN == TRUE) +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_ble_multi_adv_enb @@ -5798,7 +5824,9 @@ void btm_dm_ble_multi_adv_disable(tBTA_DM_MSG *p_data) p_data->ble_multi_adv_disable.inst_id, p_ref, BTA_FAILURE); } } +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) +#if (BLE_42_DTM_TEST_EN == TRUE) void bta_dm_ble_gap_dtm_tx_start(tBTA_DM_MSG *p_data) { BTM_BleTransmitterTest(p_data->dtm_tx_start.tx_channel, p_data->dtm_tx_start.len_of_data, p_data->dtm_tx_start.pkt_payload, p_data->dtm_tx_start.p_dtm_cmpl_cback); @@ -5808,20 +5836,14 @@ void bta_dm_ble_gap_dtm_rx_start(tBTA_DM_MSG *p_data) { BTM_BleReceiverTest(p_data->dtm_rx_start.rx_channel, p_data->dtm_rx_start.p_dtm_cmpl_cback); } +#endif // #if (BLE_42_DTM_TEST_EN == TRUE) +#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) void bta_dm_ble_gap_dtm_stop(tBTA_DM_MSG *p_data) { BTM_BleTestEnd(p_data->dtm_stop.p_dtm_cmpl_cback); } - -void bta_dm_ble_gap_clear_adv(tBTA_DM_MSG *p_data) -{ - if (BTM_BleClearAdv(p_data->ble_clear_adv.p_clear_adv_cback) == FALSE) { - if (p_data->ble_clear_adv.p_clear_adv_cback) { - (*p_data->ble_clear_adv.p_clear_adv_cback)(BTA_FAILURE); - } - } -} +#endif // #if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) void bta_dm_ble_gap_set_rpa_timeout(tBTA_DM_MSG *p_data) { @@ -5845,7 +5867,14 @@ void bta_dm_ble_gap_set_privacy_mode(tBTA_DM_MSG *p_data) p_data->ble_set_privacy_mode.privacy_mode, p_data->ble_set_privacy_mode.p_cback); } -#if (BLE_50_FEATURE_SUPPORT == TRUE) +void bta_dm_read_ble_channel_map(tBTA_DM_MSG *p_data) +{ + if (p_data && p_data->ch_map.read_ch_map_cb) { + BTM_ReadChannelMap(p_data->ch_map.remote_addr, p_data->ch_map.read_ch_map_cb); + } +} + +#if (BLE_50_DTM_TEST_EN == TRUE) void bta_dm_ble_gap_dtm_enhance_tx_start(tBTA_DM_MSG *p_data) { BTM_BleEnhancedTransmitterTest(p_data->dtm_enh_tx_start.tx_channel, p_data->dtm_enh_tx_start.len_of_data, @@ -5857,7 +5886,8 @@ void bta_dm_ble_gap_dtm_enhance_rx_start(tBTA_DM_MSG *p_data) BTM_BleEnhancedReceiverTest(p_data->dtm_enh_rx_start.rx_channel, p_data->dtm_enh_rx_start.phy, p_data->dtm_enh_rx_start.modulation_index, p_data->dtm_enh_rx_start.p_dtm_cmpl_cback); } - +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) void bta_dm_ble_gap_read_phy(tBTA_DM_MSG *p_data) { //tBTM_STATUS btm_status = 0; @@ -5883,6 +5913,7 @@ void bta_dm_ble_gap_set_prefer_phy(tBTA_DM_MSG *p_data) p_data->ble_set_per_phy.phy_options); } +#if (BLE_50_EXTEND_ADV_EN == TRUE) void bta_dm_ble_gap_ext_adv_set_rand_addr(tBTA_DM_MSG *p_data) { BTM_BleSetExtendedAdvRandaddr(p_data->ble_set_ext_adv_rand_addr.instance, p_data->ble_set_ext_adv_rand_addr.rand_addr); @@ -5923,7 +5954,9 @@ void bta_dm_ble_gap_ext_adv_set_clear(tBTA_DM_MSG *p_data) { BTM_BleExtAdvSetClear(); } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) void bta_dm_ble_gap_periodic_adv_set_params(tBTA_DM_MSG *p_data) { APPL_TRACE_API("%s, instance = %d", __func__, p_data->ble_set_periodic_adv_params.instance); @@ -5950,7 +5983,9 @@ void bta_dm_ble_gap_periodic_adv_enable(tBTA_DM_MSG *p_data) BTM_BlePeriodicAdvEnable(p_data->ble_enable_periodic_adv.instance, p_data->ble_enable_periodic_adv.enable); } +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) void bta_dm_ble_gap_periodic_adv_create_sync(tBTA_DM_MSG *p_data) { APPL_TRACE_API("%s", __func__); @@ -5995,8 +6030,9 @@ void bta_dm_ble_gap_periodic_adv_clear_dev(tBTA_DM_MSG *p_data) APPL_TRACE_API("%s", __func__); BTM_BlePeriodicAdvClearDev(); } +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) - +#if (BLE_50_EXTEND_SCAN_EN == TRUE) void bta_dm_ble_gap_set_ext_scan_params(tBTA_DM_MSG *p_data) { APPL_TRACE_API("%s", __func__); @@ -6010,14 +6046,14 @@ void bta_dm_ble_gap_ext_scan(tBTA_DM_MSG *p_data) BTM_BleExtendedScan(p_data->ble_ext_scan.start, p_data->ble_ext_scan.duration, p_data->ble_ext_scan.period); } +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) void bta_dm_ble_gap_set_prefer_ext_conn_params(tBTA_DM_MSG *p_data) { tBTM_EXT_CONN_PARAMS conn_params; conn_params.phy_mask = p_data->ble_set_per_ext_conn_params.phy_mask; - APPL_TRACE_API("%s, start = %d, duration = %d, period = %d", __func__, p_data->ble_ext_scan.start, p_data->ble_ext_scan.duration, - p_data->ble_ext_scan.period); + APPL_TRACE_API("%s, phy_mask %d", __func__, p_data->ble_set_per_ext_conn_params.phy_mask); if (conn_params.phy_mask & BTA_PHY_1M_MASK) { memcpy(&conn_params.phy_1m_conn_params, &p_data->ble_set_per_ext_conn_params.phy_1m_conn_params, @@ -6029,7 +6065,7 @@ void bta_dm_ble_gap_set_prefer_ext_conn_params(tBTA_DM_MSG *p_data) sizeof(tBTA_DM_BLE_CONN_PARAMS)); } - if (conn_params.phy_mask & BTAS_PHY_CODED_MASK) { + if (conn_params.phy_mask & BTA_PHY_CODED_MASK) { memcpy(&conn_params.phy_coded_conn_params, &p_data->ble_set_per_ext_conn_params.phy_coded_conn_params, sizeof(tBTA_DM_BLE_CONN_PARAMS)); } @@ -6069,6 +6105,240 @@ void bta_dm_ble_gap_set_periodic_adv_sync_trans_params(tBTA_DM_MSG *p_data) p_data->ble_set_past_params.params.cte_type); } #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) + +#if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +void bta_dm_ble_big_create(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + tBTA_DM_BLE_BIG_CREATE_PARAMS param = p_data->big_creat.big_creat_param; + BTM_BleBigCreate(param.big_handle, param.adv_handle, param.num_bis, + param.sdu_interval, param.max_sdu, param.max_transport_latency, + param.rtn, param.phy, param.packing, param.framing, + param.encryption, ¶m.broadcast_code[0]); +} + +void bta_dm_ble_big_create_test(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + tBTA_DM_BLE_BIG_CREATE_TEST_PARAMS param = p_data->big_creat_test.big_creat_test_param; + BTM_BleBigCreateTest(param.big_handle, param.adv_handle, param.num_bis, + param.sdu_interval, param.iso_interval, param.nse, + param.max_sdu, param.max_pdu, param.phy, + param.packing, param.framing, param.bn, param.irc, + param.pto, param.encryption, ¶m.broadcast_code[0]); +} + +void bta_dm_ble_big_terminate(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + tBTA_DM_BLE_BIG_TERMINATE_PARAMS param = p_data->big_terminate.big_terminate_param; + BTM_BleBigTerminate(param.big_handle, param.reason); +} +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +void bta_dm_ble_big_sync_create(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + tBTA_DM_BLE_BIG_SYNC_CREATE_PARAMS param = p_data->big_sync.big_sync_param; + BTM_BleBigSyncCreate(param.big_handle, param.sync_handle, + param.encryption, ¶m.bc_code[0], + param.mse, param.big_sync_timeout, + param.num_bis, ¶m.bis[0]); +} + +void bta_dm_ble_big_sync_terminate(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + tBTA_DM_BLE_BIG_SYNC_TERMINATE_PARAMS param = p_data->big_sync_terminate.big_sync_terminate_param; + BTM_BleBigSyncTerminate(param.big_handle); +} +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + +void bta_dm_ble_iso_set_data_path(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + tBTA_DM_BLE_ISO_SET_DATA_PATH_PARAMS param = p_data->iso_set_data_path.iso_data_path_param; + BTM_BleIsoSetDataPath(param.conn_handle, param.data_path_dir, param.data_path_id, param.coding_fmt, + param.company_id, param.vs_codec_id, param.controller_delay, param.codec_len, + param.codec_cfg); +} + +void bta_dm_ble_iso_remove_data_path(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + tBTA_DM_BLE_ISO_REMOVE_DATA_PATH_PARAMS param = p_data->iso_remove_data_path.iso_data_path_remove_param; + BTM_BleIsoRemoveDataPath(param.conn_handle, param.data_path_dir); +} + +void bta_dm_ble_iso_read_tx_sync(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + BTM_BleIsoReadTxSync(p_data->iso_read_tx_sync.iso_hdl); +} + +void bta_dm_ble_iso_read_link_quality(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + BTM_BleIsoReadLinkQuality(p_data->iso_read_link_quality.iso_hdl); +} + +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +void bta_dm_ble_set_cig_params(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + BTM_BleSetCigParams(p_data->api_cig_params.cig_id, p_data->api_cig_params.sdu_int_c_to_p, p_data->api_cig_params.sdu_int_p_to_c, p_data->api_cig_params.worse_case_SCA, p_data->api_cig_params.packing, + p_data->api_cig_params.framing, p_data->api_cig_params.mtl_c_to_p, p_data->api_cig_params.mtl_p_to_c, p_data->api_cig_params.cis_cnt, (uint8_t *)p_data->api_cig_params.cis_params); +} + +void bta_dm_ble_set_cig_params_test(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + BTM_BleSetCigParamsTest(p_data->api_cig_params_test.cig_id, p_data->api_cig_params_test.sdu_int_c_to_p, p_data->api_cig_params_test.sdu_int_p_to_c, + p_data->api_cig_params_test.ft_c_to_p, p_data->api_cig_params_test.ft_p_to_c, p_data->api_cig_params_test.iso_interval, + p_data->api_cig_params_test.worse_case_SCA, p_data->api_cig_params_test.packing, p_data->api_cig_params_test.framing, + p_data->api_cig_params_test.cis_cnt, (uint8_t *)p_data->api_cig_params_test.cis_params_test); +} + +void bta_dm_ble_create_cis(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + BTM_BleCreateCis(p_data->create_cis.cis_count, (uint8_t *)&p_data->create_cis.cis_hdls[0]); +} + +void bta_dm_ble_remove_cig(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + BTM_BleRemoveCig(p_data->remove_cig.cig_id); +} +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +void bta_dm_ble_accept_cis_req(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + BTM_BleAcceptCisReq(p_data->accept_cis_req.cis_handle); +} + +void bta_dm_ble_reject_cis_req(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + BTM_BleRejectCisReq(p_data->reject_cis_req.cis_handle, p_data->reject_cis_req.reason); +} +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_EN == TRUE) +void bta_dm_ble_discon_cis(tBTA_DM_MSG *p_data) +{ + APPL_TRACE_API("%s", __func__); + BTM_BleDisconCis(p_data->discon_cis.cis_handle, p_data->discon_cis.reason); +} +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) + +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +void bta_dm_ble_set_cte_trans_params(tBTA_DM_MSG *p_data) +{ + BTM_BleSetCteTransParams(p_data->set_cte_trans_params.adv_handle, p_data->set_cte_trans_params.cte_len, p_data->set_cte_trans_params.cte_type, + p_data->set_cte_trans_params.cte_count, p_data->set_cte_trans_params.switching_pattern_len, p_data->set_cte_trans_params.antenna_ids); +} + +void bta_dm_ble_set_cte_trans_enable(tBTA_DM_MSG *p_data) +{ + BTM_BleCteSetConnectionlessTransEnable(p_data->set_trans_en.adv_handle, p_data->set_trans_en.cte_enable); +} + +void bta_dm_ble_set_iq_sampling_en(tBTA_DM_MSG *p_data) +{ + BTM_BleCteSetConnectionlessIqSamplingEnable(p_data->iq_samp_en.sync_handle, p_data->iq_samp_en.sampling_en, p_data->iq_samp_en.slot_dur, + p_data->iq_samp_en.max_sampled_ctes, p_data->iq_samp_en.switching_pattern_len, p_data->iq_samp_en.antenna_ids); +} +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +void bta_dm_ble_set_conn_cte_recv_params(tBTA_DM_MSG *p_data) +{ + BTM_BleCteSetConnectionReceiveParams(p_data->recv_params.conn_handle, p_data->recv_params.sampling_en, p_data->recv_params.slot_dur, + p_data->recv_params.switching_pattern_len, p_data->recv_params.antenna_ids); +} + +void bta_dm_ble_set_conn_trans_params(tBTA_DM_MSG *p_data) +{ + BTM_BleCteSetConnectionTransParams(p_data->conn_trans_params.conn_handle, p_data->conn_trans_params.cte_types, + p_data->conn_trans_params.switching_pattern_len, p_data->conn_trans_params.antenna_ids); +} + +void bta_dm_ble_set_conn_cte_req_en(tBTA_DM_MSG *p_data) +{ + BTM_BleCteSetConnectionRequestEnable(p_data->conn_req_en.conn_handle, p_data->conn_req_en.enable, p_data->conn_req_en.cte_req_interval, + p_data->conn_req_en.req_cte_len, p_data->conn_req_en.req_cte_Type); +} + +void bta_dm_ble_set_conn_cte_rsp_en(tBTA_DM_MSG *p_data) +{ + BTM_BleCteSetConnectionRspEnable(p_data->conn_rsp_en.conn_handle, p_data->conn_rsp_en.enable); +} +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + +void bta_dm_ble_read_cte_ant_infor(tBTA_DM_MSG *p_data) +{ + BTM_BleCteReadAntInfor(); +} +#endif // #if (BLE_FEAT_CTE_EN == TRUE) + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +void bta_dm_api_enh_read_trans_power_level(tBTA_DM_MSG *p_data) +{ + BTM_BleEnhReadTransPowerLevel(p_data->enh_read_trans_pwr_level.conn_handle, p_data->enh_read_trans_pwr_level.phy); +} + +void bta_dm_api_read_rem_trans_power_level(tBTA_DM_MSG *p_data) +{ + BTM_BleReadRemoteTransPwrLevel(p_data->remote_trans_pwr_level.conn_handle, p_data->remote_trans_pwr_level.phy); +} + +void bta_dm_api_set_path_loss_report_params(tBTA_DM_MSG *p_data) +{ + BTM_BleSetPathLossRptParams(p_data->path_loss_rpt_params.conn_handle, p_data->path_loss_rpt_params.high_threshold, p_data->path_loss_rpt_params.high_hysteresis, + p_data->path_loss_rpt_params.low_threshold, p_data->path_loss_rpt_params.low_hysteresis, p_data->path_loss_rpt_params.min_time_spent); +} + +void bta_dm_api_set_path_loss_reporting_en(tBTA_DM_MSG *p_data) +{ + BTM_BleSetPathLossRptEnable(p_data->path_loss_rpt_en.conn_handle, p_data->path_loss_rpt_en.enable); +} + +void bta_dm_api_set_trans_power_reporting_en(tBTA_DM_MSG *p_data) +{ + BTM_BleSetTransPwrRptEnable(p_data->trans_pwr_rpt_en.conn_handle, p_data->trans_pwr_rpt_en.local_enable, p_data->trans_pwr_rpt_en.remote_enable); +} +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +void bta_dm_api_set_default_subrate(tBTA_DM_MSG *p_data) +{ + BTM_BleSetDefaultSubrate(p_data->default_subrate.subrate_min, p_data->default_subrate.subrate_max, p_data->default_subrate.max_latency, + p_data->default_subrate.continuation_number, p_data->default_subrate.supervision_timeout); +} + +void bta_dm_api_subrate_request(tBTA_DM_MSG *p_data) +{ + BTM_BleSubrateRequest(p_data->subrate_request.conn_handle, p_data->subrate_request.subrate_min, p_data->subrate_request.subrate_max, + p_data->subrate_request.max_latency, p_data->subrate_request.continuation_number, p_data->subrate_request.supervision_timeout); +} +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + +#if (BLE_50_FEATURE_SUPPORT == TRUE) +void bta_dm_ble_set_host_feature(tBTA_DM_MSG *p_data) +{ + BTM_BleSetHostFeature(p_data->set_host_feat.bit_num, p_data->set_host_feat.bit_val); +} +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + +#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_ble_setup_storage @@ -6100,7 +6370,9 @@ void bta_dm_ble_setup_storage (tBTA_DM_MSG *p_data) btm_status); } } +#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) +#if (BLE_HOST_BATCH_SCAN_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_ble_enable_batch_scan @@ -6158,7 +6430,9 @@ void bta_dm_ble_disable_batch_scan (tBTA_DM_MSG *p_data) btm_status); } } +#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) +#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_ble_read_scan_reports @@ -6185,7 +6459,9 @@ void bta_dm_ble_read_scan_reports(tBTA_DM_MSG *p_data) btm_status); } } +#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) /******************************************************************************* ** ** Function bta_dm_ble_track_advertiser @@ -6218,6 +6494,7 @@ void bta_dm_ble_track_advertiser(tBTA_DM_MSG *p_data) p_data->ble_track_advert.p_track_adv_cback(&track_adv_data); } } +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) /******************************************************************************* ** @@ -6394,6 +6671,7 @@ void bta_dm_scan_filter_param_setup (tBTA_DM_MSG *p_data) } #endif +#if (BLE_HOST_ENERGY_INFO_EN == TRUE) /******************************************************************************* ** ** Function bta_ble_enable_scan_cmpl @@ -6441,6 +6719,7 @@ void bta_dm_ble_get_energy_info(tBTA_DM_MSG *p_data) bta_ble_energy_info_cmpl(0, 0, 0, 0, btm_status); } } +#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) #if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE) && SDP_INCLUDED == TRUE) #ifndef BTA_DM_GATT_CLOSE_DELAY_TOUT @@ -6653,7 +6932,9 @@ void btm_dm_start_gatt_discovery (BD_ADDR bd_addr) btm_dm_start_disc_gatt_services(bta_dm_search_cb.conn_id); } else { //TODO need to add addr_type in future - BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, BLE_ADDR_UNKNOWN_TYPE, TRUE, BTA_GATT_TRANSPORT_LE, FALSE); + BTA_GATTC_Enh_Open(bta_dm_search_cb.client_if, bd_addr, BLE_ADDR_UNKNOWN_TYPE, TRUE, + BTA_GATT_TRANSPORT_LE, FALSE, BLE_ADDR_UNKNOWN_TYPE, 0, NULL, NULL, NULL); + } } #endif /* #if (GATTC_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/bta/dm/bta_dm_api.c b/lib/bt/host/bluedroid/bta/dm/bta_dm_api.c index a2282cd9..08510894 100644 --- a/lib/bt/host/bluedroid/bta/dm/bta_dm_api.c +++ b/lib/bt/host/bluedroid/bta/dm/bta_dm_api.c @@ -29,6 +29,7 @@ #include "stack/btm_api.h" #include "btm_int.h" #include +#include #include "bta/utl.h" #include "osi/allocator.h" @@ -109,7 +110,7 @@ tBTA_STATUS BTA_DisableBluetooth(void) return BTA_SUCCESS; } - +#if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) /******************************************************************************* ** ** Function BTA_EnableTestMode @@ -155,6 +156,7 @@ void BTA_DisableTestMode(void) bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) /******************************************************************************* ** @@ -229,6 +231,7 @@ void BTA_DmCfgCoexStatus(UINT8 op, UINT8 type, UINT8 status) } #endif +#if (BLE_VENDOR_HCI_EN == TRUE) void BTA_DmsendVendorHciCmd(UINT16 opcode, UINT8 param_len, UINT8 *p_param_buf, tBTA_SEND_VENDOR_HCI_CMPL_CBACK p_vendor_cmd_complete_cback) { tBTA_DM_API_SEND_VENDOR_HCI_CMD *p_msg; @@ -244,6 +247,57 @@ void BTA_DmsendVendorHciCmd(UINT16 opcode, UINT8 param_len, UINT8 *p_param_buf, } } +/******************************************************************************* +** +** Function BTA_DmBleClearAdv +** +** Description This function is called to clear Advertising +** +** Parameters p_adv_data_cback : clear adv complete callback. +** +** Returns None +** +*******************************************************************************/ +void BTA_DmBleClearAdv (tBTA_CLEAR_ADV_CMPL_CBACK *p_clear_adv_cback) +{ + tBTA_DM_API_CLEAR_ADV *p_msg; + + if ((p_msg = (tBTA_DM_API_CLEAR_ADV *) + osi_malloc(sizeof(tBTA_DM_API_CLEAR_ADV))) != NULL) { + p_msg->hdr.event = BTA_DM_API_BLE_CLEAR_ADV_EVT; + p_msg->p_clear_adv_cback = p_clear_adv_cback; + + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapSetCsaSupport(uint8_t csa_select, tBTA_SET_CSA_SUPPORT_CMPL_CBACK *p_callback) +{ + tBTA_DM_API_BLE_SET_CSA_SUPPORT *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_SET_CSA_SUPPORT *)osi_malloc(sizeof(tBTA_DM_API_BLE_SET_CSA_SUPPORT))) + != NULL) { + p_msg->hdr.event = BTA_DM_API_BLE_SET_CSA_SUPPORT_EVT; + p_msg->csa_select = csa_select; + p_msg->p_cback = p_callback; + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapSetVendorEventMask(uint32_t evt_mask, tBTA_SET_VENDOR_EVT_MASK_CBACK *p_callback) +{ + tBTA_DM_API_BLE_SET_VENDOR_EVT_MASK *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_SET_VENDOR_EVT_MASK *)osi_malloc(sizeof(tBTA_DM_API_BLE_SET_VENDOR_EVT_MASK))) + != NULL) { + p_msg->hdr.event = BTA_DM_API_BLE_SET_VENDOR_EVT_MASK_EVT; + p_msg->evt_mask = evt_mask; + p_msg->p_cback = p_callback; + bta_sys_sendmsg(p_msg); + } +} +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) + #if (CLASSIC_BT_INCLUDED == TRUE) void BTA_DmConfigEir(tBTA_DM_EIR_CONF *eir_config) @@ -486,6 +540,7 @@ void BTA_DmClearWhiteList(tBTA_UPDATE_WHITELIST_CBACK *update_wl_cb) } } +#if (BLE_HOST_READ_TX_POWER_EN == TRUE) void BTA_DmBleReadAdvTxPower(tBTA_CMPL_CB *cmpl_cb) { tBTA_DM_API_READ_ADV_TX_POWER *p_msg; @@ -495,6 +550,22 @@ void BTA_DmBleReadAdvTxPower(tBTA_CMPL_CB *cmpl_cb) bta_sys_sendmsg(p_msg); } } +#endif // BLE_HOST_READ_TX_POWER_EN + +void BTA_DmBleReadChannelMap(BD_ADDR remote_device, tBTA_CMPL_CB *p_callback) +{ + if (!remote_device || !p_callback) { + return; + } + tBTA_DM_API_READ_CH_MAP *p_msg; + + if ((p_msg = (tBTA_DM_API_READ_CH_MAP *)osi_malloc(sizeof(tBTA_DM_API_READ_CH_MAP))) != NULL) { + p_msg->hdr.event = BTA_DM_API_BLE_READ_CH_MAP_EVT; + memcpy(p_msg->remote_addr, remote_device, sizeof(BD_ADDR)); + p_msg->read_ch_map_cb = p_callback; + bta_sys_sendmsg(p_msg); + } +} #endif ///BLE_INCLUDED == TRUE void BTA_DmReadRSSI(BD_ADDR remote_addr, tBTA_TRANSPORT transport, tBTA_CMPL_CB *cmpl_cb) @@ -509,6 +580,7 @@ void BTA_DmReadRSSI(BD_ADDR remote_addr, tBTA_TRANSPORT transport, tBTA_CMPL_CB } } +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function BTA_DmSetVisibility @@ -538,6 +610,7 @@ void BTA_DmSetVisibility(tBTA_DM_DISC disc_mode, tBTA_DM_CONN conn_mode, UINT8 p } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -1086,23 +1159,70 @@ UINT16 BTA_DmGetConnectionState( BD_ADDR bd_addr ) tBTA_STATUS BTA_DmSetLocalDiRecord( tBTA_DI_RECORD *p_device_info, UINT32 *p_handle ) { - tBTA_STATUS status = BTA_FAILURE; + tBTA_STATUS status = BTA_FAILURE; if (bta_dm_di_cb.di_num < BTA_DI_NUM_MAX) { if (SDP_SetLocalDiRecord((tSDP_DI_RECORD *)p_device_info, p_handle) == SDP_SUCCESS) { if (!p_device_info->primary_record) { - bta_dm_di_cb.di_handle[bta_dm_di_cb.di_num] = *p_handle; - bta_dm_di_cb.di_num ++; + for (uint8_t i = 1; i < BTA_DI_NUM_MAX; i++) { + if (!bta_dm_di_cb.di_handle[i]) { + bta_dm_di_cb.di_handle[i] = *p_handle; + break; + } + } + bta_dm_di_cb.di_num++; + } else if (!bta_dm_di_cb.di_handle[0]) { + bta_dm_di_cb.di_handle[0] = *p_handle; + bta_dm_di_cb.di_num++; + } else { + assert(bta_dm_di_cb.di_handle[0] == (*p_handle)); } - bta_sys_add_uuid(UUID_SERVCLASS_PNP_INFORMATION); - status = BTA_SUCCESS; + if (!bta_dm_di_cb.uuid_added) { + bta_sys_add_uuid(UUID_SERVCLASS_PNP_INFORMATION); + bta_dm_di_cb.uuid_added = TRUE; + } + + status = BTA_SUCCESS; + } + } + + return status; +} + +/******************************************************************************* +** +** Function BTA_DmRemoveLocalDiRecord +** +** Description This function removes a DI record from the local SDP database. +** +** Returns BTA_SUCCESS if record is removed successfully, otherwise error code. +** +*******************************************************************************/ +tBTA_STATUS BTA_DmRemoveLocalDiRecord(UINT32 handle) +{ + tBTA_STATUS status = BTA_FAILURE; + + for (uint8_t i = 0; i < BTA_DI_NUM_MAX; i++) { + if (bta_dm_di_cb.di_handle[i] == handle) { + if (SDP_DeleteRecord(handle)) { + bta_dm_di_cb.di_handle[i] = 0; + bta_dm_di_cb.di_num--; + status = BTA_SUCCESS; + break; + } } } + if (bta_dm_di_cb.di_num == 0 && bta_dm_di_cb.uuid_added) { + bta_sys_remove_uuid(UUID_SERVCLASS_PNP_INFORMATION); + } + return status; } #endif ///SDP_INCLUDED == TRUE + +#if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) /******************************************************************************* ** ** Function bta_dmexecutecallback @@ -1125,6 +1245,7 @@ void bta_dmexecutecallback (tBTA_DM_EXEC_CBACK *p_callback, void *p_param) bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) /******************************************************************************* ** @@ -1335,6 +1456,7 @@ void BTA_DmSetBlePrefConnParams(BD_ADDR bd_addr, #endif } +#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) /******************************************************************************* ** ** Function BTA_DmSetBleConnScanParams @@ -1359,7 +1481,9 @@ void BTA_DmSetBleConnScanParams(UINT32 scan_interval, UINT32 scan_window) bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) +#if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) /******************************************************************************* ** ** Function BTA_DmSetBleScanParams @@ -1393,8 +1517,9 @@ void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval, bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) - +#if (BLE_42_SCAN_EN == TRUE) /******************************************************************************* ** ** Function BTA_DmSetBleScanFilterParams @@ -1434,46 +1559,9 @@ void BTA_DmSetBleScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, } +#endif // #if (BLE_42_SCAN_EN == TRUE) -/******************************************************************************* -** -** Function BTA_DmSetBleAdvParams -** -** Description This function sets the advertising parameters BLE functionality. -** It is to be called when device act in peripheral or broadcaster -** role. -** -** -** Returns void -** -*******************************************************************************/ -void BTA_DmSetBleAdvParams (UINT16 adv_int_min, UINT16 adv_int_max, - tBLE_BD_ADDR *p_dir_bda) -{ -#if BLE_INCLUDED == TRUE - tBTA_DM_API_BLE_ADV_PARAMS *p_msg; - - APPL_TRACE_API ("BTA_DmSetBleAdvParam: %d, %d\n", adv_int_min, adv_int_max); - - if ((p_msg = (tBTA_DM_API_BLE_ADV_PARAMS *) osi_malloc(sizeof(tBTA_DM_API_BLE_ADV_PARAMS) - + sizeof(tBLE_BD_ADDR))) != NULL) { - memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_ADV_PARAMS) + sizeof(tBLE_BD_ADDR)); - - p_msg->hdr.event = BTA_DM_API_BLE_ADV_PARAM_EVT; - - p_msg->adv_int_min = adv_int_min; - p_msg->adv_int_max = adv_int_max; - - if (p_dir_bda != NULL) { - p_msg->p_dir_bda = (tBLE_BD_ADDR *)(p_msg + 1); - memcpy(p_msg->p_dir_bda, p_dir_bda, sizeof(tBLE_BD_ADDR)); - } - - bta_sys_sendmsg(p_msg); - } -#endif -} - +#if (BLE_42_ADV_EN == TRUE) void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max, UINT8 adv_type, tBLE_ADDR_TYPE addr_type_own, tBTM_BLE_ADV_CHNL_MAP chnl_map, tBTM_BLE_AFP adv_fil_pol, @@ -1507,6 +1595,8 @@ void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max, } #endif } +#endif // #if (BLE_42_ADV_EN == TRUE) + #endif ///BLE_INCLUDED == TRUE @@ -1515,6 +1605,7 @@ void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max, ********************************************************************************/ #if BLE_INCLUDED == TRUE +#if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** ** Function BTA_DmBleSetAdvConfig @@ -1576,35 +1667,6 @@ void BTA_DmBleSetAdvConfigRaw (UINT8 *p_raw_adv, UINT32 raw_adv_len, } } -/******************************************************************************* -** -** Function BTA_DmBleSetLongAdv -** -** Description This function is called to set long Advertising data -** -** Parameters adv_data : long advertising data. -** adv_data_len : long advertising data length. -** p_adv_data_cback : set long adv data complete callback. -** -** Returns None -** -*******************************************************************************/ -void BTA_DmBleSetLongAdv (UINT8 *adv_data, UINT32 adv_data_len, - tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback) -{ - tBTA_DM_API_SET_LONG_ADV *p_msg; - - if ((p_msg = (tBTA_DM_API_SET_LONG_ADV *) - osi_malloc(sizeof(tBTA_DM_API_SET_LONG_ADV))) != NULL) { - p_msg->hdr.event = BTA_DM_API_BLE_SET_LONG_ADV_EVT; - p_msg->p_adv_data_cback = p_adv_data_cback; - p_msg->adv_data = adv_data; - p_msg->adv_data_len = adv_data_len; - - bta_sys_sendmsg(p_msg); - } -} - /******************************************************************************* ** ** Function BTA_DmBleSetScanRsp @@ -1661,6 +1723,7 @@ void BTA_DmBleSetScanRspRaw (UINT8 *p_raw_scan_rsp, UINT32 raw_scan_rsp_len, bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** @@ -1689,7 +1752,7 @@ void BTA_DmUpdateDuplicateExceptionalList(UINT8 subcode, UINT32 type, BD_ADDR de bta_sys_sendmsg(p_msg); } } - +#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) /******************************************************************************* ** ** Function BTA_DmBleSetStorageParams @@ -1730,7 +1793,9 @@ extern void BTA_DmBleSetStorageParams(UINT8 batch_scan_full_max, bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) +#if (BLE_HOST_BATCH_SCAN_EN == TRUE) /******************************************************************************* ** ** Function BTA_DmBleEnableBatchScan @@ -1789,7 +1854,9 @@ extern void BTA_DmBleDisableBatchScan(tBTA_DM_BLE_REF_VALUE ref_value) bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) +#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) /******************************************************************************* ** ** Function BTA_DmBleReadScanReports @@ -1815,7 +1882,9 @@ extern void BTA_DmBleReadScanReports(tBTA_BLE_BATCH_SCAN_MODE scan_type, bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) /******************************************************************************* ** ** Function BTA_DmBleTrackAdvertiser @@ -1841,6 +1910,7 @@ extern void BTA_DmBleTrackAdvertiser(tBTA_DM_BLE_REF_VALUE ref_value, bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) #endif @@ -1848,7 +1918,7 @@ extern void BTA_DmBleTrackAdvertiser(tBTA_DM_BLE_REF_VALUE ref_value, ** BLE ADV data management API ********************************************************************************/ #if BLE_INCLUDED == TRUE - +#if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** ** Function BTA_DmBleBroadcast @@ -1878,30 +1948,8 @@ extern void BTA_DmBleBroadcast (BOOLEAN start, tBTA_START_STOP_ADV_CMPL_CBACK *p bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_42_ADV_EN == TRUE) -/******************************************************************************* -** -** Function BTA_DmBleClearAdv -** -** Description This function is called to clear Advertising -** -** Parameters p_adv_data_cback : clear adv complete callback. -** -** Returns None -** -*******************************************************************************/ -void BTA_DmBleClearAdv (tBTA_CLEAR_ADV_CMPL_CBACK *p_clear_adv_cback) -{ - tBTA_DM_API_CLEAR_ADV *p_msg; - - if ((p_msg = (tBTA_DM_API_CLEAR_ADV *) - osi_malloc(sizeof(tBTA_DM_API_CLEAR_ADV))) != NULL) { - p_msg->hdr.event = BTA_DM_API_BLE_CLEAR_ADV_EVT; - p_msg->p_clear_adv_cback = p_clear_adv_cback; - - bta_sys_sendmsg(p_msg); - } -} #endif /******************************************************************************* ** @@ -2175,6 +2223,7 @@ void BTA_DmBleConfigLocalIcon(uint16_t icon) } } +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) /******************************************************************************* ** ** Function BTA_BleEnableAdvInstance @@ -2308,6 +2357,7 @@ void BTA_BleDisableAdvInstance (UINT8 inst_id) //this function just used fo bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) /******************************************************************************* ** @@ -2490,6 +2540,7 @@ void BTA_DmBleScanFilterSetup(UINT8 action, tBTA_DM_BLE_PF_FILT_INDEX filt_index #endif } +#if (BLE_HOST_ENERGY_INFO_EN == TRUE) /******************************************************************************* ** ** Function BTA_DmBleGetEnergyInfo @@ -2515,6 +2566,7 @@ void BTA_DmBleGetEnergyInfo(tBTA_BLE_ENERGY_INFO_CBACK *p_cmpl_cback) bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) /******************************************************************************* ** @@ -2636,6 +2688,7 @@ void BTA_DmBleSetDataLength(BD_ADDR remote_device, UINT16 tx_data_length, tBTA_S } } +#if (BLE_42_DTM_TEST_EN == TRUE) void BTA_DmBleDtmTxStart(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) { tBTA_DM_API_BLE_DTM_TX_START *p_msg; @@ -2665,7 +2718,9 @@ void BTA_DmBleDtmRxStart(uint8_t rx_channel, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_42_DTM_TEST_EN == TRUE) +#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) void BTA_DmBleDtmStop(tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) { tBTA_DM_API_BLE_DTM_STOP *p_msg; @@ -2678,6 +2733,7 @@ void BTA_DmBleDtmStop(tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) bta_sys_sendmsg(p_msg); } } +#endif // #if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) void BTA_DmBleSetPrivacyMode(uint8_t addr_type, BD_ADDR addr, uint8_t privacy_mode, tBTA_SET_PRIVACY_MODE_CMPL_CBACK *p_cback) { @@ -2740,6 +2796,7 @@ void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_TRANSPORT transport, tBTA_DM_ENCR } #endif ///SMP_INCLUDED == TRUE +#if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) /******************************************************************************* ** ** Function BTA_DmCloseACL @@ -2771,8 +2828,10 @@ void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev, tBTA_TRANSPORT transpor bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) #if BLE_INCLUDED == TRUE +#if (BLE_HOST_BLE_OBSERVE_EN == TRUE) /******************************************************************************* ** ** Function BTA_DmBleObserve @@ -2813,7 +2872,9 @@ extern void BTA_DmBleObserve(BOOLEAN start, UINT32 duration, bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_HOST_BLE_OBSERVE_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) /******************************************************************************* ** ** Function BTA_DmBleScan @@ -2854,7 +2915,9 @@ extern void BTA_DmBleScan(BOOLEAN start, UINT32 duration, bta_sys_sendmsg(p_msg); } } +#endif // #if (BLE_42_SCAN_EN == TRUE) +#if (BLE_HOST_STOP_ADV_UNUSED == TRUE) /******************************************************************************* ** ** Function BTA_DmBleStopAdvertising @@ -2879,7 +2942,7 @@ extern void BTA_DmBleStopAdvertising(void) bta_sys_sendmsg(p_msg); } } - +#endif // #if (BLE_HOST_STOP_ADV_UNUSED == TRUE) /******************************************************************************* ** @@ -2979,6 +3042,133 @@ void BTA_DmClearRandAddress(void) } } +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +void BTA_DmBleGapEnhReadTransPwrLevel(uint16_t conn_handle, uint8_t phy) +{ + tBTA_DM_API_BLE_ENH_READ_TANS_PWR_LEVEL *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_ENH_READ_TANS_PWR_LEVEL *)osi_malloc(sizeof(tBTA_DM_API_BLE_ENH_READ_TANS_PWR_LEVEL))) + != NULL) { + p_msg->hdr.event = BTA_DM_API_ENH_READ_TRANS_POWER_LEVEL; + p_msg->conn_handle = conn_handle; + p_msg->phy = phy; + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapReadRemoteTransPwrLevel(uint16_t conn_handle, uint8_t phy) +{ + tBTA_DM_API_BLE_READ_REMOTE_TANS_PWR_LEVEL *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_READ_REMOTE_TANS_PWR_LEVEL *)osi_malloc(sizeof(tBTA_DM_API_BLE_READ_REMOTE_TANS_PWR_LEVEL))) + != NULL) { + p_msg->hdr.event = BTA_DM_API_READ_REM_TRANS_POWER_LEVEL; + p_msg->conn_handle = conn_handle; + p_msg->phy = phy; + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapSetPathLossRptParams(uint16_t conn_handle, uint8_t high_threshold, uint8_t high_hysteresis, + uint8_t low_threshold, uint8_t low_hysteresis, uint16_t min_time_spent) +{ + tBTA_DM_API_BLE_SET_PATH_LOSS_RPT_PARAMS *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_SET_PATH_LOSS_RPT_PARAMS *)osi_malloc(sizeof(tBTA_DM_API_BLE_SET_PATH_LOSS_RPT_PARAMS))) + != NULL) { + p_msg->hdr.event = BTA_DM_API_SET_PATH_LOSS_REPORT_PARAMS; + p_msg->conn_handle = conn_handle; + p_msg->high_threshold = high_threshold; + p_msg->high_hysteresis = high_hysteresis; + p_msg->low_threshold = low_threshold; + p_msg->low_hysteresis = low_hysteresis; + p_msg->min_time_spent = min_time_spent; + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapSetPathLossRptEnable(uint16_t conn_handle, uint8_t enable) +{ + tBTA_DM_API_BLE_SET_PATH_LOSS_RPT_ENABLE *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_SET_PATH_LOSS_RPT_ENABLE *)osi_malloc(sizeof(tBTA_DM_API_BLE_SET_PATH_LOSS_RPT_ENABLE))) + != NULL) { + p_msg->hdr.event = BTA_DM_API_SET_PATH_LOSS_REPORTING_EN; + p_msg->conn_handle = conn_handle; + p_msg->enable = enable; + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapSetTransPwrRptEnable(uint16_t conn_handle, uint8_t local_enable, uint8_t remote_enable) +{ + tBTA_DM_API_BLE_SET_TRANS_PWR_RPT_ENABLE *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_SET_TRANS_PWR_RPT_ENABLE *)osi_malloc(sizeof(tBTA_DM_API_BLE_SET_TRANS_PWR_RPT_ENABLE))) + != NULL) { + p_msg->hdr.event = BTA_DM_API_SET_TRANS_POWER_REPORTING_EN; + p_msg->conn_handle = conn_handle; + p_msg->local_enable = local_enable; + p_msg->remote_enable = remote_enable; + bta_sys_sendmsg(p_msg); + } +} +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +void BTA_DmBleGapSetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency, uint16_t continuation_number, uint16_t supervision_timeout) +{ + tBTA_DM_API_BLE_SET_DEFAULT_SUBRATE *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_SET_DEFAULT_SUBRATE *)osi_malloc(sizeof(tBTA_DM_API_BLE_SET_DEFAULT_SUBRATE))) + != NULL) { + p_msg->hdr.event = BTA_DM_API_SET_DEFALT_SUBRATE; + p_msg->subrate_min = subrate_min; + p_msg->subrate_max = subrate_max; + p_msg->max_latency = max_latency; + p_msg->continuation_number = continuation_number; + p_msg->supervision_timeout = supervision_timeout; + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmBleGapSubrateReqest(uint16_t conn_handle, uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency, uint16_t continuation_number, uint16_t supervision_timeout) +{ + tBTA_DM_API_BLE_SUBRATE_REQUEST *p_msg; + + if ((p_msg = (tBTA_DM_API_BLE_SUBRATE_REQUEST *)osi_malloc(sizeof(tBTA_DM_API_BLE_SUBRATE_REQUEST))) + != NULL) { + p_msg->hdr.event = BTA_DM_API_SUBRATE_REQUEST; + p_msg->conn_handle = conn_handle; + p_msg->subrate_min = subrate_min; + p_msg->subrate_max = subrate_max; + p_msg->max_latency = max_latency; + p_msg->continuation_number = continuation_number; + p_msg->supervision_timeout = supervision_timeout; + bta_sys_sendmsg(p_msg); + } +} +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + +#if (BLE_50_FEATURE_SUPPORT == TRUE) +void BTA_DmBleGapSetHostFeature(uint16_t bit_num, uint8_t bit_val) +{ + tBTA_DM_API_SET_HOST_FEATURE *p_msg; + APPL_TRACE_API("%s", __func__); + if ((p_msg = (tBTA_DM_API_SET_HOST_FEATURE *) osi_malloc(sizeof(tBTA_DM_API_SET_HOST_FEATURE))) != NULL) { + memset(p_msg, 0, sizeof(tBTA_DM_API_SET_HOST_FEATURE)); + p_msg->hdr.event = BTA_DM_API_SET_HOST_FEATURE_EVT; + + p_msg->bit_num = bit_num; + p_msg->bit_val = bit_val; + //start sent the msg to the bta system control module + bta_sys_sendmsg(p_msg); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + /******************************************************************************* ** ** Function BTA_VendorInit @@ -3082,7 +3272,7 @@ void BTA_DmBleGapSetPreferedPHY(BD_ADDR addr, APPL_TRACE_ERROR("%s malloc failed", __func__); } } - +#if (BLE_50_EXTEND_ADV_EN == TRUE) void BTA_DmBleGapExtAdvSetRandaddr(UINT16 instance, BD_ADDR addr) { tBTA_DM_API_EXT_ADV_SET_RAND_ADDR *p_msg; @@ -3188,7 +3378,9 @@ void BTA_DmBleGapExtAdvSetClear(void) APPL_TRACE_ERROR("%s malloc failed", __func__); } } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) void BTA_DmBleGapPeriodicAdvSetParams(UINT8 instance, tBTA_DM_BLE_Periodic_Adv_Params *params) { @@ -3245,7 +3437,9 @@ void BTA_DmBleGapPeriodicAdvEnable(UINT8 enable, UINT8 instance) } } +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) void BTA_DmBleGapPeriodicAdvCreateSync(tBTA_DM_BLE_Periodic_Sync_Params *params) { tBTA_DM_API_PERIODIC_ADV_SYNC *p_msg; @@ -3347,7 +3541,9 @@ void BTA_DmBleGapPeriodicAdvClearDev(void) } } +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if (BLE_50_EXTEND_SCAN_EN == TRUE) void BTA_DmBleGapSetExtScanParams(tBTA_DM_BLE_EXT_SCAN_PARAMS *params) { tBTA_DM_API_SET_EXT_SCAN_PARAMS *p_msg; @@ -3381,6 +3577,7 @@ void BTA_DmBleGapExtScan(BOOLEAN start, UINT32 duration, UINT16 period) } } +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) void BTA_DmBleGapPreferExtConnectParamsSet(BD_ADDR bd_addr, UINT8 phy_mask, @@ -3434,7 +3631,9 @@ void BTA_DmBleGapExtConnect(tBLE_ADDR_TYPE own_addr_type, const BD_ADDR peer_add } } +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_DTM_TEST_EN == TRUE) void BTA_DmBleDtmEnhTxStart(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, uint8_t phy, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) { tBTA_DM_API_BLE_DTM_ENH_TX_START *p_msg; @@ -3467,8 +3666,7 @@ void BTA_DmBleDtmEnhRxStart(uint8_t rx_channel, uint8_t phy, uint8_t modulation_ bta_sys_sendmsg(p_msg); } } - -#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) void BTA_DmBleGapPeriodicAdvRecvEnable(UINT16 sync_handle, UINT8 enable) @@ -3538,4 +3736,500 @@ void BTA_DmBleGapSetPeriodicAdvSyncTransParams(BD_ADDR peer_addr, tBTA_DM_BLE_PA } #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +void BTA_DmBleGapIsoBigCreate(tBTA_DM_BLE_BIG_CREATE_PARAMS *p_big_creat_param) +{ + tBTA_DM_API_BIG_CREATE *p_msg; + APPL_TRACE_API("%s.", __func__); + if ((p_msg = (tBTA_DM_API_BIG_CREATE *) osi_malloc(sizeof(tBTA_DM_API_BIG_CREATE))) != NULL) { + memset(p_msg, 0, sizeof(tBTA_DM_API_BIG_CREATE)); + p_msg->hdr.event = BTA_DM_API_ISO_BIG_CREATE_EVT; + p_msg->big_creat_param.big_handle = p_big_creat_param->big_handle; + p_msg->big_creat_param.adv_handle = p_big_creat_param->adv_handle; + p_msg->big_creat_param.num_bis = p_big_creat_param->num_bis; + p_msg->big_creat_param.sdu_interval = p_big_creat_param->sdu_interval; + p_msg->big_creat_param.max_sdu = p_big_creat_param->max_sdu; + p_msg->big_creat_param.max_transport_latency = p_big_creat_param->max_transport_latency; + p_msg->big_creat_param.rtn = p_big_creat_param->rtn; + p_msg->big_creat_param.phy = p_big_creat_param->phy; + p_msg->big_creat_param.packing = p_big_creat_param->packing; + p_msg->big_creat_param.framing = p_big_creat_param->framing; + p_msg->big_creat_param.encryption = p_big_creat_param->encryption; + memcpy(&p_msg->big_creat_param.broadcast_code[0], p_big_creat_param->broadcast_code, 16); + //start sent the msg to the bta system control module + bta_sys_sendmsg(p_msg); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } + +} + +void BTA_DmBleGapIsoBigCreateTest(tBTA_DM_BLE_BIG_CREATE_TEST_PARAMS *p_big_creat_test_param) +{ + tBTA_DM_API_BIG_CREATE_TEST *p_msg; + APPL_TRACE_API("%s.", __func__); + if ((p_msg = (tBTA_DM_API_BIG_CREATE_TEST *) osi_malloc(sizeof(tBTA_DM_API_BIG_CREATE_TEST))) != NULL) { + memset(p_msg, 0, sizeof(tBTA_DM_API_BIG_CREATE_TEST)); + p_msg->hdr.event = BTA_DM_API_ISO_BIG_CREATE_TEST_EVT; + p_msg->big_creat_test_param.big_handle = p_big_creat_test_param->big_handle; + p_msg->big_creat_test_param.adv_handle = p_big_creat_test_param->adv_handle; + p_msg->big_creat_test_param.num_bis = p_big_creat_test_param->num_bis; + p_msg->big_creat_test_param.sdu_interval = p_big_creat_test_param->sdu_interval; + p_msg->big_creat_test_param.iso_interval = p_big_creat_test_param->iso_interval; + p_msg->big_creat_test_param.nse = p_big_creat_test_param->nse; + p_msg->big_creat_test_param.max_sdu = p_big_creat_test_param->max_sdu; + p_msg->big_creat_test_param.max_pdu = p_big_creat_test_param->max_pdu; + p_msg->big_creat_test_param.phy = p_big_creat_test_param->phy; + p_msg->big_creat_test_param.packing = p_big_creat_test_param->packing; + p_msg->big_creat_test_param.framing = p_big_creat_test_param->framing; + p_msg->big_creat_test_param.bn = p_big_creat_test_param->bn; + p_msg->big_creat_test_param.irc = p_big_creat_test_param->irc; + p_msg->big_creat_test_param.pto = p_big_creat_test_param->pto; + p_msg->big_creat_test_param.encryption = p_big_creat_test_param->encryption; + memcpy(&p_msg->big_creat_test_param.broadcast_code[0], p_big_creat_test_param->broadcast_code, 16); + + //start sent the msg to the bta system control module + bta_sys_sendmsg(p_msg); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} + +void BTA_DmBleGapIsoBigTerminate(tBTA_DM_BLE_BIG_TERMINATE_PARAMS *p_big_terminate_param) +{ + tBTA_DM_API_BIG_TERMINATE *p_msg; + APPL_TRACE_API("%s.", __func__); + if ((p_msg = (tBTA_DM_API_BIG_TERMINATE *) osi_malloc(sizeof(tBTA_DM_API_BIG_TERMINATE))) != NULL) { + memset(p_msg, 0, sizeof(tBTA_DM_API_BIG_TERMINATE)); + p_msg->hdr.event = BTA_DM_API_ISO_BIG_TERMINATE_EVT; + p_msg->big_terminate_param.big_handle = p_big_terminate_param->big_handle; + p_msg->big_terminate_param.reason = p_big_terminate_param->reason; + + //start sent the msg to the bta system control module + bta_sys_sendmsg(p_msg); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +void BTA_DmBleGapIsoBigSyncCreate(tBTA_DM_BLE_BIG_SYNC_CREATE_PARAMS *p_big_sync_param) +{ + tBTA_DM_API_BIG_SYNC_CREATE *p_msg; + APPL_TRACE_API("%s.", __func__); + if ((p_msg = (tBTA_DM_API_BIG_SYNC_CREATE *) osi_malloc(sizeof(tBTA_DM_API_BIG_SYNC_CREATE))) != NULL) { + memset(p_msg, 0, sizeof(tBTA_DM_API_BIG_SYNC_CREATE)); + p_msg->hdr.event = BTA_DM_API_ISO_BIG_SYNC_CREATE_EVT; + + p_msg->big_sync_param.big_handle = p_big_sync_param->big_handle; + p_msg->big_sync_param.sync_handle = p_big_sync_param->sync_handle; + p_msg->big_sync_param.encryption = p_big_sync_param->encryption; + memcpy(&p_msg->big_sync_param.bc_code[0], &p_big_sync_param->bc_code[0], 16); + p_msg->big_sync_param.mse = p_big_sync_param->mse; + p_msg->big_sync_param.big_sync_timeout = p_big_sync_param->big_sync_timeout; + p_msg->big_sync_param.num_bis = p_big_sync_param->num_bis; + memcpy(&p_msg->big_sync_param.bis[0], &p_big_sync_param->bis[0], p_big_sync_param->num_bis); + + //start sent the msg to the bta system control module + bta_sys_sendmsg(p_msg); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} + +void BTA_DmBleGapIsoBigSyncTerminate(tBTA_DM_BLE_BIG_SYNC_TERMINATE_PARAMS *p_big_sync_terminate_param) +{ + tBTA_DM_API_BIG_SYNC_TERMINATE *p_msg; + APPL_TRACE_API("%s.", __func__); + if ((p_msg = (tBTA_DM_API_BIG_SYNC_TERMINATE *) osi_malloc(sizeof(tBTA_DM_API_BIG_SYNC_TERMINATE))) != NULL) { + memset(p_msg, 0, sizeof(tBTA_DM_API_BIG_SYNC_TERMINATE)); + p_msg->hdr.event = BTA_DM_API_ISO_BIG_SYNC_TERMINATE_EVT; + + p_msg->big_sync_terminate_param.big_handle = p_big_sync_terminate_param->big_handle; + + //start sent the msg to the bta system control module + bta_sys_sendmsg(p_msg); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +void BTA_DmBleGapIsoDataPathSet(tBTA_DM_BLE_ISO_SET_DATA_PATH_PARAMS *p_iso_data_path_param) +{ + tBTA_DM_API_ISO_DATA_PATH *p_msg; + uint8_t codec_cfg_len = p_iso_data_path_param->codec_len; + APPL_TRACE_API("%s", __func__); + if ((p_msg = (tBTA_DM_API_ISO_DATA_PATH *) osi_malloc(sizeof(tBTA_DM_API_ISO_DATA_PATH) + codec_cfg_len)) != NULL) { + memset(p_msg, 0, sizeof(tBTA_DM_API_ISO_DATA_PATH)); + p_msg->hdr.event = BTA_DM_API_ISO_SET_DATA_PATH_EVT; + + p_msg->iso_data_path_param.conn_handle = p_iso_data_path_param->conn_handle; + p_msg->iso_data_path_param.data_path_dir = p_iso_data_path_param->data_path_dir; + p_msg->iso_data_path_param.data_path_id = p_iso_data_path_param->data_path_id; + p_msg->iso_data_path_param.coding_fmt = p_iso_data_path_param->coding_fmt; + p_msg->iso_data_path_param.company_id = p_iso_data_path_param->company_id; + p_msg->iso_data_path_param.vs_codec_id = p_iso_data_path_param->vs_codec_id; + p_msg->iso_data_path_param.controller_delay = p_iso_data_path_param->controller_delay; + p_msg->iso_data_path_param.codec_len = p_iso_data_path_param->codec_len; + p_msg->iso_data_path_param.codec_cfg = (codec_cfg_len != 0) ? (UINT8 *)(p_msg + 1) : NULL; + if (codec_cfg_len) { + memcpy(p_msg->iso_data_path_param.codec_cfg, p_iso_data_path_param->codec_cfg, p_iso_data_path_param->codec_len); + } + //start sent the msg to the bta system control module + bta_sys_sendmsg(p_msg); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} + +void BTA_DmBleGapIsoDataPathRemove(tBTA_DM_BLE_ISO_REMOVE_DATA_PATH_PARAMS *p_iso_data_path_param) +{ + tBTA_DM_API_ISO_DATA_PATH_REMOVE *p_msg; + APPL_TRACE_API("%s", __func__); + if ((p_msg = (tBTA_DM_API_ISO_DATA_PATH_REMOVE *) osi_malloc(sizeof(tBTA_DM_API_ISO_DATA_PATH_REMOVE))) != NULL) { + memset(p_msg, 0, sizeof(tBTA_DM_API_ISO_DATA_PATH_REMOVE)); + p_msg->hdr.event = BTA_DM_API_ISO_REMOVE_DATA_PATH_EVT; + + p_msg->iso_data_path_remove_param.conn_handle = p_iso_data_path_param->conn_handle; + p_msg->iso_data_path_remove_param.data_path_dir = p_iso_data_path_param->data_path_dir; + //start sent the msg to the bta system control module + bta_sys_sendmsg(p_msg); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} + +void BTA_DmBleGapIsoReadTxSync(uint16_t iso_handle) +{ + tBTA_DM_API_ISO_READ_TX_SYNC *p_msg; + APPL_TRACE_API("%s", __func__); + if ((p_msg = (tBTA_DM_API_ISO_READ_TX_SYNC *) osi_malloc(sizeof(tBTA_DM_API_ISO_READ_TX_SYNC))) != NULL) { + memset(p_msg, 0, sizeof(tBTA_DM_API_ISO_READ_TX_SYNC)); + p_msg->hdr.event = BTA_DM_API_ISO_READ_TX_SYNC_EVT; + + p_msg->iso_hdl= iso_handle; + //start sent the msg to the bta system control module + bta_sys_sendmsg(p_msg); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} + +void BTA_DmBleGapIsoReadLinkQuality(uint16_t iso_handle) +{ + tBTA_DM_API_ISO_READ_LINK_QUALITY *p_msg; + APPL_TRACE_API("%s", __func__); + if ((p_msg = (tBTA_DM_API_ISO_READ_LINK_QUALITY *) osi_malloc(sizeof(tBTA_DM_API_ISO_READ_LINK_QUALITY))) != NULL) { + memset(p_msg, 0, sizeof(tBTA_DM_API_ISO_READ_LINK_QUALITY)); + p_msg->hdr.event = BTA_DM_API_ISO_READ_LINK_QUALITY_EVT; + + p_msg->iso_hdl= iso_handle; + //start sent the msg to the bta system control module + bta_sys_sendmsg(p_msg); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} + +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +void BTA_DmBleIsoSetCigParams(uint8_t cig_id, uint32_t sdu_int_c_to_p, uint32_t sdu_int_p_to_c, uint8_t worse_case_SCA, uint8_t packing, + uint8_t framing, uint16_t mtl_c_to_p, uint16_t mtl_p_to_c, uint8_t cis_cnt, uint8_t *cis_params) +{ + tBTA_DM_API_SET_CIG_PARAM *p_buf; + if ((p_buf = (tBTA_DM_API_SET_CIG_PARAM *)osi_malloc(sizeof(tBTA_DM_API_SET_CIG_PARAM))) != NULL) { + p_buf->hdr.event = BTA_DM_API_SET_CIG_PARAMS_EVT; + p_buf->cig_id = cig_id; + p_buf->sdu_int_c_to_p = sdu_int_c_to_p; + p_buf->sdu_int_p_to_c = sdu_int_p_to_c; + p_buf->worse_case_SCA = worse_case_SCA; + p_buf->packing = packing; + p_buf->framing = framing; + p_buf->mtl_c_to_p = mtl_c_to_p; + p_buf->mtl_p_to_c = mtl_p_to_c; + p_buf->cis_cnt = cis_cnt; + memcpy(&p_buf->cis_params[0], cis_params, sizeof(struct bta_iso_cis_params) * cis_cnt); + + bta_sys_sendmsg(p_buf); + } + return; +} + +void BTA_DmBleIsoSetCigParamsTest(uint8_t cig_id, uint32_t sdu_int_c_to_p, uint32_t sdu_int_p_to_c, uint8_t ft_c_to_p, uint8_t ft_p_to_c, + uint16_t iso_interval, uint8_t worse_case_SCA, uint8_t packing, uint8_t framing, uint8_t cis_cnt, uint8_t *cis_params_test) +{ + tBTA_DM_API_SET_CIG_PARAM_TEST *p_buf; + if ((p_buf = (tBTA_DM_API_SET_CIG_PARAM_TEST *)osi_malloc(sizeof(tBTA_DM_API_SET_CIG_PARAM_TEST))) != NULL) { + p_buf->hdr.event = BTA_DM_API_SET_CIG_PARAMS_TEST_EVT; + p_buf->cig_id = cig_id; + p_buf->sdu_int_c_to_p = sdu_int_c_to_p; + p_buf->sdu_int_p_to_c = sdu_int_p_to_c; + p_buf->ft_c_to_p = ft_c_to_p; + p_buf->ft_p_to_c = ft_p_to_c; + p_buf->iso_interval = iso_interval; + p_buf->worse_case_SCA = worse_case_SCA; + p_buf->packing = packing; + p_buf->framing = framing; + p_buf->cis_cnt = cis_cnt; + memcpy(&p_buf->cis_params_test[0], cis_params_test, sizeof(struct bta_iso_cis_params_test) * cis_cnt); + + bta_sys_sendmsg(p_buf); + } + return; +} + +void BTA_DmBleIsoCreateCis(uint8_t cig_count, uint8_t *cis_hdl_info) +{ + tBTA_DM_API_CREATE_CIS_PARAM *p_buf; + if ((p_buf = (tBTA_DM_API_CREATE_CIS_PARAM *)osi_malloc(sizeof(tBTA_DM_API_CREATE_CIS_PARAM))) != NULL) { + p_buf->hdr.event = BTA_DM_API_CREATE_CIS_EVT; + p_buf->cis_count = cig_count; + + struct bta_iso_cis_hdls *hdls = (struct bta_iso_cis_hdls *)cis_hdl_info; + + for (uint8_t i = 0; i < cig_count; i++) + { + p_buf->cis_hdls[i].cis_hdl = hdls[i].cis_hdl; + p_buf->cis_hdls[i].acl_hdl = hdls[i].acl_hdl; + } + + bta_sys_sendmsg(p_buf); + } + return; +} + +void BTA_DmBleIsoRemoveCig(uint8_t cig_id) +{ + tBTA_DM_API_REMOVE_CIG_PARAM *p_buf; + if ((p_buf = (tBTA_DM_API_REMOVE_CIG_PARAM *)osi_malloc(sizeof(tBTA_DM_API_REMOVE_CIG_PARAM))) != NULL) { + p_buf->hdr.event = BTA_DM_API_REMOVE_CIG_PARAMS_EVT; + p_buf->cig_id = cig_id; + bta_sys_sendmsg(p_buf); + } + return; +} + +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +void BTA_DmBleIsoAcceptCisReq(uint16_t cis_handle) +{ + tBTA_DM_API_ACCEPT_CIS_REQ_PARAM *p_buf; + if ((p_buf = (tBTA_DM_API_ACCEPT_CIS_REQ_PARAM *)osi_malloc(sizeof(tBTA_DM_API_ACCEPT_CIS_REQ_PARAM))) != NULL) { + p_buf->hdr.event = BTA_DM_API_ACCEPT_CIS_REQ_PARAMS_EVT; + p_buf->cis_handle = cis_handle; + bta_sys_sendmsg(p_buf); + } + return; +} + +void BTA_DmBleIsoRejectCisReq(uint16_t cis_handle, uint8_t reason) +{ + tBTA_DM_API_REJECT_CIS_REQ_PARAM *p_buf; + if ((p_buf = (tBTA_DM_API_REJECT_CIS_REQ_PARAM *)osi_malloc(sizeof(tBTA_DM_API_REJECT_CIS_REQ_PARAM))) != NULL) { + p_buf->hdr.event = BTA_DM_API_REJECT_CIS_REQ_PARAMS_EVT; + p_buf->cis_handle = cis_handle; + p_buf->reason = reason; + bta_sys_sendmsg(p_buf); + } + return; +} +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_EN == TRUE) +void BTA_DmBleIsoDisconCis(uint16_t cis_handle, uint8_t reason) +{ + tBTA_DM_API_DISCON_CIS_PARAM *p_buf; + if ((p_buf = (tBTA_DM_API_DISCON_CIS_PARAM *)osi_malloc(sizeof(tBTA_DM_API_DISCON_CIS_PARAM))) != NULL) { + p_buf->hdr.event = BTA_DM_API_DISCON_CIS_EVT; + p_buf->cis_handle = cis_handle; + p_buf->reason = reason; + bta_sys_sendmsg(p_buf); + } + return; +} +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) + +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_CTE_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +void BTA_DmBleCteSetConnectionlessTransParams(uint8_t adv_handle, uint8_t cte_len, uint8_t cte_type, + uint8_t cte_count, uint8_t switching_pattern_len, uint8_t *antenna_ids) +{ + APPL_TRACE_API("%s", __func__); + + tBTA_DM_BLE_CTE_SET_TRANS_PARAMS *p_buf; + if ((p_buf = (tBTA_DM_BLE_CTE_SET_TRANS_PARAMS *) osi_malloc(sizeof(tBTA_DM_BLE_CTE_SET_TRANS_PARAMS) + switching_pattern_len)) != NULL) { + memset(p_buf, 0, sizeof(tBTA_DM_BLE_CTE_SET_TRANS_PARAMS) + switching_pattern_len); + p_buf->hdr.event = BTA_DM_API_CTE_SET_TRANS_PARAMS; + + p_buf->adv_handle = adv_handle; + p_buf->cte_len = cte_len; + p_buf->cte_type = cte_type; + p_buf->cte_count = cte_count; + p_buf->switching_pattern_len = switching_pattern_len; + p_buf->antenna_ids = (switching_pattern_len != 0) ? (UINT8 *)(p_buf + 1) : NULL; + if (switching_pattern_len) { + memcpy(p_buf->antenna_ids, antenna_ids, switching_pattern_len); + } + //start sent the msg to the bta system control module + bta_sys_sendmsg(p_buf); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} + +void BTA_DmBleCteSetConnectionlessTransEnable(uint8_t adv_handle, uint8_t cte_en) +{ + APPL_TRACE_API("%s", __func__); + + tBTA_DM_BLE_CTE_SET_TRANS_ENABLE *p_buf; + if ((p_buf = (tBTA_DM_BLE_CTE_SET_TRANS_ENABLE *) osi_malloc(sizeof(tBTA_DM_BLE_CTE_SET_TRANS_ENABLE))) != NULL) { + memset(p_buf, 0, sizeof(tBTA_DM_BLE_CTE_SET_TRANS_ENABLE)); + p_buf->hdr.event = BTA_DM_API_CTE_SET_TRANS_ENABLE; + + p_buf->adv_handle = adv_handle; + p_buf->cte_enable = cte_en; + // start sent the msg to the bta system control module + bta_sys_sendmsg(p_buf); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} + +void BTA_DmBleCteSetConnectionlessIqSamplingEnable(uint16_t sync_handle, uint8_t sampling_en, uint8_t slot_dur, + uint8_t max_sampled_ctes, uint8_t switching_pattern_len, uint8_t *ant_ids) +{ + APPL_TRACE_API("%s", __func__); + + tBTA_DM_BLE_CTE_IQ_SAMP_EN *p_buf; + if ((p_buf = (tBTA_DM_BLE_CTE_IQ_SAMP_EN *) osi_malloc(sizeof(tBTA_DM_BLE_CTE_IQ_SAMP_EN) + switching_pattern_len)) != NULL) { + memset(p_buf, 0, sizeof(tBTA_DM_BLE_CTE_IQ_SAMP_EN) + switching_pattern_len); + p_buf->hdr.event = BTA_DM_API_CTE_SET_IQ_SAMPLING_EN; + + p_buf->sync_handle = sync_handle; + p_buf->sampling_en = sampling_en; + p_buf->slot_dur = slot_dur; + p_buf->max_sampled_ctes = max_sampled_ctes; + p_buf->switching_pattern_len = switching_pattern_len; + p_buf->antenna_ids = (switching_pattern_len != 0) ? (UINT8 *)(p_buf + 1) : NULL; + if (switching_pattern_len) { + memcpy(p_buf->antenna_ids, ant_ids, switching_pattern_len); + } + // start sent the msg to the bta system control module + bta_sys_sendmsg(p_buf); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +void BTA_DmBleCteSetConnectionReceiveParams(uint16_t conn_handle, uint8_t sampling_en, uint8_t slot_dur, + uint8_t switching_pattern_len, uint8_t *ant_ids) +{ + APPL_TRACE_API("%s", __func__); + + tBTA_DM_BLE_CTE_RECV_PARAMS *p_buf; + if ((p_buf = (tBTA_DM_BLE_CTE_RECV_PARAMS *) osi_malloc(sizeof(tBTA_DM_BLE_CTE_RECV_PARAMS) + switching_pattern_len)) != NULL) { + memset(p_buf, 0, sizeof(tBTA_DM_BLE_CTE_RECV_PARAMS) + switching_pattern_len); + p_buf->hdr.event = BTA_DM_API_CTE_SET_CONN_CTE_RECV_PARAMS; + + p_buf->conn_handle = conn_handle; + p_buf->sampling_en = sampling_en; + p_buf->slot_dur = slot_dur; + p_buf->switching_pattern_len = switching_pattern_len; + p_buf->antenna_ids = (switching_pattern_len != 0) ? (UINT8 *)(p_buf + 1) : NULL; + if (switching_pattern_len) { + memcpy(p_buf->antenna_ids, ant_ids, switching_pattern_len); + } + // start sent the msg to the bta system control module + bta_sys_sendmsg(p_buf); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} + +void BTA_DmBleCteSetConnectionTransParams(uint16_t conn_handle, uint8_t cte_types, uint8_t switching_pattern_len, uint8_t *ant_ids) +{ + APPL_TRACE_API("%s", __func__); + + tBTA_DM_BLE_CONN_CTE_TRANS_PARAMS *p_buf; + if ((p_buf = (tBTA_DM_BLE_CONN_CTE_TRANS_PARAMS *) osi_malloc(sizeof(tBTA_DM_BLE_CONN_CTE_TRANS_PARAMS) + switching_pattern_len)) != NULL) { + memset(p_buf, 0, sizeof(tBTA_DM_BLE_CONN_CTE_TRANS_PARAMS) + switching_pattern_len); + p_buf->hdr.event = BTA_DM_API_CTE_SET_CONN_CTE_TRANS_PARAMS; + + p_buf->conn_handle = conn_handle; + p_buf->cte_types = cte_types; + p_buf->switching_pattern_len = switching_pattern_len; + p_buf->antenna_ids = (switching_pattern_len != 0) ? (UINT8 *)(p_buf + 1) : NULL; + if (switching_pattern_len) { + memcpy(p_buf->antenna_ids, ant_ids, switching_pattern_len); + } + // start sent the msg to the bta system control module + bta_sys_sendmsg(p_buf); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} + +void BTA_DmBleCteSetConnectionRequestEnable(uint16_t conn_handle, uint8_t enable, uint16_t cte_req_interval, + uint8_t req_cte_len, uint8_t req_cte_Type) +{ + APPL_TRACE_API("%s", __func__); + + tBTA_DM_BLE_CONN_CTE_REQ_EN *p_buf; + if ((p_buf = (tBTA_DM_BLE_CONN_CTE_REQ_EN *) osi_malloc(sizeof(tBTA_DM_BLE_CONN_CTE_REQ_EN))) != NULL) { + memset(p_buf, 0, sizeof(tBTA_DM_BLE_CONN_CTE_REQ_EN)); + p_buf->hdr.event = BTA_DM_API_CTE_SET_CONN_CTE_REQUEST_EN; + + p_buf->conn_handle = conn_handle; + p_buf->enable = enable; + p_buf->cte_req_interval = cte_req_interval; + p_buf->req_cte_len = req_cte_len; + p_buf->req_cte_Type = req_cte_Type; + // start sent the msg to the bta system control module + bta_sys_sendmsg(p_buf); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} + +void BTA_DmBleCteSetConnectionRspEnable(uint16_t conn_handle, uint8_t enable) +{ + APPL_TRACE_API("%s", __func__); + + tBTA_DM_BLE_CONN_CTE_RSP_EN *p_buf; + if ((p_buf = (tBTA_DM_BLE_CONN_CTE_RSP_EN *) osi_malloc(sizeof(tBTA_DM_BLE_CONN_CTE_RSP_EN))) != NULL) { + memset(p_buf, 0, sizeof(tBTA_DM_BLE_CONN_CTE_RSP_EN)); + p_buf->hdr.event = BTA_DM_API_CTE_SET_CONN_CTE_RESPONSE_EN; + + p_buf->conn_handle = conn_handle; + p_buf->enable = enable; + // start sent the msg to the bta system control module + bta_sys_sendmsg(p_buf); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +void BTA_DmBleCteReadAntInfor(void) +{ + APPL_TRACE_API("%s", __func__); + + tBTA_DM_BLE_READ_ANT_INFOR *p_buf; + if ((p_buf = (tBTA_DM_BLE_READ_ANT_INFOR *) osi_malloc(sizeof(tBTA_DM_BLE_READ_ANT_INFOR))) != NULL) { + memset(p_buf, 0, sizeof(tBTA_DM_BLE_READ_ANT_INFOR)); + p_buf->hdr.event = BTA_DM_API_CTE_READ_ANTENNA_INFOR; + // start sent the msg to the bta system control module + bta_sys_sendmsg(p_buf); + } else { + APPL_TRACE_ERROR("%s malloc failed", __func__); + } +} + +#endif // #if (BLE_FEAT_CTE_EN == TRUE) #endif diff --git a/lib/bt/host/bluedroid/bta/dm/bta_dm_cfg.c b/lib/bt/host/bluedroid/bta/dm/bta_dm_cfg.c index a4792ce8..81bbd466 100644 --- a/lib/bt/host/bluedroid/bta/dm/bta_dm_cfg.c +++ b/lib/bt/host/bluedroid/bta/dm/bta_dm_cfg.c @@ -151,13 +151,13 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = { (BTA_DM_PM_SSR2), /* the SSR entry */ #endif { - {{BTA_DM_PM_SNIFF_A2DP_IDX, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */ + {{BTA_DM_PM_SNIFF_AG_OPEN_IDX, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */ {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */ {{BTA_DM_PM_SNIFF_SCO_OPEN_IDX, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open, active */ - {{BTA_DM_PM_SNIFF_A2DP_IDX, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close sniff */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ + {{BTA_DM_PM_SNIFF_SCO_CLOSE_IDX, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close sniff */ + {{BTA_DM_PM_SNIFF_AG_IDLE_IDX, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ {{BTA_DM_PM_RETRY, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ } @@ -231,9 +231,9 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = { {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open, active */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close sniff */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ + {{BTA_DM_PM_SNIFF3, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open, active */ + {{BTA_DM_PM_SNIFF, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close sniff */ + {{BTA_DM_PM_SNIFF, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ {{BTA_DM_PM_RETRY, 7000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ } @@ -409,7 +409,7 @@ tBTA_DM_SSR_SPEC bta_dm_ssr_spec[] = { /*max_lat, min_rmt_to, min_loc_to*/ {0, 0, 0}, /* BTA_DM_PM_SSR0 - do not use SSR */ {0, 0, 2}, /* BTA_DM_PM_SSR1 - HH, can NOT share entry with any other profile, - seting default max latency and min remote timeout as 0, + setting default max latency and min remote timeout as 0, and always read individual device preference from HH module */ {1200, 2, 2}, /* BTA_DM_PM_SSR2 - others (as long as sniff is allowed)*/ {360, 160, 1600} /* BTA_DM_PM_SSR3 - HD */ @@ -466,7 +466,7 @@ tBTA_DM_EIR_CONF bta_dm_eir_cfg = { { /* mask of UUID list in EIR */ 0xFFFFFFFF, /* LSB is the first UUID of the first 32 UUIDs in BTM_EIR_UUID_LKUP_TBL */ 0xFFFFFFFF /* LSB is the first UUID of the next 32 UUIDs in BTM_EIR_UUID_LKUP_TBL */ - /* BTM_EIR_UUID_LKUP_TBL can be overrided */ + /* BTM_EIR_UUID_LKUP_TBL can be overridden */ }, #endif // BTA_EIR_CANNED_UUID_LIST FALSE, /* Not included TX power*/ diff --git a/lib/bt/host/bluedroid/bta/dm/bta_dm_co.c b/lib/bt/host/bluedroid/bta/dm/bta_dm_co.c index c6b62f3a..5c7ee9bd 100644 --- a/lib/bt/host/bluedroid/bta/dm/bta_dm_co.c +++ b/lib/bt/host/bluedroid/bta/dm/bta_dm_co.c @@ -52,6 +52,18 @@ tBTE_APPL_CFG bte_appl_cfg = { BTM_BLE_ONLY_ACCEPT_SPECIFIED_SEC_AUTH_DISABLE, BTM_BLE_OOB_DISABLE, }; + +void bta_dm_co_security_param_init(void) +{ + bte_appl_cfg.ble_auth_req = BTA_LE_AUTH_REQ_SC_MITM_BOND; + bte_appl_cfg.ble_io_cap = BTM_LOCAL_IO_CAPS_BLE; + bte_appl_cfg.ble_init_key = BTM_BLE_INITIATOR_KEY_SIZE; + bte_appl_cfg.ble_resp_key = BTM_BLE_RESPONDER_KEY_SIZE; + bte_appl_cfg.ble_max_key_size = BTM_BLE_MAX_KEY_SIZE; + bte_appl_cfg.ble_min_key_size = BTM_BLE_MIN_KEY_SIZE; + bte_appl_cfg.ble_accept_auth_enable = BTM_BLE_ONLY_ACCEPT_SPECIFIED_SEC_AUTH_DISABLE; + bte_appl_cfg.oob_support = BTM_BLE_OOB_DISABLE; +}; #endif #if (defined CLASSIC_BT_INCLUDED && CLASSIC_BT_INCLUDED == TRUE) diff --git a/lib/bt/host/bluedroid/bta/dm/bta_dm_main.c b/lib/bt/host/bluedroid/bta/dm/bta_dm_main.c index 99736d8e..9fe5e769 100644 --- a/lib/bt/host/bluedroid/bta/dm/bta_dm_main.c +++ b/lib/bt/host/bluedroid/bta/dm/bta_dm_main.c @@ -67,7 +67,12 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { #if (ESP_COEX_VSC_INCLUDED == TRUE) bta_dm_cfg_coex_status, /* BTA_DM_API_CFG_COEX_ST_EVT */ #endif +#if (BLE_VENDOR_HCI_EN == TRUE) bta_dm_send_vendor_hci, /* BTA_DM_API_SEND_VENDOR_HCI_CMD_EVT */ + bta_dm_ble_gap_clear_adv, /* BTA_DM_API_BLE_CLEAR_ADV_EVT */ + bta_dm_ble_gap_set_csa_support, /* BTA_DM_API_BLE_SET_CSA_SUPPORT_EVT */ + bta_dm_ble_gap_set_vendor_evt_mask, /* BTA_DM_API_BLE_SET_VENDOR_EVT_MASK_EVT */ +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) #if (CLASSIC_BT_INCLUDED == TRUE) bta_dm_config_eir, /* BTA_DM_API_CONFIG_EIR_EVT */ bta_dm_set_page_timeout, /* BTA_DM_API_PAGE_TO_SET_EVT */ @@ -76,15 +81,18 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { #if (ENC_KEY_SIZE_CTRL_MODE != ENC_KEY_SIZE_CTRL_MODE_NONE) bta_dm_set_min_enc_key_size, /* BTA_DM_API_SET_MIN_ENC_KEY_SIZE_EVT */ #endif -#endif + bta_dm_set_afh_channels, /* BTA_DM_API_SET_AFH_CHANNELS_EVT */ #if (SDP_INCLUDED == TRUE) bta_dm_read_rmt_name, /* BTA_DM_API_GET_REMOTE_NAME_EVT*/ #endif bta_dm_set_visibility, /* BTA_DM_API_SET_VISIBILITY_EVT */ +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) bta_dm_acl_change, /* BTA_DM_ACL_CHANGE_EVT */ bta_dm_add_device, /* BTA_DM_API_ADD_DEVICE_EVT */ +#if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) bta_dm_close_acl, /* BTA_DM_API_REMOVE_ACL_EVT */ +#endif // #if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) #if (SMP_INCLUDED == TRUE) /* security API events */ bta_dm_bond, /* BTA_DM_API_BOND_EVT */ @@ -130,11 +138,21 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { #endif ///SMP_INCLUDED == TRUE bta_dm_ble_set_bg_conn_type, bta_dm_ble_set_conn_params, /* BTA_DM_API_BLE_CONN_PARAM_EVT */ +#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) bta_dm_ble_set_conn_scan_params, /* BTA_DM_API_BLE_CONN_SCAN_PARAM_EVT */ +#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) +#if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) bta_dm_ble_set_scan_params, /* BTA_DM_API_BLE_SCAN_PARAM_EVT */ +#endif // #if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) +#if (BLE_42_SCAN_EN == TRUE) bta_dm_ble_set_scan_fil_params, /* BTA_DM_API_BLE_SCAN_FIL_PARAM_EVT */ +#endif // #if (BLE_42_SCAN_EN == TRUE) +#if (BLE_HOST_BLE_OBSERVE_EN == TRUE) bta_dm_ble_observe, /* BTA_DM_API_BLE_OBSERVE_EVT */ +#endif // #if (BLE_HOST_BLE_OBSERVE_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) bta_dm_ble_scan, /* BTA_DM_API_BLE_SCAN_EVT */ +#endif // #if (BLE_42_SCAN_EN == TRUE) bta_dm_ble_update_conn_params, /* BTA_DM_API_UPDATE_CONN_PARAM_EVT */ /* This handler function added by Yulong at 2016/9/9 to support the @@ -145,12 +163,14 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { Yulong at 2016/10/19 to support stop the ble advertising setting by the APP */ +#if (BLE_HOST_STOP_ADV_UNUSED == TRUE) bta_dm_ble_stop_advertising, /* BTA_DM_API_BLE_STOP_ADV_EVT */ +#endif // #if (BLE_HOST_STOP_ADV_UNUSED == TRUE) #if BLE_PRIVACY_SPT == TRUE bta_dm_ble_config_local_privacy, /* BTA_DM_API_LOCAL_PRIVACY_EVT */ #endif bta_dm_ble_config_local_icon, /* BTA_DM_API_LOCAL_ICON_EVT */ - bta_dm_ble_set_adv_params, /* BTA_DM_API_BLE_ADV_PARAM_EVT */ +#if (BLE_42_ADV_EN == TRUE) bta_dm_ble_set_adv_params_all, /* BTA_DM_API_BLE_ADV_PARAM_All_EVT */ bta_dm_ble_set_adv_config, /* BTA_DM_API_BLE_SET_ADV_CONFIG_EVT */ /* New function to allow set raw adv @@ -161,36 +181,54 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { response data to HCI */ bta_dm_ble_set_scan_rsp_raw, /* BTA_DM_API_BLE_SET_SCAN_RSP_RAW_EVT */ bta_dm_ble_broadcast, /* BTA_DM_API_BLE_BROADCAST_EVT */ +#endif // #if (BLE_42_ADV_EN == TRUE) bta_dm_ble_set_data_length, /* BTA_DM_API_SET_DATA_LENGTH_EVT */ - bta_dm_ble_set_long_adv, /* BTA_DM_API_BLE_SET_LONG_ADV_EVT */ #if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE bta_dm_cfg_filter_cond, /* BTA_DM_API_CFG_FILTER_COND_EVT */ bta_dm_scan_filter_param_setup, /* BTA_DM_API_SCAN_FILTER_SETUP_EVT */ bta_dm_enable_scan_filter, /* BTA_DM_API_SCAN_FILTER_ENABLE_EVT */ #endif +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) bta_dm_ble_multi_adv_enb, /* BTA_DM_API_BLE_MULTI_ADV_ENB_EVT */ bta_dm_ble_multi_adv_upd_param, /* BTA_DM_API_BLE_MULTI_ADV_PARAM_UPD_EVT */ bta_dm_ble_multi_adv_data, /* BTA_DM_API_BLE_MULTI_ADV_DATA_EVT */ btm_dm_ble_multi_adv_disable, /* BTA_DM_API_BLE_MULTI_ADV_DISABLE_EVT */ +#endif // BLE_HOST_BLE_MULTI_ADV_EN +#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) bta_dm_ble_setup_storage, /* BTA_DM_API_BLE_SETUP_STORAGE_EVT */ +#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) +#if (BLE_HOST_BATCH_SCAN_EN == TRUE) bta_dm_ble_enable_batch_scan, /* BTA_DM_API_BLE_ENABLE_BATCH_SCAN_EVT */ bta_dm_ble_disable_batch_scan, /* BTA_DM_API_BLE_DISABLE_BATCH_SCAN_EVT */ +#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) +#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) bta_dm_ble_read_scan_reports, /* BTA_DM_API_BLE_READ_SCAN_REPORTS_EVT */ +#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) bta_dm_ble_track_advertiser, /* BTA_DM_API_BLE_TRACK_ADVERTISER_EVT */ +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) +#if (BLE_HOST_ENERGY_INFO_EN == TRUE) bta_dm_ble_get_energy_info, /* BTA_DM_API_BLE_ENERGY_INFO_EVT */ +#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) bta_dm_ble_disconnect, /* BTA_DM_API_BLE_DISCONNECT_EVT */ #endif - +#if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) bta_dm_enable_test_mode, /* BTA_DM_API_ENABLE_TEST_MODE_EVT */ bta_dm_disable_test_mode, /* BTA_DM_API_DISABLE_TEST_MODE_EVT */ +#endif // #if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) +#if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) bta_dm_execute_callback, /* BTA_DM_API_EXECUTE_CBACK_EVT */ - +#endif // #if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) +#if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) bta_dm_remove_all_acl, /* BTA_DM_API_REMOVE_ALL_ACL_EVT */ +#endif // #if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) bta_dm_remove_device, /* BTA_DM_API_REMOVE_DEVICE_EVT */ bta_dm_ble_set_channels, /* BTA_DM_API_BLE_SET_CHANNELS_EVT */ bta_dm_update_white_list, /* BTA_DM_API_UPDATE_WHITE_LIST_EVT */ bta_dm_clear_white_list, /* BTA_DM_API_CLEAR_WHITE_LIST_EVT */ +#if (BLE_HOST_READ_TX_POWER_EN == TRUE) bta_dm_ble_read_adv_tx_power, /* BTA_DM_API_BLE_READ_ADV_TX_POWER_EVT */ +#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) bta_dm_read_rssi, /* BTA_DM_API_READ_RSSI_EVT */ #if BLE_INCLUDED == TRUE bta_dm_ble_update_duplicate_exceptional_list,/* BTA_DM_API_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_EVT */ @@ -199,28 +237,38 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { bta_dm_ble_gap_read_phy, /* BTA_DM_API_READ_PHY_EVT */ bta_dm_ble_gap_set_prefer_default_phy, /* BTA_DM_API_SET_PER_DEF_PHY_EVT */ bta_dm_ble_gap_set_prefer_phy, /* BTA_DM_API_SET_PER_PHY_EVT */ +#if (BLE_50_EXTEND_ADV_EN == TRUE) bta_dm_ble_gap_ext_adv_set_rand_addr, /* BTA_DM_API_SET_EXT_ADV_RAND_ADDR_EVT */ bta_dm_ble_gap_ext_adv_set_params, /* BTA_DM_API_SET_EXT_ADV_PARAMS_EVT */ bta_dm_ble_gap_config_ext_adv_data_raw, /* BTA_DM_API_CFG_ADV_DATA_RAW_EVT */ bta_dm_ble_gap_start_ext_adv, /* BTA_DM_API_EXT_ADV_ENABLE_EVT */ bta_dm_ble_gap_ext_adv_set_remove, /* BTA_DM_API_EXT_ADV_SET_REMOVE_EVT */ bta_dm_ble_gap_ext_adv_set_clear, /* BTA_DM_API_EXT_ADV_SET_CLEAR_EVT */ +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) bta_dm_ble_gap_periodic_adv_set_params, /* BTA_DM_API_PERIODIC_ADV_SET_PARAMS_EVT */ bta_dm_ble_gap_periodic_adv_cfg_data_raw, /* BTA_DM_API_PERIODIC_ADV_CFG_DATA_EVT */ bta_dm_ble_gap_periodic_adv_enable, /* BTA_DM_API_PERIODIC_ADV_ENABLE_EVT */ +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) bta_dm_ble_gap_periodic_adv_create_sync, /* BTA_DM_API_PERIODIC_ADV_SYNC_EVT */ bta_dm_ble_gap_periodic_adv_sync_cancel, /* BTA_DM_API_PERIODIC_ADV_SYNC_CANCEL_EVT */ bta_dm_ble_gap_periodic_adv_sync_terminate, /* BTA_DM_API_PERIODIC_ADV_SYNC_TERMINATE_EVT */ bta_dm_ble_gap_periodic_adv_add_dev_to_list, /* BTA_DM_API_PERIODIC_ADV_ADD_DEV_TO_LSIT_EVT */ bta_dm_ble_gap_periodic_adv_remove_dev_from_list, /* BTA_DM_API_PERIODIC_ADV_REMOVE_DEV_FROM_LSIT_EVT */ bta_dm_ble_gap_periodic_adv_clear_dev, /* BTA_DM_API_PERIODIC_ADV_CLEAR_DEV_EVT */ +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if (BLE_50_EXTEND_SCAN_EN == TRUE) bta_dm_ble_gap_set_ext_scan_params, /* BTA_DM_API_SET_EXT_SCAN_PARAMS_EVT */ bta_dm_ble_gap_ext_scan, /* BTA_DM_API_START_EXT_SCAN_EVT */ +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) bta_dm_ble_gap_set_prefer_ext_conn_params, /* BTA_DM_API_SET_PERF_EXT_CONN_PARAMS_EVT */ NULL, /* BTA_DM_API_EXT_CONN_EVT */ +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_DTM_TEST_EN == TRUE) bta_dm_ble_gap_dtm_enhance_tx_start, /* BTA_DM_API_DTM_ENH_TX_START_EVT */ bta_dm_ble_gap_dtm_enhance_rx_start, /* BTA_DM_API_DTM_ENH_RX_START_EVT */ -#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) bta_dm_ble_gap_periodic_adv_recv_enable, /* BTA_DM_API_PERIODIC_ADV_RECV_ENABLE_EVT */ bta_dm_ble_gap_periodic_adv_sync_trans, /* BTA_DM_API_PERIODIC_ADV_SYNC_TRANS_EVT */ @@ -228,14 +276,74 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { bta_dm_ble_gap_set_periodic_adv_sync_trans_params, /* BTA_DM_API_SET_PERIODIC_ADV_SYNC_TRANS_PARAMS_EVT */ #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) #if BLE_INCLUDED == TRUE +#if (BLE_42_DTM_TEST_EN == TRUE) bta_dm_ble_gap_dtm_tx_start, /* BTA_DM_API_DTM_TX_START_EVT */ bta_dm_ble_gap_dtm_rx_start, /* BTA_DM_API_DTM_RX_START_EVT */ +#endif // #if (BLE_42_DTM_TEST_EN == TRUE) +#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) bta_dm_ble_gap_dtm_stop, /* BTA_DM_API_DTM_STOP_EVT */ - bta_dm_ble_gap_clear_adv, /* BTA_DM_API_BLE_CLEAR_ADV_EVT */ +#endif // #if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) bta_dm_ble_gap_set_rpa_timeout, /* BTA_DM_API_SET_RPA_TIMEOUT_EVT */ bta_dm_ble_gap_add_dev_to_resolving_list, /* BTA_DM_API_ADD_DEV_TO_RESOLVING_LIST_EVT */ bta_dm_ble_gap_set_privacy_mode, /* BTA_DM_API_SET_PRIVACY_MODE_EVT */ + bta_dm_read_ble_channel_map, /* BTA_DM_API_BLE_READ_CH_MAP_EVT */ #endif +#if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + bta_dm_ble_big_create, /* BTA_DM_API_ISO_BIG_CREATE_EVT */ + bta_dm_ble_big_create_test, /* BTA_DM_API_ISO_BIG_CREATE_TEST_EVT */ + bta_dm_ble_big_terminate, /* BTA_DM_API_ISO_BIG_TERMINATE_EVT */ +#endif// #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + bta_dm_ble_big_sync_create, /* BTA_DM_API_ISO_BIG_SYNC_CREATE_EVT */ + bta_dm_ble_big_sync_terminate, /* BTA_DM_API_ISO_BIG_SYNC_TERMINATE_EVT */ +#endif// #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + bta_dm_ble_iso_set_data_path, /* BTA_DM_API_ISO_SET_DATA_PATH_EVT */ + bta_dm_ble_iso_remove_data_path, /* BTA_DM_API_ISO_REMOVE_DATA_PATH_EVT */ + bta_dm_ble_iso_read_tx_sync, /* BTA_DM_API_ISO_READ_TX_SYNC_EVT */ + bta_dm_ble_iso_read_link_quality, /* BTA_DM_API_ISO_READ_LINK_QUALITY_EVT */ +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + bta_dm_ble_set_cig_params, /* BTA_DM_API_SET_CIG_PARAMS_EVT */ + bta_dm_ble_set_cig_params_test, /* BTA_DM_API_SET_CIG_PARAMS_TEST_EVT */ + bta_dm_ble_create_cis, /* BTA_DM_API_CREATE_CIS_EVT */ + bta_dm_ble_remove_cig, /* BTA_DM_API_REMOVE_CIG_PARAMS_EVT*/ +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + bta_dm_ble_accept_cis_req, /* BTA_DM_API_ACCEPT_CIS_REQ_PARAMS_EVT */ + bta_dm_ble_reject_cis_req, /* BTA_DM_API_REJECT_CIS_REQ_PARAMS_EVT */ +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_EN == TRUE) + bta_dm_ble_discon_cis, /* BTA_DM_API_DISCON_CIS_EVT */ +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) +#endif // #if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + bta_dm_ble_set_cte_trans_params, /* BTA_DM_API_CTE_SET_TRANS_PARAMS */ + bta_dm_ble_set_cte_trans_enable, /* BTA_DM_API_CTE_SET_TRANS_ENABLE */ + bta_dm_ble_set_iq_sampling_en, /* BTA_DM_API_CTE_SET_IQ_SAMPLING_EN */ +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + bta_dm_ble_set_conn_cte_recv_params, /* BTA_DM_API_CTE_SET_CONN_CTE_RECV_PARAMS */ + bta_dm_ble_set_conn_trans_params, /* BTA_DM_API_CTE_SET_CONN_CTE_TRANS_PARAMS */ + bta_dm_ble_set_conn_cte_req_en, /* BTA_DM_API_CTE_SET_CONN_CTE_REQUEST_EN */ + bta_dm_ble_set_conn_cte_rsp_en, /* BTA_DM_API_CTE_SET_CONN_CTE_RESPONSE_EN */ +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + bta_dm_ble_read_cte_ant_infor, /* BTA_DM_API_CTE_READ_ANTENNA_INFOR */ +#endif // #if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + bta_dm_api_enh_read_trans_power_level, /* BTA_DM_API_ENH_READ_TRANS_POWER_LEVEL */ + bta_dm_api_read_rem_trans_power_level, /* BTA_DM_API_READ_REM_TRANS_POWER_LEVEL */ + bta_dm_api_set_path_loss_report_params, /* BTA_DM_API_SET_PATH_LOSS_REPORT_PARAMS */ + bta_dm_api_set_path_loss_reporting_en, /* BTA_DM_API_SET_PATH_LOSS_REPORTING_EN */ + bta_dm_api_set_trans_power_reporting_en, /* BTA_DM_API_SET_TRANS_POWER_REPORTING_EN */ +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) + bta_dm_api_set_default_subrate, /* BTA_DM_API_SET_DEFALT_SUBRATE */ + bta_dm_api_subrate_request, /* BTA_DM_API_SUBRATE_REQUEST */ +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) + bta_dm_ble_set_host_feature, /* BTA_DM_API_SET_HOST_FEATURE_EVT */ +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) }; diff --git a/lib/bt/host/bluedroid/bta/dm/bta_dm_pm.c b/lib/bt/host/bluedroid/bta/dm/bta_dm_pm.c index 149b4fac..8167ddf9 100644 --- a/lib/bt/host/bluedroid/bta/dm/bta_dm_pm.c +++ b/lib/bt/host/bluedroid/bta/dm/bta_dm_pm.c @@ -75,7 +75,7 @@ void bta_dm_init_pm(void) { memset(&bta_dm_conn_srvcs, 0x00, sizeof(bta_dm_conn_srvcs)); - /* if there are no power manger entries, so not register */ + /* if there are no power manager entries, so not register */ if (p_bta_dm_pm_cfg[0].app_id != 0) { bta_sys_pm_register((tBTA_SYS_CONN_CBACK *)bta_dm_pm_cback); @@ -694,9 +694,9 @@ static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index) #endif { #if (BTM_SSR_INCLUDED == TRUE) - /* Dont initiate Sniff if controller has alreay accepted + /* Dont initiate Sniff if controller has already accepted * remote sniff params. This avoid sniff loop issue with - * some agrresive headsets who use sniff latencies more than + * some aggressive headsets who use sniff latencies more than * DUT supported range of Sniff intervals.*/ if ((mode == BTM_PM_MD_SNIFF) && (p_peer_dev->info & BTA_DM_DI_ACP_SNIFF)) { APPL_TRACE_DEBUG("%s: already in remote initiate sniff", __func__); @@ -917,7 +917,7 @@ void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data) } else { #if (BTM_SSR_INCLUDED == TRUE) if (p_dev->prev_low) { - /* need to send the SSR paramaters to controller again */ + /* need to send the SSR parameters to controller again */ bta_dm_pm_ssr(p_dev->peer_bdaddr); } p_dev->prev_low = BTM_PM_STS_ACTIVE; @@ -980,6 +980,7 @@ void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data) ) { tBTA_DM_SEC conn; conn.mode_chg.mode = p_data->pm_status.status; + conn.mode_chg.interval = p_data->pm_status.value; bdcpy(conn.mode_chg.bd_addr, p_data->pm_status.bd_addr); bta_dm_cb.p_sec_cback(BTA_DM_PM_MODE_CHG_EVT, (tBTA_DM_SEC *)&conn); } diff --git a/lib/bt/host/bluedroid/bta/dm/include/bta_dm_int.h b/lib/bt/host/bluedroid/bta/dm/include/bta_dm_int.h index 8adc430b..e724b37c 100644 --- a/lib/bt/host/bluedroid/bta/dm/include/bta_dm_int.h +++ b/lib/bt/host/bluedroid/bta/dm/include/bta_dm_int.h @@ -57,7 +57,12 @@ enum { #if (ESP_COEX_VSC_INCLUDED == TRUE) BTA_DM_API_CFG_COEX_ST_EVT, #endif +#if (BLE_VENDOR_HCI_EN == TRUE) BTA_DM_API_SEND_VENDOR_HCI_CMD_EVT, + BTA_DM_API_BLE_CLEAR_ADV_EVT, + BTA_DM_API_BLE_SET_CSA_SUPPORT_EVT, + BTA_DM_API_BLE_SET_VENDOR_EVT_MASK_EVT, +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) #if (CLASSIC_BT_INCLUDED == TRUE) BTA_DM_API_CONFIG_EIR_EVT, BTA_DM_API_PAGE_TO_SET_EVT, @@ -65,17 +70,19 @@ enum { BTA_DM_API_SET_ACL_PKT_TYPES_EVT, #if (ENC_KEY_SIZE_CTRL_MODE != ENC_KEY_SIZE_CTRL_MODE_NONE) BTA_DM_API_SET_MIN_ENC_KEY_SIZE_EVT, -#endif #endif BTA_DM_API_SET_AFH_CHANNELS_EVT, #if (SDP_INCLUDED == TRUE) BTA_DM_API_GET_REMOTE_NAME_EVT, #endif BTA_DM_API_SET_VISIBILITY_EVT, +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) BTA_DM_ACL_CHANGE_EVT, BTA_DM_API_ADD_DEVICE_EVT, +#if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) BTA_DM_API_REMOVE_ACL_EVT, +#endif // #if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) #if (SMP_INCLUDED == TRUE) /* security API events */ BTA_DM_API_BOND_EVT, @@ -121,13 +128,23 @@ enum { #endif ///SMP_INCLUDED == TRUE BTA_DM_API_BLE_SET_BG_CONN_TYPE, BTA_DM_API_BLE_CONN_PARAM_EVT, +#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) BTA_DM_API_BLE_CONN_SCAN_PARAM_EVT, +#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) +#if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) BTA_DM_API_BLE_SCAN_PARAM_EVT, +#endif // #if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) /*******This event added by Yulong at 2016/10/25 to support the scan filter setting for the APP******/ +#if (BLE_42_SCAN_EN == TRUE) BTA_DM_API_BLE_SCAN_FIL_PARAM_EVT, +#endif // #if (BLE_42_SCAN_EN == TRUE) +#if (BLE_HOST_BLE_OBSERVE_EN == TRUE) BTA_DM_API_BLE_OBSERVE_EVT, +#endif // #if (BLE_HOST_BLE_OBSERVE_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) BTA_DM_API_BLE_SCAN_EVT, +#endif // #if (BLE_42_SCAN_EN == TRUE) BTA_DM_API_UPDATE_CONN_PARAM_EVT, /*******This event added by Yulong at 2016/9/9 to support the random address setting for the APP******/ @@ -135,15 +152,17 @@ enum { BTA_DM_API_CLEAR_RAND_ADDR_EVT, /*******This event added by Yulong at 2016/10/19 to support stop the ble advertising setting by the APP******/ +#if (BLE_HOST_STOP_ADV_UNUSED == TRUE) BTA_DM_API_BLE_STOP_ADV_EVT, +#endif // #if (BLE_HOST_STOP_ADV_UNUSED == TRUE) #if BLE_PRIVACY_SPT == TRUE BTA_DM_API_LOCAL_PRIVACY_EVT, #endif BTA_DM_API_LOCAL_ICON_EVT, - BTA_DM_API_BLE_ADV_PARAM_EVT, /*******This event added by Yulong at 2016/10/20 to support setting the ble advertising param by the APP******/ +#if (BLE_42_ADV_EN == TRUE) BTA_DM_API_BLE_ADV_PARAM_All_EVT, BTA_DM_API_BLE_SET_ADV_CONFIG_EVT, /* Add for set raw advertising data */ @@ -152,36 +171,55 @@ enum { /* Add for set raw scan response data */ BTA_DM_API_BLE_SET_SCAN_RSP_RAW_EVT, BTA_DM_API_BLE_BROADCAST_EVT, +#endif // #if (BLE_42_ADV_EN == TRUE) BTA_DM_API_SET_DATA_LENGTH_EVT, - BTA_DM_API_BLE_SET_LONG_ADV_EVT, #if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE BTA_DM_API_CFG_FILTER_COND_EVT, BTA_DM_API_SCAN_FILTER_SETUP_EVT, BTA_DM_API_SCAN_FILTER_ENABLE_EVT, #endif +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) BTA_DM_API_BLE_MULTI_ADV_ENB_EVT, BTA_DM_API_BLE_MULTI_ADV_PARAM_UPD_EVT, BTA_DM_API_BLE_MULTI_ADV_DATA_EVT, BTA_DM_API_BLE_MULTI_ADV_DISABLE_EVT, +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) +#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) BTA_DM_API_BLE_SETUP_STORAGE_EVT, +#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) +#if (BLE_HOST_BATCH_SCAN_EN == TRUE) BTA_DM_API_BLE_ENABLE_BATCH_SCAN_EVT, BTA_DM_API_BLE_DISABLE_BATCH_SCAN_EVT, +#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) +#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) BTA_DM_API_BLE_READ_SCAN_REPORTS_EVT, +#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) BTA_DM_API_BLE_TRACK_ADVERTISER_EVT, +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) +#if (BLE_HOST_ENERGY_INFO_EN == TRUE) BTA_DM_API_BLE_ENERGY_INFO_EVT, +#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) BTA_DM_API_BLE_DISCONNECT_EVT, #endif - +#if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) BTA_DM_API_ENABLE_TEST_MODE_EVT, BTA_DM_API_DISABLE_TEST_MODE_EVT, +#endif // #if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) +#if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) BTA_DM_API_EXECUTE_CBACK_EVT, +#endif // #if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) +#if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) BTA_DM_API_REMOVE_ALL_ACL_EVT, +#endif // #if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) BTA_DM_API_REMOVE_DEVICE_EVT, BTA_DM_API_BLE_SET_CHANNELS_EVT, BTA_DM_API_UPDATE_WHITE_LIST_EVT, BTA_DM_API_CLEAR_WHITE_LIST_EVT, +#if (BLE_HOST_READ_TX_POWER_EN == TRUE) BTA_DM_API_BLE_READ_ADV_TX_POWER_EVT, +#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) BTA_DM_API_READ_RSSI_EVT, #if BLE_INCLUDED == TRUE BTA_DM_API_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_EVT, @@ -190,28 +228,38 @@ enum { BTA_DM_API_READ_PHY_EVT, BTA_DM_API_SET_PER_DEF_PHY_EVT, BTA_DM_API_SET_PER_PHY_EVT, +#if (BLE_50_EXTEND_ADV_EN == TRUE) BTA_DM_API_SET_EXT_ADV_RAND_ADDR_EVT, BTA_DM_API_SET_EXT_ADV_PARAMS_EVT, BTA_DM_API_CFG_ADV_DATA_RAW_EVT, BTA_DM_API_EXT_ADV_ENABLE_EVT, BTA_DM_API_EXT_ADV_SET_REMOVE_EVT, BTA_DM_API_EXT_ADV_SET_CLEAR_EVT, +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) BTA_DM_API_PERIODIC_ADV_SET_PARAMS_EVT, BTA_DM_API_PERIODIC_ADV_CFG_DATA_EVT, BTA_DM_API_PERIODIC_ADV_ENABLE_EVT, +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) BTA_DM_API_PERIODIC_ADV_SYNC_EVT, BTA_DM_API_PERIODIC_ADV_SYNC_CANCEL_EVT, BTA_DM_API_PERIODIC_ADV_SYNC_TERMINATE_EVT, BTA_DM_API_PERIODIC_ADV_ADD_DEV_TO_LSIT_EVT, BTA_DM_API_PERIODIC_ADV_REMOVE_DEV_FROM_LSIT_EVT, BTA_DM_API_PERIODIC_ADV_CLEAR_DEV_EVT, +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if (BLE_50_EXTEND_SCAN_EN == TRUE) BTA_DM_API_SET_EXT_SCAN_PARAMS_EVT, BTA_DM_API_START_EXT_SCAN_EVT, +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) BTA_DM_API_SET_PERF_EXT_CONN_PARAMS_EVT, BTA_DM_API_EXT_CONN_EVT, +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_DTM_TEST_EN == TRUE) BTA_DM_API_DTM_ENH_TX_START_EVT, BTA_DM_API_DTM_ENH_RX_START_EVT, -#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) BTA_DM_API_PERIODIC_ADV_RECV_ENABLE_EVT, BTA_DM_API_PERIODIC_ADV_SYNC_TRANS_EVT, @@ -219,14 +267,74 @@ enum { BTA_DM_API_SET_PERIODIC_ADV_SYNC_TRANS_PARAMS_EVT, #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) #if BLE_INCLUDED == TRUE +#if (BLE_42_DTM_TEST_EN == TRUE) BTA_DM_API_DTM_TX_START_EVT, BTA_DM_API_DTM_RX_START_EVT, +#endif // #if (BLE_42_DTM_TEST_EN == TRUE) +#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) BTA_DM_API_DTM_STOP_EVT, - BTA_DM_API_BLE_CLEAR_ADV_EVT, +#endif // #if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) BTA_DM_API_SET_RPA_TIMEOUT_EVT, BTA_DM_API_ADD_DEV_TO_RESOLVING_LIST_EVT, BTA_DM_API_SET_PRIVACY_MODE_EVT, + BTA_DM_API_BLE_READ_CH_MAP_EVT, #endif +#if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + BTA_DM_API_ISO_BIG_CREATE_EVT, + BTA_DM_API_ISO_BIG_CREATE_TEST_EVT, + BTA_DM_API_ISO_BIG_TERMINATE_EVT, +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + BTA_DM_API_ISO_BIG_SYNC_CREATE_EVT, + BTA_DM_API_ISO_BIG_SYNC_TERMINATE_EVT, +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + BTA_DM_API_ISO_SET_DATA_PATH_EVT, + BTA_DM_API_ISO_REMOVE_DATA_PATH_EVT, + BTA_DM_API_ISO_READ_TX_SYNC_EVT, + BTA_DM_API_ISO_READ_LINK_QUALITY_EVT, +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + BTA_DM_API_SET_CIG_PARAMS_EVT, + BTA_DM_API_SET_CIG_PARAMS_TEST_EVT, + BTA_DM_API_CREATE_CIS_EVT, + BTA_DM_API_REMOVE_CIG_PARAMS_EVT, +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + BTA_DM_API_ACCEPT_CIS_REQ_PARAMS_EVT, + BTA_DM_API_REJECT_CIS_REQ_PARAMS_EVT, +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_EN == TRUE) + BTA_DM_API_DISCON_CIS_EVT, +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) +#endif // #if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + BTA_DM_API_CTE_SET_TRANS_PARAMS, + BTA_DM_API_CTE_SET_TRANS_ENABLE, + BTA_DM_API_CTE_SET_IQ_SAMPLING_EN, +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + BTA_DM_API_CTE_SET_CONN_CTE_RECV_PARAMS, + BTA_DM_API_CTE_SET_CONN_CTE_TRANS_PARAMS, + BTA_DM_API_CTE_SET_CONN_CTE_REQUEST_EN, + BTA_DM_API_CTE_SET_CONN_CTE_RESPONSE_EN, +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + BTA_DM_API_CTE_READ_ANTENNA_INFOR, +#endif // #if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + BTA_DM_API_ENH_READ_TRANS_POWER_LEVEL, + BTA_DM_API_READ_REM_TRANS_POWER_LEVEL, + BTA_DM_API_SET_PATH_LOSS_REPORT_PARAMS, + BTA_DM_API_SET_PATH_LOSS_REPORTING_EN, + BTA_DM_API_SET_TRANS_POWER_REPORTING_EN, +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) + BTA_DM_API_SET_DEFALT_SUBRATE, + BTA_DM_API_SUBRATE_REQUEST, +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) + BTA_DM_API_SET_HOST_FEATURE_EVT, +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) BTA_DM_MAX_EVT }; @@ -367,10 +475,13 @@ typedef struct { tBTA_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_CMPL_CBACK *exceptional_list_cb; }tBTA_DM_API_UPDATE_DUPLICATE_EXCEPTIONAL_LIST; +#if (BLE_HOST_READ_TX_POWER_EN == TRUE) typedef struct { BT_HDR hdr; tBTA_CMPL_CB *read_tx_power_cb; }tBTA_DM_API_READ_ADV_TX_POWER; +#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) + #endif ///BLE_INCLUDED == TRUE typedef struct { @@ -380,6 +491,12 @@ typedef struct { tBTA_CMPL_CB *read_rssi_cb; }tBTA_DM_API_READ_RSSI; +typedef struct { + BT_HDR hdr; + BD_ADDR remote_addr; + tBTA_CMPL_CB *read_ch_map_cb; +} tBTA_DM_API_READ_CH_MAP; + /* data type for BTA_DM_API_SET_VISIBILITY_EVT */ typedef struct { BT_HDR hdr; @@ -626,12 +743,14 @@ typedef struct { UINT8 transport; } tBTA_DM_API_REMOVE_DEVICE; +#if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) /* data type for BTA_DM_API_EXECUTE_CBACK_EVT */ typedef struct { BT_HDR hdr; void *p_param; tBTA_DM_EXEC_CBACK *p_exec_cback; } tBTA_DM_API_EXECUTE_CBACK; +#endif // #if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) /* data type for tBTA_DM_API_SET_ENCRYPTION */ typedef struct { @@ -737,13 +856,14 @@ typedef struct { tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback; } tBTA_DM_API_BLE_SCAN_FILTER_PARAMS; - +#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) /* set scan parameter for BLE connections */ typedef struct { BT_HDR hdr; UINT16 scan_int; UINT16 scan_window; } tBTA_DM_API_BLE_CONN_SCAN_PARAMS; +#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) /* Data type for start/stop observe */ typedef struct { @@ -801,14 +921,6 @@ typedef struct { tBTA_ADD_DEV_TO_RESOLVING_LIST_CMPL_CBACK *p_add_dev_to_resolving_list_callback; // Callback function pointer } tBTA_DM_API_ADD_DEV_TO_RESOLVING_LIST; -/* set adv parameter for BLE advertising */ -typedef struct { - BT_HDR hdr; - UINT16 adv_int_min; - UINT16 adv_int_max; - tBLE_BD_ADDR *p_dir_bda; -} tBTA_DM_API_BLE_ADV_PARAMS; - /* set adv parameter for BLE advertising */ typedef struct { BT_HDR hdr; @@ -829,6 +941,7 @@ typedef struct { } tBTA_DM_API_BLE_FEATURE; +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) /* multi adv data structure */ typedef struct { BT_HDR hdr; @@ -855,6 +968,7 @@ typedef struct { BT_HDR hdr; UINT8 inst_id; } tBTA_DM_API_BLE_MULTI_ADV_DISABLE; +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) typedef struct { BT_HDR hdr; @@ -872,13 +986,7 @@ typedef struct { tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback; } tBTA_DM_API_SET_ADV_CONFIG_RAW; -typedef struct { - BT_HDR hdr; - UINT8 *adv_data; - UINT8 adv_data_len; - tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback; -} tBTA_DM_API_SET_LONG_ADV; - +#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) typedef struct { BT_HDR hdr; UINT8 batch_scan_full_max; @@ -889,7 +997,9 @@ typedef struct { tBTA_BLE_SCAN_REP_CBACK *p_read_rep_cback; tBTA_DM_BLE_REF_VALUE ref_value; } tBTA_DM_API_SET_STORAGE_CONFIG; +#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) +#if (BLE_HOST_BATCH_SCAN_EN == TRUE) typedef struct { BT_HDR hdr; tBTA_BLE_BATCH_SCAN_MODE scan_mode; @@ -904,29 +1014,37 @@ typedef struct { BT_HDR hdr; tBTA_DM_BLE_REF_VALUE ref_value; } tBTA_DM_API_DISABLE_SCAN; +#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) +#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) typedef struct { BT_HDR hdr; tBTA_BLE_BATCH_SCAN_MODE scan_type; tBTA_DM_BLE_REF_VALUE ref_value; } tBTA_DM_API_READ_SCAN_REPORTS; +#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) typedef struct { BT_HDR hdr; tBTA_DM_BLE_REF_VALUE ref_value; tBTA_BLE_TRACK_ADV_CBACK *p_track_adv_cback; } tBTA_DM_API_TRACK_ADVERTISER; +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) +#if (BLE_HOST_ENERGY_INFO_EN == TRUE) typedef struct { BT_HDR hdr; tBTA_BLE_ENERGY_INFO_CBACK *p_energy_info_cback; } tBTA_DM_API_ENERGY_INFO; +#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) typedef struct { BT_HDR hdr; BD_ADDR remote_bda; } tBTA_DM_API_BLE_DISCONNECT; +#if (BLE_42_DTM_TEST_EN == TRUE) typedef struct { BT_HDR hdr; UINT8 tx_channel; @@ -940,6 +1058,7 @@ typedef struct { UINT8 rx_channel; tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback; } tBTA_DM_API_BLE_DTM_RX_START; +#endif // #if (BLE_42_DTM_TEST_EN == TRUE) typedef struct { BT_HDR hdr; @@ -959,8 +1078,87 @@ typedef struct { tBTA_SET_PRIVACY_MODE_CMPL_CBACK *p_cback; } tBTA_DM_API_SET_PRIVACY_MODE; +typedef struct { + BT_HDR hdr; + UINT8 csa_select; + tBTA_SET_CSA_SUPPORT_CMPL_CBACK *p_cback; +} tBTA_DM_API_BLE_SET_CSA_SUPPORT; + +typedef struct { + BT_HDR hdr; + UINT32 evt_mask; + tBTA_SET_VENDOR_EVT_MASK_CBACK *p_cback; +} tBTA_DM_API_BLE_SET_VENDOR_EVT_MASK; + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 phy; +} tBTA_DM_API_BLE_ENH_READ_TANS_PWR_LEVEL; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 phy; +} tBTA_DM_API_BLE_READ_REMOTE_TANS_PWR_LEVEL; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 high_threshold; + UINT8 high_hysteresis; + UINT8 low_threshold; + UINT8 low_hysteresis; + UINT16 min_time_spent; +} tBTA_DM_API_BLE_SET_PATH_LOSS_RPT_PARAMS; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 enable; +} tBTA_DM_API_BLE_SET_PATH_LOSS_RPT_ENABLE; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 local_enable; + UINT8 remote_enable; +} tBTA_DM_API_BLE_SET_TRANS_PWR_RPT_ENABLE; +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +typedef struct { + BT_HDR hdr; + UINT16 subrate_min; + UINT16 subrate_max; + UINT16 max_latency; + UINT16 continuation_number; + UINT16 supervision_timeout; +} tBTA_DM_API_BLE_SET_DEFAULT_SUBRATE; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT16 subrate_min; + UINT16 subrate_max; + UINT16 max_latency; + UINT16 continuation_number; + UINT16 supervision_timeout; +} tBTA_DM_API_BLE_SUBRATE_REQUEST; +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + +#if (BLE_50_FEATURE_SUPPORT == TRUE) +typedef struct { + BT_HDR hdr; + uint16_t bit_num; + uint8_t bit_val; +} tBTA_DM_API_SET_HOST_FEATURE; +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + #endif /* BLE_INCLUDED */ +#if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) /* data type for BTA_DM_API_REMOVE_ACL_EVT */ typedef struct { BT_HDR hdr; @@ -969,13 +1167,17 @@ typedef struct { tBTA_TRANSPORT transport; } tBTA_DM_API_REMOVE_ACL; +#endif // #if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) +#if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) /* data type for BTA_DM_API_REMOVE_ALL_ACL_EVT */ typedef struct { BT_HDR hdr; tBTA_DM_LINK_TYPE link_type; } tBTA_DM_API_REMOVE_ALL_ACL; +#endif // #if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) + typedef struct { BT_HDR hdr; BD_ADDR bd_addr; @@ -1013,8 +1215,8 @@ typedef struct { tBTA_DM_BLE_REF_VALUE ref_value; } tBTA_DM_API_SCAN_FILTER_PARAM_SETUP; #endif -#if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_DTM_TEST_EN == TRUE) typedef struct { BT_HDR hdr; UINT8 tx_channel; @@ -1030,10 +1232,12 @@ typedef struct { UINT8 modulation_index; tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback; } tBTA_DM_API_BLE_DTM_ENH_RX_START; +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) #define BTA_PHY_1M_MASK (1 << 0) #define BTA_PHY_2M_MASK (1 << 1) -#define BTAS_PHY_CODED_MASK (1 << 2) +#define BTA_PHY_CODED_MASK (1 << 2) typedef struct { BT_HDR hdr; BD_ADDR bd_addr; @@ -1199,6 +1403,215 @@ typedef struct { } tBTA_DM_API_SET_PAST_PARAMS; #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +typedef struct { + BT_HDR hdr; + tBTA_DM_BLE_BIG_CREATE_PARAMS big_creat_param; +} tBTA_DM_API_BIG_CREATE; +typedef struct { + BT_HDR hdr; + tBTA_DM_BLE_BIG_CREATE_TEST_PARAMS big_creat_test_param; +} tBTA_DM_API_BIG_CREATE_TEST; +typedef struct { + BT_HDR hdr; + tBTA_DM_BLE_BIG_TERMINATE_PARAMS big_terminate_param; +} tBTA_DM_API_BIG_TERMINATE; +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +typedef struct { + BT_HDR hdr; + tBTA_DM_BLE_BIG_SYNC_CREATE_PARAMS big_sync_param; +} tBTA_DM_API_BIG_SYNC_CREATE; + +typedef struct { + BT_HDR hdr; + tBTA_DM_BLE_BIG_SYNC_TERMINATE_PARAMS big_sync_terminate_param; +} tBTA_DM_API_BIG_SYNC_TERMINATE; +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +typedef struct { + BT_HDR hdr; + tBTA_DM_BLE_ISO_SET_DATA_PATH_PARAMS iso_data_path_param; +} tBTA_DM_API_ISO_DATA_PATH; + +typedef struct { + BT_HDR hdr; + tBTA_DM_BLE_ISO_REMOVE_DATA_PATH_PARAMS iso_data_path_remove_param; +} tBTA_DM_API_ISO_DATA_PATH_REMOVE; + +typedef struct { + BT_HDR hdr; + uint16_t iso_hdl; +} tBTA_DM_API_ISO_READ_TX_SYNC; + +typedef struct { + BT_HDR hdr; + uint16_t iso_hdl; +} tBTA_DM_API_ISO_READ_LINK_QUALITY; + +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +struct bta_iso_cis_params { + UINT8 cis_id; + UINT16 max_sdu_c_to_p; + UINT16 max_sdu_p_to_c; + UINT8 phy_c_to_p; + UINT8 phy_p_to_c; + UINT8 rtn_c_to_p; + UINT8 rtn_p_to_c; +} __attribute__((packed)); + +struct bta_iso_cis_params_test { + UINT8 cis_id; + UINT8 nse; + UINT16 max_sdu_c_to_p; + UINT16 max_sdu_p_to_c; + UINT16 max_pdu_c_to_p; + UINT16 max_pdu_p_to_c; + UINT8 phy_c_to_p; + UINT8 phy_p_to_c; + UINT8 bn_c_to_p; + UINT8 bn_p_to_c; +} __attribute__((packed)); + +typedef struct { + BT_HDR hdr; + UINT8 cig_id; + UINT32 sdu_int_c_to_p; + UINT32 sdu_int_p_to_c; + UINT8 worse_case_SCA; + UINT8 packing; + UINT8 framing; + UINT16 mtl_c_to_p; // max_transport_latency_c_to_p + UINT16 mtl_p_to_c; // max_transport_latency_p_to_c + UINT8 cis_cnt; + struct bta_iso_cis_params cis_params[BLE_ISO_CIS_MAX_COUNT]; +} tBTA_DM_API_SET_CIG_PARAM; + +typedef struct { + BT_HDR hdr; + UINT8 cig_id; + UINT32 sdu_int_c_to_p; + UINT32 sdu_int_p_to_c; + UINT8 ft_c_to_p; + UINT8 ft_p_to_c; + UINT16 iso_interval; + UINT8 worse_case_SCA; + UINT8 packing; + UINT8 framing; + UINT8 cis_cnt; + struct bta_iso_cis_params_test cis_params_test[BLE_ISO_CIS_MAX_COUNT]; +} tBTA_DM_API_SET_CIG_PARAM_TEST; + +struct bta_iso_cis_hdls { + uint16_t cis_hdl; + uint16_t acl_hdl; +}__attribute__((packed)); + +typedef struct { + BT_HDR hdr; + uint8_t cis_count; + struct bta_iso_cis_hdls cis_hdls[BLE_ISO_CIS_MAX_COUNT]; +} tBTA_DM_API_CREATE_CIS_PARAM; + +typedef struct { + BT_HDR hdr; + UINT8 cig_id; +} tBTA_DM_API_REMOVE_CIG_PARAM; + +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +typedef struct { + BT_HDR hdr; + UINT16 cis_handle; +} tBTA_DM_API_ACCEPT_CIS_REQ_PARAM; + +typedef struct { + BT_HDR hdr; + UINT16 cis_handle; + UINT8 reason; +} tBTA_DM_API_REJECT_CIS_REQ_PARAM; +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_EN == TRUE) +typedef struct { + BT_HDR hdr; + UINT16 cis_handle; + UINT8 reason; +} tBTA_DM_API_DISCON_CIS_PARAM; +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) + +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_CTE_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +typedef struct { + BT_HDR hdr; + UINT8 adv_handle; + UINT8 cte_len; + UINT8 cte_type; + UINT8 cte_count; + UINT8 switching_pattern_len; + UINT8 *antenna_ids; +} tBTA_DM_BLE_CTE_SET_TRANS_PARAMS; + +typedef struct { + BT_HDR hdr; + UINT8 adv_handle; + UINT8 cte_enable; +} tBTA_DM_BLE_CTE_SET_TRANS_ENABLE; + +typedef struct { + BT_HDR hdr; + UINT16 sync_handle; + UINT8 sampling_en; + UINT8 slot_dur; + UINT8 max_sampled_ctes; + UINT8 switching_pattern_len; + UINT8 *antenna_ids; +} tBTA_DM_BLE_CTE_IQ_SAMP_EN; +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 sampling_en; + UINT8 slot_dur; + UINT8 switching_pattern_len; + UINT8 *antenna_ids; +} tBTA_DM_BLE_CTE_RECV_PARAMS; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 cte_types; + UINT8 switching_pattern_len; + UINT8 *antenna_ids; +} tBTA_DM_BLE_CONN_CTE_TRANS_PARAMS; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 enable; + UINT16 cte_req_interval; + UINT8 req_cte_len; + UINT8 req_cte_Type; +} tBTA_DM_BLE_CONN_CTE_REQ_EN; + +typedef struct { + BT_HDR hdr; + UINT16 conn_handle; + UINT8 enable; +} tBTA_DM_BLE_CONN_CTE_RSP_EN; +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + +typedef struct { + BT_HDR hdr; +} tBTA_DM_BLE_READ_ANT_INFOR; +#endif // #if (BLE_FEAT_CTE_EN == TRUE) + /* union of all data types */ typedef union { /* event buffer header */ @@ -1227,10 +1640,14 @@ typedef union { #if (BLE_INCLUDED == TRUE) tBTA_DM_API_BLE_SET_CHANNELS ble_set_channels; tBTA_DM_API_UPDATE_WHITE_LIST white_list; +#if (BLE_HOST_READ_TX_POWER_EN == TRUE) tBTA_DM_API_READ_ADV_TX_POWER read_tx_power; +#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) #endif ///BLE_INCLUDED == TRUE tBTA_DM_API_READ_RSSI rssi; + tBTA_DM_API_READ_CH_MAP ch_map; + tBTA_DM_API_SET_VISIBILITY set_visibility; tBTA_DM_API_ADD_DEVICE add_dev; @@ -1278,9 +1695,9 @@ typedef union { #endif /* #if (BTA_DM_QOS_INCLUDED == TRUE) */ tBTA_DM_API_DI_DISC di_disc; - +#if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) tBTA_DM_API_EXECUTE_CBACK exec_cback; - +#endif // #if (BLE_HOST_EXECUTE_CBACK_EN == TRUE) tBTA_DM_API_SET_ENCRYPTION set_encryption; #if BLE_INCLUDED == TRUE @@ -1291,19 +1708,21 @@ typedef union { tBTA_DM_API_BLE_SEC_GRANT ble_sec_grant; tBTA_DM_API_BLE_SET_BG_CONN_TYPE ble_set_bd_conn_type; tBTA_DM_API_BLE_CONN_PARAMS ble_set_conn_params; +#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) tBTA_DM_API_BLE_CONN_SCAN_PARAMS ble_set_conn_scan_params; +#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) +#if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) tBTA_DM_API_BLE_SCAN_PARAMS ble_set_scan_params; +#endif // #if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) tBTA_DM_API_BLE_SCAN_FILTER_PARAMS ble_set_scan_fil_params; tBTA_DM_API_BLE_OBSERVE ble_observe; tBTA_DM_API_BLE_SCAN ble_scan; tBTA_DM_API_ENABLE_PRIVACY ble_remote_privacy; tBTA_DM_API_LOCAL_PRIVACY ble_local_privacy; tBTA_DM_API_LOCAL_ICON ble_local_icon; - tBTA_DM_API_BLE_ADV_PARAMS ble_set_adv_params; tBTA_DM_API_BLE_ADV_PARAMS_ALL ble_set_adv_params_all; tBTA_DM_API_SET_ADV_CONFIG ble_set_adv_data; tBTA_DM_API_SET_ADV_CONFIG_RAW ble_set_adv_data_raw; - tBTA_DM_API_SET_LONG_ADV ble_set_long_adv_data; #if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE tBTA_DM_API_SCAN_FILTER_PARAM_SETUP ble_scan_filt_param_setup; tBTA_DM_API_CFG_FILTER_COND ble_cfg_filter_cond; @@ -1315,61 +1734,148 @@ typedef union { tBTA_DM_APT_CLEAR_ADDR clear_addr; tBTA_DM_API_SET_RPA_TIMEOUT set_rpa_timeout; tBTA_DM_API_ADD_DEV_TO_RESOLVING_LIST add_dev_to_resolving_list; + +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) tBTA_DM_API_BLE_MULTI_ADV_ENB ble_multi_adv_enb; tBTA_DM_API_BLE_MULTI_ADV_PARAM ble_multi_adv_param; tBTA_DM_API_BLE_MULTI_ADV_DATA ble_multi_adv_data; tBTA_DM_API_BLE_MULTI_ADV_DISABLE ble_multi_adv_disable; - +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) +#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) tBTA_DM_API_SET_STORAGE_CONFIG ble_set_storage; +#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) +#if (BLE_HOST_BATCH_SCAN_EN == TRUE) tBTA_DM_API_ENABLE_SCAN ble_enable_scan; +#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) +#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) tBTA_DM_API_READ_SCAN_REPORTS ble_read_reports; +#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) +#if (BLE_HOST_BATCH_SCAN_EN == TRUE) tBTA_DM_API_DISABLE_SCAN ble_disable_scan; +#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) tBTA_DM_API_TRACK_ADVERTISER ble_track_advert; +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) +#if (BLE_HOST_ENERGY_INFO_EN == TRUE) tBTA_DM_API_ENERGY_INFO ble_energy_info; +#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) tBTA_DM_API_BLE_DISCONNECT ble_disconnect; tBTA_DM_API_UPDATE_DUPLICATE_EXCEPTIONAL_LIST ble_duplicate_exceptional_list; #if (BLE_50_FEATURE_SUPPORT == TRUE) tBTA_DM_API_READ_PHY ble_read_phy; tBTA_DM_API_SET_PER_DEF_PHY ble_set_per_def_phy; tBTA_DM_API_SET_PER_PHY ble_set_per_phy; +#if (BLE_50_EXTEND_ADV_EN == TRUE) tBTA_DM_API_EXT_ADV_SET_RAND_ADDR ble_set_ext_adv_rand_addr; tBTA_DM_API_EXT_ADV_SET_PARAMS ble_set_ext_adv_params; tBTA_DM_API_CFG_EXT_ADV_DATA ble_cfg_ext_adv_data; tBTA_DM_API_BLE_EXT_ADV ble_start_ext_adv; tBTA_DM_API_BLE_EXT_ADV_SET_REMOVE ble_ext_adv_set_remove; tBTA_DM_API_BLE_EXT_ADV_SET_CLEAR ble_ext_adv_set_clear; +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) tBTA_DM_API_BLE_PERIODIC_ADV_SET_PARAMS ble_set_periodic_adv_params; tBTA_DM_API_CFG_PERIODIC_ADV_DATA ble_cfg_periodic_adv_data; tBTA_DM_API_ENABLE_PERIODIC_ADV ble_enable_periodic_adv; +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) tBTA_DM_API_PERIODIC_ADV_SYNC ble_periodic_adv_sync; tBTA_DM_API_PERIODIC_ADV_SYNC_CANCEL ble_periodic_adv_sync_cancel; tBTA_DM_API_PERIODIC_ADV_SYNC_TERM ble_periodic_adv_sync_term; tBTA_DM_API_PERIODIC_ADV_ADD_DEV_TO_LIST ble_periodic_adv_add_dev_to_list; tBTA_DM_API_PERIODIC_ADV_REMOVE_DEV_FROM_LIST ble_periodic_adv_remove_dev_from_list; tBTA_DM_API_PERIODIC_ADV_DEV_CLEAR ble_periodic_adv_clear_dev; +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if (BLE_50_EXTEND_SCAN_EN == TRUE) tBTA_DM_API_SET_EXT_SCAN_PARAMS ble_set_ext_scan_params; tBTA_DM_API_EXT_SCAN ble_ext_scan; +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) tBTA_DM_API_SET_PER_EXT_CONN_PARAMS ble_set_per_ext_conn_params; +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_DTM_TEST_EN == TRUE) tBTA_DM_API_BLE_DTM_ENH_TX_START dtm_enh_tx_start; tBTA_DM_API_BLE_DTM_ENH_RX_START dtm_enh_rx_start; -#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) tBTA_DM_API_PERIODIC_ADV_RECV_ENABLE ble_periodic_adv_recv_enable; tBTA_DM_API_PERIODIC_ADV_SYNC_TRANS ble_periodic_adv_sync_trans; tBTA_DM_API_PERIODIC_ADV_SET_INFO_TRANS ble_periodic_adv_set_info_trans; tBTA_DM_API_SET_PAST_PARAMS ble_set_past_params; #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) - +#if (BLE_42_DTM_TEST_EN == TRUE) tBTA_DM_API_BLE_DTM_TX_START dtm_tx_start; tBTA_DM_API_BLE_DTM_RX_START dtm_rx_start; +#endif // #if (BLE_42_DTM_TEST_EN == TRUE) tBTA_DM_API_BLE_DTM_STOP dtm_stop; tBTA_DM_API_CLEAR_ADV ble_clear_adv; tBTA_DM_API_SET_PRIVACY_MODE ble_set_privacy_mode; + tBTA_DM_API_BLE_SET_CSA_SUPPORT ble_set_csa_support; + tBTA_DM_API_BLE_SET_VENDOR_EVT_MASK ble_set_vendor_evt_mask; #endif - +#if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) tBTA_DM_API_REMOVE_ACL remove_acl; +#endif // #if (BLE_HOST_REMOVE_AN_ACL_EN == TRUE) +#if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) tBTA_DM_API_REMOVE_ALL_ACL remove_all_acl; - +#endif // #if (BLE_HOST_REMOVE_ALL_ACL_EN == TRUE) + +#if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + tBTA_DM_API_BIG_CREATE big_creat; + tBTA_DM_API_BIG_CREATE_TEST big_creat_test; + tBTA_DM_API_BIG_TERMINATE big_terminate; +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + tBTA_DM_API_BIG_SYNC_CREATE big_sync; + tBTA_DM_API_BIG_SYNC_TERMINATE big_sync_terminate; +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + tBTA_DM_API_ISO_DATA_PATH iso_set_data_path; + tBTA_DM_API_ISO_DATA_PATH_REMOVE iso_remove_data_path; + tBTA_DM_API_ISO_READ_TX_SYNC iso_read_tx_sync; + tBTA_DM_API_ISO_READ_LINK_QUALITY iso_read_link_quality; +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + tBTA_DM_API_SET_CIG_PARAM api_cig_params; + tBTA_DM_API_SET_CIG_PARAM_TEST api_cig_params_test; + tBTA_DM_API_CREATE_CIS_PARAM create_cis; + tBTA_DM_API_REMOVE_CIG_PARAM remove_cig; +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + tBTA_DM_API_ACCEPT_CIS_REQ_PARAM accept_cis_req; + tBTA_DM_API_REJECT_CIS_REQ_PARAM reject_cis_req; +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_EN == TRUE) + tBTA_DM_API_DISCON_CIS_PARAM discon_cis; +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) +#endif // #if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + tBTA_DM_BLE_CTE_SET_TRANS_PARAMS set_cte_trans_params; + tBTA_DM_BLE_CTE_SET_TRANS_ENABLE set_trans_en; + tBTA_DM_BLE_CTE_IQ_SAMP_EN iq_samp_en; +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + tBTA_DM_BLE_CTE_RECV_PARAMS recv_params; + tBTA_DM_BLE_CONN_CTE_TRANS_PARAMS conn_trans_params; + tBTA_DM_BLE_CONN_CTE_REQ_EN conn_req_en; + tBTA_DM_BLE_CONN_CTE_RSP_EN conn_rsp_en; +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + tBTA_DM_BLE_READ_ANT_INFOR read_ant_infor; +#endif // #if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + tBTA_DM_API_BLE_ENH_READ_TANS_PWR_LEVEL enh_read_trans_pwr_level; + tBTA_DM_API_BLE_READ_REMOTE_TANS_PWR_LEVEL remote_trans_pwr_level; + tBTA_DM_API_BLE_SET_PATH_LOSS_RPT_PARAMS path_loss_rpt_params; + tBTA_DM_API_BLE_SET_PATH_LOSS_RPT_ENABLE path_loss_rpt_en; + tBTA_DM_API_BLE_SET_TRANS_PWR_RPT_ENABLE trans_pwr_rpt_en; +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) + tBTA_DM_API_BLE_SET_DEFAULT_SUBRATE default_subrate; + tBTA_DM_API_BLE_SUBRATE_REQUEST subrate_request; +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) + tBTA_DM_API_SET_HOST_FEATURE set_host_feat; +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) } tBTA_DM_MSG; @@ -1483,8 +1989,12 @@ typedef struct { tBTA_DM_BLE_PF_CFG_CBACK *p_scan_filt_cfg_cback; tBTA_DM_BLE_PF_STATUS_CBACK *p_scan_filt_status_cback; tBTA_DM_BLE_PF_PARAM_CBACK *p_scan_filt_param_cback; +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) tBTA_BLE_MULTI_ADV_CBACK *p_multi_adv_cback; +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) +#if (BLE_HOST_ENERGY_INFO_EN == TRUE) tBTA_BLE_ENERGY_INFO_CBACK *p_energy_info_cback; +#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) #endif UINT16 state; BOOLEAN disabling; @@ -1590,6 +2100,7 @@ typedef struct { #if (SDP_INCLUDED == TRUE) tSDP_DISCOVERY_DB *p_di_db; /* pointer to the DI discovery database */ #endif ///SDP_INCLUDED == TRUE + BOOLEAN uuid_added; UINT8 di_num; /* total local DI record number */ UINT32 di_handle[BTA_DI_NUM_MAX]; /* local DI record handle, the first one is primary record */ } tBTA_DM_DI_CB; @@ -1748,7 +2259,10 @@ extern void bta_dm_update_white_list(tBTA_DM_MSG *p_data); extern void bta_dm_clear_white_list(tBTA_DM_MSG *p_data); extern void bta_dm_ble_read_adv_tx_power(tBTA_DM_MSG *p_data); extern void bta_dm_read_rssi(tBTA_DM_MSG *p_data); +extern void bta_dm_read_ble_channel_map(tBTA_DM_MSG *p_data); +#if (CLASSIC_BT_INCLUDED == TRUE) extern void bta_dm_set_visibility (tBTA_DM_MSG *p_data); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) extern void bta_dm_set_scan_config(tBTA_DM_MSG *p_data); extern void bta_dm_vendor_spec_command(tBTA_DM_MSG *p_data); @@ -1774,7 +2288,9 @@ extern void bta_dm_ble_set_bg_conn_type (tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_conn_params (tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_scan_params(tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_scan_fil_params(tBTA_DM_MSG *p_data); +#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) extern void bta_dm_ble_set_conn_scan_params (tBTA_DM_MSG *p_data); +#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) #if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE) && SDP_INCLUDED == TRUE) && (GATTC_INCLUDED == TRUE) extern void bta_dm_close_gatt_conn(tBTA_DM_MSG *p_data); #endif /* ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE) && SDP_INCLUDED == TRUE) && (GATTC_INCLUDED == TRUE) */ @@ -1784,19 +2300,22 @@ extern void bta_dm_ble_update_conn_params (tBTA_DM_MSG *p_data); extern void bta_dm_ble_disconnect (tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_rand_address(tBTA_DM_MSG *p_data); extern void bta_dm_ble_clear_rand_address(tBTA_DM_MSG *p_data); +#if (BLE_HOST_STOP_ADV_UNUSED == TRUE) extern void bta_dm_ble_stop_advertising(tBTA_DM_MSG *p_data); +#endif // #if (BLE_HOST_STOP_ADV_UNUSED == TRUE) extern void bta_dm_ble_config_local_privacy (tBTA_DM_MSG *p_data); extern void bta_dm_ble_config_local_icon (tBTA_DM_MSG *p_data); -extern void bta_dm_ble_set_adv_params (tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_adv_params_all(tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_adv_config (tBTA_DM_MSG *p_data); -extern void bta_dm_ble_set_long_adv (tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_adv_config_raw (tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_scan_rsp (tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_scan_rsp_raw (tBTA_DM_MSG *p_data); extern void bta_dm_ble_broadcast (tBTA_DM_MSG *p_data); extern void bta_dm_ble_set_data_length(tBTA_DM_MSG *p_data); extern void bta_dm_ble_update_duplicate_exceptional_list(tBTA_DM_MSG *p_data); +#if SMP_INCLUDED == TRUE +extern void bta_dm_co_security_param_init(void); +#endif #if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE extern void bta_dm_cfg_filter_cond (tBTA_DM_MSG *p_data); extern void bta_dm_scan_filter_param_setup (tBTA_DM_MSG *p_data); @@ -1806,16 +2325,22 @@ extern void btm_dm_ble_multi_adv_disable(tBTA_DM_MSG *p_data); extern void bta_dm_ble_multi_adv_data(tBTA_DM_MSG *p_data); extern void bta_dm_ble_multi_adv_upd_param(tBTA_DM_MSG *p_data); extern void bta_dm_ble_multi_adv_enb(tBTA_DM_MSG *p_data); +#if (BLE_42_DTM_TEST_EN == TRUE) extern void bta_dm_ble_gap_dtm_tx_start(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_dtm_rx_start(tBTA_DM_MSG *p_data); +#endif// #if (BLE_42_DTM_TEST_EN == TRUE) extern void bta_dm_ble_gap_dtm_stop(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_clear_adv(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_set_rpa_timeout(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_add_dev_to_resolving_list(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_set_privacy_mode(tBTA_DM_MSG *p_data); -#if (BLE_50_FEATURE_SUPPORT == TRUE) +extern void bta_dm_ble_gap_set_csa_support(tBTA_DM_MSG *p_data); +extern void bta_dm_ble_gap_set_vendor_evt_mask(tBTA_DM_MSG *p_data); +#if (BLE_50_DTM_TEST_EN == TRUE) extern void bta_dm_ble_gap_dtm_enhance_tx_start(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_dtm_enhance_rx_start(tBTA_DM_MSG *p_data); +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) extern void bta_dm_ble_gap_read_phy(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_set_prefer_default_phy(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_set_prefer_phy(tBTA_DM_MSG *p_data); @@ -1826,12 +2351,20 @@ extern void bta_dm_ble_gap_set_ext_scan_params(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_ext_scan(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_set_prefer_ext_conn_params(tBTA_DM_MSG *p_data); #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) extern void bta_dm_ble_setup_storage(tBTA_DM_MSG *p_data); +#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) extern void bta_dm_ble_enable_batch_scan(tBTA_DM_MSG *p_data); extern void bta_dm_ble_disable_batch_scan(tBTA_DM_MSG *p_data); extern void bta_dm_ble_read_scan_reports(tBTA_DM_MSG *p_data); + +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) extern void bta_dm_ble_track_advertiser(tBTA_DM_MSG *p_data); +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) + +#if (BLE_HOST_ENERGY_INFO_EN == TRUE) extern void bta_dm_ble_get_energy_info(tBTA_DM_MSG *p_data); +#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) #endif extern void bta_dm_set_encryption(tBTA_DM_MSG *p_data); @@ -1950,4 +2483,64 @@ extern void bta_dm_ble_gap_periodic_adv_set_info_trans(tBTA_DM_MSG *p_data); extern void bta_dm_ble_gap_set_periodic_adv_sync_trans_params(tBTA_DM_MSG *p_data); #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +extern void bta_dm_ble_big_create(tBTA_DM_MSG *p_data); +extern void bta_dm_ble_big_create_test(tBTA_DM_MSG *p_data); +extern void bta_dm_ble_big_terminate(tBTA_DM_MSG *p_data); +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +extern void bta_dm_ble_big_sync_create(tBTA_DM_MSG *p_data); +extern void bta_dm_ble_big_sync_terminate(tBTA_DM_MSG *p_data); +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +extern void bta_dm_ble_iso_set_data_path(tBTA_DM_MSG *p_data); +extern void bta_dm_ble_iso_remove_data_path(tBTA_DM_MSG *p_data); +extern void bta_dm_ble_iso_read_tx_sync(tBTA_DM_MSG *p_data); +void bta_dm_ble_iso_read_link_quality(tBTA_DM_MSG *p_data); +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +void bta_dm_ble_set_cig_params(tBTA_DM_MSG *p_data); +void bta_dm_ble_set_cig_params_test(tBTA_DM_MSG *p_data); +void bta_dm_ble_create_cis(tBTA_DM_MSG *p_data); +void bta_dm_ble_remove_cig(tBTA_DM_MSG *p_data); +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +void bta_dm_ble_accept_cis_req(tBTA_DM_MSG *p_data); +void bta_dm_ble_reject_cis_req(tBTA_DM_MSG *p_data); +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_EN == TRUE) +void bta_dm_ble_discon_cis(tBTA_DM_MSG *p_data); +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +void bta_dm_ble_set_cte_trans_params(tBTA_DM_MSG *p_data); +void bta_dm_ble_set_cte_trans_enable(tBTA_DM_MSG *p_data); +void bta_dm_ble_set_iq_sampling_en(tBTA_DM_MSG *p_data); +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +void bta_dm_ble_set_conn_cte_recv_params(tBTA_DM_MSG *p_data); +void bta_dm_ble_set_conn_trans_params(tBTA_DM_MSG *p_data); +void bta_dm_ble_set_conn_cte_req_en(tBTA_DM_MSG *p_data); +void bta_dm_ble_set_conn_cte_rsp_en(tBTA_DM_MSG *p_data); +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + +void bta_dm_ble_read_cte_ant_infor(tBTA_DM_MSG *p_data); +#endif // #if (BLE_FEAT_CTE_EN == TRUE) + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +void bta_dm_api_enh_read_trans_power_level(tBTA_DM_MSG *p_data); +void bta_dm_api_read_rem_trans_power_level(tBTA_DM_MSG *p_data); +void bta_dm_api_set_path_loss_report_params(tBTA_DM_MSG *p_data); +void bta_dm_api_set_path_loss_reporting_en(tBTA_DM_MSG *p_data); +void bta_dm_api_set_trans_power_reporting_en(tBTA_DM_MSG *p_data); +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +void bta_dm_api_set_default_subrate(tBTA_DM_MSG *p_data); +void bta_dm_api_subrate_request(tBTA_DM_MSG *p_data); +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) +extern void bta_dm_ble_set_host_feature(tBTA_DM_MSG *p_data); +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #endif /* BTA_DM_INT_H */ diff --git a/lib/bt/host/bluedroid/bta/gatt/bta_gattc_act.c b/lib/bt/host/bluedroid/bta/gatt/bta_gattc_act.c index b2302fa4..eb2b091e 100644 --- a/lib/bt/host/bluedroid/bta/gatt/bta_gattc_act.c +++ b/lib/bt/host/bluedroid/bta/gatt/bta_gattc_act.c @@ -36,6 +36,7 @@ #include "osi/allocator.h" #include "osi/mutex.h" #include "bta_hh_int.h" +#include "btm_int.h" #if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE) #include "bta_hh_int.h" @@ -63,13 +64,14 @@ static void bta_gattc_cmpl_sendmsg(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_CL_COMPLETE *p_data); static void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb); -static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg); +void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg); static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda); static void bta_gattc_cong_cback (UINT16 conn_id, BOOLEAN congested); static void bta_gattc_req_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE type, tGATTS_DATA *p_data); static tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_id, BD_ADDR remote_bda); extern void btc_gattc_congest_callback(tBTA_GATTC *param); +extern uint32_t BTM_BleUpdateOwnType(uint8_t *own_bda_type, tBTM_START_ADV_CMPL_CBACK *cb); static const tGATT_CBACK bta_gattc_cl_cback = { bta_gattc_conn_cback, @@ -154,7 +156,7 @@ void bta_gattc_disable(tBTA_GATTC_CB *p_cb) APPL_TRACE_DEBUG("bta_gattc_disable"); if (p_cb->state != BTA_GATTC_STATE_ENABLED) { - APPL_TRACE_ERROR("not enabled or disable in pogress"); + APPL_TRACE_ERROR("not enabled or disable in progress"); return; } @@ -227,7 +229,7 @@ void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data) if ((p_buf = (tBTA_GATTC_INT_START_IF *) osi_malloc(sizeof(tBTA_GATTC_INT_START_IF))) != NULL) { p_buf->hdr.event = BTA_GATTC_INT_START_IF_EVT; p_buf->client_if = p_cb->cl_rcb[i].client_if; - APPL_TRACE_DEBUG("GATTC getbuf sucess.\n"); + APPL_TRACE_DEBUG("GATTC getbuf success.\n"); bta_sys_sendmsg(p_buf); status = BTA_GATT_OK; } else { @@ -336,6 +338,10 @@ void bta_gattc_process_api_open (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg) UNUSED(p_cb); if (p_clreg != NULL) { + if (p_msg->api_conn.own_addr_type <= BLE_ADDR_TYPE_MAX) { + // update own address type for creating connection + BTM_BleUpdateOwnType(&p_msg->api_conn.own_addr_type, NULL); + } if (p_msg->api_conn.is_direct) { if ((p_clcb = bta_gattc_find_alloc_clcb(p_msg->api_conn.client_if, p_msg->api_conn.remote_bda, @@ -503,6 +509,7 @@ void bta_gattc_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) tBTA_GATTC_DATA gattc_data; BOOLEAN found_app = FALSE; tGATT_TCB *p_tcb; + tBTM_SEC_DEV_REC *p_dev_rec = NULL; if (!p_clcb || !p_data) { return; @@ -512,6 +519,33 @@ void bta_gattc_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) if(p_tcb) { found_app = gatt_find_specific_app_in_hold_link(p_tcb, p_clcb->p_rcb->client_if); } + + if (p_data->api_conn.phy_mask) { + p_dev_rec = btm_find_or_alloc_dev(p_data->api_conn.remote_bda); + if (p_dev_rec) { + if (p_data->api_conn.is_aux) { +#if (BLE_50_FEATURE_SUPPORT == TRUE) + p_dev_rec->ext_conn_params.phy_mask = p_data->api_conn.phy_mask; + if (p_data->api_conn.phy_mask & BTA_BLE_PHY_1M_MASK) { + memcpy(&p_dev_rec->ext_conn_params.phy_1m_conn_params, &p_data->api_conn.phy_1m_conn_params, sizeof(tBTA_BLE_CONN_PARAMS)); + } + if (p_data->api_conn.phy_mask & BTA_BLE_PHY_2M_MASK) { + memcpy(&p_dev_rec->ext_conn_params.phy_2m_conn_params, &p_data->api_conn.phy_2m_conn_params, sizeof(tBTA_BLE_CONN_PARAMS)); + } + if (p_data->api_conn.phy_mask & BTA_BLE_PHY_CODED_MASK) { + memcpy(&p_dev_rec->ext_conn_params.phy_coded_conn_params, &p_data->api_conn.phy_coded_conn_params, sizeof(tBTA_BLE_CONN_PARAMS)); + } +#endif + } else { + if (p_data->api_conn.phy_mask & BTA_BLE_PHY_1M_MASK) { + memcpy(&p_dev_rec->conn_params, &p_data->api_conn.phy_1m_conn_params, sizeof(tBTA_BLE_CONN_PARAMS)); + } + } + } else { + APPL_TRACE_ERROR("Unknown Device, setting rejected"); + } + } + /* open/hold a connection */ if (!GATT_Connect(p_clcb->p_rcb->client_if, p_data->api_conn.remote_bda, p_data->api_conn.remote_addr_type, TRUE, p_data->api_conn.transport, p_data->api_conn.is_aux)) { @@ -841,6 +875,9 @@ void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) (* p_cback)(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC *)&cb_data); } + // Please note that BTA_GATTC_CLOSE_EVT will run in the BTC task. + // because bta_gattc_deregister_cmpl did not execute as expected(this is a known issue), + // we will run it again in bta_gattc_clcb_dealloc_by_conn_id. if (p_clreg->num_clcb == 0 && p_clreg->dereg_pending) { bta_gattc_deregister_cmpl(p_clreg); } @@ -1672,7 +1709,7 @@ void bta_gattc_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) ** Returns void ** *******************************************************************************/ -static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg) +void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg) { tBTA_GATTC_CB *p_cb = &bta_gattc_cb; tBTA_GATTC_IF client_if = p_clreg->client_if; @@ -1804,8 +1841,8 @@ static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda) *******************************************************************************/ void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg) { - tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_srvr_cache(p_msg->api_conn.remote_bda); - tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0]; + tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_srvr_cache(p_msg->api_refresh.remote_bda); + tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0]; BOOLEAN found = FALSE; UINT8 i; UNUSED(p_cb); @@ -1925,7 +1962,7 @@ void bta_gattc_process_api_cache_get_addr_list(tBTA_GATTC_CB *p_cb, tBTA_GATTC_D *******************************************************************************/ void bta_gattc_process_api_cache_clean(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg) { - tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_srvr_cache(p_msg->api_conn.remote_bda); + tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_srvr_cache(p_msg->api_clean.remote_bda); UNUSED(p_cb); if (p_srvc_cb != NULL && p_srvc_cb->p_srvc_cache != NULL) { @@ -2118,7 +2155,7 @@ void bta_gattc_process_indicate(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_CL_COMPL bta_gattc_proc_other_indication(p_clcb, op, p_data, ¬ify); } } else if (op == GATTC_OPTYPE_INDICATION) { - /* no one intersted and need ack? */ + /* no one interested and need ack? */ APPL_TRACE_DEBUG("%s no one interested, ack now", __func__); GATTC_SendHandleValueConfirm(conn_id, handle); } @@ -2235,7 +2272,7 @@ static void bta_gattc_req_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYP ** ** Function bta_gattc_init_clcb_conn ** -** Description Initaite a BTA CLCB connection +** Description Initiate a BTA CLCB connection ** ** Returns void ** @@ -2252,7 +2289,7 @@ void bta_gattc_init_clcb_conn(UINT8 cif, BD_ADDR remote_bda) return; } - /* initaite a new connection here */ + /* initiate a new connection here */ if ((p_clcb = bta_gattc_clcb_alloc(cif, remote_bda, BTA_GATT_TRANSPORT_LE)) != NULL) { gattc_data.hdr.layer_specific = p_clcb->bta_conn_id = conn_id; @@ -2289,92 +2326,6 @@ void bta_gattc_process_listen_all(UINT8 cif) } } } -/******************************************************************************* -** -** Function bta_gattc_listen -** -** Description Start or stop a listen for connection -** -** Returns void -** -********************************************************************************/ -void bta_gattc_listen(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg) -{ - tBTA_GATTC_RCB *p_clreg = bta_gattc_cl_get_regcb(p_msg->api_listen.client_if); - tBTA_GATTC cb_data; - UNUSED(p_cb); - - cb_data.reg_oper.status = BTA_GATT_ERROR; - cb_data.reg_oper.client_if = p_msg->api_listen.client_if; - - if (p_clreg == NULL) { - APPL_TRACE_ERROR("bta_gattc_listen failed, unknown client_if: %d", - p_msg->api_listen.client_if); - return; - } - /* mark bg conn record */ - if (bta_gattc_mark_bg_conn(p_msg->api_listen.client_if, - (BD_ADDR_PTR) p_msg->api_listen.remote_bda, - p_msg->api_listen.start, - TRUE)) { - if (!GATT_Listen(p_msg->api_listen.client_if, - p_msg->api_listen.start, - p_msg->api_listen.remote_bda)) { - APPL_TRACE_ERROR("Listen failure"); - (*p_clreg->p_cback)(BTA_GATTC_LISTEN_EVT, &cb_data); - } else { - cb_data.status = BTA_GATT_OK; - - (*p_clreg->p_cback)(BTA_GATTC_LISTEN_EVT, &cb_data); - - if (p_msg->api_listen.start) { - /* if listen to a specific target */ - if (p_msg->api_listen.remote_bda != NULL) { - - /* if is a connected remote device */ - if (L2CA_GetBleConnRole(p_msg->api_listen.remote_bda) == HCI_ROLE_SLAVE && - bta_gattc_find_clcb_by_cif(p_msg->api_listen.client_if, - p_msg->api_listen.remote_bda, - BTA_GATT_TRANSPORT_LE) == NULL) { - - bta_gattc_init_clcb_conn(p_msg->api_listen.client_if, - p_msg->api_listen.remote_bda); - } - } - /* if listen to all */ - else { - APPL_TRACE_DEBUG("Listen For All now"); - /* go through all connected device and send - callback for all connected slave connection */ - bta_gattc_process_listen_all(p_msg->api_listen.client_if); - } - } - } - } -} - -/******************************************************************************* -** -** Function bta_gattc_broadcast -** -** Description Start or stop broadcasting -** -** Returns void -** -********************************************************************************/ -void bta_gattc_broadcast(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg) -{ - tBTA_GATTC_RCB *p_clreg = bta_gattc_cl_get_regcb(p_msg->api_listen.client_if); - tBTA_GATTC cb_data; - UNUSED(p_cb); - - cb_data.reg_oper.client_if = p_msg->api_listen.client_if; - cb_data.reg_oper.status = BTM_BleBroadcast(p_msg->api_listen.start, NULL); - //TODO need modify callback if used - if (p_clreg && p_clreg->p_cback) { - (*p_clreg->p_cback)(BTA_GATTC_LISTEN_EVT, &cb_data); - } -} /******************************************************************************* ** diff --git a/lib/bt/host/bluedroid/bta/gatt/bta_gattc_api.c b/lib/bt/host/bluedroid/bta/gatt/bta_gattc_api.c index 6e2586d6..8ac0ec4c 100644 --- a/lib/bt/host/bluedroid/bta/gatt/bta_gattc_api.c +++ b/lib/bt/host/bluedroid/bta/gatt/bta_gattc_api.c @@ -128,7 +128,7 @@ void BTA_GATTC_AppDeregister(tBTA_GATTC_IF client_if) /******************************************************************************* ** -** Function BTA_GATTC_Open +** Function BTA_GATTC_Enh_Open ** ** Description Open a direct connection or add a background auto connection ** bd address @@ -142,8 +142,10 @@ void BTA_GATTC_AppDeregister(tBTA_GATTC_IF client_if) ** Returns void ** *******************************************************************************/ -void BTA_GATTC_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, tBTA_ADDR_TYPE remote_addr_type, - BOOLEAN is_direct, tBTA_GATT_TRANSPORT transport, BOOLEAN is_aux) +void BTA_GATTC_Enh_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, tBTA_ADDR_TYPE remote_addr_type, + BOOLEAN is_direct, tBTA_GATT_TRANSPORT transport, BOOLEAN is_aux, tBTA_ADDR_TYPE own_addr_type, + UINT8 phy_mask, tBTA_BLE_CONN_PARAMS *phy_1m_conn_params, tBTA_BLE_CONN_PARAMS *phy_2m_conn_params, + tBTA_BLE_CONN_PARAMS *phy_coded_conn_params) { tBTA_GATTC_API_OPEN *p_buf; @@ -155,8 +157,18 @@ void BTA_GATTC_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, tBTA_ADDR_TYPE p_buf->transport = transport; p_buf->is_aux = is_aux; p_buf->remote_addr_type = remote_addr_type; + p_buf->own_addr_type = own_addr_type; + p_buf->phy_mask = phy_mask; memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN); - + if ((phy_mask & BTA_BLE_PHY_1M_MASK) && phy_1m_conn_params) { + memcpy(&p_buf->phy_1m_conn_params, phy_1m_conn_params, sizeof(tBTA_BLE_CONN_PARAMS)); + } + if ((phy_mask & BTA_BLE_PHY_2M_MASK) && phy_2m_conn_params) { + memcpy(&p_buf->phy_2m_conn_params, phy_2m_conn_params, sizeof(tBTA_BLE_CONN_PARAMS)); + } + if ((phy_mask & BTA_BLE_PHY_CODED_MASK) && phy_coded_conn_params) { + memcpy(&p_buf->phy_coded_conn_params, phy_coded_conn_params, sizeof(tBTA_BLE_CONN_PARAMS)); + } bta_sys_sendmsg(p_buf); } @@ -472,7 +484,7 @@ void BTA_GATTC_GetGattDb(UINT16 conn_id, UINT16 start_handle, UINT16 end_handle ** Description This function is called to read a characteristics value ** ** Parameters conn_id - connection ID. -** handle - characteritic handle to read. +** handle - characteristic handle to read. ** ** Returns None ** @@ -607,7 +619,7 @@ void BTA_GATTC_ReadMultipleVariable(UINT16 conn_id, tBTA_GATTC_MULTI *p_read_mul ** ** Parameters conn_id - connection ID. ** s_handle - start handle. -** e_handle - end hanle +** e_handle - end handle ** uuid - The attribute UUID. ** ** Returns None @@ -687,7 +699,7 @@ void BTA_GATTC_WriteCharValue ( UINT16 conn_id, ** Description This function is called to write descriptor value. ** ** Parameters conn_id - connection ID -** handle - descriptor hadle to write. +** handle - descriptor handle to write. ** write_type - write type. ** p_value - the value to be written. ** @@ -738,7 +750,7 @@ void BTA_GATTC_WriteCharDescr (UINT16 conn_id, ** Description This function is called to prepare write a characteristic value. ** ** Parameters conn_id - connection ID. -** p_char_id - GATT characteritic ID of the service. +** p_char_id - GATT characteristic ID of the service. ** offset - offset of the write value. ** len: length of the data to be written. ** p_value - the value to be written. @@ -781,7 +793,7 @@ void BTA_GATTC_PrepareWrite (UINT16 conn_id, UINT16 handle, ** Description This function is called to prepare write a characteristic descriptor value. ** ** Parameters conn_id - connection ID. -** p_char_descr_id - GATT characteritic descriptor ID of the service. +** p_char_descr_id - GATT characteristic descriptor ID of the service. ** offset - offset of the write value. ** len: length of the data to be written. ** p_value - the value to be written. @@ -1010,9 +1022,9 @@ void BTA_GATTC_Refresh(BD_ADDR remote_bda, bool erase_flash) if(bta_sys_is_register(BTA_ID_GATTC) == FALSE) { return; } - tBTA_GATTC_API_OPEN *p_buf; + tBTA_GATTC_API_CACHE_REFRESH *p_buf; - if ((p_buf = (tBTA_GATTC_API_OPEN *) osi_malloc(sizeof(tBTA_GATTC_API_OPEN))) != NULL) { + if ((p_buf = (tBTA_GATTC_API_CACHE_REFRESH *) osi_malloc(sizeof(tBTA_GATTC_API_CACHE_REFRESH))) != NULL) { p_buf->hdr.event = BTA_GATTC_API_REFRESH_EVT; memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN); @@ -1068,9 +1080,9 @@ void BTA_GATTC_Clean(BD_ADDR remote_bda) bta_gattc_cache_reset(remote_bda); #endif - tBTA_GATTC_API_OPEN *p_buf; + tBTA_GATTC_API_CACHE_CLEAN *p_buf; - if ((p_buf = (tBTA_GATTC_API_OPEN *) osi_malloc(sizeof(tBTA_GATTC_API_OPEN))) != NULL) { + if ((p_buf = (tBTA_GATTC_API_CACHE_CLEAN *) osi_malloc(sizeof(tBTA_GATTC_API_CACHE_CLEAN))) != NULL) { p_buf->hdr.event = BTA_GATTC_API_CACHE_CLEAN_EVT; memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN); @@ -1078,66 +1090,6 @@ void BTA_GATTC_Clean(BD_ADDR remote_bda) } return; } -/******************************************************************************* -** -** Function BTA_GATTC_Listen -** -** Description Start advertisement to listen for connection request for a GATT -** client application. -** -** Parameters client_if: server interface. -** start: to start or stop listening for connection -** remote_bda: remote device BD address, if listen to all device -** use NULL. -** -** Returns void -** -*******************************************************************************/ -void BTA_GATTC_Listen(tBTA_GATTC_IF client_if, BOOLEAN start, BD_ADDR_PTR target_bda) -{ - tBTA_GATTC_API_LISTEN *p_buf; - - if ((p_buf = (tBTA_GATTC_API_LISTEN *) osi_malloc((UINT16)(sizeof(tBTA_GATTC_API_LISTEN) + BD_ADDR_LEN))) != NULL) { - p_buf->hdr.event = BTA_GATTC_API_LISTEN_EVT; - - p_buf->client_if = client_if; - p_buf->start = start; - if (target_bda) { - p_buf->remote_bda = (UINT8 *)(p_buf + 1); - memcpy(p_buf->remote_bda, target_bda, BD_ADDR_LEN); - } else { - p_buf->remote_bda = NULL; - } - - bta_sys_sendmsg(p_buf); - } - return; -} - -/******************************************************************************* -** -** Function BTA_GATTC_Broadcast -** -** Description Start broadcasting (non-connectable advertisements) -** -** Parameters client_if: client interface. -** start: to start or stop listening for connection -** -** Returns void -** -*******************************************************************************/ -void BTA_GATTC_Broadcast(tBTA_GATTC_IF client_if, BOOLEAN start) -{ - tBTA_GATTC_API_LISTEN *p_buf; - - if ((p_buf = (tBTA_GATTC_API_LISTEN *) osi_malloc((UINT16)(sizeof(tBTA_GATTC_API_LISTEN) + BD_ADDR_LEN))) != NULL) { - p_buf->hdr.event = BTA_GATTC_API_BROADCAST_EVT; - p_buf->client_if = client_if; - p_buf->start = start; - bta_sys_sendmsg(p_buf); - } - return; -} /* Add For BLE PTS */ uint8_t BTA_GATTC_AutoDiscoverEnable(uint8_t enable) diff --git a/lib/bt/host/bluedroid/bta/gatt/bta_gattc_main.c b/lib/bt/host/bluedroid/bta/gatt/bta_gattc_main.c index 0cc55995..c1d1e720 100644 --- a/lib/bt/host/bluedroid/bta/gatt/bta_gattc_main.c +++ b/lib/bt/host/bluedroid/bta/gatt/bta_gattc_main.c @@ -381,15 +381,6 @@ BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg) case BTA_GATTC_API_CACHE_CLEAN_EVT: bta_gattc_process_api_cache_clean(p_cb, (tBTA_GATTC_DATA *) p_msg); break; -#if BLE_INCLUDED == TRUE - case BTA_GATTC_API_LISTEN_EVT: - bta_gattc_listen(p_cb, (tBTA_GATTC_DATA *) p_msg); - break; - case BTA_GATTC_API_BROADCAST_EVT: - bta_gattc_broadcast(p_cb, (tBTA_GATTC_DATA *) p_msg); - break; -#endif - case BTA_GATTC_ENC_CMPL_EVT: bta_gattc_process_enc_cmpl(p_cb, (tBTA_GATTC_DATA *) p_msg); break; @@ -485,8 +476,6 @@ static char *gattc_evt_code(tBTA_GATTC_INT_EVT evt_code) return "BTA_GATTC_API_REFRESH_EVT"; case BTA_GATTC_API_CACHE_CLEAN_EVT: return "BTA_GATTC_API_CACHE_CLEAN_EVT"; - case BTA_GATTC_API_LISTEN_EVT: - return "BTA_GATTC_API_LISTEN_EVT"; case BTA_GATTC_API_DISABLE_EVT: return "BTA_GATTC_API_DISABLE_EVT"; case BTA_GATTC_API_CFG_MTU_EVT: @@ -538,9 +527,14 @@ void bta_gattc_deinit(void) uint8_t bta_gattc_cl_rcb_active_count(void) { uint8_t count = 0; + uint8_t dm_gattc_uuid[16]; + + // When SDP is included, Bluedroid stack will register the DM GATTC application + memset(dm_gattc_uuid, 0x87, 16); for (uint8_t i = 0; i < BTA_GATTC_CL_MAX; i ++) { - if (bta_gattc_cb.cl_rcb[i].in_use) { + if (bta_gattc_cb.cl_rcb[i].in_use && + memcmp(bta_gattc_cb.cl_rcb[i].app_uuid.uu.uuid128, dm_gattc_uuid, 16)) { count++; } } diff --git a/lib/bt/host/bluedroid/bta/gatt/bta_gattc_utils.c b/lib/bt/host/bluedroid/bta/gatt/bta_gattc_utils.c index 2265e282..b47a9d97 100644 --- a/lib/bt/host/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/lib/bt/host/bluedroid/bta/gatt/bta_gattc_utils.c @@ -160,7 +160,7 @@ UINT8 bta_gattc_num_reg_app(void) ** ** Function bta_gattc_find_clcb_by_cif ** -** Description get clcb by client interface and remote bd adddress +** Description get clcb by client interface and remote bd address ** ** Returns pointer to the clcb ** @@ -322,12 +322,18 @@ void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb) } } +extern void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg); void bta_gattc_clcb_dealloc_by_conn_id(UINT16 conn_id) { tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); if (p_clcb) { + tBTA_GATTC_RCB *p_clreg = p_clcb->p_rcb; bta_gattc_clcb_dealloc(p_clcb); + // there is a workaround: if there is no connect, we will reset it. + if (p_clreg && p_clreg->num_clcb == 0 && p_clreg->dereg_pending) { + bta_gattc_deregister_cmpl(p_clreg); + } } } @@ -517,7 +523,7 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) cmd_data->api_write.p_value = (UINT8 *)(cmd_data + 1); memcpy(cmd_data->api_write.p_value, p_data->api_write.p_value, len); } else { - APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memery.", __func__, __LINE__); + APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__); return FALSE; } } else { @@ -525,7 +531,7 @@ BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) memset(cmd_data, 0, sizeof(tBTA_GATTC_DATA)); memcpy(cmd_data, p_data, sizeof(tBTA_GATTC_DATA)); } else { - APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memery.", __func__, __LINE__); + APPL_TRACE_ERROR("%s(), line = %d, alloc fail, no memory.", __func__, __LINE__); return FALSE; } } @@ -919,7 +925,7 @@ BOOLEAN bta_gattc_conn_dealloc(BD_ADDR remote_bda) ** ** Function bta_gattc_find_int_conn_clcb ** -** Description try to locate a clcb when an internal connecion event arrives. +** Description try to locate a clcb when an internal connection event arrives. ** ** Returns pointer to the clcb ** diff --git a/lib/bt/host/bluedroid/bta/gatt/bta_gatts_act.c b/lib/bt/host/bluedroid/bta/gatt/bta_gatts_act.c index d09eaa96..692c59c6 100644 --- a/lib/bt/host/bluedroid/bta/gatt/bta_gatts_act.c +++ b/lib/bt/host/bluedroid/bta/gatt/bta_gatts_act.c @@ -723,8 +723,6 @@ void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg) } else { APPL_TRACE_ERROR("%s, malloc failed", __func__); } - } else { - APPL_TRACE_ERROR("%s, incorrect length", __func__); } (*p_rcb->p_cback)(BTA_GATTS_CONF_EVT, &cb_data); if (cb_data.req_data.value != NULL) { @@ -733,7 +731,7 @@ void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg) } } } else { - APPL_TRACE_ERROR("Not an registered servce attribute ID: 0x%04x", + APPL_TRACE_ERROR("Not a registered service attribute ID: 0x%04x", p_msg->api_indicate.attr_id); } } @@ -884,46 +882,11 @@ void bta_gatts_send_service_change_indication (tBTA_GATTS_DATA *p_msg) } } -/******************************************************************************* -** -** Function bta_gatts_listen -** -** Description Start or stop listening for LE connection on a GATT server -** -** Returns none. -** -*******************************************************************************/ -void bta_gatts_listen(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg) -{ - tBTA_GATTS_RCB *p_rcb = bta_gatts_find_app_rcb_by_app_if(p_msg->api_listen.server_if); - tBTA_GATTS cb_data; - UNUSED(p_cb); - - cb_data.reg_oper.status = BTA_GATT_OK; - cb_data.reg_oper.server_if = p_msg->api_listen.server_if; - - if (p_rcb == NULL) { - APPL_TRACE_ERROR("Unknown GATTS application"); - return; - } - - if (!GATT_Listen(p_msg->api_listen.server_if, - p_msg->api_listen.start, - p_msg->api_listen.remote_bda)) { - cb_data.status = BTA_GATT_ERROR; - APPL_TRACE_ERROR("bta_gatts_listen Listen failed"); - } - - if (p_rcb->p_cback) { - (*p_rcb->p_cback)(BTA_GATTS_LISTEN_EVT, &cb_data); - } -} - /******************************************************************************* ** ** Function bta_gatts_show_local_database ** -** Description print loacl service database +** Description print local service database ** ** Returns none. ** diff --git a/lib/bt/host/bluedroid/bta/gatt/bta_gatts_api.c b/lib/bt/host/bluedroid/bta/gatt/bta_gatts_api.c index ffe3abec..4e1f76f6 100644 --- a/lib/bt/host/bluedroid/bta/gatt/bta_gatts_api.c +++ b/lib/bt/host/bluedroid/bta/gatt/bta_gatts_api.c @@ -603,43 +603,6 @@ void BTA_GATTS_SendServiceChangeIndication(tBTA_GATTS_IF server_if, BD_ADDR remo } -/******************************************************************************* -** -** Function BTA_GATTS_Listen -** -** Description Start advertisement to listen for connection request for a -** GATT server -** -** Parameters server_if: server interface. -** start: to start or stop listening for connection -** remote_bda: remote device BD address, if listen to all device -** use NULL. -** -** Returns void -** -*******************************************************************************/ -void BTA_GATTS_Listen(tBTA_GATTS_IF server_if, BOOLEAN start, BD_ADDR_PTR target_bda) -{ - tBTA_GATTS_API_LISTEN *p_buf; - - if ((p_buf = (tBTA_GATTS_API_LISTEN *) osi_malloc((UINT16)(sizeof(tBTA_GATTS_API_LISTEN) + BD_ADDR_LEN))) != NULL) { - p_buf->hdr.event = BTA_GATTS_API_LISTEN_EVT; - - p_buf->server_if = server_if; - p_buf->start = start; - - if (target_bda) { - p_buf->remote_bda = (UINT8 *)(p_buf + 1); - memcpy(p_buf->remote_bda, target_bda, BD_ADDR_LEN); - } else { - p_buf->remote_bda = NULL; - } - - bta_sys_sendmsg(p_buf); - } - return; -} - uint8_t BTA_GATTS_SetServiceChangeMode(uint8_t mode) { tGATT_STATUS status; diff --git a/lib/bt/host/bluedroid/bta/gatt/bta_gatts_main.c b/lib/bt/host/bluedroid/bta/gatt/bta_gatts_main.c index fe83d151..bf1174c5 100644 --- a/lib/bt/host/bluedroid/bta/gatt/bta_gatts_main.c +++ b/lib/bt/host/bluedroid/bta/gatt/bta_gatts_main.c @@ -112,9 +112,6 @@ BOOLEAN bta_gatts_hdl_event(BT_HDR *p_msg) bta_gatts_set_attr_value(p_srvc_cb, (tBTA_GATTS_DATA *) p_msg); break; } - case BTA_GATTS_API_LISTEN_EVT: - bta_gatts_listen(p_cb, (tBTA_GATTS_DATA *) p_msg); - break; case BTA_GATTS_API_ADD_INCL_SRVC_EVT: case BTA_GATTS_API_ADD_CHAR_EVT: case BTA_GATTS_API_ADD_DESCR_EVT: diff --git a/lib/bt/host/bluedroid/bta/gatt/include/bta_gattc_int.h b/lib/bt/host/bluedroid/bta/gatt/include/bta_gattc_int.h index 108358ca..cb877fcf 100644 --- a/lib/bt/host/bluedroid/bta/gatt/include/bta_gattc_int.h +++ b/lib/bt/host/bluedroid/bta/gatt/include/bta_gattc_int.h @@ -66,8 +66,6 @@ enum { BTA_GATTC_INT_START_IF_EVT, BTA_GATTC_API_REG_EVT, BTA_GATTC_API_DEREG_EVT, - BTA_GATTC_API_LISTEN_EVT, - BTA_GATTC_API_BROADCAST_EVT, BTA_GATTC_API_DISABLE_EVT, BTA_GATTC_ENC_CMPL_EVT, BTA_GATTC_API_CACHE_ASSOC_EVT, @@ -110,7 +108,7 @@ typedef enum { #define BTA_GATTC_WRITE_PREPARE GATT_WRITE_PREPARE #define BTA_GATTC_INVALID_HANDLE 0 -/* internal strucutre for GATTC register API */ +/* internal structure for GATTC register API */ typedef struct { BT_HDR hdr; tBT_UUID app_uuid; @@ -133,9 +131,20 @@ typedef struct { BOOLEAN is_direct; BOOLEAN is_aux; tBTA_TRANSPORT transport; + tBTA_ADDR_TYPE own_addr_type; + UINT8 phy_mask; + tBTA_BLE_CONN_PARAMS phy_1m_conn_params; + tBTA_BLE_CONN_PARAMS phy_2m_conn_params; + tBTA_BLE_CONN_PARAMS phy_coded_conn_params; } tBTA_GATTC_API_OPEN; -typedef tBTA_GATTC_API_OPEN tBTA_GATTC_API_CANCEL_OPEN; +typedef struct { + BT_HDR hdr; + BD_ADDR remote_bda; + tBTA_ADDR_TYPE remote_addr_type; + tBTA_GATTC_IF client_if; + BOOLEAN is_direct; +} tBTA_GATTC_API_CANCEL_OPEN; typedef struct { BT_HDR hdr; @@ -190,18 +199,15 @@ typedef struct { tBTA_GATTC_EVT cmpl_evt; }tBTA_GATTC_API_READ_MULTI; -typedef struct { - BT_HDR hdr; - BD_ADDR_PTR remote_bda; - tBTA_GATTC_IF client_if; - BOOLEAN start; -} tBTA_GATTC_API_LISTEN; - - typedef struct { BT_HDR hdr; } tBTA_GATTC_API_CFG_MTU; +typedef struct { + BT_HDR hdr; + BD_ADDR remote_bda; +} tBTA_GATTC_API_CACHE_REFRESH; + typedef struct { BT_HDR hdr; tBTA_GATTC_IF client_if; @@ -215,6 +221,11 @@ typedef struct { tBTA_GATTC_IF client_if; } tBTA_GATTC_API_GET_ADDR; +typedef struct { + BT_HDR hdr; + BD_ADDR remote_bda; +} tBTA_GATTC_API_CACHE_CLEAN; + typedef struct { BT_HDR hdr; BD_ADDR remote_bda; @@ -247,16 +258,16 @@ typedef union { tBTA_GATTC_API_EXEC api_exec; tBTA_GATTC_API_READ_MULTI api_read_multi; tBTA_GATTC_API_CFG_MTU api_mtu; + tBTA_GATTC_API_CACHE_REFRESH api_refresh; tBTA_GATTC_API_CACHE_ASSOC api_assoc; tBTA_GATTC_API_GET_ADDR api_get_addr; + tBTA_GATTC_API_CACHE_CLEAN api_clean; tBTA_GATTC_OP_CMPL op_cmpl; tBTA_GATTC_INT_CONN int_conn; tBTA_GATTC_ENC_CMPL enc_cmpl; tBTA_GATTC_INT_START_IF int_start_if; tBTA_GATTC_INT_DEREG int_dereg; - /* if peripheral role is supported */ - tBTA_GATTC_API_LISTEN api_listen; } tBTA_GATTC_DATA; @@ -313,7 +324,7 @@ typedef struct { UINT16 total_char; UINT16 total_attr; UINT8 srvc_hdl_chg; /* service handle change indication pending */ - UINT16 attr_index; /* cahce NV saving/loading attribute index */ + UINT16 attr_index; /* cache NV saving/loading attribute index */ UINT16 mtu; bool update_incl_srvc; @@ -484,10 +495,6 @@ extern void bta_gattc_process_api_cache_clean(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DA extern void bta_gattc_process_api_cache_assoc(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg); extern void bta_gattc_process_api_cache_get_addr_list(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg); extern void bta_gattc_cfg_mtu(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data); -#if BLE_INCLUDED == TRUE -extern void bta_gattc_listen(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg); -extern void bta_gattc_broadcast(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg); -#endif /* utility functions */ extern tBTA_GATTC_CLCB *bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda, tBTA_TRANSPORT transport); extern tBTA_GATTC_CLCB *bta_gattc_find_clcb_by_conn_id (UINT16 conn_id); diff --git a/lib/bt/host/bluedroid/bta/gatt/include/bta_gatts_int.h b/lib/bt/host/bluedroid/bta/gatt/include/bta_gatts_int.h index 51d6fd4e..854a28a2 100644 --- a/lib/bt/host/bluedroid/bta/gatt/include/bta_gatts_int.h +++ b/lib/bt/host/bluedroid/bta/gatt/include/bta_gatts_int.h @@ -51,7 +51,6 @@ enum { BTA_GATTS_API_OPEN_EVT, BTA_GATTS_API_CANCEL_OPEN_EVT, BTA_GATTS_API_CLOSE_EVT, - BTA_GATTS_API_LISTEN_EVT, BTA_GATTS_API_DISABLE_EVT, BTA_GATTS_API_SEND_SERVICE_CHANGE_EVT, BTA_GATTS_API_SHOW_LOCAL_DATABASE_EVT @@ -64,7 +63,7 @@ typedef UINT16 tBTA_GATTS_INT_EVT; /* max number of services allowed in the device */ #define BTA_GATTS_MAX_SRVC_NUM GATT_MAX_SR_PROFILES -/* internal strucutre for GATTC register API */ +/* internal structure for GATTC register API */ typedef struct { BT_HDR hdr; tBT_UUID app_uuid; @@ -148,13 +147,6 @@ typedef struct { typedef tBTA_GATTS_API_OPEN tBTA_GATTS_API_CANCEL_OPEN; -typedef struct { - BT_HDR hdr; - BD_ADDR_PTR remote_bda; - tBTA_GATTS_IF server_if; - BOOLEAN start; -} tBTA_GATTS_API_LISTEN; - typedef struct { BT_HDR hdr; tBTA_GATTS_IF server_if; @@ -177,8 +169,6 @@ typedef union { tBTA_GATTS_API_CANCEL_OPEN api_cancel_open; tBTA_GATTS_INT_START_IF int_start_if; - /* if peripheral role is supported */ - tBTA_GATTS_API_LISTEN api_listen; tBTA_GATTS_API_SEND_SERVICE_CHANGE api_send_service_change; } tBTA_GATTS_DATA; @@ -250,7 +240,6 @@ extern void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_m extern void bta_gatts_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg); extern void bta_gatts_cancel_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg); extern void bta_gatts_close (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg); -extern void bta_gatts_listen(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg); extern void bta_gatts_send_service_change_indication (tBTA_GATTS_DATA *p_msg); extern void bta_gatts_show_local_database (void); diff --git a/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_api.c b/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_api.c index 4b1d91ee..331f6595 100644 --- a/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_api.c +++ b/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_api.c @@ -339,6 +339,73 @@ void BTA_AgCiData(UINT16 handle) bta_sys_sendmsg(p_buf); } } + +/******************************************************************************* +** +** Function BTA_AgAudioBuffAlloc +** +** Description Allocate an audio buffer with specific size, reserve enough +** space and offset for lower layer to send the buffer directly. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_AgAudioBuffAlloc(UINT16 size, UINT8 **pp_buff, UINT8 **pp_data) +{ + /* reserve 1 byte at last, when the size is mSBC frame size (57), then we got a buffer that can hold 60 bytes data */ + BT_HDR *p_buf= (BT_HDR *)osi_calloc(sizeof(BT_HDR) + BTA_AG_BUFF_OFFSET_MIN + BTA_AG_H2_HEADER_LEN + size + 1); + if (p_buf != NULL) { + /* mSBC offset is large than CVSD, so this is also work in CVSD air mode */ + p_buf->offset = BTA_AG_BUFF_OFFSET_MIN + BTA_AG_H2_HEADER_LEN; + *pp_buff = (UINT8 *)p_buf; + *pp_data = (UINT8 *)(p_buf + 1) + p_buf->offset; + } +} + +/******************************************************************************* +** +** Function BTA_AgAudioBuffFree +** +** Description Free an audio buffer. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_AgAudioBuffFree(UINT8 *p_buf) +{ + osi_free(p_buf); +} + +/******************************************************************************* +** +** Function BTA_AgAudioDataSend +** +** Description Send audio data to lower level, whether success or not, buffer +** is consumed. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_AgAudioDataSend(UINT16 handle, UINT8 *p_buff_start, UINT8 *p_data, UINT16 data_len) +{ + BT_HDR *p_buf = (BT_HDR *)p_buff_start; + tBTA_AG_SCB *p_scb; + assert(p_data - (UINT8 *)(p_buf + 1) >= 0); + if ((p_scb = bta_ag_scb_by_idx(handle)) != NULL) { + p_buf->event = BTA_AG_API_SCO_DATA_SEND_EVT; + p_buf->layer_specific = handle; + p_buf->offset = p_data - (UINT8 *)(p_buf + 1); + p_buf->len = data_len; + bta_sys_sendmsg(p_buf); + } + else { + osi_free(p_buf); + } +} + #endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */ #endif /* #if (BTA_AG_INCLUDED == TRUE)*/ diff --git a/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c b/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c index 6bccfe1b..2cf985c7 100644 --- a/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c +++ b/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c @@ -358,7 +358,7 @@ void bta_hf_ag_bqb_brsf_ctrl(BOOLEAN enable) #endif /* BT_HF_AG_BQB_INCLUDED */ /******************************************* -* Funcitons Result +* Function Results ********************************************/ /******************************************************************************* ** diff --git a/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c b/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c index bcf3cc6e..39daa0de 100644 --- a/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c +++ b/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c @@ -89,6 +89,8 @@ enum BTA_AG_SETCODEC, BTA_AG_SEND_RING, BTA_AG_CI_SCO_DATA, + BTA_AG_SCO_DATA_SEND, + BTA_AG_SCO_DATA_FREE, BTA_AG_CI_RX_DATA, BTA_AG_RCVD_SLC_READY, BTA_AG_PKT_STAT_NUMS, @@ -133,6 +135,8 @@ const tBTA_AG_ACTION bta_ag_action[] = bta_ag_setcodec, bta_ag_send_ring, bta_ag_ci_sco_data, + bta_ag_sco_data_send, + bta_ag_sco_data_free, bta_ag_ci_rx_data, bta_ag_rcvd_slc_ready, bta_ag_pkt_stat_nums @@ -155,6 +159,7 @@ const UINT8 bta_ag_st_init[][BTA_AG_NUM_COLS] = /* API_AUDIO_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST}, /* API_RESULT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST}, /* API_SETCODEC_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST}, +/* API_SCO_DATA_SEND_EVT */ {BTA_AG_SCO_DATA_FREE, BTA_AG_IGNORE, BTA_AG_INIT_ST}, /* RFC_OPEN_EVT */ {BTA_AG_RFC_ACP_OPEN, BTA_AG_SCO_LISTEN, BTA_AG_OPEN_ST}, /* RFC_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST}, /* RFC_SRV_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST}, @@ -185,6 +190,7 @@ const UINT8 bta_ag_st_opening[][BTA_AG_NUM_COLS] = /* API_AUDIO_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST}, /* API_RESULT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST}, /* API_SETCODEC_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST}, +/* API_SCO_DATA_SEND_EVT */ {BTA_AG_SCO_DATA_FREE, BTA_AG_IGNORE, BTA_AG_OPENING_ST}, /* RFC_OPEN_EVT */ {BTA_AG_RFC_OPEN, BTA_AG_SCO_LISTEN, BTA_AG_OPEN_ST}, /* RFC_CLOSE_EVT */ {BTA_AG_RFC_FAIL, BTA_AG_IGNORE, BTA_AG_INIT_ST}, /* RFC_SRV_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST}, @@ -215,6 +221,7 @@ const UINT8 bta_ag_st_open[][BTA_AG_NUM_COLS] = /* API_AUDIO_CLOSE_EVT */ {BTA_AG_SCO_CLOSE, BTA_AG_IGNORE, BTA_AG_OPEN_ST}, /* API_RESULT_EVT */ {BTA_AG_RESULT, BTA_AG_IGNORE, BTA_AG_OPEN_ST}, /* API_SETCODEC_EVT */ {BTA_AG_SETCODEC, BTA_AG_IGNORE, BTA_AG_OPEN_ST}, +/* API_SCO_DATA_SEND_EVT */ {BTA_AG_SCO_DATA_SEND, BTA_AG_IGNORE, BTA_AG_OPEN_ST}, /* RFC_OPEN_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST}, /* RFC_CLOSE_EVT */ {BTA_AG_RFC_CLOSE, BTA_AG_IGNORE, BTA_AG_INIT_ST}, /* RFC_SRV_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST}, @@ -245,6 +252,7 @@ const UINT8 bta_ag_st_closing[][BTA_AG_NUM_COLS] = /* API_AUDIO_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST}, /* API_RESULT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST}, /* API_SETCODEC_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST}, +/* API_SCO_DATA_SEND_EVT */ {BTA_AG_SCO_DATA_FREE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST}, /* RFC_OPEN_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST}, /* RFC_CLOSE_EVT */ {BTA_AG_RFC_CLOSE, BTA_AG_IGNORE, BTA_AG_INIT_ST}, /* RFC_SRV_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST}, @@ -360,9 +368,9 @@ static char *bta_ag_evt_str(UINT16 event, tBTA_AG_RES result) case BTA_AG_API_DISABLE_EVT: return "Disable AG"; case BTA_AG_CI_SCO_DATA_EVT: - return "SCO data Callin"; + return "SCO data Call In"; case BTA_AG_CI_SLC_READY_EVT: - return "SLC Ready Callin"; + return "SLC Ready Call In"; case BTA_AG_PKT_STAT_NUMS_GET_EVT: return "Get Packet Nums"; default: @@ -433,6 +441,7 @@ static tBTA_AG_SCB *bta_ag_scb_alloc(void) #if (BTM_WBS_INCLUDED == TRUE) p_scb->codec_updated = FALSE; #endif + p_scb->p_sco_data = NULL; /* set up timers */ p_scb->act_timer.param = (UINT32) p_scb; p_scb->act_timer.p_cback = bta_ag_timer_cback; @@ -473,6 +482,10 @@ void bta_ag_scb_dealloc(tBTA_AG_SCB *p_scb) #if (BTM_WBS_INCLUDED == TRUE) bta_sys_free_timer(&p_scb->cn_timer); #endif + if (p_scb->p_sco_data != NULL) { + osi_free(p_scb->p_sco_data); + p_scb->p_sco_data = NULL; + } bta_sys_free_timer(&p_scb->colli_timer); /* initialize control block */ @@ -774,7 +787,7 @@ static void bta_ag_api_enable(tBTA_AG_DATA *p_data) bta_ag_cb.scb->negotiated_codec = BTM_SCO_CODEC_CVSD; } - /* set deault setting for eSCO/SCO */ + /* set default setting for eSCO/SCO */ BTM_WriteVoiceSettings(AG_VOICE_SETTINGS); bta_sys_collision_register (BTA_ID_AG, bta_ag_collision_cback); /* call callback with enable event */ @@ -943,6 +956,7 @@ void bta_ag_sm_execute(tBTA_AG_SCB *p_scb, UINT16 event, tBTA_AG_DATA *p_data) BOOLEAN bta_ag_hdl_event(BT_HDR *p_msg) { tBTA_AG_SCB *p_scb; + BOOLEAN free_msg = TRUE; APPL_TRACE_DEBUG("bta_ag_hdl_event: Event 0x%04x ", p_msg->event); switch (p_msg->event) { @@ -966,15 +980,22 @@ BOOLEAN bta_ag_hdl_event(BT_HDR *p_msg) bta_ag_api_result((tBTA_AG_DATA *) p_msg); break; - /* all others reference scb by handle */ + case BTA_AG_API_SCO_DATA_SEND_EVT: + free_msg = FALSE; + /* fall through */ default: + /* all others reference scb by handle */ if ((p_scb = bta_ag_scb_by_idx(p_msg->layer_specific)) != NULL) { APPL_TRACE_DEBUG("bta_ag_hdl_event: p_scb 0x%08x ", (unsigned int)p_scb); bta_ag_sm_execute(p_scb, p_msg->event, (tBTA_AG_DATA *) p_msg); } + else { + /* free message if p_scb not found */ + free_msg = TRUE; + } break; } - return TRUE; + return free_msg; } #endif /* #if (BTA_AG_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c b/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c index 661d2372..f2196c6b 100644 --- a/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c +++ b/lib/bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c @@ -345,9 +345,10 @@ static void bta_ag_sco_read_cback(UINT16 sco_inx, BT_HDR *p_data, tBTM_SCO_DATA_ APPL_TRACE_DEBUG("bta_ag_sco_read_cback: status(%d)", status); } +#if (BTA_HFP_EXT_CODEC == FALSE) /* Callout function must free the data. */ bta_ag_sco_co_in_data(p_data, status); - osi_free(p_data); +#endif } #endif /******************************************************************************* @@ -459,6 +460,37 @@ static void bta_ag_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p } } +#if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTA_HFP_EXT_CODEC == TRUE) + +/******************************************************************************* +** +** Function bta_ag_sco_get_frame_size +** +** Description Get SCO frame size. +** +** +** Returns SCO frame size +** +*******************************************************************************/ +static UINT16 bta_ag_sco_get_frame_size(tBTA_AG_SCB *p_scb) +{ + UINT16 frame_size = 0; + switch (p_scb->air_mode) + { + case BTM_SCO_AIR_MODE_CVSD: + frame_size = p_scb->out_pkt_len; + break; + case BTM_SCO_AIR_MODE_TRANSPNT: + frame_size = BTA_AG_MSBC_FRAME_SIZE; + break; + default: + break; + } + return frame_size; +} + +#endif + /******************************************************************************* ** ** Function bta_ag_cback_sco @@ -471,14 +503,19 @@ static void bta_ag_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p *******************************************************************************/ static void bta_ag_cback_sco(tBTA_AG_SCB *p_scb, UINT8 event) { - tBTA_AG_HDR sco; - - sco.handle = bta_ag_scb_to_idx(p_scb); - sco.app_id = p_scb->app_id; - sco.sync_conn_handle = BTM_ReadScoHandle(p_scb->sco_idx); + tBTA_AG_AUDIO_STAT audio_stat = {0}; + + audio_stat.hdr.handle = bta_ag_scb_to_idx(p_scb); + audio_stat.hdr.app_id = p_scb->app_id; + audio_stat.hdr.sync_conn_handle = BTM_ReadScoHandle(p_scb->sco_idx); +#if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTA_HFP_EXT_CODEC == TRUE) + if (event != BTA_AG_AUDIO_CLOSE_EVT) { + audio_stat.preferred_frame_size = bta_ag_sco_get_frame_size(p_scb); + } +#endif /* call close cback */ - (*bta_ag_cb.p_cback)(event, (tBTA_AG *) &sco); + (*bta_ag_cb.p_cback)(event, (tBTA_AG *) &audio_stat); } /******************************************************************************* @@ -784,7 +821,7 @@ static void bta_ag_sco_event(tBTA_AG_SCB *p_scb, UINT8 event) p_scb->sco_idx, p_sco->state, bta_ag_sco_state_str(p_sco->state), event, bta_ag_sco_evt_str(event)); -#if (BTM_SCO_HCI_INCLUDED == TRUE) +#if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTA_HFP_EXT_CODEC == FALSE) BT_HDR *p_buf; if (event == BTA_AG_SCO_CI_DATA_E) { @@ -1633,6 +1670,11 @@ void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); } + if (p_scb->p_sco_data != NULL) { + osi_free(p_scb->p_sco_data); + p_scb->p_sco_data = NULL; + } + /* call app callback */ bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT); #if (BTM_WBS_INCLUDED == TRUE) @@ -1665,7 +1707,7 @@ void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data bta_ag_cb.sco.state == BTA_AG_SCO_CLOSE_XFER_ST || bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_XFER_ST) { - /* If script overrided sco parameter by BTA_CMD_SET_ESCO_PARAM */ + /* If script override sco parameter by BTA_CMD_SET_ESCO_PARAM */ if (bta_ag_cb.sco.param_updated) { resp = bta_ag_cb.sco.params; @@ -1736,7 +1778,7 @@ void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data ** ** Function bta_ag_ci_sco_data ** -** Description Process the SCO data ready callin event +** Description Process the SCO data ready call in event ** ** ** Returns void @@ -1752,6 +1794,288 @@ void bta_ag_ci_sco_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) #endif } +#if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTA_HFP_EXT_CODEC == TRUE) + +/******************************************************************************* +** +** Function bta_ag_write_sco_data +** +** Description Write two SCO data buffers to specified instance +** +** +** Returns void +** +*******************************************************************************/ +static void bta_ag_write_sco_data(tBTA_AG_SCB *p_scb, BT_HDR *p_buf1, BT_HDR *p_buf2) +{ + BTM_WriteScoData(p_scb->sco_idx, p_buf1); + if (p_buf2 != NULL) { + BTM_WriteScoData(p_scb->sco_idx, p_buf2); + } +} + +/******************************************************************************* +** +** Function bta_ag_sco_data_send_cvsd +** +** Description Process SCO data of CVSD air mode +** +** +** Returns void +** +*******************************************************************************/ +static void bta_ag_sco_data_send_cvsd(tBTA_AG_SCB *p_scb, BT_HDR *p_buf) +{ + UINT16 out_pkt_len = p_scb->out_pkt_len; + + if (p_scb->p_sco_data != NULL) { + /* the remaining data of last sending operation */ + BT_HDR *p_buf_last = p_scb->p_sco_data; + /* remaining data len should small than out_pkt_len */ + assert(p_buf_last->len < out_pkt_len); + BT_HDR *p_buf2 = osi_calloc(sizeof(BT_HDR) + BTA_AG_BUFF_OFFSET_MIN + out_pkt_len); + if (p_buf2 == NULL) { + osi_free(p_buf); + osi_free(p_buf_last); + p_scb->p_sco_data = NULL; + APPL_TRACE_WARNING("%s, no memory", __FUNCTION__); + return; + } + p_buf2->offset = BTA_AG_BUFF_OFFSET_MIN; + UINT8 *p_data = (UINT8 *)(p_buf2 + 1) + p_buf2->offset; + memcpy(p_data, (UINT8 *)(p_buf_last + 1) + p_buf_last->offset, p_buf_last->len); + + if (p_buf->len + p_buf_last->len < out_pkt_len) { + memcpy(p_data + p_buf_last->len, (UINT8 *)(p_buf + 1) + p_buf->offset, p_buf->len); + p_buf2->len = p_buf->len + p_buf_last->len; + osi_free(p_buf); + osi_free(p_buf_last); + p_scb->p_sco_data = p_buf2; + } + else { + UINT16 copy_len = out_pkt_len - p_buf_last->len; + memcpy(p_data + p_buf_last->len, (UINT8 *)(p_buf + 1) + p_buf->offset, copy_len); + p_buf2->len = out_pkt_len; + p_buf->offset += copy_len; + p_buf->len -= copy_len; + osi_free(p_buf_last); + p_scb->p_sco_data = NULL; + bta_ag_write_sco_data(p_scb, p_buf2, NULL); + + if (p_buf->len == 0) { + osi_free(p_buf); + } + else { + /* recursive call, this will only called once */ + bta_ag_sco_data_send_cvsd(p_scb, p_buf); + } + } + } + else if (p_buf->len < out_pkt_len) { + p_scb->p_sco_data = p_buf; + } + else { + /* p_scb->p_sco_data != NULL && p_buf->len >= out_pkt_len */ + while (1) { + if (p_buf->len == out_pkt_len) { + bta_ag_write_sco_data(p_scb, p_buf, NULL); + break; + } + else { + BT_HDR *p_buf2 = osi_calloc(sizeof(BT_HDR) + BTA_AG_BUFF_OFFSET_MIN + out_pkt_len); + if (p_buf2 == NULL) { + osi_free(p_buf); + APPL_TRACE_WARNING("%s, no memory", __FUNCTION__); + return; + } + p_buf2->offset = BTA_AG_BUFF_OFFSET_MIN; + UINT8 *p_data = (UINT8 *)(p_buf2 + 1) + p_buf2->offset; + memcpy(p_data, (UINT8 *)(p_buf + 1) + p_buf->offset, out_pkt_len); + p_buf2->len = out_pkt_len; + p_buf->offset += out_pkt_len; + p_buf->len -= out_pkt_len; + bta_ag_write_sco_data(p_scb, p_buf2, NULL); + } + if (p_buf->len < out_pkt_len) { + p_scb->p_sco_data = p_buf; + break; + } + } + } +} + +/******************************************************************************* +** +** Function bta_ag_sco_data_send_msbc +** +** Description Process SCO data of mSBC air mode +** +** +** Returns void +** +*******************************************************************************/ +static void bta_ag_sco_data_send_msbc(tBTA_AG_SCB *p_scb, BT_HDR *p_buf) +{ + UINT16 out_pkt_len = p_scb->out_pkt_len; + if (p_buf->len == BTA_AG_MSBC_FRAME_SIZE && p_buf->offset >= BTA_AG_BUFF_OFFSET_MIN + BTA_AG_H2_HEADER_LEN) { + /* add H2 header */ + p_buf->offset -= BTA_AG_H2_HEADER_LEN; + UINT8 *p_data = (UINT8 *)(p_buf + 1) + p_buf->offset; + bta_ag_h2_header((UINT16 *)p_data); + /* add header len, add addition one bytes, the len is BTA_AG_SCO_OUT_PKT_LEN_2EV3 now */ + p_buf->len += BTA_AG_H2_HEADER_LEN + 1; + + if (out_pkt_len == BTA_AG_SCO_OUT_PKT_LEN_2EV3) { + /* mSBC frame can be send directly */ + bta_ag_write_sco_data(p_scb, p_buf, NULL); + } + else if (out_pkt_len == BTA_AG_SCO_OUT_PKT_LEN_EV3) { + /* need to split into 2 sco packages for sending */ + BT_HDR *p_buf2 = osi_calloc(sizeof(BT_HDR) + BTA_AG_BUFF_OFFSET_MIN + BTA_AG_SCO_OUT_PKT_LEN_EV3); + if (p_buf2 == NULL) { + /* free the first buff too */ + osi_free(p_buf); + APPL_TRACE_WARNING("%s, no memory", __FUNCTION__); + return; + } + p_buf2->offset = BTA_AG_BUFF_OFFSET_MIN; + p_buf2->len = BTA_AG_SCO_OUT_PKT_LEN_EV3; + UINT8 *p_data2 = (UINT8 *)(p_buf2 + 1) + p_buf2->offset; + memcpy(p_data2, p_data + BTA_AG_SCO_OUT_PKT_LEN_EV3, BTA_AG_SCO_OUT_PKT_LEN_EV3); + /* update the first packet len */ + p_buf->len = BTA_AG_SCO_OUT_PKT_LEN_EV3; + bta_ag_write_sco_data(p_scb, p_buf, p_buf2); + } + else { + osi_free(p_buf); + APPL_TRACE_WARNING("%s, invalid out pkt len: %d", __FUNCTION__, out_pkt_len); + } + } + else if (p_buf->len != 0 && p_buf->len % BTA_AG_MSBC_FRAME_SIZE == 0) { + /* multiple mSBC frame in the buffer, or just one but offset is too small */ + UINT8 *p_data = (UINT8 *)(p_buf + 1) + p_buf->offset; + UINT16 total_len = p_buf->len; + if (out_pkt_len == BTA_AG_SCO_OUT_PKT_LEN_2EV3) { + while (total_len != 0) { + BT_HDR *p_buf2 = osi_calloc(sizeof(BT_HDR) + BTA_AG_BUFF_OFFSET_MIN + BTA_AG_SCO_OUT_PKT_LEN_2EV3); + if (p_buf2 == NULL) { + APPL_TRACE_WARNING("%s, no memory", __FUNCTION__); + break; + } + p_buf2->offset = BTA_AG_BUFF_OFFSET_MIN; + p_buf2->len = BTA_AG_SCO_OUT_PKT_LEN_2EV3; + UINT8 *p_data2 = (UINT8 *)(p_buf2 + 1) + p_buf2->offset; + bta_ag_h2_header((UINT16 *)p_data2); + p_data2 += BTA_AG_H2_HEADER_LEN; + memcpy(p_data2, p_data, BTA_AG_MSBC_FRAME_SIZE); + p_data += BTA_AG_MSBC_FRAME_SIZE; + total_len -= BTA_AG_MSBC_FRAME_SIZE; + bta_ag_write_sco_data(p_scb, p_buf2, NULL); + } + } + else if (out_pkt_len == BTA_AG_SCO_OUT_PKT_LEN_EV3) { + while (total_len != 0) { + BT_HDR *p_buf2 = osi_calloc(sizeof(BT_HDR) + BTA_AG_BUFF_OFFSET_MIN + BTA_AG_SCO_OUT_PKT_LEN_EV3); + if (p_buf2 == NULL) { + APPL_TRACE_WARNING("%s, no memory", __FUNCTION__); + break; + } + BT_HDR *p_buf3 = osi_calloc(sizeof(BT_HDR) + BTA_AG_BUFF_OFFSET_MIN + BTA_AG_SCO_OUT_PKT_LEN_EV3); + if (p_buf3 == NULL) { + /* free the first buff too */ + osi_free(p_buf2); + APPL_TRACE_WARNING("%s, no memory", __FUNCTION__); + break; + } + + /* build first packet, include H2 header */ + p_buf2->offset = BTA_AG_BUFF_OFFSET_MIN; + p_buf2->len = BTA_AG_SCO_OUT_PKT_LEN_EV3; + UINT8 *p_data2 = (UINT8 *)(p_buf2 + 1) + p_buf2->offset; + bta_ag_h2_header((UINT16 *)p_data2); + p_data2 += BTA_AG_H2_HEADER_LEN; + memcpy(p_data2, p_data, BTA_AG_SCO_OUT_PKT_LEN_EV3 - BTA_AG_H2_HEADER_LEN); + p_data += BTA_AG_SCO_OUT_PKT_LEN_EV3 - BTA_AG_H2_HEADER_LEN; + total_len -= BTA_AG_SCO_OUT_PKT_LEN_EV3 - BTA_AG_H2_HEADER_LEN; + + /* build second packet, not include header */ + p_buf3->offset = BTA_AG_BUFF_OFFSET_MIN; + p_buf3->len = BTA_AG_SCO_OUT_PKT_LEN_EV3; + UINT8 *p_data3 = (UINT8 *)(p_buf3 + 1) + p_buf3->offset; + memcpy(p_data3, p_data, BTA_AG_MSBC_FRAME_SIZE - BTA_AG_H2_HEADER_LEN - BTA_AG_SCO_OUT_PKT_LEN_EV3); + p_data += BTA_AG_MSBC_FRAME_SIZE - BTA_AG_H2_HEADER_LEN - BTA_AG_SCO_OUT_PKT_LEN_EV3; + total_len -= BTA_AG_MSBC_FRAME_SIZE - BTA_AG_H2_HEADER_LEN - BTA_AG_SCO_OUT_PKT_LEN_EV3; + bta_ag_write_sco_data(p_scb, p_buf2, p_buf3); + } + } + else { + APPL_TRACE_WARNING("%s, invalid out pkt len: %d", __FUNCTION__, out_pkt_len); + } + osi_free(p_buf); + } + else { + APPL_TRACE_WARNING("%s, unaccepted data len: %d", __FUNCTION__, p_buf->len); + osi_free(p_buf); + } +} + +#endif + +/******************************************************************************* +** +** Function bta_ag_sco_data_send +** +** Description Route SCO data to specific processing function based on air mode +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_sco_data_send(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + BT_HDR *p_buf = (BT_HDR *) p_data; + +#if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTA_HFP_EXT_CODEC == TRUE) + if (bta_ag_cb.sco.state != BTA_AG_SCO_OPEN_ST || bta_ag_cb.sco.cur_idx != p_scb->sco_idx) { + osi_free(p_data); + APPL_TRACE_WARNING("%s: SCO invalid state", __FUNCTION__); + return; + } + + switch (p_scb->air_mode) + { + case BTM_SCO_AIR_MODE_CVSD: + bta_ag_sco_data_send_cvsd(p_scb, p_buf); + break; + case BTM_SCO_AIR_MODE_TRANSPNT: + bta_ag_sco_data_send_msbc(p_scb, p_buf); + break; + default: + osi_free(p_buf); + APPL_TRACE_WARNING("%s: unsupported air mode: %d", __FUNCTION__, p_scb->air_mode); + break; + } +#else + osi_free(p_buf); +#endif +} + +/******************************************************************************* +** +** Function bta_ag_sco_data_free +** +** Description Free SCO data +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_sco_data_free(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + UNUSED(p_scb); + osi_free(p_data); +} + /******************************************************************************* ** ** Function bta_ag_set_esco_param diff --git a/lib/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h b/lib/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h index 9ced8b36..c8b7be36 100644 --- a/lib/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h +++ b/lib/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h @@ -96,6 +96,19 @@ BTA_AG_FEAT_VREC | BTA_AG_FEAT_INBAND | \ BTA_AG_FEAT_VTAG) +#if (BTM_SCO_HCI_INCLUDED == TRUE) +/* 1 (offset can not be 0) + HCI_SCO_PREAMBLE */ +#define BTA_AG_BUFF_OFFSET_MIN (1 + HCI_SCO_PREAMBLE_SIZE) +/* mSBC H2 header length */ +#define BTA_AG_H2_HEADER_LEN 2 +/* mSBC frame size not include H1/H2 header */ +#define BTA_AG_MSBC_FRAME_SIZE 57 +/* max user data len of sco packet type EV3 */ +#define BTA_AG_SCO_OUT_PKT_LEN_EV3 30 +/* max user data len of sco packet type 2-EV3 */ +#define BTA_AG_SCO_OUT_PKT_LEN_2EV3 60 +#endif + enum { /* these events are handled by the state machine */ @@ -107,6 +120,7 @@ enum BTA_AG_API_AUDIO_CLOSE_EVT, BTA_AG_API_RESULT_EVT, BTA_AG_API_SETCODEC_EVT, + BTA_AG_API_SCO_DATA_SEND_EVT, BTA_AG_RFC_OPEN_EVT, BTA_AG_RFC_CLOSE_EVT, BTA_AG_RFC_SRV_CLOSE_EVT, @@ -295,6 +309,7 @@ typedef struct TIMER_LIST_ENT cn_timer; /* codec negotiation timer */ #endif UINT16 sco_idx; /* SCO connection index */ + BT_HDR *p_sco_data; /* remaining SCO data of last sending operation */ BOOLEAN in_use; /* scb in use */ BOOLEAN dealloc; /* TRUE if service shutting down */ BOOLEAN clip_enabled; /* set to TRUE if HF enables CLIP reporting */ @@ -452,10 +467,13 @@ extern void bta_ag_result(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); extern void bta_ag_setcodec(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); extern void bta_ag_send_ring(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); extern void bta_ag_ci_sco_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); +extern void bta_ag_sco_data_send(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); +extern void bta_ag_sco_data_free(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); extern void bta_ag_set_esco_param(BOOLEAN set_reset, tBTM_ESCO_PARAMS *param); extern void bta_ag_ci_rx_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); extern void bta_ag_rcvd_slc_ready(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); extern void bta_ag_pkt_stat_nums(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); +extern void bta_ag_h2_header(UINT16 *p_buf); #endif /* #if (BTA_AG_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_act.c b/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_act.c index 0e0c43ad..930f30a5 100644 --- a/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_act.c +++ b/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_act.c @@ -511,7 +511,9 @@ void bta_hf_client_rfc_data(tBTA_HF_CLIENT_DATA *p_data) break; } + bta_sys_busy(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); bta_hf_client_at_parse(buf, len); + bta_sys_idle(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); /* no more data to read, we're done */ if (len < BTA_HF_CLIENT_RFC_READ_MAX) { diff --git a/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_api.c b/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_api.c index 6149d8c4..748d62db 100644 --- a/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_api.c +++ b/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_api.c @@ -44,9 +44,9 @@ static const uint8_t bta_hf_client_cb_data_size[] = { sizeof(tBTA_HF_CLIENT_OPEN), // #define BTA_HF_CLIENT_OPEN_EVT 2 0, // #define BTA_HF_CLIENT_CLOSE_EVT 3 sizeof(tBTA_HF_CLIENT_CONN), // #define BTA_HF_CLIENT_CONN_EVT 4 - sizeof(tBTA_HF_CLIENT_HDR), // #define BTA_HF_CLIENT_AUDIO_OPEN_EVT 5 - sizeof(tBTA_HF_CLIENT_HDR), //#define BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT 6 - sizeof(tBTA_HF_CLIENT_HDR), // #define BTA_HF_CLIENT_AUDIO_CLOSE_EVT 7 + sizeof(tBTA_HF_CLIENT_AUDIO_STAT), // #define BTA_HF_CLIENT_AUDIO_OPEN_EVT 5 + sizeof(tBTA_HF_CLIENT_AUDIO_STAT), // #define BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT 6 + sizeof(tBTA_HF_CLIENT_AUDIO_STAT), // #define BTA_HF_CLIENT_AUDIO_CLOSE_EVT 7 sizeof(tBTA_HF_CLIENT_VAL), // #define BTA_HF_CLIENT_SPK_EVT 8 sizeof(tBTA_HF_CLIENT_VAL), // #define BTA_HF_CLIENT_MIC_EVT 9 sizeof(tBTA_HF_CLIENT_IND), //#define BTA_HF_CLIENT_IND_EVT 10 @@ -322,6 +322,16 @@ void BTA_HfClientPktStatsNumsGet(UINT16 sync_conn_handle) } } +/******************************************************************************* +** +** Function BTA_HfClientCiData +** +** Description Send SCO outgoing data ready event +** +** +** Returns void +** +*******************************************************************************/ void BTA_HfClientCiData(void) { BT_HDR *p_buf; @@ -330,8 +340,79 @@ void BTA_HfClientCiData(void) bta_sys_sendmsg(p_buf); } } + +/******************************************************************************* +** +** Function BTA_HfClientAudioBuffAlloc +** +** Description Allocate an audio buffer with specific size, reserve enough +** space and offset for lower layer to send the buffer directly. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientAudioBuffAlloc(UINT16 size, UINT8 **pp_buff, UINT8 **pp_data) +{ + /* reserve 1 byte at last, when the size is mSBC frame size (57), then we got a buffer that can hold 60 bytes data */ + BT_HDR *p_buf= (BT_HDR *)osi_calloc(sizeof(BT_HDR) + BTA_HF_CLIENT_BUFF_OFFSET_MIN + BTA_HF_CLIENT_H2_HEADER_LEN + size + 1); + if (p_buf != NULL) { + /* mSBC offset is large than CVSD, so this is work in CVSD air mode */ + p_buf->offset = BTA_HF_CLIENT_BUFF_OFFSET_MIN + BTA_HF_CLIENT_H2_HEADER_LEN; + *pp_buff = (UINT8 *)p_buf; + *pp_data = (UINT8 *)(p_buf + 1) + p_buf->offset; + } +} + +/******************************************************************************* +** +** Function BTA_HfClientAudioBuffFree +** +** Description Free an audio buffer. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientAudioBuffFree(UINT8 *p_buf) +{ + osi_free(p_buf); +} + +/******************************************************************************* +** +** Function BTA_HfClientAudioDataSend +** +** Description Send audio data to lower layer, whether success or not, buffer +** is consumed. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientAudioDataSend(UINT16 sync_conn_hdl, UINT8 *p_buff_start, UINT8 *p_data, UINT16 data_len) +{ + /* currently, sync_conn_hdl is not used */ + BT_HDR *p_buf = (BT_HDR *)p_buff_start; + assert(p_data - (UINT8 *)(p_buf + 1) >= 0); + p_buf->event = BTA_HF_CLIENT_SCO_DATA_SEND_EVT; + p_buf->offset = p_data - (UINT8 *)(p_buf + 1); + p_buf->len = data_len; + bta_sys_sendmsg(p_buf); +} + #endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) */ +/******************************************************************************* +** +** Function BTA_HfClientGetCbDataSize +** +** Description Get callback data size of specific event +** +** +** Returns void +** +*******************************************************************************/ int BTA_HfClientGetCbDataSize(tBTA_HF_CLIENT_EVT event) { return bta_hf_client_cb_data_size[event]; diff --git a/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c b/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c index 4124a10f..b87c4869 100644 --- a/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c +++ b/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_main.c @@ -24,6 +24,7 @@ #include "bta/bta_sys.h" #include "bta/bta_hf_client_api.h" #include "bta_hf_client_int.h" +#include "osi/allocator.h" #if BT_HF_CLIENT_BQB_INCLUDED static BOOLEAN s_bta_hf_client_bqb_clip_flag = TRUE; @@ -79,6 +80,8 @@ enum { BTA_HF_CLIENT_SEND_AT_CMD, #if (BTM_SCO_HCI_INCLUDED == TRUE) BTA_HF_CLIENT_CI_SCO_DATA, + BTA_HF_CLIENT_SCO_DATA_SEND, + BTA_HF_CLIENT_SCO_DATA_FREE, BTA_HF_CLIENT_PKT_STAT_NUMS, #endif BTA_HF_CLIENT_NUM_ACTIONS, @@ -118,6 +121,8 @@ const tBTA_HF_CLIENT_ACTION bta_hf_client_action[] = { /* BTA_HF_CLIENT_SEND_AT_CMD */ bta_hf_client_send_at_cmd, #if (BTM_SCO_HCI_INCLUDED == TRUE) /* BTA_HF_CLIENT_CI_SCO_DATA */ bta_hf_client_ci_sco_data, + /* BTA_HF_CLIENT_SCO_DATA_SEND */ bta_hf_client_sco_data_send, + /* BTA_HF_CLIENT_SCO_DATA_FREE */ bta_hf_client_sco_data_free, /* BTA_HF_CLIENT_PKT_STAT_NUMS */ bta_hf_client_pkt_stat_nums, #endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ }; @@ -149,6 +154,7 @@ const UINT8 bta_hf_client_st_init[][BTA_HF_CLIENT_NUM_COLS] = { /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, #if (BTM_SCO_HCI_INCLUDED == TRUE ) /* CI_SCO_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* SCO_DATA_SEND_EVT */ {BTA_HF_CLIENT_SCO_DATA_FREE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, /* PKT_STAT_NUMS_GET_EVT */ {BTA_HF_CLIENT_PKT_STAT_NUMS, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, #endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ }; @@ -175,6 +181,7 @@ const UINT8 bta_hf_client_st_opening[][BTA_HF_CLIENT_NUM_COLS] = { /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, #if (BTM_SCO_HCI_INCLUDED == TRUE) /* CI_SCO_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, + /* SCO_DATA_SEND_EVT */ {BTA_HF_CLIENT_SCO_DATA_FREE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, /* PKT_STAT_NUMS_GET_EVT */ {BTA_HF_CLIENT_PKT_STAT_NUMS, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, #endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ }; @@ -201,6 +208,7 @@ const UINT8 bta_hf_client_st_open[][BTA_HF_CLIENT_NUM_COLS] = { /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_SEND_AT_CMD, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, #if (BTM_SCO_HCI_INCLUDED == TRUE ) /* CI_SCO_DATA_EVT */ {BTA_HF_CLIENT_CI_SCO_DATA, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, + /* SCO_DATA_SEND_EVT */ {BTA_HF_CLIENT_SCO_DATA_SEND, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, /* PKT_STAT_NUMS_GET_EVT */ {BTA_HF_CLIENT_PKT_STAT_NUMS, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, #endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ }; @@ -227,6 +235,7 @@ const UINT8 bta_hf_client_st_closing[][BTA_HF_CLIENT_NUM_COLS] = { /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, #if (BTM_SCO_HCI_INCLUDED == TRUE ) /* CI_SCO_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* SCO_DATA_SEND_EVT */ {BTA_HF_CLIENT_SCO_DATA_FREE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, /* PKT_STAT_NUMS_GET_EVT */ {BTA_HF_CLIENT_PKT_STAT_NUMS, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, #endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ }; @@ -284,6 +293,7 @@ void bta_hf_client_scb_init(void) memset(&bta_hf_client_cb.scb, 0, sizeof(tBTA_HF_CLIENT_SCB)); bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX; bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD; + bta_hf_client_cb.scb.p_sco_data = NULL; } /******************************************************************************* @@ -299,6 +309,10 @@ void bta_hf_client_scb_init(void) void bta_hf_client_scb_disable(void) { APPL_TRACE_DEBUG("%s", __FUNCTION__); + if (bta_hf_client_cb.scb.p_sco_data != NULL) { + osi_free(bta_hf_client_cb.scb.p_sco_data); + bta_hf_client_cb.scb.p_sco_data = NULL; + } bta_hf_client_scb_init(); @@ -413,7 +427,11 @@ static void bta_hf_client_api_enable(tBTA_HF_CLIENT_DATA *p_data) /* check if mSBC support enabled */ if (bta_hf_client_version >= HFP_HF_VERSION_1_6) { +#if (BTM_WBS_INCLUDED == TRUE) bta_hf_client_cb.msbc_enabled = TRUE; +#else + bta_hf_client_cb.msbc_enabled = FALSE; +#endif } else{ bta_hf_client_cb.msbc_enabled = FALSE; } @@ -466,6 +484,7 @@ static void bta_hf_client_api_disable(tBTA_HF_CLIENT_DATA *p_data) *******************************************************************************/ BOOLEAN bta_hf_client_hdl_event(BT_HDR *p_msg) { + BOOLEAN free_msg = TRUE; #if BTA_HF_CLIENT_DEBUG == TRUE APPL_TRACE_DEBUG("bta_hf_client_hdl_event %s (0x%x)", bta_hf_client_evt_str(p_msg->event), p_msg->event); #endif @@ -480,12 +499,16 @@ BOOLEAN bta_hf_client_hdl_event(BT_HDR *p_msg) case BTA_HF_CLIENT_API_DISABLE_EVT: bta_hf_client_api_disable((tBTA_HF_CLIENT_DATA *) p_msg); break; - +#if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTA_HFP_EXT_CODEC == TRUE) + case BTA_HF_CLIENT_SCO_DATA_SEND_EVT: + free_msg = false; + /* fall through */ +#endif default: bta_hf_client_sm_execute(p_msg->event, (tBTA_HF_CLIENT_DATA *) p_msg); break; } - return TRUE; + return free_msg; } /******************************************************************************* diff --git a/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_sco.c b/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_sco.c index d464a889..11437fb9 100644 --- a/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_sco.c +++ b/lib/bt/host/bluedroid/bta/hf_client/bta_hf_client_sco.c @@ -177,6 +177,36 @@ static BOOLEAN bta_hf_client_sco_remove(BOOLEAN only_active) return removed_started; } +#if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTA_HFP_EXT_CODEC == TRUE) + +/******************************************************************************* +** +** Function bta_hf_client_sco_get_frame_size +** +** Description Get SCO frame size +** +** Returns frame size +** +*******************************************************************************/ +static UINT16 bta_hf_client_sco_get_frame_size(void) +{ + UINT16 frame_size = 0; + switch (bta_hf_client_cb.scb.air_mode) + { + case BTM_SCO_AIR_MODE_CVSD: + frame_size = bta_hf_client_cb.scb.out_pkt_len; + break; + case BTM_SCO_AIR_MODE_TRANSPNT: + frame_size = BTA_HF_CLIENT_MSBC_FRAME_SIZE; + break; + default: + break; + } + return frame_size; +} + +#endif + /******************************************************************************* ** ** Function bta_hf_client_cback_sco @@ -189,13 +219,17 @@ static BOOLEAN bta_hf_client_sco_remove(BOOLEAN only_active) *******************************************************************************/ void bta_hf_client_cback_sco(UINT8 event) { - tBTA_HF_CLIENT_HDR evt; - - memset(&evt, 0, sizeof(evt)); - evt.sync_conn_handle = BTM_ReadScoHandle(bta_hf_client_cb.scb.sco_idx); + tBTA_HF_CLIENT_AUDIO_STAT audio_stat; + memset(&audio_stat, 0, sizeof(audio_stat)); + audio_stat.hdr.sync_conn_handle = BTM_ReadScoHandle(bta_hf_client_cb.scb.sco_idx); +#if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTA_HFP_EXT_CODEC == TRUE) + if (event != BTA_HF_CLIENT_AUDIO_CLOSE_EVT) { + audio_stat.preferred_frame_size = bta_hf_client_sco_get_frame_size(); + } +#endif /* call app cback */ - (*bta_hf_client_cb.p_cback)(event, (tBTA_HF_CLIENT_HDR *) &evt); + (*bta_hf_client_cb.p_cback)(event, &audio_stat); } #if (BTM_SCO_HCI_INCLUDED == TRUE ) @@ -217,7 +251,6 @@ static void bta_hf_client_sco_read_cback (UINT16 sco_idx, BT_HDR *p_data, tBTM_S } bta_hf_client_sco_co_in_data (p_data, status); - osi_free(p_data); } #endif /* BTM_SCO_HCI_INCLUDED */ @@ -307,7 +340,7 @@ void bta_hf_client_pkt_stat_nums(tBTA_HF_CLIENT_DATA *p_data) ** ** Function bta_hf_client_ci_sco_data ** -** Description Process the SCO data ready callin event +** Description Process the SCO data ready call in event ** ** ** Returns void @@ -318,6 +351,281 @@ void bta_hf_client_ci_sco_data(tBTA_HF_CLIENT_DATA *p_data) UNUSED(p_data); bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CI_DATA_E); } + +/******************************************************************************* +** +** Function bta_hf_client_write_sco_data +** +** Description Write two SCO data buffers to specified instance +** +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_write_sco_data(BT_HDR *p_buf1, BT_HDR *p_buf2) +{ + BTM_WriteScoData(bta_hf_client_cb.scb.sco_idx, p_buf1); + if (p_buf2 != NULL) { + BTM_WriteScoData(bta_hf_client_cb.scb.sco_idx, p_buf2); + } +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_data_send_cvsd +** +** Description Process SCO data of CVSD air mode +** +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_sco_data_send_cvsd(BT_HDR *p_buf, UINT8 out_pkt_len) +{ + if (bta_hf_client_cb.scb.p_sco_data != NULL) { + /* the remaining data of last sending operation */ + BT_HDR *p_buf_last = bta_hf_client_cb.scb.p_sco_data; + /* remaining data len should small than out_pkt_len */ + assert(p_buf_last->len < out_pkt_len); + BT_HDR *p_buf2 = osi_calloc(sizeof(BT_HDR) + BTA_HF_CLIENT_BUFF_OFFSET_MIN + out_pkt_len); + if (p_buf2 == NULL) { + osi_free(p_buf); + osi_free(p_buf_last); + bta_hf_client_cb.scb.p_sco_data = NULL; + APPL_TRACE_WARNING("%s, no memory", __FUNCTION__); + return; + } + p_buf2->offset = BTA_HF_CLIENT_BUFF_OFFSET_MIN; + + UINT8 *p_data = (UINT8 *)(p_buf2 + 1) + p_buf2->offset; + memcpy(p_data, (UINT8 *)(p_buf_last + 1) + p_buf_last->offset, p_buf_last->len); + + if (p_buf->len + p_buf_last->len < out_pkt_len) { + memcpy(p_data + p_buf_last->len, (UINT8 *)(p_buf + 1) + p_buf->offset, p_buf->len); + p_buf2->len = p_buf->len + p_buf_last->len; + osi_free(p_buf); + osi_free(p_buf_last); + bta_hf_client_cb.scb.p_sco_data = p_buf2; + } + else { + UINT16 copy_len = out_pkt_len - p_buf_last->len; + memcpy(p_data + p_buf_last->len, (UINT8 *)(p_buf + 1) + p_buf->offset, copy_len); + p_buf2->len = out_pkt_len; + p_buf->offset += copy_len; + p_buf->len -= copy_len; + osi_free(p_buf_last); + bta_hf_client_cb.scb.p_sco_data = NULL; + bta_hf_client_write_sco_data(p_buf2, NULL); + if (p_buf->len == 0) { + osi_free(p_buf); + } + else { + /* Recursive call, this will only called once */ + bta_hf_client_sco_data_send_cvsd(p_buf, out_pkt_len); + } + } + } + else if (p_buf->len < out_pkt_len) { + bta_hf_client_cb.scb.p_sco_data = p_buf; + } + else { + /* bta_hf_client_cb.scb.p_sco_data == NULL && p_buf->len >= out_pkt_len */ + while (1) { + if (p_buf->len == out_pkt_len) { + bta_hf_client_write_sco_data(p_buf, NULL); + break; + } + else { + BT_HDR *p_buf2 = osi_calloc(sizeof(BT_HDR) + BTA_HF_CLIENT_BUFF_OFFSET_MIN + out_pkt_len); + if (p_buf2 == NULL) { + osi_free(p_buf); + APPL_TRACE_WARNING("%s, no memory", __FUNCTION__); + return; + } + p_buf2->offset = BTA_HF_CLIENT_BUFF_OFFSET_MIN; + UINT8 *p_data = (UINT8 *)(p_buf2 + 1) + p_buf2->offset; + memcpy(p_data, (UINT8 *)(p_buf + 1) + p_buf->offset, out_pkt_len); + p_buf2->len = out_pkt_len; + p_buf->offset += out_pkt_len; + p_buf->len -= out_pkt_len; + bta_hf_client_write_sco_data(p_buf2, NULL); + } + if (p_buf->len < out_pkt_len) { + bta_hf_client_cb.scb.p_sco_data = p_buf; + break; + } + } + } +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_data_send_msbc +** +** Description Process SCO data of mSBC air mode +** +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_sco_data_send_msbc(BT_HDR *p_buf, UINT8 out_pkt_len) +{ + if (p_buf->len == BTA_HF_CLIENT_MSBC_FRAME_SIZE && p_buf->offset >= BTA_HF_CLIENT_BUFF_OFFSET_MIN + BTA_HF_CLIENT_H2_HEADER_LEN) { + /* add H2 header */ + p_buf->offset -= BTA_HF_CLIENT_H2_HEADER_LEN; + UINT8 *p_data = (UINT8 *)(p_buf + 1) + p_buf->offset; + bta_hf_client_h2_header((UINT16 *)p_data); + /* add header len, add addition one bytes, the len is BTA_HF_CLIENT_SCO_OUT_PKT_LEN_2EV3 now */ + p_buf->len += BTA_HF_CLIENT_H2_HEADER_LEN + 1; + + if (out_pkt_len == BTA_HF_CLIENT_SCO_OUT_PKT_LEN_2EV3) { + /* mSBC frame can be send directly */ + bta_hf_client_write_sco_data(p_buf, NULL); + } + else if (out_pkt_len == BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3) { + /* need to split into 2 sco packages for sending */ + BT_HDR *p_buf2 = osi_calloc(sizeof(BT_HDR) + BTA_HF_CLIENT_BUFF_OFFSET_MIN + BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3); + if (p_buf2 == NULL) { + /* free the first buff too */ + osi_free(p_buf); + APPL_TRACE_WARNING("%s, no memory", __FUNCTION__); + return; + } + p_buf2->offset = BTA_HF_CLIENT_BUFF_OFFSET_MIN; + p_buf2->len = BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3; + UINT8 *p_data2 = (UINT8 *)(p_buf2 + 1) + p_buf2->offset; + memcpy(p_data2, p_data + BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3, BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3); + /* update the first packet len */ + p_buf->len = BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3; + bta_hf_client_write_sco_data(p_buf, p_buf2); + } + else { + osi_free(p_buf); + APPL_TRACE_WARNING("%s, invalid out pkt len: %d", __FUNCTION__, out_pkt_len); + } + } + else if (p_buf->len != 0 && p_buf->len % BTA_HF_CLIENT_MSBC_FRAME_SIZE == 0) { + /* multiple mSBC frame in the buffer, or just one but offset is too small */ + UINT8 *p_data = (UINT8 *)(p_buf + 1) + p_buf->offset; + UINT16 total_len = p_buf->len; + if (out_pkt_len == BTA_HF_CLIENT_SCO_OUT_PKT_LEN_2EV3) { + while (total_len != 0) { + BT_HDR *p_buf2 = osi_calloc(sizeof(BT_HDR) + BTA_HF_CLIENT_BUFF_OFFSET_MIN + BTA_HF_CLIENT_SCO_OUT_PKT_LEN_2EV3); + if (p_buf2 == NULL) { + APPL_TRACE_WARNING("%s, no memory", __FUNCTION__); + break; + } + p_buf2->offset = BTA_HF_CLIENT_BUFF_OFFSET_MIN; + p_buf2->len = BTA_HF_CLIENT_SCO_OUT_PKT_LEN_2EV3; + UINT8 *p_data2 = (UINT8 *)(p_buf2 + 1) + p_buf2->offset; + bta_hf_client_h2_header((UINT16 *)p_data2); + p_data2 += BTA_HF_CLIENT_H2_HEADER_LEN; + memcpy(p_data2, p_data, BTA_HF_CLIENT_MSBC_FRAME_SIZE); + p_data += BTA_HF_CLIENT_MSBC_FRAME_SIZE; + total_len -= BTA_HF_CLIENT_MSBC_FRAME_SIZE; + bta_hf_client_write_sco_data(p_buf2, NULL); + } + } + else if (out_pkt_len == BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3) { + while (total_len != 0) { + BT_HDR *p_buf2 = osi_calloc(sizeof(BT_HDR) + BTA_HF_CLIENT_BUFF_OFFSET_MIN + BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3); + if (p_buf2 == NULL) { + APPL_TRACE_WARNING("%s, no memory", __FUNCTION__); + break; + } + BT_HDR *p_buf3 = osi_calloc(sizeof(BT_HDR) + BTA_HF_CLIENT_BUFF_OFFSET_MIN + BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3); + if (p_buf3 == NULL) { + /* free the first buff too */ + osi_free(p_buf2); + APPL_TRACE_WARNING("%s, no memory", __FUNCTION__); + break; + } + + /* build first packet, include H2 header */ + p_buf2->offset = BTA_HF_CLIENT_BUFF_OFFSET_MIN; + p_buf2->len = BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3; + UINT8 *p_data2 = (UINT8 *)(p_buf2 + 1) + p_buf2->offset; + bta_hf_client_h2_header((UINT16 *)p_data2); + p_data2 += BTA_HF_CLIENT_H2_HEADER_LEN; + memcpy(p_data2, p_data, BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3 - BTA_HF_CLIENT_H2_HEADER_LEN); + p_data += BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3 - BTA_HF_CLIENT_H2_HEADER_LEN; + total_len -= BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3 - BTA_HF_CLIENT_H2_HEADER_LEN; + + /* build second packet, not include header */ + p_buf3->offset = BTA_HF_CLIENT_BUFF_OFFSET_MIN; + p_buf3->len = BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3; + UINT8 *p_data3 = (UINT8 *)(p_buf3 + 1) + p_buf3->offset; + memcpy(p_data3, p_data, BTA_HF_CLIENT_MSBC_FRAME_SIZE - BTA_HF_CLIENT_H2_HEADER_LEN - BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3); + p_data += BTA_HF_CLIENT_MSBC_FRAME_SIZE - BTA_HF_CLIENT_H2_HEADER_LEN - BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3; + total_len -= BTA_HF_CLIENT_MSBC_FRAME_SIZE - BTA_HF_CLIENT_H2_HEADER_LEN - BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3; + bta_hf_client_write_sco_data(p_buf2, p_buf3); + } + } + else { + APPL_TRACE_WARNING("%s, invalid out pkt len: %d", __FUNCTION__, out_pkt_len); + } + osi_free(p_buf); + } + else { + APPL_TRACE_WARNING("%s, unaccepted data len: %d", __FUNCTION__, p_buf->len); + osi_free(p_buf); + } +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_data_send +** +** Description Route SCO data to specific processing function based on air mode +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_sco_data_send(tBTA_HF_CLIENT_DATA *p_data) +{ + BT_HDR *p_buf = (BT_HDR *) p_data; + + if (bta_hf_client_cb.scb.sco_state != BTA_HF_CLIENT_SCO_OPEN_ST) { + osi_free(p_data); + APPL_TRACE_WARNING("%s: SCO not open", __FUNCTION__); + return; + } + + UINT8 out_pkt_len = bta_hf_client_cb.scb.out_pkt_len; + UINT8 air_mode = bta_hf_client_cb.scb.air_mode; + + switch (air_mode) + { + case BTM_SCO_AIR_MODE_CVSD: + bta_hf_client_sco_data_send_cvsd(p_buf, out_pkt_len); + break; + case BTM_SCO_AIR_MODE_TRANSPNT: + bta_hf_client_sco_data_send_msbc(p_buf, out_pkt_len); + break; + default: + osi_free(p_buf); + APPL_TRACE_WARNING("%s: unsupported air mode: %d", __FUNCTION__, air_mode); + break; + } +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_data_free +** +** Description Free SCO data buffer +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_sco_data_free(tBTA_HF_CLIENT_DATA *p_data) +{ + /* just free the sco data buffer */ + osi_free(p_data); +} + #endif /******************************************************************************* @@ -539,12 +847,9 @@ static void bta_hf_client_sco_event(UINT8 event) APPL_TRACE_DEBUG("%s state: %d event: %d", __FUNCTION__, bta_hf_client_cb.scb.sco_state, event); -#if (BTM_SCO_HCI_INCLUDED == TRUE ) - tBTA_HF_CLIENT_SCB *p_scb = &bta_hf_client_cb.scb; +#if (BTM_SCO_HCI_INCLUDED == TRUE ) && (BTA_HFP_EXT_CODEC == FALSE) BT_HDR *p_buf; -#endif - -#if (BTM_SCO_HCI_INCLUDED == TRUE ) + tBTA_HF_CLIENT_SCB *p_scb = &bta_hf_client_cb.scb; if (event == BTA_HF_CLIENT_SCO_CI_DATA_E) { UINT16 pkt_offset = 1 + HCI_SCO_PREAMBLE_SIZE; UINT16 len_to_send = 0; @@ -890,6 +1195,11 @@ void bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA *p_data) bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); + if (bta_hf_client_cb.scb.p_sco_data != NULL) { + osi_free(bta_hf_client_cb.scb.p_sco_data); + bta_hf_client_cb.scb.p_sco_data = NULL; + } + /* call app callback */ bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT); diff --git a/lib/bt/host/bluedroid/bta/hf_client/include/bta_hf_client_int.h b/lib/bt/host/bluedroid/bta/hf_client/include/bta_hf_client_int.h index 0732a96c..d2b34518 100644 --- a/lib/bt/host/bluedroid/bta/hf_client/include/bta_hf_client_int.h +++ b/lib/bt/host/bluedroid/bta/hf_client/include/bta_hf_client_int.h @@ -44,6 +44,19 @@ #define BTA_HF_CLIENT_COLLISION_TIMER 2411 #endif +#if (BTM_SCO_HCI_INCLUDED == TRUE ) +/* 1 (offset can not be 0) + HCI_SCO_PREAMBLE */ +#define BTA_HF_CLIENT_BUFF_OFFSET_MIN (1 + HCI_SCO_PREAMBLE_SIZE) +/* mSBC H2 header length */ +#define BTA_HF_CLIENT_H2_HEADER_LEN 2 +/* mSBC frame size not include H1/H2 header */ +#define BTA_HF_CLIENT_MSBC_FRAME_SIZE 57 +/* max user data len of sco packet type EV3 */ +#define BTA_HF_CLIENT_SCO_OUT_PKT_LEN_EV3 30 +/* max user data len of sco packet type 2-EV3 */ +#define BTA_HF_CLIENT_SCO_OUT_PKT_LEN_2EV3 60 +#endif + enum { /* these events are handled by the state machine */ BTA_HF_CLIENT_API_REGISTER_EVT = BTA_SYS_EVT_START(BTA_ID_HS), @@ -65,6 +78,7 @@ enum { BTA_HF_CLIENT_SEND_AT_CMD_EVT, #if (BTM_SCO_HCI_INCLUDED == TRUE ) BTA_HF_CLIENT_CI_SCO_DATA_EVT, + BTA_HF_CLIENT_SCO_DATA_SEND_EVT, BTA_HF_CLIENT_PKT_NUMS_GET_EVT, #endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ BTA_HF_CLIENT_MAX_EVT, @@ -138,7 +152,6 @@ typedef union { tBTA_HF_CLIENT_RFC rfc; tBTA_HF_CLIENT_DATA_VAL val; tBTA_HF_CLIENT_PKT_STAT_GET pkt_stat; - } tBTA_HF_CLIENT_DATA; /* type for each service control block */ @@ -158,6 +171,7 @@ typedef struct { UINT16 sco_idx; /* SCO handle */ UINT8 sco_state; /* SCO state variable */ BOOLEAN sco_close_rfc; /* TRUE if also close RFCOMM after SCO */ + BT_HDR *p_sco_data; /* remaining SCO data of last sending operation */ BOOLEAN retry_with_sco_only; BOOLEAN deregister; /* TRUE if service shutting down */ BOOLEAN svc_conn; /* set to TRUE when service level connection is up */ @@ -312,5 +326,8 @@ extern void bta_hf_client_send_at_cmd(tBTA_HF_CLIENT_DATA *p_data); #if (BTM_SCO_HCI_INCLUDED == TRUE ) extern void bta_hf_client_pkt_stat_nums(tBTA_HF_CLIENT_DATA *p_data); extern void bta_hf_client_ci_sco_data(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_h2_header(UINT16 *p_buf); +extern void bta_hf_client_sco_data_send(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_sco_data_free(tBTA_HF_CLIENT_DATA *p_data); #endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ #endif /* #if (BTA_HF_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/bta/hh/bta_hh_le.c b/lib/bt/host/bluedroid/bta/hh/bta_hh_le.c index a80314ef..f5697dff 100644 --- a/lib/bt/host/bluedroid/bta/hh/bta_hh_le.c +++ b/lib/bt/host/bluedroid/bta/hh/bta_hh_le.c @@ -117,7 +117,7 @@ static void bta_hh_le_hid_report_dbg(tBTA_HH_DEV_CB *p_cb) if (p_cb->hid_srvc[i].in_use) { p_rpt = &p_cb->hid_srvc[i].report[0]; - APPL_TRACE_DEBUG("\t HID serivce inst: %d", i); + APPL_TRACE_DEBUG("\t HID service inst: %d", i); for (j = 0; j < BTA_HH_LE_RPT_MAX; j ++, p_rpt++) { rpt_name = "Unknown"; @@ -334,14 +334,15 @@ void bta_hh_le_open_conn(tBTA_HH_DEV_CB *p_cb, BD_ADDR remote_bda) bta_hh_cb.le_cb_index[BTA_HH_GET_LE_CB_IDX(p_cb->hid_handle)] = p_cb->index; p_cb->in_use = TRUE; - BTA_GATTC_Open(bta_hh_cb.gatt_if, remote_bda, BLE_ADDR_UNKNOWN_TYPE, TRUE, BTA_GATT_TRANSPORT_LE, FALSE); + BTA_GATTC_Enh_Open(bta_hh_cb.gatt_if, remote_bda, BLE_ADDR_UNKNOWN_TYPE, TRUE, + BTA_GATT_TRANSPORT_LE, FALSE, BLE_ADDR_UNKNOWN_TYPE, 0, NULL, NULL, NULL); } /******************************************************************************* ** ** Function bta_hh_le_fill_16bits_gatt_id ** -** Description Utility function to fill a GATT ID strucure +** Description Utility function to fill a GATT ID structure ** *******************************************************************************/ void bta_hh_le_fill_16bits_gatt_id(UINT8 inst_id, UINT16 uuid, tBTA_GATT_ID *p_output) @@ -355,7 +356,7 @@ void bta_hh_le_fill_16bits_gatt_id(UINT8 inst_id, UINT16 uuid, tBTA_GATT_ID *p_ ** ** Function bta_hh_le_fill_16bits_srvc_id ** -** Description Utility function to fill a service ID strucure with a 16 bits +** Description Utility function to fill a service ID structure with a 16 bits ** service UUID. ** *******************************************************************************/ @@ -372,7 +373,7 @@ void bta_hh_le_fill_16bits_srvc_id(BOOLEAN is_pri, UINT8 inst_id, UINT16 srvc_uu ** ** Function bta_hh_le_fill_16bits_char_id ** -** Description Utility function to fill a char ID strucure with a 16 bits +** Description Utility function to fill a char ID structure with a 16 bits ** char UUID. ** *******************************************************************************/ @@ -624,7 +625,7 @@ tBTA_HH_STATUS bta_hh_le_read_char_dscrpt(tBTA_HH_DEV_CB *p_cb, UINT16 srvc_uuid ** ** Function bta_hh_le_read_rpt_ref_descr ** -** Description read report refernece descriptors in service discovery process +** Description read report reference descriptors in service discovery process ** *******************************************************************************/ void bta_hh_le_read_rpt_ref_descr(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_LE_RPT *p_rpt) @@ -841,7 +842,7 @@ void bta_hh_le_register_input_notif(tBTA_HH_DEV_CB *p_dev_cb, UINT8 srvc_inst, } } /* - else unknow protocol mode */ + else unknown protocol mode */ } } } @@ -1486,7 +1487,7 @@ void bta_hh_le_gatt_disc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_STATUS status) { APPL_TRACE_DEBUG("bta_hh_le_gatt_disc_cmpl "); - /* if open sucessful or protocol mode not desired, keep the connection open but inform app */ + /* if open successful or protocol mode not desired, keep the connection open but inform app */ if (status == BTA_HH_OK || status == BTA_HH_ERR_PROTO) { /* assign a special APP ID temp, since device type unknown */ p_cb->app_id = BTA_HH_APP_ID_LE; @@ -1504,7 +1505,7 @@ void bta_hh_le_gatt_disc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_STATUS status) ** ** Function bta_hh_le_srvc_expl_srvc ** -** Description This function discover the next avaible HID service. +** Description This function discover the next available HID service. ** ** Parameters: ** @@ -2076,7 +2077,7 @@ void bta_hh_w4_le_read_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf) ** ** Function bta_hh_w4_le_write_cmpl ** -** Description Write charactersitic complete event at W4_CONN st. +** Description Write characteristic complete event at W4_CONN st. ** ** Parameters: ** @@ -2104,7 +2105,7 @@ void bta_hh_w4_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf) ** ** Function bta_hh_le_write_cmpl ** -** Description Write charactersitic complete event at CONN st. +** Description Write characteristic complete event at CONN st. ** ** Parameters: ** @@ -2162,7 +2163,7 @@ void bta_hh_le_write_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf) ** ** Function bta_hh_le_write_char_descr_cmpl ** -** Description Write charactersitic descriptor complete event +** Description Write characteristic descriptor complete event ** ** Parameters: ** @@ -2216,7 +2217,7 @@ void bta_hh_le_write_char_descr_cmpl(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_b ** ** Function bta_hh_le_input_rpt_notify ** -** Description process the notificaton event, most likely for input report. +** Description process the notification event, most likely for input report. ** ** Parameters: ** @@ -2357,7 +2358,7 @@ void bta_hh_gatt_close(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data) ** ** Function bta_hh_le_api_disc_act ** -** Description initaite a Close API to a remote HID device +** Description initiate a Close API to a remote HID device ** ** Returns void ** @@ -2601,7 +2602,8 @@ static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, BOOLEAN check_bond) if (/*p_cb->dscp_info.flag & BTA_HH_LE_NORMAL_CONN &&*/ !p_cb->in_bg_conn && to_add) { /* add device into BG connection to accept remote initiated connection */ - BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, BLE_ADDR_UNKNOWN_TYPE, FALSE, BTA_GATT_TRANSPORT_LE, FALSE); + BTA_GATTC_Enh_Open(bta_hh_cb.gatt_if, p_cb->addr, BLE_ADDR_UNKNOWN_TYPE, FALSE, + BTA_GATT_TRANSPORT_LE, FALSE, BLE_ADDR_UNKNOWN_TYPE, 0, NULL, NULL); p_cb->in_bg_conn = TRUE; BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL); @@ -2682,7 +2684,7 @@ void bta_hh_le_update_scpp(tBTA_HH_DEV_CB *p_dev_cb, tBTA_HH_DATA *p_buf) if (!p_dev_cb->is_le_device || p_dev_cb->mode != BTA_HH_PROTO_RPT_MODE || p_dev_cb->scps_supported == FALSE) { - APPL_TRACE_ERROR("Can not set ScPP scan paramter as boot host, or remote does not support ScPP "); + APPL_TRACE_ERROR("Can not set ScPP scan parameter as boot host, or remote does not support ScPP "); cback_data.handle = p_dev_cb->hid_handle; cback_data.status = BTA_HH_ERR; @@ -2908,7 +2910,7 @@ static void bta_hh_le_search_scps_chars(tBTA_HH_DEV_CB *p_cb) ** ** Function bta_hh_le_register_scpp_notif ** -** Description register scan parameter refresh notitication complete +** Description register scan parameter refresh notification complete ** ** ** Parameters: @@ -2919,7 +2921,7 @@ static void bta_hh_le_register_scpp_notif(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_ST UINT8 sec_flag = 0; tBTA_GATTC_CHAR_ID char_id; - /* if write scan parameter sucessful */ + /* if write scan parameter successful */ /* if bonded and notification is not enabled, configure the client configuration */ if (status == BTA_GATT_OK && (p_dev_cb->scps_notify & BTA_HH_LE_SCPS_NOTIFY_SPT) != 0 && @@ -2949,7 +2951,7 @@ static void bta_hh_le_register_scpp_notif(tBTA_HH_DEV_CB *p_dev_cb, tBTA_GATT_ST ** ** Function bta_hh_le_register_scpp_notif_cmpl ** -** Description action function to register scan parameter refresh notitication +** Description action function to register scan parameter refresh notification ** ** Parameters: ** diff --git a/lib/bt/host/bluedroid/bta/include/bta/bta_ag_api.h b/lib/bt/host/bluedroid/bta/include/bta/bta_ag_api.h index 35bb6ab5..ac714d85 100644 --- a/lib/bt/host/bluedroid/bta/include/bta/bta_ag_api.h +++ b/lib/bt/host/bluedroid/bta/include/bta/bta_ag_api.h @@ -112,7 +112,7 @@ typedef UINT8 tBTA_AG_STATUS; /* It is safe to use the same value as BTA_AG_HANDLE_ALL * HANDLE_ALL is used for delivering indication * SCO_NO_CHANGE is used for changing sco behavior - * They donot interfere with each other + * They do not interfere with each other */ #define BTA_AG_HANDLE_SCO_NO_CHANGE 0xFFFF @@ -363,6 +363,13 @@ typedef struct tBTA_AG_CHLD_FEAT chld_feat; } tBTA_AG_CONN; +/* data associated with BTA_AG_AUDIO_OPEN_EVT, BTA_AG_AUDIO_CLOSE_EVT or BTA_AG_AUDIO_MSBC_OPEN_EVT */ +typedef struct +{ + tBTA_AG_HDR hdr; + UINT16 preferred_frame_size; +} tBTA_AG_AUDIO_STAT; + /* data associated with AT command event */ typedef struct { @@ -427,6 +434,7 @@ typedef union tBTA_AG_OPEN open; tBTA_AG_CLOSE close; tBTA_AG_CONN conn; + tBTA_AG_AUDIO_STAT audio_stat; tBTA_AG_IND ind; tBTA_AG_VAL val; //add @@ -619,6 +627,45 @@ void BTA_AgPktStatsNumsGet(UINT16 handle, UINT16 sync_conn_handle); ** *******************************************************************************/ void BTA_AgCiData(UINT16 handle); + +/******************************************************************************* +** +** Function BTA_AgAudioBuffAlloc +** +** Description Allocate an audio buffer with specific size, reserve enough +** space and offset for lower layer to send the buffer directly. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_AgAudioBuffAlloc(UINT16 size, UINT8 **pp_buff, UINT8 **pp_data); + +/******************************************************************************* +** +** Function BTA_AgAudioBuffFree +** +** Description Free an audio buffer. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_AgAudioBuffFree(UINT8 *p_buf); + +/******************************************************************************* +** +** Function BTA_AgAudioDataSend +** +** Description Send audio data to lower layer, whether success or not, buffer +** is consumed. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_AgAudioDataSend(UINT16 handle, UINT8 *p_buff_start, UINT8 *p_data, UINT16 data_len); + #endif /*#if (BTM_SCO_HCI_INCLUDED == TRUE ) */ #ifdef __cplusplus diff --git a/lib/bt/host/bluedroid/bta/include/bta/bta_api.h b/lib/bt/host/bluedroid/bta/include/bta/bta_api.h index 75a81994..aa1b632a 100644 --- a/lib/bt/host/bluedroid/bta/include/bta/bta_api.h +++ b/lib/bt/host/bluedroid/bta/include/bta/bta_api.h @@ -439,6 +439,10 @@ typedef tBTM_ADD_DEV_TO_RESOLVING_LIST_CMPL_CBACK tBTA_ADD_DEV_TO_RESOLVING_LIST typedef tBTM_SET_PRIVACY_MODE_CMPL_CBACK tBTA_SET_PRIVACY_MODE_CMPL_CBACK; +typedef tBTM_SET_CSA_SUPPORT_CMPL_CBACK tBTA_SET_CSA_SUPPORT_CMPL_CBACK; + +typedef tBTM_SET_VENDOR_EVT_MASK_CBACK tBTA_SET_VENDOR_EVT_MASK_CBACK; + typedef tBTM_CMPL_CB tBTA_CMPL_CB; typedef tBTM_VSC_CMPL tBTA_VSC_CMPL; @@ -447,6 +451,8 @@ typedef tBTM_TX_POWER_RESULTS tBTA_TX_POWER_RESULTS; typedef tBTM_RSSI_RESULTS tBTA_RSSI_RESULTS; +typedef tBTM_BLE_CH_MAP_RESULTS tBTA_BLE_CH_MAP_RESULTS; + typedef tBTM_SET_AFH_CHANNELS_RESULTS tBTA_SET_AFH_CHANNELS_RESULTS; typedef tBTM_BLE_SET_CHANNELS_RESULTS tBTA_BLE_SET_CHANNELS_RESULTS; @@ -537,7 +543,9 @@ enum { }; typedef tBTM_BLE_BATCH_SCAN_EVT tBTA_BLE_BATCH_SCAN_EVT; +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) typedef tBTM_BLE_TRACK_ADV_ACTION tBTA_BLE_TRACK_ADV_ACTION; +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) // #endif /* BLE customer specific feature function type definitions */ @@ -1001,6 +1009,7 @@ typedef struct { typedef struct { BD_ADDR bd_addr; /* BD address peer device. */ tBTA_PM_MODE mode; /* the new connection role */ + UINT16 interval; /* Number of baseband slots */ } tBTA_DM_MODE_CHG; typedef struct { @@ -1044,6 +1053,7 @@ typedef union { /* Security callback */ typedef void (tBTA_DM_SEC_CBACK)(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *p_data); +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) #define BTA_BLE_MULTI_ADV_ILLEGAL 0 /* multi adv callback event */ @@ -1057,6 +1067,8 @@ typedef UINT8 tBTA_BLE_MULTI_ADV_EVT; /* multi adv callback */ typedef void (tBTA_BLE_MULTI_ADV_CBACK)(tBTA_BLE_MULTI_ADV_EVT event, UINT8 inst_id, void *p_ref, tBTA_STATUS status); +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) + typedef UINT32 tBTA_DM_BLE_REF_VALUE; #define BTA_DM_BLE_PF_ENABLE_EVT BTM_BLE_PF_ENABLE @@ -1249,8 +1261,9 @@ typedef UINT8 tBTA_DM_BLE_ADV_STATE; typedef UINT8 tBTA_DM_BLE_ADV_INFO_PRESENT; typedef UINT8 tBTA_DM_BLE_RSSI_VALUE; typedef UINT16 tBTA_DM_BLE_ADV_INFO_TIMESTAMP; - +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) typedef tBTM_BLE_TRACK_ADV_DATA tBTA_DM_BLE_TRACK_ADV_DATA; +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) typedef void (tBTA_BLE_SCAN_THRESHOLD_CBACK)(tBTA_DM_BLE_REF_VALUE ref_value); @@ -1268,18 +1281,22 @@ typedef void (tBTA_START_STOP_ADV_CMPL_CBACK) (tBTA_STATUS status); typedef void (tBTA_CLEAR_ADV_CMPL_CBACK) (tBTA_STATUS status); +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) typedef void (tBTA_BLE_TRACK_ADV_CMPL_CBACK)(int action, tBTA_STATUS status, tBTA_DM_BLE_PF_AVBL_SPACE avbl_space, tBTA_DM_BLE_REF_VALUE ref_value); typedef void (tBTA_BLE_TRACK_ADV_CBACK)(tBTA_DM_BLE_TRACK_ADV_DATA *p_adv_data); +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) +#if (BLE_HOST_ENERGY_INFO_EN == TRUE) typedef void (tBTA_BLE_ENERGY_INFO_CBACK)(tBTA_DM_BLE_TX_TIME_MS tx_time, tBTA_DM_BLE_RX_TIME_MS rx_time, tBTA_DM_BLE_IDLE_TIME_MS idle_time, tBTA_DM_BLE_ENERGY_USED energy_used, tBTA_DM_CONTRL_STATE ctrl_state, tBTA_STATUS status); +#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) #else typedef UINT8 tBTA_DM_BLE_SEC_ACT; @@ -1350,10 +1367,22 @@ typedef UINT8 tBTA_DM_PM_ACTION; #define BTA_DM_PM_SNIFF_HD_IDLE_IDX BTA_DM_PM_SNIFF4 #endif +#ifndef BTA_DM_PM_SNIFF_AG_OPEN_IDX +#define BTA_DM_PM_SNIFF_AG_OPEN_IDX BTA_DM_PM_SNIFF +#endif + +#ifndef BTA_DM_PM_SNIFF_AG_IDLE_IDX +#define BTA_DM_PM_SNIFF_AG_IDLE_IDX BTA_DM_PM_SNIFF +#endif + #ifndef BTA_DM_PM_SNIFF_SCO_OPEN_IDX #define BTA_DM_PM_SNIFF_SCO_OPEN_IDX BTA_DM_PM_SNIFF3 #endif +#ifndef BTA_DM_PM_SNIFF_SCO_CLOSE_IDX +#define BTA_DM_PM_SNIFF_SCO_CLOSE_IDX BTA_DM_PM_SNIFF +#endif + #ifndef BTA_DM_PM_SNIFF_HD_ACTIVE_IDX #define BTA_DM_PM_SNIFF_HD_ACTIVE_IDX BTA_DM_PM_SNIFF5 #endif @@ -1497,18 +1526,18 @@ typedef UINT8 tBTA_DM_LINK_TYPE; #define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_INCLUDE_TX_PWR (1 << 6) #define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_MASK (0x7F) -#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_IND (ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ - ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE |\ - ESP_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE) -#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_LD_DIR (ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ - ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE |\ - ESP_BLE_GAP_SET_EXT_ADV_PROP_DIRECTED) -#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_HD_DIR (ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ - ESP_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE |\ - ESP_BLE_GAP_SET_EXT_ADV_PROP_HD_DIRECTED) -#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_SCAN (ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ - ESP_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE) -#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_NONCONN (ESP_BLE_GAP_SET_EXT_ADV_PROP_LEGACY) +#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_IND (BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ + BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE |\ + BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE) +#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_LD_DIR (BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ + BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE |\ + BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_DIRECTED) +#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_HD_DIR (BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ + BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE |\ + BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_HD_DIRECTED) +#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_SCAN (BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY |\ + BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_SCANNABLE) +#define BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_NONCONN (BTA_DM_BLE_GAP_SET_EXT_ADV_PROP_LEGACY) typedef UINT16 tBTA_DM_BLE_EXT_ADV_TYPE_MASK; @@ -1560,15 +1589,16 @@ typedef struct { typedef struct { UINT8 filter_policy; - #if (CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH) +#if (BLE_FEAT_CREATE_SYNC_ENH == TRUE) UINT8 reports_disabled; UINT8 filter_duplicates; - #endif +#endif // (BLE_FEAT_CREATE_SYNC_ENH == TRUE) UINT8 sid; tBLE_ADDR_TYPE addr_type; BD_ADDR addr; UINT16 skip; UINT16 sync_timeout; + UINT8 sync_cte_type; } tBTA_DM_BLE_Periodic_Sync_Params; typedef struct { @@ -1600,6 +1630,7 @@ typedef struct { #define BTA_DM_BLE_5_GAP_READ_PHY_COMPLETE_EVT BTM_BLE_5_GAP_READ_PHY_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_SET_PREFERED_DEFAULT_PHY_COMPLETE_EVT BTM_BLE_5_GAP_SET_PREFERED_DEFAULT_PHY_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_SET_PREFERED_PHY_COMPLETE_EVT BTM_BLE_5_GAP_SET_PREFERED_PHY_COMPLETE_EVT +#if (BLE_50_EXTEND_ADV_EN == TRUE) #define BTA_DM_BLE_5_GAP_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT BTM_BLE_5_GAP_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_EXT_ADV_SET_PARAMS_COMPLETE_EVT BTM_BLE_5_GAP_EXT_ADV_SET_PARAMS_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_EXT_ADV_DATA_SET_COMPLETE_EVT BTM_BLE_5_GAP_EXT_ADV_DATA_SET_COMPLETE_EVT @@ -1608,29 +1639,42 @@ typedef struct { #define BTA_DM_BLE_5_GAP_EXT_ADV_STOP_COMPLETE_EVT BTM_BLE_5_GAP_EXT_ADV_STOP_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_EXT_ADV_SET_REMOVE_COMPLETE_EVT BTM_BLE_5_GAP_EXT_ADV_SET_REMOVE_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_EXT_ADV_SET_CLEAR_COMPLETE_EVT BTM_BLE_5_GAP_EXT_ADV_SET_CLEAR_COMPLETE_EVT +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) #define BTA_DM_BLE_5_GAP_PERIODIC_ADV_SET_PARAMS_COMPLETE_EVT BTM_BLE_5_GAP_PERIODIC_ADV_SET_PARAMS_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_PERIODIC_ADV_DATA_SET_COMPLETE_EVT BTM_BLE_5_GAP_PERIODIC_ADV_DATA_SET_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_PERIODIC_ADV_START_COMPLETE_EVT BTM_BLE_5_GAP_PERIODIC_ADV_START_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_PERIODIC_ADV_STOP_COMPLETE_EVT BTM_BLE_5_GAP_PERIODIC_ADV_STOP_COMPLETE_EVT +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) #define BTA_DM_BLE_5_GAP_PERIODIC_ADV_CREATE_SYNC_COMPLETE_EVT BTM_BLE_5_GAP_PERIODIC_ADV_CREATE_SYNC_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_PERIODIC_ADV_SYNC_CANCEL_COMPLETE_EVT BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_CANCEL_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_PERIODIC_ADV_SYNC_TERMINATE_COMPLETE_EVT BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_TERMINATE_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_PERIODIC_ADV_ADD_DEV_COMPLETE_EVT BTM_BLE_5_GAP_PERIODIC_ADV_ADD_DEV_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_PERIODIC_ADV_REMOVE_DEV_COMPLETE_EVT BTM_BLE_5_GAP_PERIODIC_ADV_REMOVE_DEV_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_PERIODIC_ADV_CLEAR_DEV_COMPLETE_EVT BTM_BLE_5_GAP_PERIODIC_ADV_CLEAR_DEV_COMPLETE_EVT +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if (BLE_50_EXTEND_SCAN_EN == TRUE) #define BTA_DM_BLE_5_GAP_SET_EXT_SCAN_PARAMS_COMPLETE_EVT BTM_BLE_5_GAP_SET_EXT_SCAN_PARAMS_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_EXT_SCAN_START_COMPLETE_EVT BTM_BLE_5_GAP_EXT_SCAN_START_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_EXT_SCAN_STOP_COMPLETE_EVT BTM_BLE_5_GAP_EXT_SCAN_STOP_COMPLETE_EVT +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) #define BTA_DM_BLE_5_GAP_PREFER_EXT_CONN_PARAMS_SET_COMPLETE_EVT BTM_BLE_5_GAP_PREFER_EXT_CONN_PARAMS_SET_COMPLETE_EVT #define BTA_DM_BLE_5_GAP_PHY_UPDATE_COMPLETE_EVT BTM_BLE_5_GAP_PHY_UPDATE_COMPLETE_EVT +#if (BLE_50_EXTEND_SCAN_EN == TRUE) #define BTA_DM_BLE_5_GAP_EXT_ADV_REPORT_EVT BTM_BLE_5_GAP_EXT_ADV_REPORT_EVT #define BTA_DM_BLE_5_GAP_SCAN_TIMEOUT_EVT BTM_BLE_5_GAP_SCAN_TIMEOUT_EVT +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) #define BTA_DM_BLE_5_GAP_ADV_TERMINATED_EVT BTM_BLE_5_GAP_ADV_TERMINATED_EVT #define BTA_DM_BLE_5_GAP_SCAN_REQ_RECEIVED_EVT BTM_BLE_5_GAP_SCAN_REQ_RECEIVED_EVT +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) #define BTA_DM_BLE_5_GAP_CHANNEL_SELETE_ALGORITHM_EVT BTM_BLE_5_GAP_CHANNEL_SELETE_ALGORITHM_EVT +#if (BLE_50_EXTEND_SYNC_EN == TRUE) #define BTA_DM_BLE_5_GAP_PERIODIC_ADV_REPORT_EVT BTM_BLE_5_GAP_PERIODIC_ADV_REPORT_EVT #define BTA_DM_BLE_5_GAP_PERIODIC_ADV_SYNC_LOST_EVT BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_LOST_EVT #define BTA_DM_BLE_5_GAP_PERIODIC_ADV_SYNC_ESTAB_EVT BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_ESTAB_EVT +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) #define BTA_BLE_GAP_PERIODIC_ADV_RECV_ENABLE_COMPLETE_EVT BTM_BLE_GAP_PERIODIC_ADV_RECV_ENABLE_COMPLETE_EVT #define BTA_BLE_GAP_PERIODIC_ADV_SYNC_TRANS_COMPLETE_EVT BTM_BLE_GAP_PERIODIC_ADV_SYNC_TRANS_COMPLETE_EVT @@ -1638,6 +1682,25 @@ typedef struct { #define BTA_BLE_GAP_SET_PAST_PARAMS_COMPLETE_EVT BTM_BLE_GAP_SET_PAST_PARAMS_COMPLETE_EVT #define BTA_BLE_GAP_PERIODIC_ADV_SYNC_TRANS_RECV_EVT BTM_BLE_GAP_PERIODIC_ADV_SYNC_TRANS_RECV_EVT #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#define BTA_BLE_GAP_ENH_READ_TRANS_POWER_LEVEL_EVT BTM_BLE_GAP_ENH_READ_TRANS_POWER_LEVEL_EVT +#define BTA_BLE_GAP_READ_REMOTE_TRANS_POWER_LEVEL_EVT BTM_BLE_GAP_READ_REMOTE_TRANS_POWER_LEVEL_EVT +#define BTA_BLE_GAP_SET_PATH_LOSS_REPORTING_PARAMS_EVT BTM_BLE_GAP_SET_PATH_LOSS_REPORTING_PARAMS_EVT +#define BTA_BLE_GAP_SET_PATH_LOSS_REPORTING_ENABLE_EVT BTM_BLE_GAP_SET_PATH_LOSS_REPORTING_ENABLE_EVT +#define BTA_BLE_GAP_SET_TRANS_POWER_REPORTING_ENABLE_EVT BTM_BLE_GAP_SET_TRANS_POWER_REPORTING_ENABLE_EVT +#define BTA_BLE_GAP_PATH_LOSS_THRESHOLD_EVT BTM_BLE_GAP_PATH_LOSS_THRESHOLD_EVT +#define BTA_BLE_GAP_TRANMIT_POWER_REPORTING_EVT BTM_BLE_GAP_TRANMIT_POWER_REPORTING_EVT +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +#define BTA_BLE_GAP_SET_DEFAULT_SUBRATE_EVT BTM_BLE_GAP_SET_DEFAULT_SUBRATE_EVT +#define BTA_BLE_GAP_SUBRATE_REQUEST_EVT BTM_BLE_GAP_SUBRATE_REQUEST_EVT +#define BTA_BLE_GAP_SUBRATE_CHANGE_EVT BTM_BLE_GAP_SUBRATE_CHANGE_EVT +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) +#define BTA_BLE_GAP_SET_HOST_FEATURE_EVT BTM_BLE_GAP_SET_HOST_FEATURE_EVT +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + #define BTA_DM_BLE_5_GAP_UNKNOWN_EVT BTM_BLE_5_GAP_UNKNOWN_EVT typedef tBTM_BLE_5_GAP_EVENT tBTA_DM_BLE_5_GAP_EVENT; @@ -1648,6 +1711,62 @@ extern tBTM_BLE_5_HCI_CBACK ble_5_hci_cb; #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#define BTA_BLE_ISO_BIG_CREATE_COMPLETE_EVT BTM_BLE_ISO_BIG_CREATE_COMPLETE_EVT +#define BTA_BLE_ISO_BIG_TERMINATE_COMPLETE_EVT BTM_BLE_ISO_BIG_TERMINATE_COMPLETE_EVT +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +#define BTA_BLE_ISO_BIG_SYNC_ESTABLISHED_EVT BTM_BLE_ISO_BIG_SYNC_ESTABLISHED_EVT +#define BTA_BLE_ISO_BIG_SYNC_LOST_EVT BTM_BLE_ISO_BIG_SYNC_LOST_EVT +#define BTA_BLE_ISO_BIG_SYNC_TERMINATE_COMPLETE_EVT BTM_BLE_ISO_BIG_SYNC_TERMINATE_COMPLETE_EVT +#define BTA_BLE_ISO_BIGINFO_ADV_REPORT_EVT BTM_BLE_ISO_BIGINFO_ADV_REPORT_EVT +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +#define BTA_BLE_ISO_DATA_PATH_UPFATE_EVT BTM_BLE_ISO_DATA_PATH_UPFATE_EVT +#define BTA_BLE_ISO_READ_TX_SYNC_EVT BTM_BLE_ISO_READ_TX_SYNC_EVT +#define BTA_BLE_ISO_READ_LINK_QUALITY_EVT BTM_BLE_ISO_READ_LINK_QUALITY_EVT +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#define BTA_BLE_ISO_SET_CIG_PARAMS_EVT BTM_BLE_ISO_SET_CIG_PARAMS_EVT +#define BTA_BLE_ISO_CREATE_CIS_EVT BTM_BLE_ISO_CREATE_CIS_EVT +#define BTA_BLE_ISO_REMOVE_CIG_EVT BTM_BLE_ISO_REMOVE_CIG_EVT +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#define BTA_BLE_ISO_ACCEPT_CIS_REQ_EVT BTM_BLE_ISO_ACCEPT_CIS_REQ_EVT +#define BTA_BLE_ISO_REJECT_CIS_REQ_EVT BTM_BLE_ISO_REJECT_CIS_REQ_EVT +#define BTA_BLE_ISO_CIS_REQUEST_EVT BTM_BLE_ISO_CIS_REQUEST_EVT +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_EN == TRUE) +#define BTA_BLE_ISO_CIS_ESTABLISHED_EVT BTM_BLE_ISO_CIS_ESTABLISHED_EVT +#define BTA_BLE_ISO_CIS_DISCONNECTED_EVT BTM_BLE_ISO_CIS_DISCONNECTED_EVT +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) + +#define BTA_DM_BLE_ISO_UNKNOWN_EVT BTM_BLE_ISO_UNKNOWN_EVT +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#define BTA_BLE_CTE_SET_TRANS_PARAMS_EVT BTM_BLE_CTE_SET_TRANS_PARAMS_EVT +#define BTA_BLE_CTE_SET_TRANS_ENABLE_EVT BTM_BLE_CTE_SET_TRANS_ENABLE_EVT +#define BTA_BLE_CTE_SET_IQ_SAMP_ENABLE_EVT BTM_BLE_CTE_SET_IQ_SAMP_ENABLE_EVT +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +#define BTA_BLE_CTE_SET_CONN_RECV_PARAMS_EVT BTM_BLE_CTE_SET_CONN_RECV_PARAMS_EVT +#define BTA_BLE_CTE_SET_CONN_TRANS_PARAMS_EVT BTM_BLE_CTE_SET_CONN_TRANS_PARAMS_EVT +#define BTA_BLE_CTE_SET_CONN_REQ_ENABLE_EVT BTM_BLE_CTE_SET_CONN_REQ_ENABLE_EVT +#define BTA_BLE_CTE_SET_CONN_RSP_ENABLE_EVT BTM_BLE_CTE_SET_CONN_RSP_ENABLE_EVT +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +#define BTA_BLE_CTE_READ_ANT_INFOR_EVT BTM_BLE_CTE_READ_ANT_INFOR_EVT +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#define BTA_BLE_CTE_CONNLESS_IQ_REPORT_EVT BTM_BLE_CTE_CONNLESS_IQ_REPORT_EVT +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +#define BTA_BLE_CTE_CONN_IQ_REPORT_EVT BTM_BLE_CTE_CONN_IQ_REPORT_EVT +#define BTA_BLE_CTE_REQUEST_FAILED_EVT BTM_BLE_CTE_REQUEST_FAILED_EVT +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +#endif // #if (BLE_FEAT_CTE_EN == TRUE) + #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) typedef struct { UINT8 mode; @@ -1657,6 +1776,77 @@ typedef struct { } tBTA_DM_BLE_PAST_PARAMS; #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_FEAT_ISO_EN == TRUE) +typedef struct { + UINT8 big_handle; + UINT8 adv_handle; + UINT8 num_bis; + UINT32 sdu_interval; + UINT16 max_sdu; + UINT16 max_transport_latency; + UINT8 rtn; + UINT8 phy; + UINT8 packing; + UINT8 framing; + UINT8 encryption; + UINT8 broadcast_code[16]; +} tBTA_DM_BLE_BIG_CREATE_PARAMS; + +typedef struct { + UINT8 big_handle; + UINT8 adv_handle; + UINT8 num_bis; + UINT32 sdu_interval; + UINT16 iso_interval; + UINT8 nse; + UINT16 max_sdu; + UINT16 max_pdu; + UINT8 phy; + UINT8 packing; + UINT8 framing; + UINT8 bn; + UINT8 irc; + UINT8 pto; + UINT8 encryption; + UINT8 broadcast_code[16]; +} tBTA_DM_BLE_BIG_CREATE_TEST_PARAMS; +typedef struct { + UINT8 big_handle; + UINT8 reason; +} tBTA_DM_BLE_BIG_TERMINATE_PARAMS; +typedef struct { + UINT8 big_handle; + UINT16 sync_handle; + UINT8 encryption; + UINT8 bc_code[16]; + UINT8 mse; + UINT16 big_sync_timeout; + UINT8 num_bis; + UINT8 bis[BLE_ISO_BIS_MAX_COUNT]; +} tBTA_DM_BLE_BIG_SYNC_CREATE_PARAMS; +typedef struct { + UINT8 big_handle; +} tBTA_DM_BLE_BIG_SYNC_TERMINATE_PARAMS; + +typedef struct { + uint16_t conn_handle; + uint8_t data_path_dir; + uint8_t data_path_id; + uint8_t coding_fmt; + uint16_t company_id; + uint16_t vs_codec_id; + uint32_t controller_delay; + uint8_t codec_len; + uint8_t *codec_cfg; +} tBTA_DM_BLE_ISO_SET_DATA_PATH_PARAMS; + +typedef struct { + uint16_t conn_handle; + uint8_t data_path_dir; +} tBTA_DM_BLE_ISO_REMOVE_DATA_PATH_PARAMS; +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + + /***************************************************************************** ** External Function Declarations *****************************************************************************/ @@ -1880,6 +2070,7 @@ extern void BTA_DmBleReadAdvTxPower(tBTA_CMPL_CB *cmpl_cb); #endif ///BLE_INCLUDED == TRUE extern void BTA_DmReadRSSI(BD_ADDR remote_addr, tBTA_TRANSPORT transport, tBTA_CMPL_CB *cmpl_cb); +extern void BTA_DmBleReadChannelMap(BD_ADDR remote_device, tBTA_CMPL_CB *p_callback); /******************************************************************************* ** @@ -2190,6 +2381,17 @@ extern UINT16 BTA_DmGetConnectionState( BD_ADDR bd_addr ); *******************************************************************************/ extern tBTA_STATUS BTA_DmSetLocalDiRecord( tBTA_DI_RECORD *p_device_info, UINT32 *p_handle ); + +/******************************************************************************* +** +** Function BTA_DmRemoveLocalDiRecord +** +** Description This function removes a DI record from the local SDP database. +** +** Returns BTA_SUCCESS if record is removed successfully, otherwise error code. +** +*******************************************************************************/ +extern tBTA_STATUS BTA_DmRemoveLocalDiRecord(UINT32 handle); #endif ///SDP_INCLUDED == TRUE /******************************************************************************* ** @@ -2466,24 +2668,6 @@ extern void BTA_DmSetBleScanFilterParams(tGATT_IF client_if, UINT32 scan_interva UINT8 addr_type_own, UINT8 scan_duplicate_filter, tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback); -/******************************************************************************* -** -** Function BTA_DmSetBleAdvParams -** -** Description This function sets the advertising parameters BLE functionality. -** It is to be called when device act in peripheral or broadcaster -** role. -** -** Parameters: adv_int_min - adv interval minimum -** adv_int_max - adv interval max -** p_dir_bda - directed adv initiator address -** -** Returns void -** -*******************************************************************************/ -extern void BTA_DmSetBleAdvParams (UINT16 adv_int_min, UINT16 adv_int_max, - tBLE_BD_ADDR *p_dir_bda); - extern void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max, UINT8 adv_type, tBLE_ADDR_TYPE addr_type_own, tBTM_BLE_ADV_CHNL_MAP chnl_map, tBTM_BLE_AFP adv_fil_pol, @@ -2614,7 +2798,9 @@ extern void BTA_DmBleScan(BOOLEAN start, UINT32 duration, tBTA_DM_SEARCH_CBACK *p_results_cb, tBTA_START_STOP_SCAN_CMPL_CBACK *p_start_stop_scan_cb); +#if (BLE_HOST_STOP_ADV_UNUSED == TRUE) extern void BTA_DmBleStopAdvertising(void); +#endif // #if (BLE_HOST_STOP_ADV_UNUSED == TRUE) extern void BTA_DmSetRandAddress(BD_ADDR rand_addr, tBTA_SET_RAND_ADDR_CBACK *p_set_rand_addr_cback); extern void BTA_DmClearRandAddress(void); @@ -2699,21 +2885,6 @@ extern void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask, extern void BTA_DmBleSetAdvConfigRaw (UINT8 *p_raw_adv, UINT32 raw_adv_len, tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback); -/******************************************************************************* -** -** Function BTA_DmBleSetLongAdv -** -** Description This function is called to set long Advertising data -** -** Parameters adv_data : long advertising data. -** adv_data_len : long advertising data length. -** p_adv_data_cback : set long adv data complete callback. -** -** Returns None -** -*******************************************************************************/ -void BTA_DmBleSetLongAdv (UINT8 *adv_data, UINT32 adv_data_len, - tBTA_SET_ADV_DATA_CMPL_CBACK *p_adv_data_cback); /******************************************************************************* ** @@ -2791,7 +2962,7 @@ extern void BTA_DmUpdateDuplicateExceptionalList(UINT8 subcode, UINT32 type, *******************************************************************************/ extern void BTA_DmBleBroadcast (BOOLEAN start, tBTA_START_STOP_ADV_CMPL_CBACK *p_start_stop_adv_cb); - +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) /******************************************************************************* ** ** Function BTA_BleEnableAdvInstance @@ -2850,6 +3021,7 @@ extern void BTA_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp, ** *******************************************************************************/ extern void BTA_BleDisableAdvInstance(UINT8 inst_id); +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) /******************************************************************************* ** @@ -2890,13 +3062,38 @@ extern void BTA_DmBleDisconnect(BD_ADDR bd_addr); ** *******************************************************************************/ extern void BTA_DmBleSetDataLength(BD_ADDR remote_device, UINT16 tx_data_length, tBTA_SET_PKT_DATA_LENGTH_CBACK *p_set_pkt_data_cback); - +#if (BLE_42_DTM_TEST_EN == TRUE) extern void BTA_DmBleDtmTxStart(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback); extern void BTA_DmBleDtmRxStart(uint8_t rx_channel, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback); +#endif // #if (BLE_42_DTM_TEST_EN == TRUE) + extern void BTA_DmBleDtmStop(tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback); extern void BTA_DmBleSetPrivacyMode(uint8_t addr_type, BD_ADDR addr, uint8_t privacy_mode, tBTA_SET_PRIVACY_MODE_CMPL_CBACK *p_cback); +extern void BTA_DmBleGapSetCsaSupport(uint8_t csa_select, tBTM_SET_CSA_SUPPORT_CMPL_CBACK *p_callback); + +extern void BTA_DmBleGapSetVendorEventMask(uint32_t evt_mask, tBTA_SET_VENDOR_EVT_MASK_CBACK *p_callback); + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +void BTA_DmBleGapEnhReadTransPwrLevel(uint16_t conn_handle, uint8_t phy); +void BTA_DmBleGapReadRemoteTransPwrLevel(uint16_t conn_handle, uint8_t phy); +void BTA_DmBleGapSetPathLossRptParams(uint16_t conn_handle, uint8_t high_threshold, uint8_t high_hysteresis, + uint8_t low_threshold, uint8_t low_hysteresis, uint16_t min_time_spent); +void BTA_DmBleGapSetPathLossRptEnable(uint16_t conn_handle, uint8_t enable); +void BTA_DmBleGapSetTransPwrRptEnable(uint16_t conn_handle, uint8_t local_enable, uint8_t remote_enable); +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +void BTA_DmBleGapSetDefaultSubrate(uint16_t subrate_min, uint16_t subrate_max, uint16_t max_latency, + uint16_t continuation_number, uint16_t supervision_timeout); +void BTA_DmBleGapSubrateReqest(uint16_t conn_handle, uint16_t subrate_min, uint16_t subrate_max, + uint16_t max_latency, uint16_t continuation_number, uint16_t supervision_timeout); +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + +#if (BLE_50_FEATURE_SUPPORT == TRUE) +extern void BTA_DmBleGapSetHostFeature(uint16_t bit_num, uint8_t bit_val); +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + /******************************************************************************* ** ** Function BTA_DmBleSetStorageParams @@ -3037,7 +3234,7 @@ extern void BTA_DmBleCfgFilterCondition(tBTA_DM_BLE_SCAN_COND_OP action, tBTA_DM_BLE_PF_CFG_CBACK *p_cmpl_cback, tBTA_DM_BLE_REF_VALUE ref_value); - +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) /******************************************************************************* ** ** Function BTA_DmBleTrackAdvertiser @@ -3052,7 +3249,9 @@ extern void BTA_DmBleCfgFilterCondition(tBTA_DM_BLE_SCAN_COND_OP action, *******************************************************************************/ extern void BTA_DmBleTrackAdvertiser(tBTA_DM_BLE_REF_VALUE ref_value, tBTA_BLE_TRACK_ADV_CBACK *p_track_adv_cback); +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) +#if (BLE_HOST_ENERGY_INFO_EN == TRUE) /******************************************************************************* ** ** Function BTA_DmBleGetEnergyInfo @@ -3065,6 +3264,7 @@ extern void BTA_DmBleTrackAdvertiser(tBTA_DM_BLE_REF_VALUE ref_value, ** *******************************************************************************/ extern void BTA_DmBleGetEnergyInfo(tBTA_BLE_ENERGY_INFO_CBACK *p_cmpl_cback); +#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) /******************************************************************************* ** @@ -3151,11 +3351,13 @@ extern void BTA_DmBleGapPreferExtConnectParamsSet(BD_ADDR bd_addr, const tBTA_DM_BLE_CONN_PARAMS *phy_coded_conn_params); extern void BTA_DmBleGapExtConnect(tBLE_ADDR_TYPE own_addr_type, const BD_ADDR peer_addr); +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_DTM_TEST_EN == TRUE) extern void BTA_DmBleDtmEnhTxStart(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, uint8_t phy, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback); extern void BTA_DmBleDtmEnhRxStart(uint8_t rx_channel, uint8_t phy, uint8_t modulation_index, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback); -#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) extern void BTA_DmBleGapPeriodicAdvRecvEnable(UINT16 sync_handle, UINT8 enable); @@ -3167,6 +3369,57 @@ extern void BTA_DmBleGapPeriodicAdvSetInfoTrans(BD_ADDR peer_addr, UINT16 servic extern void BTA_DmBleGapSetPeriodicAdvSyncTransParams(BD_ADDR peer_addr, tBTA_DM_BLE_PAST_PARAMS *params); #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +extern void BTA_DmBleGapIsoBigCreate(tBTA_DM_BLE_BIG_CREATE_PARAMS *p_big_creat_param); +extern void BTA_DmBleGapIsoBigCreateTest(tBTA_DM_BLE_BIG_CREATE_TEST_PARAMS *p_big_creat_test_param); +extern void BTA_DmBleGapIsoBigTerminate(tBTA_DM_BLE_BIG_TERMINATE_PARAMS *p_big_terminate_param); +#endif// #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +extern void BTA_DmBleGapIsoBigSyncCreate(tBTA_DM_BLE_BIG_SYNC_CREATE_PARAMS *p_big_sync_param); +extern void BTA_DmBleGapIsoBigSyncTerminate(tBTA_DM_BLE_BIG_SYNC_TERMINATE_PARAMS *p_big_sync_terminate_param); +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +extern void BTA_DmBleGapIsoDataPathSet(tBTA_DM_BLE_ISO_SET_DATA_PATH_PARAMS *p_iso_data_path_param); +extern void BTA_DmBleGapIsoDataPathRemove(tBTA_DM_BLE_ISO_REMOVE_DATA_PATH_PARAMS *p_iso_data_path_param); +extern void BTA_DmBleGapIsoReadTxSync(uint16_t iso_handle); +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +extern void BTA_DmBleIsoSetCigParams(uint8_t cig_id, uint32_t sdu_int_c_to_p, uint32_t sdu_int_p_to_c, uint8_t worse_case_SCA, uint8_t packing, + uint8_t framing, uint16_t mtl_c_to_p, uint16_t mtl_p_to_c, uint8_t cis_cnt, uint8_t *cis_params); +void BTA_DmBleIsoSetCigParamsTest(uint8_t cig_id, uint32_t sdu_int_c_to_p, uint32_t sdu_int_p_to_c, uint8_t ft_c_to_p, uint8_t ft_p_to_c, + uint16_t iso_interval, uint8_t worse_case_SCA, uint8_t packing, uint8_t framing, uint8_t cis_cnt, uint8_t *cis_params_test); +extern void BTA_DmBleIsoCreateCis(uint8_t cig_count, uint8_t *cis_hdl_info); +extern void BTA_DmBleIsoRemoveCig(uint8_t cig_id); +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +extern void BTA_DmBleIsoAcceptCisReq(uint16_t cis_handle); +extern void BTA_DmBleIsoRejectCisReq(uint16_t cis_handle, uint8_t reason); +#endif // BLE_FEAT_ISO_CIG_PERIPHERAL_EN +#if (BLE_FEAT_ISO_CIG_EN == TRUE) +extern void BTA_DmBleIsoDisconCis(uint16_t cis_handle, uint8_t reason); +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) +#endif // if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +void BTA_DmBleCteSetConnectionlessTransParams(uint8_t adv_handle, uint8_t cte_len, uint8_t cte_type, + uint8_t cte_count, uint8_t switching_pattern_len, uint8_t *antenna_ids); +void BTA_DmBleCteSetConnectionlessTransEnable(uint8_t adv_handle, uint8_t cte_en); +void BTA_DmBleCteSetConnectionlessIqSamplingEnable(uint16_t sync_handle, uint8_t sampling_en, uint8_t slot_dur, + uint8_t max_sampled_ctes, uint8_t switching_pattern_len, uint8_t *ant_ids); +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +void BTA_DmBleCteSetConnectionReceiveParams(uint16_t conn_handle, uint8_t sampling_en, uint8_t slot_dur, + uint8_t switching_pattern_len, uint8_t *ant_ids); + +void BTA_DmBleCteSetConnectionTransParams(uint16_t conn_handle, uint8_t cte_types, uint8_t switching_pattern_len, uint8_t *ant_ids); +void BTA_DmBleCteSetConnectionRequestEnable(uint16_t conn_handle, uint8_t enable, uint16_t cte_req_interval, + uint8_t req_cte_len, uint8_t req_cte_Type); +void BTA_DmBleCteSetConnectionRspEnable(uint16_t conn_handle, uint8_t enable); +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +void BTA_DmBleCteReadAntInfor(void); +#endif // if (BLE_FEAT_CTE_EN == TRUE) + #endif enum { diff --git a/lib/bt/host/bluedroid/bta/include/bta/bta_ar_api.h b/lib/bt/host/bluedroid/bta/include/bta/bta_ar_api.h index 2823d674..20f11281 100644 --- a/lib/bt/host/bluedroid/bta/include/bta/bta_ar_api.h +++ b/lib/bt/host/bluedroid/bta/include/bta/bta_ar_api.h @@ -18,7 +18,7 @@ /****************************************************************************** * - * This is the public interface file for the simulatenous advanced + * This is the public interface file for the simultaneous advanced * audio/video streaming (AV) source and sink of BTA, Broadcom's Bluetooth * application layer for mobile phones. * @@ -35,6 +35,10 @@ #if (BTA_AR_INCLUDED == TRUE) +#ifdef __cplusplus +extern "C" { +#endif + /***************************************************************************** ** Constants and data types *****************************************************************************/ diff --git a/lib/bt/host/bluedroid/bta/include/bta/bta_av_api.h b/lib/bt/host/bluedroid/bta/include/bta/bta_av_api.h index ddf72b96..5a670bd0 100644 --- a/lib/bt/host/bluedroid/bta/include/bta/bta_av_api.h +++ b/lib/bt/host/bluedroid/bta/include/bta/bta_av_api.h @@ -43,14 +43,14 @@ #define BTA_AV_FAIL_STREAM 3 /* stream connection failed */ #define BTA_AV_FAIL_RESOURCES 4 /* no resources */ #define BTA_AV_FAIL_ROLE 5 /* failed due to role management related issues */ -#define BTA_AV_FAIL_GET_CAP 6 /* get capability failed due to no SEP availale on the peer */ +#define BTA_AV_FAIL_GET_CAP 6 /* get capability failed due to no SEP available on the peer */ typedef UINT8 tBTA_AV_STATUS; /* AV features masks */ #define BTA_AV_FEAT_RCTG 0x0001 /* remote control target */ #define BTA_AV_FEAT_RCCT 0x0002 /* remote control controller */ -#define BTA_AV_FEAT_PROTECT 0x0004 /* streaming media contect protection */ +#define BTA_AV_FEAT_PROTECT 0x0004 /* streaming media context protection */ #define BTA_AV_FEAT_VENDOR 0x0008 /* remote control vendor dependent commands */ #define BTA_AV_FEAT_REPORT 0x0020 /* use reporting service for VDP */ #define BTA_AV_FEAT_METADATA 0x0040 /* remote control Metadata Transfer command/response */ @@ -60,6 +60,7 @@ typedef UINT8 tBTA_AV_STATUS; #define BTA_AV_FEAT_ADV_CTRL 0x0200 /* remote control Advanced Control command/response */ #define BTA_AV_FEAT_DELAY_RPT 0x0400 /* allow delay reporting */ #define BTA_AV_FEAT_ACP_START 0x0800 /* start stream when 2nd SNK was accepted */ +#define BTA_AV_FEAT_COVER_ART 0x1000 /* remote control target cover art */ /* Internal features */ #define BTA_AV_FEAT_NO_SCO_SSPD 0x8000 /* Do not suspend av streaming as to AG events(SCO or Call) */ @@ -107,6 +108,7 @@ typedef UINT8 tBTA_AV_HNDL; #define BTA_AV_MAX_VDP_MTU 1008 #endif +#define BTA_AV_CA_IMG_HDL_LEN 7 /* Cover Art image handle len, fixed to 7 */ /* codec type */ #define BTA_AV_CODEC_SBC A2D_MEDIA_CT_SBC /* SBC media codec type */ @@ -224,6 +226,12 @@ typedef UINT8 tBTA_AV_CODE; typedef UINT8 tBTA_AV_ERR; +/* type codes for BTA_AV_API_CA_GET */ +#define BTA_AV_CA_GET_IMAGE_PROPERTIES 0x01 +#define BTA_AV_CA_GET_IMAGE 0x02 +#define BTA_AV_CA_GET_LINKED_THUMBNAIL 0x03 + +typedef UINT8 tBTA_AV_GET_TYPE; /* AV callback events */ #define BTA_AV_ENABLE_EVT 0 /* AV enabled */ @@ -248,13 +256,19 @@ typedef UINT8 tBTA_AV_ERR; #define BTA_AV_META_MSG_EVT 17 /* metadata messages */ #define BTA_AV_REJECT_EVT 18 /* incoming connection rejected */ #define BTA_AV_RC_FEAT_EVT 19 /* remote control channel peer supported features update */ -#define BTA_AV_MEDIA_SINK_CFG_EVT 20 /* command to configure codec */ +#define BTA_AV_MEDIA_CFG_EVT 20 /* command to configure codec */ #define BTA_AV_MEDIA_DATA_EVT 21 /* sending data to Media Task */ #define BTA_AV_SET_DELAY_VALUE_EVT 22 /* set delay reporting value */ #define BTA_AV_GET_DELAY_VALUE_EVT 23 /* get delay reporting value */ #define BTA_AV_SNK_PSC_CFG_EVT 24 /* Protocol service capabilities. */ +#define BTA_AV_SEP_REG_EVT 25 /* stream endpoint registered */ + +/* still keep Cover Art event here if Cover Art feature not enabled */ +#define BTA_AV_CA_STATUS_EVT 26 /* Cover Art Client status event */ +#define BTA_AV_CA_DATA_EVT 27 /* Cover Art response body data */ + /* Max BTA event */ -#define BTA_AV_MAX_EVT 25 +#define BTA_AV_MAX_EVT 28 /* function types for call-out functions */ @@ -328,6 +342,12 @@ typedef struct { tBTA_AVRC_CO_FUNCTS *p_bta_avrc_cos; } tBTA_AV_REGISTER; +/* Event associated with BTA_AV_SEP_REG_EVT */ +typedef struct { + UINT8 seid; + tBTA_AV_STATUS reg_state; +} tBTA_AV_SEP_REG; + /* data associated with BTA_AV_OPEN_EVT */ #define BTA_AV_EDR_2MBPS 0x01 #define BTA_AV_EDR_3MBPS 0x02 @@ -341,6 +361,7 @@ typedef struct { BOOLEAN starting; tBTA_AV_EDR edr; /* 0, if peer device does not support EDR */ UINT8 sep; /* sep type of peer device */ + UINT16 mtu; } tBTA_AV_OPEN; /* data associated with BTA_AV_CLOSE_EVT */ @@ -482,11 +503,31 @@ typedef struct { } tBTA_AV_SNK_PSC_CFG; +#if BTA_AV_CA_INCLUDED + +/* data associated with BTA_AV_CA_STATUS_EVT */ +typedef struct { + BOOLEAN connected; /* whether Cover Art connection is connected */ + UINT16 reason; /* connect failed or disconnect reason */ +} tBTA_AV_CA_STATUS; + +/* data associated with BTA_AV_CA_DATA_EVT */ +typedef struct { + UINT16 status; /* OBEX response status */ + BOOLEAN final; /* final data packet */ + UINT16 data_len; /* data len */ + UINT8 *p_data; /* point to the data in p_hdr */ + BT_HDR *p_hdr; /* after data pass to application, free this packet */ +} tBTA_AV_CA_DATA; + +#endif + /* union of data associated with AV callback */ typedef union { tBTA_AV_CHNL chnl; tBTA_AV_ENABLE enable; tBTA_AV_REGISTER registr; + tBTA_AV_SEP_REG sep_reg; tBTA_AV_OPEN open; tBTA_AV_CLOSE close; tBTA_AV_START start; @@ -506,6 +547,10 @@ typedef union { tBTA_AV_RC_FEAT rc_feat; tBTA_AV_DELAY delay; tBTA_AV_SNK_PSC_CFG psc; +#if BTA_AV_CA_INCLUDED + tBTA_AV_CA_STATUS ca_status; + tBTA_AV_CA_DATA ca_data; +#endif } tBTA_AV; /* union of data associated with AV Media callback */ @@ -621,6 +666,8 @@ void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name, tBTA_AV_CO_FUNCTS *bta_av_cos, tBTA_AVRC_CO_FUNCTS *bta_avrc_cos, UINT8 tsep); +void BTA_AvRegSEP(tBTA_AV_CHNL chnl, UINT8 idx, UINT8 tsep, tBTA_AV_CODEC codec_type, UINT8 *p_codec_info, tBTA_AV_DATA_CBACK *p_data_cback); + /******************************************************************************* ** ** Function BTA_AvDeregister @@ -865,6 +912,47 @@ void BTA_AvMetaRsp(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE rsp_code, *******************************************************************************/ void BTA_AvMetaCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CMD cmd_code, BT_HDR *p_pkt); +#if BTA_AV_CA_INCLUDED + +/******************************************************************************* +** +** Function BTA_AvCaOpen +** +** Description Open a Cover Art OBEX connection to peer device. This function +** can only be used if peer device TG support Cover Art feature and +** AV is enabled with feature BTA_AV_FEAT_METADATA. +** +** Returns void +** +*******************************************************************************/ +void BTA_AvCaOpen(UINT8 rc_handle, UINT16 pref_packet_len); + +/******************************************************************************* +** +** Function BTA_AvCaClose +** +** Description Close a Cover Art OBEX connection. +** +** Returns void +** +*******************************************************************************/ +void BTA_AvCaClose(UINT8 rc_handle); + +/******************************************************************************* +** +** Function BTA_AvCaGet +** +** Description Start the process to get image properties, get image or get +** linked thumbnail. This function can only be used if Cover Art +** OBEX connection is established. +** +** Returns void +** +*******************************************************************************/ +void BTA_AvCaGet(UINT8 rc_handle, tBTA_AV_GET_TYPE type, UINT8 *image_handle, UINT8 *image_descriptor, UINT16 image_descriptor_len); + +#endif /* BTA_AV_CA_INCLUDED */ + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/bluedroid/bta/include/bta/bta_av_sbc.h b/lib/bt/host/bluedroid/bta/include/bta/bta_av_sbc.h index fccc02fa..751c6488 100644 --- a/lib/bt/host/bluedroid/bta/include/bta/bta_av_sbc.h +++ b/lib/bt/host/bluedroid/bta/include/bta/bta_av_sbc.h @@ -194,6 +194,18 @@ extern UINT8 bta_av_sbc_cfg_for_cap(UINT8 *p_peer, tA2D_SBC_CIE *p_cap, tA2D_SBC *******************************************************************************/ extern UINT8 bta_av_sbc_cfg_in_cap(UINT8 *p_cfg, tA2D_SBC_CIE *p_cap); +/******************************************************************************* +** +** Function bta_av_sbc_cfg_in_external_codec_cap +** +** Description This function checks whether an SBC codec configuration +** is allowable for the given external codec capabilities. +** +** Returns 0 if ok, nonzero if error. +** +*******************************************************************************/ +extern UINT8 bta_av_sbc_cfg_in_external_codec_cap(UINT8 *p_cfg, UINT8 *p_cap); + /******************************************************************************* ** ** Function bta_av_sbc_cfg_matches_cap diff --git a/lib/bt/host/bluedroid/bta/include/bta/bta_gatt_api.h b/lib/bt/host/bluedroid/bta/include/bta/bta_gatt_api.h index 183e3acc..a42d1408 100644 --- a/lib/bt/host/bluedroid/bta/include/bta/bta_gatt_api.h +++ b/lib/bt/host/bluedroid/bta/include/bta/bta_gatt_api.h @@ -180,7 +180,7 @@ typedef UINT8 tBTA_GATT_STATUS; #define BTA_GATTC_ADV_VSC_EVT 34 /* ADV VSC event */ #define BTA_GATTC_CONNECT_EVT 35 /* GATTC CONNECT event */ #define BTA_GATTC_DISCONNECT_EVT 36 /* GATTC DISCONNECT event */ -#define BTA_GATTC_READ_MULTIPLE_EVT 37 /* GATTC Read mutiple event */ +#define BTA_GATTC_READ_MULTIPLE_EVT 37 /* GATTC Read multiple event */ #define BTA_GATTC_QUEUE_FULL_EVT 38 /* GATTC queue full event */ #define BTA_GATTC_ASSOC_EVT 39 /* GATTC association address event */ #define BTA_GATTC_GET_ADDR_LIST_EVT 40 /* GATTC get address list in the cache event */ @@ -728,6 +728,21 @@ typedef struct tBTA_GATTC_SERVICE *included_service; } __attribute__((packed)) tBTA_GATTC_INCLUDED_SVC; +typedef struct { + UINT16 scan_interval; + UINT16 scan_window; + UINT16 interval_min; + UINT16 interval_max; + UINT16 latency; + UINT16 supervision_timeout; + UINT16 min_ce_len; + UINT16 max_ce_len; +} tBTA_BLE_CONN_PARAMS; + +#define BTA_BLE_PHY_1M_MASK (1 << 0) +#define BTA_BLE_PHY_2M_MASK (1 << 1) +#define BTA_BLE_PHY_CODED_MASK (1 << 2) + /***************************************************************************** ** External Function Declarations *****************************************************************************/ @@ -783,9 +798,10 @@ extern void BTA_GATTC_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTC_CBACK *p_clie *******************************************************************************/ extern void BTA_GATTC_AppDeregister (tBTA_GATTC_IF client_if); + /******************************************************************************* ** -** Function BTA_GATTC_Open +** Function BTA_GATTC_Enh_Open ** ** Description Open a direct connection or add a background auto connection ** bd address @@ -793,13 +809,16 @@ extern void BTA_GATTC_AppDeregister (tBTA_GATTC_IF client_if); ** Parameters client_if: server interface. ** remote_bda: remote device BD address. ** remote_addr_type: remote device BD address type. -** is_direct: direct connection or background auto connection +** is_direct: direct connection or background auto connection. +** own_addr_type: own address type. ** ** Returns void ** *******************************************************************************/ -extern void BTA_GATTC_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, tBTA_ADDR_TYPE remote_addr_type, - BOOLEAN is_direct, tBTA_GATT_TRANSPORT transport, BOOLEAN is_aux); +extern void BTA_GATTC_Enh_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, tBTA_ADDR_TYPE remote_addr_type, + BOOLEAN is_direct, tBTA_GATT_TRANSPORT transport, BOOLEAN is_aux, tBTA_ADDR_TYPE own_addr_type, + UINT8 phy_mask, tBTA_BLE_CONN_PARAMS *phy_1m_conn_params, tBTA_BLE_CONN_PARAMS *phy_2m_conn_params, + tBTA_BLE_CONN_PARAMS *phy_coded_conn_params); /******************************************************************************* ** @@ -937,8 +956,8 @@ extern void BTA_GATTC_GetGattDb(UINT16 conn_id, UINT16 start_handle, UINT16 end_ ** ** Description This function is called to read a characteristics value ** -** Parameters conn_id - connectino ID. -** handle - characteritic handle to read. +** Parameters conn_id - connection ID. +** handle - characteristic handle to read. ** ** Returns None ** @@ -953,7 +972,7 @@ void BTA_GATTC_ReadCharacteristic(UINT16 conn_id, UINT16 handle, tBTA_GATT_AUTH_ ** ** Parameters conn_id - connection ID. ** s_handle - start handle. -** e_handle - end hanle +** e_handle - end handle ** uuid - The attribute UUID. ** ** Returns None @@ -1072,7 +1091,7 @@ extern tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications (tBTA_GATTC_IF ** Description This function is called to prepare write a characteristic value. ** ** Parameters conn_id - connection ID. -** handle - GATT characteritic handle. +** handle - GATT characteristic handle. ** offset - offset of the write value. ** len - length of the data to be written. ** p_value - the value to be written. @@ -1094,7 +1113,7 @@ extern void BTA_GATTC_PrepareWrite (UINT16 conn_id, ** Description This function is called to prepare write a characteristic descriptor value. ** ** Parameters conn_id - connection ID. -** p_char_descr_id - GATT characteritic descriptor ID of the service. +** p_char_descr_id - GATT characteristic descriptor ID of the service. ** offset - offset of the write value. ** len: length of the data to be written. ** p_value - the value to be written. @@ -1184,37 +1203,6 @@ extern void BTA_GATTC_CacheGetAddrList(tBTA_GATTC_IF client_if); *******************************************************************************/ extern void BTA_GATTC_Clean(BD_ADDR remote_bda); -/******************************************************************************* -** -** Function BTA_GATTC_Listen -** -** Description Start advertisement to listen for connection request. -** -** Parameters client_if: server interface. -** start: to start or stop listening for connection -** remote_bda: remote device BD address, if listen to all device -** use NULL. -** -** Returns void -** -*******************************************************************************/ -extern void BTA_GATTC_Listen(tBTA_GATTC_IF client_if, BOOLEAN start, BD_ADDR_PTR target_bda); - -/******************************************************************************* -** -** Function BTA_GATTC_Broadcast -** -** Description Start broadcasting (non-connectable advertisements) -** -** Parameters client_if: client interface. -** start: to start or stop listening for connection -** -** Returns void -** -*******************************************************************************/ -extern void BTA_GATTC_Broadcast(tBTA_GATTC_IF client_if, BOOLEAN start); - - /******************************************************************************* ** ** Function BTA_GATTC_ConfigureMTU @@ -1238,7 +1226,7 @@ extern void BTA_GATTC_ConfigureMTU (UINT16 conn_id); ** ** Function BTA_GATTS_Init ** -** Description This function is called to initalize GATTS module +** Description This function is called to initialize GATTS module ** ** Parameters None ** @@ -1540,24 +1528,6 @@ extern void BTA_GATTS_Close(UINT16 conn_id); void BTA_GATTS_SendServiceChangeIndication(tBTA_GATTS_IF server_if, BD_ADDR remote_bda); -/******************************************************************************* -** -** Function BTA_GATTS_Listen -** -** Description Start advertisement to listen for connection request for a -** GATT server -** -** Parameters server_if: server interface. -** start: to start or stop listening for connection -** remote_bda: remote device BD address, if listen to all device -** use NULL. -** -** Returns void -** -*******************************************************************************/ -extern void BTA_GATTS_Listen(tBTA_GATTS_IF server_if, BOOLEAN start, - BD_ADDR_PTR target_bda); - /******************************************************************************* ** ** Function BTA_GATTS_ShowLocalDatabase diff --git a/lib/bt/host/bluedroid/bta/include/bta/bta_hf_client_api.h b/lib/bt/host/bluedroid/bta/include/bta/bta_hf_client_api.h index ac834c7b..d2731d28 100644 --- a/lib/bt/host/bluedroid/bta/include/bta/bta_hf_client_api.h +++ b/lib/bt/host/bluedroid/bta/include/bta/bta_hf_client_api.h @@ -188,6 +188,12 @@ typedef struct { tBTA_HF_CLIENT_CHLD_FEAT chld_feat; } tBTA_HF_CLIENT_CONN; +/* data associated with BTA_HF_CLIENT_AUDIO_XXX_EVT */ +typedef struct { + tBTA_HF_CLIENT_HDR hdr; + UINT16 preferred_frame_size; +} tBTA_HF_CLIENT_AUDIO_STAT; + /* data associated with BTA_HF_CLIENT_IND_EVT event */ typedef struct { tBTA_HF_CLIENT_HDR hdr; @@ -251,6 +257,7 @@ typedef union { tBTA_HF_CLIENT_REGISTER reg; tBTA_HF_CLIENT_OPEN open; tBTA_HF_CLIENT_CONN conn; + tBTA_HF_CLIENT_AUDIO_STAT audio_stat; tBTA_HF_CLIENT_IND ind; tBTA_HF_CLIENT_VAL val; tBTA_HF_CLIENT_OPERATOR_NAME operator; @@ -406,9 +413,68 @@ void BTA_HfClientSendAT(UINT16 handle, tBTA_HF_CLIENT_AT_CMD_TYPE at, UINT32 val *******************************************************************************/ void BTA_HfClientPktStatsNumsGet(UINT16 sync_conn_handle); +/******************************************************************************* +** +** Function BTA_HfClientCiData +** +** Description Send SCO outgoing data ready event +** +** +** Returns void +** +*******************************************************************************/ void BTA_HfClientCiData(void); + +/******************************************************************************* +** +** Function BTA_HfClientAudioBuffAlloc +** +** Description Allocate an audio buffer with specific size, reserve enough +** space and offset for lower layer to send the buffer directly. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientAudioBuffAlloc(UINT16 size, UINT8 **pp_buff, UINT8 **pp_data); + +/******************************************************************************* +** +** Function BTA_HfClientAudioBuffFree +** +** Description Free an audio buffer. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientAudioBuffFree(UINT8 *p_buf); + +/******************************************************************************* +** +** Function BTA_HfClientAudioDataSend +** +** Description Send audio data to lower layer, whether success or not, buffer +** is consumed. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientAudioDataSend(UINT16 sync_conn_hdl, UINT8 *p_buff_start, UINT8 *p_data, UINT16 data_len); + #endif /*#if (BTM_SCO_HCI_INCLUDED == TRUE ) */ +/******************************************************************************* +** +** Function BTA_HfClientGetCbDataSize +** +** Description Get callback data size of specific event +** +** +** Returns void +** +*******************************************************************************/ int BTA_HfClientGetCbDataSize(tBTA_HF_CLIENT_EVT event); #ifdef __cplusplus diff --git a/lib/bt/host/bluedroid/bta/include/bta/bta_jv_api.h b/lib/bt/host/bluedroid/bta/include/bta/bta_jv_api.h index 660ce5cf..20c533a5 100644 --- a/lib/bt/host/bluedroid/bta/include/bta/bta_jv_api.h +++ b/lib/bt/host/bluedroid/bta/include/bta/bta_jv_api.h @@ -315,7 +315,7 @@ typedef struct { tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */ UINT32 handle; /* The connection handle */ UINT8 sec_id; /* security ID used by this server */ - UINT8 scn; /* Server channe number */ + UINT8 scn; /* Server channel number */ BOOLEAN use_co; /* TRUE to use co_rfc_data */ } tBTA_JV_RFCOMM_START; @@ -378,6 +378,7 @@ typedef struct { typedef enum { BTA_JV_SERVER_START_FAILED, BTA_JV_SERVER_RUNNING, + BTA_JV_SERVER_CONNECTED, BTA_JV_SERVER_STATUS_MAX, } tBTA_JV_SERVER_STATUS; @@ -390,7 +391,7 @@ typedef struct { typedef struct { tBTA_JV_STATUS status; /* Status of the operation */ tBTA_JV_SERVER_STATUS server_status; /* Server status */ - UINT8 scn; /* Server channe number */ + UINT16 scn; /* Server channel number */ } tBTA_JV_FREE_SCN; @@ -822,7 +823,7 @@ extern tBTA_JV_STATUS BTA_JvRfcommConfig(BOOLEAN enable_l2cap_ertm); ** ** Function BTA_JvRfcommConnect ** -** Description This function makes an RFCOMM conection to a remote BD +** Description This function makes an RFCOMM connection to a remote BD ** Address. ** When the connection is initiated or failed to initiate, ** tBTA_JV_RFCOMM_CBACK is called with BTA_JV_RFCOMM_CL_INIT_EVT @@ -956,7 +957,7 @@ UINT16 BTA_JvRfcommGetPortHdl(UINT32 handle); ** Parameters: handle, JV handle from RFCOMM or L2CAP ** app_id: app specific pm ID, can be BTA_JV_PM_ALL, see bta_dm_cfg.c for details ** BTA_JV_PM_ID_CLEAR: removes pm management on the handle. init_st is ignored and - ** BTA_JV_CONN_CLOSE is called implicitely + ** BTA_JV_CONN_CLOSE is called implicitly ** init_st: state after calling this API. typically it should be BTA_JV_CONN_OPEN ** ** Returns BTA_JV_SUCCESS, if the request is being processed. diff --git a/lib/bt/host/bluedroid/bta/include/bta/bta_pba_client_api.h b/lib/bt/host/bluedroid/bta/include/bta/bta_pba_client_api.h new file mode 100644 index 00000000..404f8ffd --- /dev/null +++ b/lib/bt/host/bluedroid/bta/include/bta/bta_pba_client_api.h @@ -0,0 +1,92 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "common/bt_target.h" +#include "stack/obex_api.h" +#include "bta/bta_pba_defs.h" + +#if BTA_PBA_CLIENT_INCLUDED + +/* Phone Book Access Profile (client) version */ +#define PBAP_PCE_VERSION 0x102 /* v1.2 */ +#define PBAP_PCE_SUPPORTED_FEATURES 0x0000003F /* support all features */ + +/* PBA Client callback events */ +#define BTA_PBA_CLIENT_ENABLE_EVT 0 /* PBA Client enabled */ +#define BTA_PBA_CLIENT_DISABLE_EVT 1 /* PBA Client disabled */ +#define BTA_PBA_CLIENT_REGISTER_EVT 2 /* PBA Client registered */ +#define BTA_PBA_CLIENT_DEREGISTER_EVT 3 /* PBA Client deregistered */ +#define BTA_PBA_CLIENT_CONN_OPEN_EVT 4 /* PBA Client connection opened */ +#define BTA_PBA_CLIENT_CONN_CLOSE_EVT 5 /* PBA Client connection closed */ +#define BTA_PBA_CLIENT_PULL_PHONE_BOOK_RSP_EVT 6 /* PBA Client pull phone book response */ +#define BTA_PBA_CLIENT_SET_PHONE_BOOK_RSP_EVT 7 /* PBA Client set phone book response */ +#define BTA_PBA_CLIENT_PULL_VCARD_LISTING_RSP_EVT 8 /* PBA Client pull vCard listing response */ +#define BTA_PBA_CLIENT_PULL_VCARD_ENTRY_RSP_EVT 9 /* PBA Client pull vCard entry response */ + +typedef enum { + BTA_PBA_CLIENT_NO_ERROR, /* operation success */ + BTA_PBA_CLIENT_FAIL, /* general fail */ + BTA_PBA_CLIENT_ALREADY_CONN, /* connection to peer device already exist */ + BTA_PBA_CLIENT_NO_RESOURCE, /* no resource */ + BTA_PBA_CLIENT_SDP_ERROR, /* error in sdp */ + BTA_PBA_CLIENT_GOEP_ERROR, /* error in goep */ + BTA_PBA_CLIENT_AUTH_FAIL, /* authenticate failed */ + BTA_PBA_CLIENT_DISABLE, /* operation failed due to pba client is disable */ + + /* these error code is related to OBEX */ + BTA_PBA_CLIENT_BAD_REQUEST = 0xC0, /* Server couldn't understand request */ + BTA_PBA_CLIENT_UNAUTHORIZED = 0xC1, /* Unauthorized */ + BTA_PBA_CLIENT_FORBIDDEN = 0xC3, /* Operation is understood but refused > */ + BTA_PBA_CLIENT_NOT_FOUND = 0xC4, /* Not found */ + BTA_PBA_CLIENT_NOT_ACCEPTABLE = 0xC6, /* Not Acceptable */ + BTA_PBA_CLIENT_PRECONDITION_FAILED = 0xCC, /* Precondition failed */ + BTA_PBA_CLIENT_NOT_IMPLEMENTED = 0xD1, /* Not implemented */ + BTA_PBA_CLIENT_SERVICE_UNAVAILABLE = 0xD3, /* Service unavailable */ +} tBTA_PBA_CLIENT_ERR; + +typedef struct { + UINT16 handle; /* connection handle */ + tBTA_PBA_CLIENT_ERR error; /* error code */ + BD_ADDR bd_addr; /* peer BD addr */ + UINT8 peer_supported_repo; /* peer supported repositories */ + UINT32 peer_supported_feat; /* peer supported feature */ +} tBTA_PBA_CLIENT_CONN; + +typedef struct { + tBTA_PBA_CLIENT_ERR status; + UINT16 handle; /* connection handle */ + BOOLEAN final; /* final data event */ + UINT8 *data; /* body data in response packet */ + UINT16 data_len; /* body data length */ + UINT8 *app_param; /* application parameters */ + UINT16 app_param_len; /* application parameters length */ + BT_HDR *pkt; /* raw buff that store all data, should be freed before return */ +} tBTA_PBA_CLIENT_RESPONSE; + +/* union of data associated with PBA Client callback */ +typedef union { + tBTA_PBA_CLIENT_CONN conn; /* CONN_OPEN_EVT, CONN_CLOSE_EVT */ + tBTA_PBA_CLIENT_RESPONSE response; /* XXX_RSP_EVT */ +} tBTA_PBA_CLIENT; + +typedef UINT8 tBTA_PBA_CLIENT_EVT; + +typedef void (tBTA_PBA_CLIENT_CBACK)(tBTA_PBA_CLIENT_EVT event, tBTA_PBA_CLIENT *p_data); + +void BTA_PbaClientEnable(tBTA_PBA_CLIENT_CBACK *p_cback); +void BTA_PbaClientDisable(void); +void BTA_PbaClientRegister(const char *server_name); +void BTA_PbaClientDeregister(void); +void BTA_PbaClientOpen(BD_ADDR bd_addr, tBTA_SEC sec_mask, UINT32 supported_feat, UINT16 mtu); +void BTA_PbaClientClose(UINT16 handle); +void BTA_PbaClientPullPhoneBook(UINT16 handle, char *name, UINT8 *app_param, UINT16 app_param_len); +void BTA_PbaClientSetPhoneBook(UINT16 handle, UINT8 flags, char *name); +void BTA_PbaClientPullvCardListing(UINT16 handle, char *name, UINT8 *app_param, UINT16 app_param_len); +void BTA_PbaClientPullvCardEntry(UINT16 handle, char *name, UINT8 *app_param, UINT16 app_param_len); + +#endif diff --git a/lib/bt/host/bluedroid/bta/include/bta/bta_pba_defs.h b/lib/bt/host/bluedroid/bta/include/bta/bta_pba_defs.h new file mode 100644 index 00000000..ce92f9cd --- /dev/null +++ b/lib/bt/host/bluedroid/bta/include/bta/bta_pba_defs.h @@ -0,0 +1,93 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/* PBAP supported repositories */ +#define BTA_PBAP_REPO_LOCAL_PHONEBOOK 0x01 +#define BTA_PBAP_REPO_SIM_CARD 0x02 +#define BTA_PBAP_REPO_SPEED_DIAL 0x04 +#define BTA_PBAP_REPO_FAVORITES 0x08 + +/* PBAP supported features */ +#define BTA_PBAP_FEAT_DOWNLOAD 0x0001 +#define BTA_PBAP_FEAT_BROWSING 0x0002 +#define BTA_PBAP_FEAT_DATABASE_IDENTIFIER 0x0004 +#define BTA_PBAP_FEAT_FLODER_VERSION_COUNTER 0x0008 +#define BTA_PBAP_FEAT_VCARD_SELECTING 0x0010 +#define BTA_PBAP_FEAT_ENHANCED_MISSED_CALLS 0x0020 +#define BTA_PBAP_FEAT_X_BT_UCI_VCARD_PROPERTY 0x0040 +#define BTA_PBAP_FEAT_X_BT_UID_VCARD_PROPERTY 0x0080 +#define BTA_PBAP_FEAT_CONTACT_REFERENCING 0x0100 +#define BTA_PBAP_FEAT_DEFAULT_CONTACT_IMAGE_FORMAT 0x0200 + +/* PBAP default supported features */ +#define BTA_PBAP_DEFAULT_SUPPORTED_FEATURES 0x0003 + +/* Application parameters tag id */ +#define BTA_PBAP_APP_PARAM_ORDER 0x01 +#define BTA_PBAP_APP_PARAM_SEARCH_VALUE 0x02 +#define BTA_PBAP_APP_PARAM_SEARCH_PROPERTY 0x03 +#define BTA_PBAP_APP_PARAM_MAX_LIST_COUNT 0x04 +#define BTA_PBAP_APP_PARAM_LIST_START_OFFSET 0x05 +#define BTA_PBAP_APP_PARAM_PROPERTY_SELECTOR 0x06 +#define BTA_PBAP_APP_PARAM_FORMAT 0x07 +#define BTA_PBAP_APP_PARAM_PHONE_BOOK_SIZE 0x08 +#define BTA_PBAP_APP_PARAM_NEW_MISSED_CALLS 0x09 +#define BTA_PBAP_APP_PARAM_PRIMARY_FOLDER_VERSION 0x0A +#define BTA_PBAP_APP_PARAM_SECONDARY_FOLDER_VERSION 0x0B +#define BTA_PBAP_APP_PARAM_VCARD_SELECTOR 0x0C +#define BTA_PBAP_APP_PARAM_DATABASE_IDENTIFIER 0x0D +#define BTA_PBAP_APP_PARAM_VCARD_SELECTOR_OPERATOR 0x0E +#define BTA_PBAP_APP_PARAM_RESET_NEW_MISSED_CALLS 0x0F +#define BTA_PBAP_APP_PARAM_PBAP_SUPPORTED_FEATURES 0x10 + +/* Application parameters length (except SearchValue) */ +#define BTA_PBAP_APP_PARAM_LENGTH_ORDER 1 +#define BTA_PBAP_APP_PARAM_LENGTH_SEARCH_PROPERTY 1 +#define BTA_PBAP_APP_PARAM_LENGTH_MAX_LIST_COUNT 2 +#define BTA_PBAP_APP_PARAM_LENGTH_LIST_START_OFFSET 2 +#define BTA_PBAP_APP_PARAM_LENGTH_PROPERTY_SELECTOR 8 +#define BTA_PBAP_APP_PARAM_LENGTH_FORMAT 1 +#define BTA_PBAP_APP_PARAM_LENGTH_PHONE_BOOK_SIZE 2 +#define BTA_PBAP_APP_PARAM_LENGTH_NEW_MISSED_CALLS 1 +#define BTA_PBAP_APP_PARAM_LENGTH_PRIMARY_FOLDER_VERSION 16 +#define BTA_PBAP_APP_PARAM_LENGTH_SECONDARY_FOLDER_VERSION 16 +#define BTA_PBAP_APP_PARAM_LENGTH_VCARD_SELECTOR 8 +#define BTA_PBAP_APP_PARAM_LENGTH_DATABASE_IDENTIFIER 16 +#define BTA_PBAP_APP_PARAM_LENGTH_VCARD_SELECTOR_OPERATOR 1 +#define BTA_PBAP_APP_PARAM_LENGTH_RESET_NEW_MISSED_CALLS 1 +#define BTA_PBAP_APP_PARAM_LENGTH_PBAP_SUPPORTED_FEATURES 4 + +/* Application parameter tag (1 byte) + Application parameter length (1 byte) */ +#define BTA_PBAP_APP_PARAM_HEADER_LENGTH 2 + +/* The minimal buff size that can hold all pull phone book application parameters */ +#define BTA_PBAP_PULL_PHONE_BOOK_APP_PARAM_BUFF_SIZE_MIN 37 + +/* The minimal buff size that can hold pull vCard listing application parameters, except the value of SearchValue */ +#define BTA_PBAP_PULL_VCARD_LISTING_APP_PARAM_BUFF_SIZE_MIN 34 + +/* The minimal buff size that can hold all pull vCard entry application parameters */ +#define BTA_PBAP_PULL_VCARD_ENTRY_APP_PARAM_BUFF_SIZE_MIN 13 + +/* Application parameters bit mask */ +#define PBAP_APP_PARAM_BIT_MASK_ORDER 0x0001 +#define PBAP_APP_PARAM_BIT_MASK_SEARCH_VALUE 0x0002 +#define PBAP_APP_PARAM_BIT_MASK_SEARCH_PROPERTY 0x0004 +#define PBAP_APP_PARAM_BIT_MASK_MAX_LIST_COUNT 0x0008 +#define PBAP_APP_PARAM_BIT_MASK_LIST_START_OFFSET 0x0010 +#define PBAP_APP_PARAM_BIT_MASK_PROPERTY_SELECTOR 0x0020 +#define PBAP_APP_PARAM_BIT_MASK_FORMAT 0x0040 +#define PBAP_APP_PARAM_BIT_MASK_PHONE_BOOK_SIZE 0x0080 +#define PBAP_APP_PARAM_BIT_MASK_NEW_MISSED_CALLS 0x0100 +#define PBAP_APP_PARAM_BIT_MASK_PRIMARY_FOLDER_VERSION 0x0200 +#define PBAP_APP_PARAM_BIT_MASK_SECONDARY_FOLDER_VERSION 0x0400 +#define PBAP_APP_PARAM_BIT_MASK_VCARD_SELECTOR 0x0800 +#define PBAP_APP_PARAM_BIT_MASK_DATABASE_IDENTIFIER 0x1000 +#define PBAP_APP_PARAM_BIT_MASK_VCARD_SELECTOR_OPERATOR 0x2000 +#define PBAP_APP_PARAM_BIT_MASK_RESET_NEW_MISSED_CALLS 0x4000 +#define PBAP_APP_PARAM_BIT_MASK_PBAP_SUPPORTED_FEATURES 0x8000 diff --git a/lib/bt/host/bluedroid/bta/include/bta/bta_sdp_api.h b/lib/bt/host/bluedroid/bta/include/bta/bta_sdp_api.h index 62b5228a..fadc8183 100644 --- a/lib/bt/host/bluedroid/bta/include/bta/bta_sdp_api.h +++ b/lib/bt/host/bluedroid/bta/include/bta/bta_sdp_api.h @@ -41,7 +41,7 @@ typedef UINT8 tBTA_SDP_STATUS; /* SDP I/F callback events */ /* events received by tBTA_SDP_DM_CBACK */ #define BTA_SDP_ENABLE_EVT 0 /* SDP service enabled */ -#define BTA_SDP_DISENABLE_EVT 1 /* SDP service disenabled */ +#define BTA_SDP_DISABLE_EVT 1 /* SDP service disenabled */ #define BTA_SDP_SEARCH_EVT 2 /* SDP search started */ #define BTA_SDP_SEARCH_COMP_EVT 3 /* SDP search complete */ #define BTA_SDP_CREATE_RECORD_USER_EVT 4 /* SDP create record complete */ @@ -67,10 +67,17 @@ typedef struct { int handle; } tBTA_SDP_CREATE_RECORD_USER; +/* data associated with BTA_SDP_REMOVE_RECORD_USER_EVT */ +typedef struct { + tBTA_SDP_STATUS status; + int handle; +} tBTA_SDP_REMOVE_RECORD_USER; + typedef union { tBTA_SDP_STATUS status; /* BTA_SDP_SEARCH_EVT */ tBTA_SDP_SEARCH_COMP sdp_search_comp; /* BTA_SDP_SEARCH_COMP_EVT */ tBTA_SDP_CREATE_RECORD_USER sdp_create_record; /* BTA_SDP_CREATE_RECORD_USER_EVT */ + tBTA_SDP_REMOVE_RECORD_USER sdp_remove_record; /* BTA_SDP_REMOVE_RECORD_USER_EVT */ } tBTA_SDP; /* SDP DM Interface callback */ @@ -78,9 +85,11 @@ typedef void (tBTA_SDP_DM_CBACK)(tBTA_SDP_EVT event, tBTA_SDP *p_data, void *use /* MCE configuration structure */ typedef struct { - UINT16 sdp_db_size; /* The size of p_sdp_db */ + UINT16 sdp_raw_size; /* The size of p_sdp_raw_data */ + UINT16 sdp_db_size; /* The size of p_sdp_db */ #if (SDP_INCLUDED == TRUE) - tSDP_DISCOVERY_DB *p_sdp_db; /* The data buffer to keep SDP database */ + UINT8 *p_sdp_raw_data; /* The data buffer to keep raw data */ + tSDP_DISCOVERY_DB *p_sdp_db; /* The data buffer to keep SDP database */ #endif ///SDP_INCLUDED == TRUE } tBTA_SDP_CFG; @@ -108,14 +117,28 @@ extern tBTA_SDP_STATUS BTA_SdpEnable(tBTA_SDP_DM_CBACK *p_cback); ** ** Function BTA_SdpDisable ** -** Description Disable the SDP search I/F service. +** Description This function is used to request a callback to perform disable +** operation. The registered callback will be called with event +** BTA_SDP_DISABLE_EVT. +** +** Returns BTA_SDP_SUCCESS, if the request is being processed. +** BTA_SDP_FAILURE, otherwise. +** +*******************************************************************************/ +extern tBTA_SDP_STATUS BTA_SdpDisable(void); + +/******************************************************************************* +** +** Function BTA_SdpCleanup +** +** Description Cleanup the SDP search I/F service. ** Free buffer for SDP configuration structure. ** ** Returns BTA_SDP_SUCCESS if successful. ** BTA_SDP_FAIL if internal failure. ** *******************************************************************************/ -extern tBTA_SDP_STATUS BTA_SdpDisable(void); +extern tBTA_SDP_STATUS BTA_SdpCleanup(void); /******************************************************************************* ** diff --git a/lib/bt/host/bluedroid/bta/include/bta/bta_sys.h b/lib/bt/host/bluedroid/bta/include/bta/bta_sys.h index 54376de6..ecf47919 100644 --- a/lib/bt/host/bluedroid/bta/include/bta/bta_sys.h +++ b/lib/bt/host/bluedroid/bta/include/bta/bta_sys.h @@ -91,7 +91,8 @@ typedef UINT16 tBTA_SYS_HW_MODULE; #define BTA_ID_GATTC 31 /* GATT Client */ #define BTA_ID_GATTS 32 /* GATT Client */ #define BTA_ID_SDP 33 /* SDP Client */ -#define BTA_ID_BLUETOOTH_MAX 34 /* last BT profile */ +#define BTA_ID_GOEPC 34 /* GOEP Client */ +#define BTA_ID_BLUETOOTH_MAX 35 /* last BT profile */ /* GENERIC */ #define BTA_ID_PRM 38 @@ -142,7 +143,7 @@ typedef void (tBTA_SYS_CONN_CBACK)(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 typedef void (tBTA_SYS_SSR_CFG_CBACK)(UINT8 id, UINT8 app_id, UINT16 latency, UINT16 tout); #if (BTA_EIR_CANNED_UUID_LIST != TRUE) -/* eir callback for adding/removeing UUID */ +/* eir callback for adding/removing UUID */ typedef void (tBTA_SYS_EIR_CBACK)(tBT_UUID uuid, BOOLEAN adding); #endif diff --git a/lib/bt/host/bluedroid/bta/include/bta/utl.h b/lib/bt/host/bluedroid/bta/include/bta/utl.h index a140832f..9dd46a75 100644 --- a/lib/bt/host/bluedroid/bta/include/bta/utl.h +++ b/lib/bt/host/bluedroid/bta/include/bta/utl.h @@ -36,6 +36,7 @@ #define BTA_UTL_CLR_COD_SERVICE_CLASS 0x04 #define BTA_UTL_SET_COD_ALL 0x08 /* take service class as the input (may clear some set bits!!) */ #define BTA_UTL_INIT_COD 0x0a +#define BTA_UTL_SET_COD_RESERVED_2 0x10 /* overwrite the two least significant bits reserved_2 */ /***************************************************************************** ** Type Definitions @@ -43,6 +44,7 @@ /** for utl_set_device_class() **/ typedef struct { + UINT8 reserved_2; UINT8 minor; UINT8 major; UINT16 service; @@ -125,11 +127,12 @@ extern void utl_freebuf(void **p); ** p_cod - Pointer to the device class to set to ** ** cmd - the fields of the device class to update. +** BTA_UTL_SET_COD_RESERVED_2 - overwrite the two least significant bits reserved_2 ** BTA_UTL_SET_COD_MAJOR_MINOR, - overwrite major, minor class ** BTA_UTL_SET_COD_SERVICE_CLASS - set the bits in the input ** BTA_UTL_CLR_COD_SERVICE_CLASS - clear the bits in the input -** BTA_UTL_SET_COD_ALL - overwrite major, minor, set the bits in service class -** BTA_UTL_INIT_COD - overwrite major, minor, and service class +** BTA_UTL_SET_COD_ALL - overwrite major, minor, set the bits in service class, reserved_2 remain unchanged +** BTA_UTL_INIT_COD - overwrite major, minor, and service class, reserved_2 remain unchanged ** ** Returns TRUE if successful, Otherwise FALSE ** diff --git a/lib/bt/host/bluedroid/bta/jv/bta_jv_act.c b/lib/bt/host/bluedroid/bta/jv/bta_jv_act.c index 214ef746..17eba5ed 100644 --- a/lib/bt/host/bluedroid/bta/jv/bta_jv_act.c +++ b/lib/bt/host/bluedroid/bta/jv/bta_jv_act.c @@ -899,6 +899,7 @@ void bta_jv_free_scn(tBTA_JV_MSG *p_data) } case BTA_JV_CONN_TYPE_L2CAP: bta_jv_set_free_psm(scn); + user_data = (tBTA_JV_FREE_SCN_USER_DATA *)fc->user_data; if (fc->p_cback) { fc->p_cback(BTA_JV_FREE_SCN_EVT, (tBTA_JV *)&evt_data, (void *)user_data); } @@ -1058,7 +1059,7 @@ void sdp_bqb_add_language_attr_ctrl(BOOLEAN enable) /** * @brief Adds a protocol list and service name (if provided) to an SDP record given by - * sdp_handle, and marks it as browseable. This is a shortcut for defining a + * sdp_handle, and marks it as browsable. This is a shortcut for defining a * set of protocols that includes L2CAP, RFCOMM, and optionally OBEX. * * @param[in] sdp_handle: SDP handle @@ -1133,9 +1134,9 @@ static bool create_base_record(const uint32_t sdp_handle, const char *name, cons } } - // Mark the service as browseable. + // Mark the service as browsable. uint16_t list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; - stage = "browseable"; + stage = "browsable"; if (!SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list)){ APPL_TRACE_ERROR("create_base_record: failed to create base service " "record, stage: %s, scn: %d, name: %s, with_obex: %d", @@ -1389,6 +1390,7 @@ void bta_jv_l2cap_close(tBTA_JV_MSG *p_data) evt_data.handle = cc->handle; evt_data.status = bta_jv_free_l2c_cb(cc->p_cb); evt_data.async = FALSE; + evt_data.user_data = (void *)cc->user_data; if (cc->p_cback) { cc->p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data); @@ -1542,19 +1544,13 @@ void bta_jv_l2cap_start_server(tBTA_JV_MSG *p_data) void bta_jv_l2cap_stop_server(tBTA_JV_MSG *p_data) { tBTA_JV_L2C_CB *p_cb; - tBTA_JV_L2CAP_CLOSE evt_data; tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server); - tBTA_JV_L2CAP_CBACK *p_cback; - void *user_data; + for (int i = 0; i < BTA_JV_MAX_L2C_CONN; i++) { if (bta_jv_cb.l2c_cb[i].psm == ls->local_psm) { p_cb = &bta_jv_cb.l2c_cb[i]; - p_cback = p_cb->p_cback; - user_data = p_cb->user_data; - evt_data.handle = p_cb->handle; - evt_data.status = bta_jv_free_l2c_cb(p_cb); - evt_data.async = FALSE; - p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data); + bta_jv_free_l2c_cb(p_cb); + // Report event when free psm break; } } @@ -1754,6 +1750,7 @@ static void bta_jv_port_mgmt_cl_cback(UINT32 code, UINT16 port_handle, void* dat evt_data.rfc_close.status = BTA_JV_FAILURE; evt_data.rfc_close.port_status = code; evt_data.rfc_close.async = TRUE; + evt_data.rfc_close.user_data = p_pcb->user_data; if (p_pcb->state == BTA_JV_ST_CL_CLOSING) { evt_data.rfc_close.async = FALSE; evt_data.rfc_close.status = BTA_JV_SUCCESS; @@ -2082,6 +2079,7 @@ static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle, void *dat evt_data.rfc_close.status = BTA_JV_FAILURE; evt_data.rfc_close.async = TRUE; evt_data.rfc_close.port_status = code; + evt_data.rfc_close.user_data = user_data; p_pcb->cong = FALSE; tBTA_JV_RFCOMM_CBACK *p_cback = p_cb->p_cback; diff --git a/lib/bt/host/bluedroid/bta/pba/bta_pba_client_act.c b/lib/bt/host/bluedroid/bta/pba/bta_pba_client_act.c new file mode 100644 index 00000000..7ed5aaa8 --- /dev/null +++ b/lib/bt/host/bluedroid/bta/pba/bta_pba_client_act.c @@ -0,0 +1,702 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "osi/allocator.h" +#include "common/bt_target.h" +#include "stack/bt_types.h" +#include "stack/obex_api.h" +#include "stack/goep_common.h" +#include "stack/goepc_api.h" +#include "bta_pba_client_int.h" + +#if BTA_PBA_CLIENT_INCLUDED + +static const UINT8 pbap_target_uuid[16] = {0x79, 0x61, 0x35, 0xf0, 0xf0, 0xc5, 0x11, 0xd8, 0x09, 0x66, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66}; +static const char *type_pull_phone_book = "x-bt/phonebook"; +static const char *type_pull_vcard_listing = "x-bt/vcard-listing"; +static const char *type_pull_vcard_entry = "x-bt/vcard"; + +#define TYPE_LEN_PULL_PHONE_BOOK 15 +#define TYPE_LEN_PULL_VCARD_LISTING 19 +#define TYPE_LEN_PULL_VCARD_ENTRY 11 + +static void free_ccb(tBTA_PBA_CLIENT_CCB *p_ccb) +{ + /* free sdp db */ + bta_pba_client_free_db(p_ccb); + + /* clear all field, set allocated to 0 */ + memset(p_ccb, 0, sizeof(tBTA_PBA_CLIENT_CCB)); +} + +static void close_goepc_and_report(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_ERR reason) +{ + /* remove goep connection */ + if (p_ccb->goep_handle != 0) { + GOEPC_Close(p_ccb->goep_handle); + p_ccb->goep_handle = 0; + } + + /* report connection closed event */ + tBTA_PBA_CLIENT_CONN conn; + conn.handle = p_ccb->allocated; + conn.error = reason; + bdcpy(conn.bd_addr, p_ccb->bd_addr); + bta_pba_client_cb.p_cback(BTA_PBA_CLIENT_CONN_CLOSE_EVT, (tBTA_PBA_CLIENT *)&conn); + + /* free ccb */ + free_ccb(p_ccb); +} + +static void build_and_send_empty_get_req(tBTA_PBA_CLIENT_CCB *p_ccb) +{ + tOBEX_PARSE_INFO info = {0}; + info.opcode = OBEX_OPCODE_GET_FINAL; + /* empty get request, try to use a smaller buff size */ + UINT16 tx_buff_size = BT_SMALL_BUFFER_SIZE < p_ccb->max_tx ? BT_SMALL_BUFFER_SIZE : p_ccb->max_tx; + UINT16 ret = GOEPC_PrepareRequest(p_ccb->goep_handle, &info, tx_buff_size); + ret |= GOEPC_RequestAddHeader(p_ccb->goep_handle, OBEX_HEADER_ID_CONNECTION_ID, (UINT8 *)(&p_ccb->goep_cid), 4); + ret |= GOEPC_SendRequest(p_ccb->goep_handle); + if (ret != GOEP_SUCCESS) { + close_goepc_and_report(p_ccb, BTA_PBA_CLIENT_GOEP_ERROR); + } +} + +static uint8_t get_operation_response_event(tBTA_PBA_CLIENT_OP operation) +{ + uint8_t event = 0; + switch (operation) + { + case BTA_PBA_CLIENT_OP_PULL_PHONE_BOOK: + event = BTA_PBA_CLIENT_PULL_PHONE_BOOK_RSP_EVT; + break; + case BTA_PBA_CLIENT_OP_SET_PHONE_BOOK: + event = BTA_PBA_CLIENT_SET_PHONE_BOOK_RSP_EVT; + break; + case BTA_PBA_CLIENT_OP_PULL_VCARD_LISTING: + event = BTA_PBA_CLIENT_PULL_VCARD_LISTING_RSP_EVT; + break; + case BTA_PBA_CLIENT_OP_PULL_VCARD_ENTRY: + event = BTA_PBA_CLIENT_PULL_VCARD_ENTRY_RSP_EVT; + break; + default: + assert(0); + break; + } + return event; +} + +static tBTA_PBA_CLIENT_ERR calculate_response_error(uint8_t response_code) +{ + tBTA_PBA_CLIENT_ERR error = BTA_PBA_CLIENT_FAIL; + /* always treat error response code as final response */ + response_code |= OBEX_FINAL_BIT_MASK; + switch (response_code) + { + case (OBEX_RESPONSE_CODE_BAD_REQUEST | OBEX_FINAL_BIT_MASK): + error = BTA_PBA_CLIENT_BAD_REQUEST; + break; + case (OBEX_RESPONSE_CODE_UNAUTHORIZED | OBEX_FINAL_BIT_MASK): + error = BTA_PBA_CLIENT_UNAUTHORIZED; + break; + case (OBEX_RESPONSE_CODE_FORBIDDEN | OBEX_FINAL_BIT_MASK): + error = BTA_PBA_CLIENT_FORBIDDEN; + break; + case (OBEX_RESPONSE_CODE_NOT_FOUND | OBEX_FINAL_BIT_MASK): + error = BTA_PBA_CLIENT_NOT_FOUND; + break; + case (OBEX_RESPONSE_CODE_NOT_ACCEPTABLE | OBEX_FINAL_BIT_MASK): + error = BTA_PBA_CLIENT_NOT_ACCEPTABLE; + break; + case (OBEX_RESPONSE_CODE_PRECONDITION_FAILED | OBEX_FINAL_BIT_MASK): + error = BTA_PBA_CLIENT_PRECONDITION_FAILED; + break; + case (OBEX_RESPONSE_CODE_NOT_IMPLEMENTED | OBEX_FINAL_BIT_MASK): + error = BTA_PBA_CLIENT_NOT_IMPLEMENTED; + break; + case (OBEX_RESPONSE_CODE_SERVICE_UNAVAILABLE | OBEX_FINAL_BIT_MASK): + error = BTA_PBA_CLIENT_SERVICE_UNAVAILABLE; + break; + default: + break; + } + return error; +} + +static void report_data_event(tBTA_PBA_CLIENT_CCB *p_ccb, UINT8 *data, UINT16 data_len, UINT8 *app_param, + UINT16 app_param_len, BOOLEAN final, BT_HDR *pkt) +{ + uint8_t event = get_operation_response_event(p_ccb->operation); + tBTA_PBA_CLIENT_RESPONSE response; + response.status = BTA_PBA_CLIENT_NO_ERROR; + response.handle = p_ccb->allocated; + response.final = final; + response.data_len = data_len; + response.data = data; + response.app_param_len = app_param_len; + response.app_param = app_param; + response.pkt = pkt; + bta_pba_client_cb.p_cback(event, (tBTA_PBA_CLIENT *)&response); +} + +static void report_error_data_event(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_ERR status) +{ + uint8_t event = get_operation_response_event(p_ccb->operation); + tBTA_PBA_CLIENT_RESPONSE response; + memset(&response, 0, sizeof(tBTA_PBA_CLIENT_RESPONSE)); + response.status = status; + response.handle = p_ccb->allocated; + response.final = TRUE; + bta_pba_client_cb.p_cback(event, (tBTA_PBA_CLIENT *)&response); +} + +static void ascii_to_utf16(const UINT8 *src, UINT16 len, UINT8 *dst) +{ + UINT16 pos = 0; + for (int i = 0 ; i < len ; i++){ + dst[pos++] = 0; + dst[pos++] = src[i]; + } +} + +void bta_pba_client_api_enable(tBTA_PBA_CLIENT_DATA *p_data) +{ + /* initialize control block */ + memset(&bta_pba_client_cb, 0, sizeof(tBTA_PBA_CLIENT_CB)); + + /* store callback function */ + bta_pba_client_cb.p_cback = p_data->api_enable.p_cback; + + bta_pba_client_cb.p_cback(BTA_PBA_CLIENT_ENABLE_EVT, NULL); +} + +void bta_pba_client_api_disable(tBTA_PBA_CLIENT_DATA *p_data) +{ + if (!bta_sys_is_register(BTA_ID_PBC)) { + return; + } + /* deregister with BTA system manager */ + bta_sys_deregister(BTA_ID_PBC); + + /* close all connections */ + for (int i = 0; i < PBA_CLIENT_MAX_CONNECTION; ++i) { + if (bta_pba_client_cb.ccb[i].allocated) { + close_goepc_and_report(&bta_pba_client_cb.ccb[i], BTA_PBA_CLIENT_DISABLE); + } + } + + /* store and clear callback function */ + tBTA_PBA_CLIENT_CBACK *p_cback = bta_pba_client_cb.p_cback; + bta_pba_client_cb.p_cback = NULL; + + if(p_cback) { + p_cback(BTA_PBA_CLIENT_DISABLE_EVT, NULL); + } +} + +void bta_pba_client_api_register(tBTA_PBA_CLIENT_DATA *p_data) +{ + /* create SDP records */ + bta_pba_client_create_record(p_data->api_register.name); + + bta_pba_client_cb.p_cback(BTA_PBA_CLIENT_REGISTER_EVT, NULL); +} + +void bta_pba_client_api_deregister(tBTA_PBA_CLIENT_DATA *p_data) +{ + /* delete SDP records */ + bta_pba_client_del_record(); + + bta_pba_client_cb.p_cback(BTA_PBA_CLIENT_DEREGISTER_EVT, NULL); +} + +void bta_pba_client_api_open(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data) +{ + p_ccb->sec_mask = p_data->api_open.sec_mask; + if (p_data->api_open.mtu < PBA_CLIENT_MIN_MTU || p_data->api_open.mtu > PBA_CLIENT_MAX_MTU) { + p_ccb->max_rx = PBA_CLIENT_MAX_MTU; + p_ccb->max_tx = PBA_CLIENT_MAX_MTU; + } + else { + p_ccb->max_rx = p_data->api_open.mtu; + p_ccb->max_tx = p_data->api_open.mtu; + } + bdcpy(p_ccb->bd_addr, p_data->api_open.bd_addr); + p_ccb->our_supported_feat = p_data->api_open.supported_feat; + if (!bta_pba_client_do_disc(p_ccb)) { + close_goepc_and_report(p_ccb, BTA_PBA_CLIENT_SDP_ERROR); + } +} + +void bta_pba_client_api_close(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data) +{ + UNUSED(p_data); + tOBEX_PARSE_INFO info = {0}; + + info.opcode = OBEX_OPCODE_DISCONNECT; + UINT16 tx_buff_size = BT_SMALL_BUFFER_SIZE < p_ccb->max_tx ? BT_SMALL_BUFFER_SIZE : p_ccb->max_tx; + UINT16 ret = GOEPC_PrepareRequest(p_ccb->goep_handle, &info, tx_buff_size); + ret |= GOEPC_RequestAddHeader(p_ccb->goep_handle, OBEX_HEADER_ID_CONNECTION_ID, (UINT8 *)(&p_ccb->goep_cid), 4); + ret |= GOEPC_SendRequest(p_ccb->goep_handle); + + if (ret != GOEP_SUCCESS) { + /* anyway, this close operation is requested by upper, set reason to success */ + close_goepc_and_report(p_ccb, BTA_PBA_CLIENT_NO_ERROR); + } +} + +void bta_pba_client_api_req(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data) +{ + tOBEX_PARSE_INFO info = {0}; + UINT16 ret; + + if (p_data->api_req.operation == BTA_PBA_CLIENT_OP_SET_PHONE_BOOK) { + info.opcode = OBEX_OPCODE_SETPATH; + info.flags = p_data->api_req.flags; + } + else { + info.opcode = OBEX_OPCODE_GET_FINAL; + } + ret = GOEPC_PrepareRequest(p_ccb->goep_handle, &info, p_ccb->max_tx); + if (ret != GOEP_SUCCESS) { + goto error; + } + + ret |= GOEPC_RequestAddHeader(p_ccb->goep_handle, OBEX_HEADER_ID_CONNECTION_ID, (UINT8 *)(&p_ccb->goep_cid), 4); + + if (p_data->api_req.operation != BTA_PBA_CLIENT_OP_SET_PHONE_BOOK) { + ret |= GOEPC_RequestSetSRM(p_ccb->goep_handle, TRUE, FALSE); + } + + if (p_data->api_req.name) { + UINT16 name_len = strlen(p_data->api_req.name) + 1; + if (name_len == 1) { + /* empty string, add empty name header */ + ret |= GOEPC_RequestAddHeader(p_ccb->goep_handle, OBEX_HEADER_ID_NAME, NULL, 0); + } + else { + UINT8 *utf16_name = osi_malloc(2 * name_len); + assert(utf16_name != NULL); + ascii_to_utf16((UINT8 *)p_data->api_req.name, name_len, utf16_name); + ret |= GOEPC_RequestAddHeader(p_ccb->goep_handle, OBEX_HEADER_ID_NAME, utf16_name, 2 * name_len); + osi_free(utf16_name); + } + osi_free(p_data->api_req.name); + p_data->api_req.name = NULL; + } + + switch (p_data->api_req.operation) + { + case BTA_PBA_CLIENT_OP_PULL_PHONE_BOOK: + ret |= GOEPC_RequestAddHeader(p_ccb->goep_handle, OBEX_HEADER_ID_TYPE, (const UINT8 *)type_pull_phone_book, TYPE_LEN_PULL_PHONE_BOOK); + break; + case BTA_PBA_CLIENT_OP_PULL_VCARD_LISTING: + ret |= GOEPC_RequestAddHeader(p_ccb->goep_handle, OBEX_HEADER_ID_TYPE, (const UINT8 *)type_pull_vcard_listing, TYPE_LEN_PULL_VCARD_LISTING); + break; + case BTA_PBA_CLIENT_OP_PULL_VCARD_ENTRY: + ret |= GOEPC_RequestAddHeader(p_ccb->goep_handle, OBEX_HEADER_ID_TYPE, (const UINT8 *)type_pull_vcard_entry, TYPE_LEN_PULL_VCARD_ENTRY); + break; + default: + break; + } + + if (p_data->api_req.app_param) { + ret |= GOEPC_RequestAddHeader(p_ccb->goep_handle, OBEX_HEADER_ID_APP_PARAM, p_data->api_req.app_param, p_data->api_req.app_param_len); + osi_free(p_data->api_req.app_param); + } + + ret |= GOEPC_SendRequest(p_ccb->goep_handle); + p_ccb->operation = p_data->api_req.operation; + if (ret != GOEP_SUCCESS) { + goto error; + } + return; + +error: + if (p_data->api_req.name) { + osi_free(p_data->api_req.name); + } + if (p_data->api_req.app_param) { + osi_free(p_data->api_req.app_param); + } + close_goepc_and_report(p_ccb, BTA_PBA_CLIENT_GOEP_ERROR); +} + +static void goep_event_callback(UINT16 handle, UINT8 event, tGOEPC_MSG *p_msg) +{ + tBTA_PBA_CLIENT_DATA *p_data = NULL; + + switch (event) + { + case GOEPC_OPENED_EVT: + p_data = (tBTA_PBA_CLIENT_DATA *)osi_malloc(sizeof(tBTA_PBA_CLIENT_DATA)); + assert(p_data != NULL); + p_data->goep_connect.hdr.event = BTA_PBA_CLIENT_GOEP_CONNECT_EVT; + p_data->goep_connect.hdr.layer_specific = handle; + p_data->goep_connect.our_mtu = p_msg->opened.our_mtu; + p_data->goep_connect.peer_mtu = p_msg->opened.peer_mtu; + break; + case GOEPC_CLOSED_EVT: + p_data = (tBTA_PBA_CLIENT_DATA *)osi_malloc(sizeof(tBTA_PBA_CLIENT_DATA)); + assert(p_data != NULL); + p_data->goep_disconnect.hdr.event = BTA_PBA_CLIENT_GOEP_DISCONNECT_EVT; + p_data->goep_disconnect.hdr.layer_specific = handle; + p_data->goep_disconnect.reason = p_msg->closed.reason; + break; + case GOEPC_RESPONSE_EVT: + p_data = (tBTA_PBA_CLIENT_DATA *)osi_malloc(sizeof(tBTA_PBA_CLIENT_DATA)); + assert(p_data != NULL); + p_data->goep_response.hdr.layer_specific = handle; + p_data->goep_response.pkt = p_msg->response.pkt; + p_data->goep_response.opcode = p_msg->response.opcode; + p_data->goep_response.srm_en = p_msg->response.srm_en; + p_data->goep_response.srm_wait = p_msg->response.srm_wait; + if (p_msg->response.final) { + p_data->goep_response.hdr.event = BTA_PBA_CLIENT_RESPONSE_FINAL_EVT; + } + else { + p_data->hdr.event = BTA_PBA_CLIENT_RESPONSE_EVT; + } + break; + case GOEPC_MTU_CHANGED_EVT: + case GOEPC_CONGEST_EVT: + case GOEPC_UNCONGEST_EVT: + /* ignore these event */ + break; + default: + APPL_TRACE_WARNING("%s, unknown goep event: %d", __FUNCTION__, event); + break; + } + if (p_data != NULL) { + bta_sys_sendmsg(p_data); + } +} + +void bta_pba_client_do_connect(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data) +{ + tBTA_PBA_CLIENT_ERR reason = BTA_PBA_CLIENT_FAIL; + + /* find attr in sdp discovery result */ + BOOLEAN found = bta_pba_client_sdp_find_attr(p_ccb); + if (found) { + tOBEX_SVR_INFO svr = {0}; + if (p_ccb->peer_l2cap_psm != 0) { + /* peer support obex over l2cap, use it */ + svr.tl = OBEX_OVER_L2CAP; + svr.l2cap.psm = p_ccb->peer_l2cap_psm; + svr.l2cap.sec_mask = p_ccb->sec_mask; + svr.l2cap.pref_mtu = 0; + bdcpy(svr.l2cap.addr, p_ccb->bd_addr); + } + else { + /* otherwise, use obex over rfcomm */ + svr.tl = OBEX_OVER_RFCOMM; + svr.rfcomm.scn = p_ccb->peer_rfcomm_scn; + svr.rfcomm.sec_mask = p_ccb->sec_mask; + svr.rfcomm.pref_mtu = 0; + bdcpy(svr.rfcomm.addr, p_ccb->bd_addr); + } + + if (GOEPC_Open(&svr, goep_event_callback, &p_ccb->goep_handle) == GOEP_SUCCESS) { + /* start connection success */ + return; + } + else { + reason = BTA_PBA_CLIENT_GOEP_ERROR; + } + } + else { + reason = BTA_PBA_CLIENT_SDP_ERROR; + } + + /* critical sdp attribute not found or start goep connection failed */ + tBTA_PBA_CLIENT_CONN conn; + conn.handle = 0; + conn.error = reason; + bdcpy(conn.bd_addr, p_ccb->bd_addr); + bta_pba_client_cb.p_cback(BTA_PBA_CLIENT_CONN_CLOSE_EVT, (tBTA_PBA_CLIENT *)&conn); + + /* free ccb */ + free_ccb(p_ccb); +} + +void bta_pba_client_authenticate(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data) +{ + /* [todo]: support authenticate */ +} + +void bta_pba_client_connect(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data) +{ + tBTA_PBA_CLIENT_CONN conn; + conn.handle = p_ccb->allocated; + conn.peer_supported_repo = p_ccb->peer_supported_repo; + conn.peer_supported_feat = p_ccb->peer_supported_feat; + conn.error = BTA_PBA_CLIENT_NO_ERROR; + bdcpy(conn.bd_addr, p_ccb->bd_addr); + bta_pba_client_cb.p_cback(BTA_PBA_CLIENT_CONN_OPEN_EVT, (tBTA_PBA_CLIENT *)&conn); +} + +void bta_pba_client_force_disconnect(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data) +{ + UNUSED(p_data); + + /* force disconnect is requested by upper, set reason to success */ + close_goepc_and_report(p_ccb, BTA_PBA_CLIENT_NO_ERROR); +} + +void bta_pba_client_response(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data) +{ + tOBEX_PARSE_INFO info; + tBTA_PBA_CLIENT_ERR reason = BTA_PBA_CLIENT_GOEP_ERROR; + + OBEX_ParseResponse(p_data->goep_response.pkt, p_data->goep_response.opcode, &info); + if (p_data->goep_response.opcode == OBEX_OPCODE_GET_FINAL && + (info.response_code == OBEX_RESPONSE_CODE_CONTINUE || info.response_code == (OBEX_RESPONSE_CODE_CONTINUE | OBEX_FINAL_BIT_MASK))) { + UINT8 *header = NULL; + UINT8 *body_data = NULL; + UINT16 body_data_len = 0; + UINT8 *app_param = NULL; + UINT16 app_param_len = 0; + while((header = OBEX_GetNextHeader(p_data->goep_response.pkt, &info)) != NULL) { + switch (*header) + { + case OBEX_HEADER_ID_BODY: + case OBEX_HEADER_ID_END_OF_BODY: + if (body_data == NULL) { + /* first body header */ + body_data = header + 3; /* skip opcode, length */ + body_data_len = OBEX_GetHeaderLength(header) - 3; + } + else { + /* another body header found */ + report_data_event(p_ccb, body_data, body_data_len, NULL, 0, FALSE, NULL); + body_data = header + 3; /* skip opcode, length */ + body_data_len = OBEX_GetHeaderLength(header) - 3; + } + break; + case OBEX_HEADER_ID_APP_PARAM: + app_param = header + 3; + app_param_len = OBEX_GetHeaderLength(header) - 3; + break; + default: + break; + } + } + if (body_data != NULL || app_param != NULL) { + /* report body data and app param, dont free packet here */ + report_data_event(p_ccb, body_data, body_data_len, app_param, app_param_len, FALSE, p_data->goep_response.pkt); + } + else { + /* not any body data or app param */ + osi_free(p_data->goep_response.pkt); + } + + /* if SRM not enable, we need to send a empty get request */ + if (!p_data->goep_response.srm_en || p_data->goep_response.srm_wait) { + build_and_send_empty_get_req(p_ccb); + } + } + else { + /* unexpected opcode or response code */ + reason = calculate_response_error(info.response_code); + goto error; + } + return; + +error: + if (p_data->goep_response.pkt != NULL) { + osi_free(p_data->goep_response.pkt); + } + close_goepc_and_report(p_ccb, reason); +} + +void bta_pba_client_response_final(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data) +{ + tOBEX_PARSE_INFO info; + UINT8 *header = NULL; + tBTA_PBA_CLIENT_ERR reason = BTA_PBA_CLIENT_FAIL; + + OBEX_ParseResponse(p_data->goep_response.pkt, p_data->goep_response.opcode, &info); + if (p_data->goep_response.opcode == OBEX_OPCODE_CONNECT) { + if (info.response_code == (OBEX_RESPONSE_CODE_OK | OBEX_FINAL_BIT_MASK)) { + /* obex connect success */ + if (info.max_packet_length < 255) { + p_ccb->max_tx = 255; + } + else if (p_ccb->max_tx > info.max_packet_length) { + p_ccb->max_tx = info.max_packet_length; + } + BOOLEAN cid_found = false; + while((header = OBEX_GetNextHeader(p_data->goep_response.pkt, &info)) != NULL) { + if (*header == OBEX_HEADER_ID_CONNECTION_ID) { + cid_found = true; + memcpy((UINT8 *)(&p_ccb->goep_cid), header + 1, 4); + break; + } + } + if (!cid_found) { + goto error; + } + + BT_HDR *p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR)); + assert(p_buf != NULL); + p_buf->event = BTA_PBA_CLIENT_CONNECT_EVT; + p_buf->layer_specific = p_ccb->allocated; + bta_sys_sendmsg(p_buf); + } + else if (info.response_code == (OBEX_RESPONSE_CODE_UNAUTHORIZED | OBEX_FINAL_BIT_MASK)){ + /* need to authenticate */ + if (p_ccb->authenticate) { + /* already try to authenticate, but failed */ + reason = BTA_PBA_CLIENT_AUTH_FAIL; + goto error; + } + + p_ccb->authenticate = TRUE; + /* [todo]: we don't support authenticate currently */ + goto error; + } + else { + /* other unexpected response code */ + goto error; + } + osi_free(p_data->goep_response.pkt); + } + else if (p_data->goep_response.opcode == OBEX_OPCODE_GET_FINAL) { + /* check response code is success */ + if (info.response_code == (OBEX_RESPONSE_CODE_OK | OBEX_FINAL_BIT_MASK)) { + UINT8 *body_data = NULL; + UINT16 body_data_len = 0; + UINT8 *app_param = NULL; + UINT16 app_param_len = 0; + while((header = OBEX_GetNextHeader(p_data->goep_response.pkt, &info)) != NULL) { + switch (*header) + { + /* actually, BODY should not in this final response */ + case OBEX_HEADER_ID_BODY: + case OBEX_HEADER_ID_END_OF_BODY: + if (body_data == NULL) { + /* first body header */ + body_data = header + 3; /* skip opcode, length */ + body_data_len = OBEX_GetHeaderLength(header) - 3; + } + else { + /* another body header found */ + report_data_event(p_ccb, body_data, body_data_len, NULL, 0, FALSE, NULL); + body_data = header + 3; /* skip opcode, length */ + body_data_len = OBEX_GetHeaderLength(header) - 3; + } + break; + case OBEX_HEADER_ID_APP_PARAM: + app_param = header + 3; + app_param_len = OBEX_GetHeaderLength(header) - 3; + break; + default: + break; + } + } + if (body_data != NULL || app_param != NULL) { + /* report body data and app param, dont free packet here */ + report_data_event(p_ccb, body_data, body_data_len, app_param, app_param_len, TRUE, p_data->goep_response.pkt); + /* done, return */ + return; + } + } + /* unexpected response code or body data not found */ + reason = calculate_response_error(info.response_code); + report_error_data_event(p_ccb, reason); + osi_free(p_data->goep_response.pkt); + + /* state machine is good, don't goto error */ + } + else if (p_data->goep_response.opcode == OBEX_OPCODE_SETPATH) { + if (info.response_code == (OBEX_RESPONSE_CODE_OK | OBEX_FINAL_BIT_MASK)) { + report_data_event(p_ccb, NULL, 0, NULL, 0, TRUE, NULL); + } + else { + reason = calculate_response_error(info.response_code); + report_error_data_event(p_ccb, reason); + } + osi_free(p_data->goep_response.pkt); + } + else if (p_data->goep_response.opcode == OBEX_OPCODE_DISCONNECT) { + /* received disconnect response, close goep connection now */ + reason = BTA_PBA_CLIENT_NO_ERROR; + close_goepc_and_report(p_ccb, reason); + osi_free(p_data->goep_response.pkt); + } + else { + /* unexpected opcode or response code */ + reason = calculate_response_error(info.response_code); + goto error; + } + return; + +error: + if (p_data->goep_response.pkt != NULL) { + osi_free(p_data->goep_response.pkt); + } + close_goepc_and_report(p_ccb, reason); +} + +void bta_pba_client_goep_connect(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data) +{ + /* limit max rx to our goep mtu */ + if (p_ccb->max_rx > p_data->goep_connect.our_mtu) { + p_ccb->max_rx = p_data->goep_connect.our_mtu; + } + /* limit max tx to peer goep mtu */ + if (p_ccb->max_tx > p_data->goep_connect.peer_mtu) { + p_ccb->max_tx = p_data->goep_connect.peer_mtu; + } + + /* build and send obex connect request */ + tOBEX_PARSE_INFO info = {0}; + info.opcode = OBEX_OPCODE_CONNECT; + info.obex_version_number = OBEX_VERSION_NUMBER; + info.max_packet_length = p_ccb->max_rx; + /* before obex connect response, we dont know the real max_tx, use BT_SMALL_BUFFER_SIZE as tx buff size */ + UINT16 ret = GOEPC_PrepareRequest(p_ccb->goep_handle, &info, BT_SMALL_BUFFER_SIZE); + /* add target header */ + ret |= GOEPC_RequestAddHeader(p_ccb->goep_handle, OBEX_HEADER_ID_TARGET, pbap_target_uuid, 16); + if (p_ccb->send_supported_feat) { + /* add application parameters with supported features */ + UINT8 app_param[6]; + app_param[0] = BTA_PBAP_APP_PARAM_PBAP_SUPPORTED_FEATURES; + app_param[1] = BTA_PBAP_APP_PARAM_LENGTH_PBAP_SUPPORTED_FEATURES; + UINT32_TO_FIELD(&app_param[2], p_ccb->our_supported_feat); + ret |= GOEPC_RequestAddHeader(p_ccb->goep_handle, OBEX_HEADER_ID_APP_PARAM, app_param, 6); + } + ret |= GOEPC_SendRequest(p_ccb->goep_handle); + if (ret != GOEP_SUCCESS) { + close_goepc_and_report(p_ccb, BTA_PBA_CLIENT_GOEP_ERROR); + } +} + +void bta_pba_client_goep_disconnect(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data) +{ + p_ccb->goep_handle = 0; + + /* report connection closed event */ + tBTA_PBA_CLIENT_CONN conn; + conn.handle = p_ccb->allocated; + bdcpy(conn.bd_addr, p_ccb->bd_addr); + conn.error = BTA_PBA_CLIENT_GOEP_ERROR; + bta_pba_client_cb.p_cback(BTA_PBA_CLIENT_CONN_CLOSE_EVT, (tBTA_PBA_CLIENT *)&conn); + free_ccb(p_ccb); +} + +void bta_pba_client_free_response(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data) +{ + if (p_data->goep_response.pkt != NULL) { + osi_free(p_data->goep_response.pkt); + } + close_goepc_and_report(p_ccb, BTA_PBA_CLIENT_GOEP_ERROR); +} + +#endif diff --git a/lib/bt/host/bluedroid/bta/pba/bta_pba_client_api.c b/lib/bt/host/bluedroid/bta/pba/bta_pba_client_api.c new file mode 100644 index 00000000..8169a7d6 --- /dev/null +++ b/lib/bt/host/bluedroid/bta/pba/bta_pba_client_api.c @@ -0,0 +1,162 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "osi/allocator.h" +#include "common/bt_target.h" +#include "stack/obex_api.h" +#include "stack/goep_common.h" +#include "stack/goepc_api.h" +#include "bta/bta_sys.h" +#include "bta/bta_api.h" +#include "bta_pba_client_int.h" + +#if BTA_PBA_CLIENT_INCLUDED + +static const tBTA_SYS_REG bta_pba_client_reg = { + bta_pba_client_hdl_event, + BTA_PbaClientDisable +}; + +void BTA_PbaClientEnable(tBTA_PBA_CLIENT_CBACK *p_cback) +{ + tBTA_PBA_CLIENT_API_ENABLE *p_buf; + + if (bta_sys_is_register(BTA_ID_PBC)) { + APPL_TRACE_ERROR("BTA PBA Client already enabled"); + return; + } + + /* register with BTA system manager */ + bta_sys_register(BTA_ID_PBC, &bta_pba_client_reg); + + if ((p_buf = (tBTA_PBA_CLIENT_API_ENABLE *)osi_malloc(sizeof(tBTA_PBA_CLIENT_API_ENABLE))) != NULL) { + p_buf->hdr.event = BTA_PBA_CLIENT_API_ENABLE_EVT; + p_buf->p_cback = p_cback; + bta_sys_sendmsg(p_buf); + } +} + +void BTA_PbaClientDisable(void) +{ + BT_HDR *p_buf; + + if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_PBA_CLIENT_API_DISABLE_EVT; + bta_sys_sendmsg(p_buf); + } +} + +void BTA_PbaClientRegister(const char *server_name) +{ + tBTA_PBA_CLIENT_API_REGISTER *p_buf; + + if ((p_buf = (tBTA_PBA_CLIENT_API_REGISTER *) osi_malloc(sizeof(tBTA_PBA_CLIENT_API_REGISTER))) != NULL) { + p_buf->hdr.event = BTA_PBA_CLIENT_API_REGISTER_EVT; + memcpy(p_buf->name, server_name, strlen(server_name) + 1); + bta_sys_sendmsg(p_buf); + } +} + +void BTA_PbaClientDeregister(void) +{ + BT_HDR *p_buf; + + if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_PBA_CLIENT_API_DEREGISTER_EVT; + bta_sys_sendmsg(p_buf); + } +} + +void BTA_PbaClientOpen(BD_ADDR bd_addr, tBTA_SEC sec_mask, UINT32 supported_feat, UINT16 mtu) +{ + tBTA_PBA_CLIENT_API_OPEN *p_buf; + + if ((p_buf = (tBTA_PBA_CLIENT_API_OPEN *)osi_malloc(sizeof(tBTA_PBA_CLIENT_API_OPEN))) != NULL) { + p_buf->hdr.event = BTA_PBA_CLIENT_API_OPEN_EVT; + p_buf->sec_mask = sec_mask; + p_buf->supported_feat = supported_feat; + p_buf->mtu = mtu; + bdcpy(p_buf->bd_addr, bd_addr); + bta_sys_sendmsg(p_buf); + } +} + +void BTA_PbaClientClose(UINT16 handle) +{ + BT_HDR *p_buf; + + if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_PBA_CLIENT_API_CLOSE_EVT; + p_buf->layer_specific = handle; + bta_sys_sendmsg(p_buf); + } +} + +void BTA_PbaClientPullPhoneBook(UINT16 handle, char *name, UINT8 *app_param, UINT16 app_param_len) +{ + tBTA_PBA_CLIENT_API_REQ *p_buf; + + if ((p_buf = (tBTA_PBA_CLIENT_API_REQ *) osi_malloc(sizeof(tBTA_PBA_CLIENT_API_REQ))) != NULL) { + p_buf->hdr.event = BTA_PBA_CLIENT_API_REQ_EVT; + p_buf->hdr.layer_specific = handle; + p_buf->operation = BTA_PBA_CLIENT_OP_PULL_PHONE_BOOK; + p_buf->name = name; + p_buf->app_param = app_param; + p_buf->app_param_len = app_param_len; + bta_sys_sendmsg(p_buf); + } +} + +void BTA_PbaClientSetPhoneBook(UINT16 handle, UINT8 flags, char *name) +{ + tBTA_PBA_CLIENT_API_REQ *p_buf; + + if ((p_buf = (tBTA_PBA_CLIENT_API_REQ *) osi_malloc(sizeof(tBTA_PBA_CLIENT_API_REQ))) != NULL) { + p_buf->hdr.event = BTA_PBA_CLIENT_API_REQ_EVT; + p_buf->hdr.layer_specific = handle; + p_buf->operation = BTA_PBA_CLIENT_OP_SET_PHONE_BOOK; + p_buf->flags = flags; + p_buf->name = name; + p_buf->app_param = NULL; + p_buf->app_param_len = 0; + bta_sys_sendmsg(p_buf); + } +} + +void BTA_PbaClientPullvCardListing(UINT16 handle, char *name, UINT8 *app_param, UINT16 app_param_len) +{ + tBTA_PBA_CLIENT_API_REQ *p_buf; + + if ((p_buf = (tBTA_PBA_CLIENT_API_REQ *) osi_malloc(sizeof(tBTA_PBA_CLIENT_API_REQ))) != NULL) { + p_buf->hdr.event = BTA_PBA_CLIENT_API_REQ_EVT; + p_buf->hdr.layer_specific = handle; + p_buf->operation = BTA_PBA_CLIENT_OP_PULL_VCARD_LISTING; + p_buf->name = name; + p_buf->app_param = app_param; + p_buf->app_param_len = app_param_len; + bta_sys_sendmsg(p_buf); + } +} + +void BTA_PbaClientPullvCardEntry(UINT16 handle, char *name, UINT8 *app_param, UINT16 app_param_len) +{ + tBTA_PBA_CLIENT_API_REQ *p_buf; + + if ((p_buf = (tBTA_PBA_CLIENT_API_REQ *) osi_malloc(sizeof(tBTA_PBA_CLIENT_API_REQ))) != NULL) { + p_buf->hdr.event = BTA_PBA_CLIENT_API_REQ_EVT; + p_buf->hdr.layer_specific = handle; + p_buf->operation = BTA_PBA_CLIENT_OP_PULL_VCARD_ENTRY; + p_buf->name = name; + p_buf->app_param = app_param; + p_buf->app_param_len = app_param_len; + bta_sys_sendmsg(p_buf); + } +} + +#endif diff --git a/lib/bt/host/bluedroid/bta/pba/bta_pba_client_main.c b/lib/bt/host/bluedroid/bta/pba/bta_pba_client_main.c new file mode 100644 index 00000000..81c389bb --- /dev/null +++ b/lib/bt/host/bluedroid/bta/pba/bta_pba_client_main.c @@ -0,0 +1,293 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "osi/allocator.h" +#include "common/bt_target.h" + +#include "stack/obex_api.h" +#include "stack/goep_common.h" +#include "stack/goepc_api.h" +#include "bta_pba_client_int.h" + +#if BTA_PBA_CLIENT_INCLUDED + +/* state machine states */ +enum { + BTA_PBA_CLIENT_INIT_ST, + BTA_PBA_CLIENT_OPENING_ST, + BTA_PBA_CLIENT_OPENED_ST, + BTA_PBA_CLIENT_REQUESTING_ST, + BTA_PBA_CLIENT_CLOSING_ST +}; + +/* state machine action enumeration list */ +enum { + BTA_PBA_CLIENT_API_OPEN, + BTA_PBA_CLIENT_API_CLOSE, + BTA_PBA_CLIENT_API_REQ, + BTA_PBA_CLIENT_DO_CONNECT, + BTA_PBA_CLIENT_AUTHENTICATE, + BTA_PBA_CLIENT_CONNECT, + BTA_PBA_CLIENT_RESPONSE, + BTA_PBA_CLIENT_RESPONSE_FINAL, + BTA_PBA_CLIENT_GOEP_CONNECT, + BTA_PBA_CLIENT_GOEP_DISCONNECT, + BTA_PBA_CLIENT_FORCE_DISCONNECT, + BTA_PBA_CLIENT_FREE_RESPONSE, + BTA_PBA_CLIENT_NUM_ACTIONS +}; + +#define BTA_PBA_CLIENT_IGNORE BTA_PBA_CLIENT_NUM_ACTIONS + +/* type for action functions */ +typedef void (*tBTA_PBA_CLIENT_ACTION)(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data); + +/* action functions table, indexed with action enum */ +const tBTA_PBA_CLIENT_ACTION bta_pba_client_action[] = { + /* BTA_PBA_CLIENT_API_OPEN */ bta_pba_client_api_open, + /* BTA_PBA_CLIENT_API_CLOSE */ bta_pba_client_api_close, + /* BTA_PBA_CLIENT_API_REQ */ bta_pba_client_api_req, + /* BTA_PBA_CLIENT_DO_CONNECT */ bta_pba_client_do_connect, + /* BTA_PBA_CLIENT_AUTHENTICATE */ bta_pba_client_authenticate, + /* BTA_PBA_CLIENT_CONNECT */ bta_pba_client_connect, + /* BTA_PBA_CLIENT_RESPONSE */ bta_pba_client_response, + /* BTA_PBA_CLIENT_RESPONSE_FINAL */ bta_pba_client_response_final, + /* BTA_PBA_CLIENT_GOEP_CONNECT */ bta_pba_client_goep_connect, + /* BTA_PBA_CLIENT_GOEP_DISCONNECT*/ bta_pba_client_goep_disconnect, + /* BTA_PBA_CLIENT_FORCE_DISCONNECT */ bta_pba_client_force_disconnect, + /* BTA_PBA_CLIENT_FREE_RESPONSE */ bta_pba_client_free_response, +}; + +/* state table information */ +#define BTA_PBA_CLIENT_ACTION 0 /* position of action */ +#define BTA_PBA_CLIENT_NEXT_STATE 1 /* position of next state */ +#define BTA_PBA_CLIENT_NUM_COLS 2 /* number of columns */ + +const uint8_t bta_pba_client_st_init[][BTA_PBA_CLIENT_NUM_COLS] = { + /* Event Action Next state */ + /* BTA_PBA_CLIENT_API_OPEN_EVT */ {BTA_PBA_CLIENT_API_OPEN, BTA_PBA_CLIENT_OPENING_ST}, + /* BTA_PBA_CLIENT_API_CLOSE_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_INIT_ST}, + /* BTA_PBA_CLIENT_API_REQ_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_INIT_ST}, + /* BTA_PBA_CLIENT_DISC_RES_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_INIT_ST}, + /* BTA_PBA_CLIENT_AUTHENTICATE_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_INIT_ST}, + /* BTA_PBA_CLIENT_CONNECT_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_INIT_ST}, + /* BTA_PBA_CLIENT_RESPONSE_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_INIT_ST}, + /* BTA_PBA_CLIENT_RESPONSE_FINAL_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_INIT_ST}, + /* BTA_PBA_CLIENT_GOEP_CONNECT_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_INIT_ST}, + /* BTA_PBA_CLIENT_GOEP_DISCONNECT_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_INIT_ST}, +}; + +const uint8_t bta_pba_client_st_opening[][BTA_PBA_CLIENT_NUM_COLS] = { + /* Event Action Next state */ + /* BTA_PBA_CLIENT_API_OPEN_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_OPENING_ST}, + /* BTA_PBA_CLIENT_API_CLOSE_EVT */ {BTA_PBA_CLIENT_FORCE_DISCONNECT, BTA_PBA_CLIENT_INIT_ST}, + /* BTA_PBA_CLIENT_API_REQ_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_OPENING_ST}, + /* BTA_PBA_CLIENT_DISC_RES_EVT */ {BTA_PBA_CLIENT_DO_CONNECT, BTA_PBA_CLIENT_OPENING_ST}, + /* BTA_PBA_CLIENT_AUTHENTICATE_EVT */ {BTA_PBA_CLIENT_AUTHENTICATE, BTA_PBA_CLIENT_OPENING_ST}, + /* BTA_PBA_CLIENT_CONNECT_EVT */ {BTA_PBA_CLIENT_CONNECT, BTA_PBA_CLIENT_OPENED_ST}, + /* BTA_PBA_CLIENT_RESPONSE_EVT */ {BTA_PBA_CLIENT_FREE_RESPONSE, BTA_PBA_CLIENT_OPENING_ST}, + /* BTA_PBA_CLIENT_RESPONSE_FINAL_EVT */ {BTA_PBA_CLIENT_RESPONSE_FINAL, BTA_PBA_CLIENT_OPENING_ST}, + /* BTA_PBA_CLIENT_GOEP_CONNECT_EVT */ {BTA_PBA_CLIENT_GOEP_CONNECT, BTA_PBA_CLIENT_OPENING_ST}, + /* BTA_PBA_CLIENT_GOEP_DISCONNECT_EVT */ {BTA_PBA_CLIENT_GOEP_DISCONNECT, BTA_PBA_CLIENT_INIT_ST}, +}; + +const uint8_t bta_pba_client_st_opened[][BTA_PBA_CLIENT_NUM_COLS] = { + /* Event Action Next state */ + /* BTA_PBA_CLIENT_API_OPEN_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_OPENED_ST}, + /* BTA_PBA_CLIENT_API_CLOSE_EVT */ {BTA_PBA_CLIENT_API_CLOSE, BTA_PBA_CLIENT_CLOSING_ST}, + /* BTA_PBA_CLIENT_API_REQ_EVT */ {BTA_PBA_CLIENT_API_REQ, BTA_PBA_CLIENT_REQUESTING_ST}, + /* BTA_PBA_CLIENT_DISC_RES_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_OPENED_ST}, + /* BTA_PBA_CLIENT_AUTHENTICATE_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_OPENED_ST}, + /* BTA_PBA_CLIENT_CONNECT_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_OPENED_ST}, + /* BTA_PBA_CLIENT_RESPONSE_EVT */ {BTA_PBA_CLIENT_FREE_RESPONSE, BTA_PBA_CLIENT_OPENED_ST}, + /* BTA_PBA_CLIENT_RESPONSE_FINAL_EVT */ {BTA_PBA_CLIENT_FREE_RESPONSE, BTA_PBA_CLIENT_OPENED_ST}, + /* BTA_PBA_CLIENT_GOEP_CONNECT_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_OPENED_ST}, + /* BTA_PBA_CLIENT_GOEP_DISCONNECT_EVT */ {BTA_PBA_CLIENT_GOEP_DISCONNECT, BTA_PBA_CLIENT_INIT_ST}, +}; + +const uint8_t bta_pba_client_st_getting[][BTA_PBA_CLIENT_NUM_COLS] = { + /* Event Action Next state */ + /* BTA_PBA_CLIENT_API_OPEN_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_REQUESTING_ST}, + /* BTA_PBA_CLIENT_API_CLOSE_EVT */ {BTA_PBA_CLIENT_FORCE_DISCONNECT, BTA_PBA_CLIENT_INIT_ST}, + /* BTA_PBA_CLIENT_API_REQ_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_REQUESTING_ST}, + /* BTA_PBA_CLIENT_DISC_RES_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_REQUESTING_ST}, + /* BTA_PBA_CLIENT_AUTHENTICATE_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_REQUESTING_ST}, + /* BTA_PBA_CLIENT_CONNECT_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_REQUESTING_ST}, + /* BTA_PBA_CLIENT_RESPONSE_EVT */ {BTA_PBA_CLIENT_RESPONSE, BTA_PBA_CLIENT_REQUESTING_ST}, + /* BTA_PBA_CLIENT_RESPONSE_FINAL_EVT */ {BTA_PBA_CLIENT_RESPONSE_FINAL, BTA_PBA_CLIENT_OPENED_ST}, + /* BTA_PBA_CLIENT_GOEP_CONNECT_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_REQUESTING_ST}, + /* BTA_PBA_CLIENT_GOEP_DISCONNECT_EVT */ {BTA_PBA_CLIENT_GOEP_DISCONNECT, BTA_PBA_CLIENT_INIT_ST}, +}; + +const uint8_t bta_pba_client_st_closing[][BTA_PBA_CLIENT_NUM_COLS] = { + /* Event Action Next state */ + /* BTA_PBA_CLIENT_API_OPEN_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_CLOSING_ST}, + /* BTA_PBA_CLIENT_API_CLOSE_EVT */ {BTA_PBA_CLIENT_FORCE_DISCONNECT, BTA_PBA_CLIENT_INIT_ST}, + /* BTA_PBA_CLIENT_API_REQ_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_CLOSING_ST}, + /* BTA_PBA_CLIENT_DISC_RES_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_CLOSING_ST}, + /* BTA_PBA_CLIENT_AUTHENTICATE_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_CLOSING_ST}, + /* BTA_PBA_CLIENT_CONNECT_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_CLOSING_ST}, + /* BTA_PBA_CLIENT_RESPONSE_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_CLOSING_ST}, + /* BTA_PBA_CLIENT_RESPONSE_FINAL_EVT */ {BTA_PBA_CLIENT_RESPONSE_FINAL, BTA_PBA_CLIENT_INIT_ST}, + /* BTA_PBA_CLIENT_GOEP_CONNECT_EVT */ {BTA_PBA_CLIENT_IGNORE, BTA_PBA_CLIENT_CLOSING_ST}, + /* BTA_PBA_CLIENT_GOEP_DISCONNECT_EVT */ {BTA_PBA_CLIENT_GOEP_DISCONNECT, BTA_PBA_CLIENT_INIT_ST}, +}; + +/* type for state table */ +typedef const UINT8 (*tBTA_PBA_CLIENT_ST_TBL)[BTA_PBA_CLIENT_NUM_COLS]; + +/* state table */ +const tBTA_PBA_CLIENT_ST_TBL bta_pba_client_st_tbl[] = { + bta_pba_client_st_init, + bta_pba_client_st_opening, + bta_pba_client_st_opened, + bta_pba_client_st_getting, + bta_pba_client_st_closing +}; + +/* PBA Client control block */ +#if BTA_DYNAMIC_MEMORY == FALSE +tBTA_PBA_CLIENT_CB bta_pba_client_cb; +#else +tBTA_PBA_CLIENT_CB *bta_pba_client_cb_ptr; +#endif + +static tBTA_PBA_CLIENT_CCB *allocate_ccb(void) +{ + tBTA_PBA_CLIENT_CCB *p_ccb = NULL; + for (int i = 0; i < PBA_CLIENT_MAX_CONNECTION; ++i) { + if (bta_pba_client_cb.ccb[i].allocated == 0) { + bta_pba_client_cb.ccb[i].allocated = i + 1; + p_ccb = &bta_pba_client_cb.ccb[i]; + break; + } + } + return p_ccb; +} + +static tBTA_PBA_CLIENT_CCB *find_ccb_by_handle(UINT16 handle) +{ + tBTA_PBA_CLIENT_CCB *p_ccb = NULL; + for (int i = 0; i < PBA_CLIENT_MAX_CONNECTION; ++i) { + if (bta_pba_client_cb.ccb[i].allocated != 0 && bta_pba_client_cb.ccb[i].allocated == handle) { + p_ccb = &bta_pba_client_cb.ccb[i]; + } + } + return p_ccb; +} + +static tBTA_PBA_CLIENT_CCB *find_ccb_by_goep_handle(UINT16 goep_handle) +{ + tBTA_PBA_CLIENT_CCB *p_ccb = NULL; + for (int i = 0; i < PBA_CLIENT_MAX_CONNECTION; ++i) { + if (bta_pba_client_cb.ccb[i].allocated != 0 && bta_pba_client_cb.ccb[i].goep_handle == goep_handle) { + p_ccb = &bta_pba_client_cb.ccb[i]; + } + } + return p_ccb; +} + +static tBTA_PBA_CLIENT_CCB *find_ccb_by_bd_addr(BD_ADDR bd_addr) +{ + tBTA_PBA_CLIENT_CCB *p_ccb = NULL; + for (int i = 0; i < PBA_CLIENT_MAX_CONNECTION; ++i) { + if (bta_pba_client_cb.ccb[i].allocated != 0 && bdcmp(bta_pba_client_cb.ccb[i].bd_addr, bd_addr) == 0) { + p_ccb = &bta_pba_client_cb.ccb[i]; + } + } + return p_ccb; +} + +void bta_pba_client_sm_execute(tBTA_PBA_CLIENT_CCB *p_ccb, UINT16 event, tBTA_PBA_CLIENT_DATA *p_data) +{ + tBTA_PBA_CLIENT_ST_TBL state_table; + UINT8 action; + + state_table = bta_pba_client_st_tbl[p_ccb->state]; + + event &= 0xff; + + p_ccb->state = state_table[event][BTA_PBA_CLIENT_NEXT_STATE]; + + if ((action = state_table[event][BTA_PBA_CLIENT_ACTION]) != BTA_PBA_CLIENT_IGNORE) { + (*bta_pba_client_action[action])(p_ccb, p_data); + } + + return; +} + +BOOLEAN bta_pba_client_hdl_event(BT_HDR *p_msg) +{ + tBTA_PBA_CLIENT_CCB *p_ccb = NULL; + BOOLEAN execute_sm = FALSE; + tBTA_PBA_CLIENT_CONN conn = {0}; + tBTA_PBA_CLIENT_DATA *p_data = (tBTA_PBA_CLIENT_DATA *)p_msg; + + switch (p_msg->event) { + case BTA_PBA_CLIENT_API_ENABLE_EVT: + bta_pba_client_api_enable(p_data); + break; + case BTA_PBA_CLIENT_API_DISABLE_EVT: + bta_pba_client_api_disable(p_data); + break; + case BTA_PBA_CLIENT_API_REGISTER_EVT: + bta_pba_client_api_register(p_data); + break; + case BTA_PBA_CLIENT_API_DEREGISTER_EVT: + bta_pba_client_api_deregister(p_data); + break; + case BTA_PBA_CLIENT_API_OPEN_EVT: + if (find_ccb_by_bd_addr(p_data->api_open.bd_addr) != NULL) { + /* already connected */ + conn.handle = 0; + conn.error = BTA_PBA_CLIENT_ALREADY_CONN; + bdcpy(conn.bd_addr, p_data->api_open.bd_addr); + bta_pba_client_cb.p_cback(BTA_PBA_CLIENT_CONN_OPEN_EVT, (tBTA_PBA_CLIENT *)&conn); + /* break, don't execute sm */ + break; + } + p_ccb = allocate_ccb(); + if (p_ccb == NULL) { + /* no resource to allocate ccb */ + conn.handle = 0; + conn.error = BTA_PBA_CLIENT_NO_RESOURCE; + bdcpy(conn.bd_addr, p_data->api_open.bd_addr); + bta_pba_client_cb.p_cback(BTA_PBA_CLIENT_CONN_OPEN_EVT, (tBTA_PBA_CLIENT *)&conn); + /* break, don't execute sm */ + break; + } + execute_sm = TRUE; + break; + case BTA_PBA_CLIENT_GOEP_CONNECT_EVT: + case BTA_PBA_CLIENT_GOEP_DISCONNECT_EVT: + case BTA_PBA_CLIENT_RESPONSE_EVT: + case BTA_PBA_CLIENT_RESPONSE_FINAL_EVT: + p_ccb = find_ccb_by_goep_handle(p_msg->layer_specific); + if (p_ccb == NULL) { + /* ignore event with invalid goep handle */ + break; + } + execute_sm = TRUE; + break; + default: + p_ccb = find_ccb_by_handle(p_msg->layer_specific); + if (p_ccb == NULL) { + /* ignore event with invalid handle */ + break; + } + execute_sm = TRUE; + } + + if (execute_sm) { + bta_pba_client_sm_execute(p_ccb, p_msg->event, (tBTA_PBA_CLIENT_DATA *) p_msg); + } + + return TRUE; +} + +#endif diff --git a/lib/bt/host/bluedroid/bta/pba/bta_pba_client_sdp.c b/lib/bt/host/bluedroid/bta/pba/bta_pba_client_sdp.c new file mode 100644 index 00000000..030ddad6 --- /dev/null +++ b/lib/bt/host/bluedroid/bta/pba/bta_pba_client_sdp.c @@ -0,0 +1,279 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "osi/allocator.h" +#include "common/bt_defs.h" +#include "stack/sdp_api.h" +#include "bta/bta_api.h" +#include "bta/bta_pba_defs.h" +#include "bta/bta_pba_client_api.h" +#include "bta_pba_client_int.h" + +#if BTA_PBA_CLIENT_INCLUDED + +/* Number of elements in service class id list. */ +#define BTA_PBA_CLIENT_NUM_SVC_ELEMS 1 + +/******************************************************************************* +** +** Function bta_pba_client_sdp_cback +** +** Description SDP callback function. +** +** +** Returns void +** +*******************************************************************************/ +static void bta_pba_client_sdp_cback(UINT16 status, void *user_data) +{ + tBTA_PBA_CLIENT_DISC_RESULT *p_buf; + tBTA_PBA_CLIENT_CCB *p_ccb = (tBTA_PBA_CLIENT_CCB *)user_data; + + APPL_TRACE_DEBUG("bta_pba_client_sdp_cback status:0x%x", status); + + if ((p_buf = (tBTA_PBA_CLIENT_DISC_RESULT *) osi_malloc(sizeof(tBTA_PBA_CLIENT_DISC_RESULT))) != NULL) { + p_buf->hdr.event = BTA_PBA_CLIENT_DISC_RES_EVT; + p_buf->hdr.layer_specific = p_ccb->allocated; + p_buf->status = status; + bta_sys_sendmsg(p_buf); + } +} + +/****************************************************************************** +** +** Function bta_pba_client_add_record +** +** Description Add PBA Client information to an SDP record. Prior to +** calling this function the application must call +** SDP_CreateRecord() to create an SDP record. +** +** Returns TRUE if function execution succeeded, +** FALSE if function execution failed. +** +******************************************************************************/ +static BOOLEAN bta_pba_client_add_record(const char *p_service_name, UINT32 sdp_handle) +{ + UINT16 svc_class_id_list[BTA_PBA_CLIENT_NUM_SVC_ELEMS]; + UINT16 version; + UINT16 profile_uuid; + BOOLEAN result = TRUE; + + APPL_TRACE_DEBUG("bta_pba_client_add_record"); + + /* add service class id list */ + svc_class_id_list[0] = UUID_SERVCLASS_PBAP_PCE; + result &= SDP_AddServiceClassIdList(sdp_handle, BTA_PBA_CLIENT_NUM_SVC_ELEMS, svc_class_id_list); + + /* add service name */ + if (p_service_name != NULL && p_service_name[0] != 0) { + result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE, + (UINT32)(strlen(p_service_name) + 1), (UINT8 *) p_service_name); + } + + /* add profile descriptor list */ + profile_uuid = UUID_SERVCLASS_PHONE_ACCESS; + version = PBAP_PCE_VERSION; + result &= SDP_AddProfileDescriptorList(sdp_handle, profile_uuid, version); + + return result; +} + +/******************************************************************************* +** +** Function bta_pba_client_create_record +** +** Description Create SDP record for registered service. +** +** +** Returns void +** +*******************************************************************************/ +void bta_pba_client_create_record(const char *p_service_name) +{ + /* add sdp record if not already registered */ + if (bta_pba_client_cb.sdp_handle == 0) { + bta_pba_client_cb.sdp_handle = SDP_CreateRecord(); + bta_pba_client_add_record(p_service_name, bta_pba_client_cb.sdp_handle); + bta_sys_add_uuid(UUID_SERVCLASS_PBAP_PCE); + } + +} + +/******************************************************************************* +** +** Function bta_pba_client_del_record +** +** Description Delete SDP record for registered service. +** +** +** Returns void +** +*******************************************************************************/ +void bta_pba_client_del_record(void) +{ + APPL_TRACE_DEBUG("bta_pba_client_del_record"); + + if (bta_pba_client_cb.sdp_handle != 0) { + SDP_DeleteRecord(bta_pba_client_cb.sdp_handle); + bta_pba_client_cb.sdp_handle = 0; + bta_sys_remove_uuid(UUID_SERVCLASS_PBAP_PCE); + } +} + +/******************************************************************************* +** +** Function bta_pba_client_sdp_find_attr +** +** Description Process SDP discovery results to find requested attribute +** +** +** Returns TRUE if results found, FALSE otherwise. +** +*******************************************************************************/ +BOOLEAN bta_pba_client_sdp_find_attr(tBTA_PBA_CLIENT_CCB *p_ccb) +{ + tSDP_DISC_REC *p_rec = NULL; + tSDP_DISC_ATTR *p_attr; + tSDP_PROTOCOL_ELEM pe; + BOOLEAN result = FALSE; + + /* loop through all records we found */ + while (TRUE) { + /* get next record; if none found, we're done */ + if ((p_rec = SDP_FindServiceInDb(p_ccb->p_disc_db, UUID_SERVCLASS_PBAP_PSE, p_rec)) == NULL) { + break; + } + + /* get rfcomm scn from proto desc list */ + if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) { + p_ccb->peer_rfcomm_scn = (UINT8) pe.params[0]; + } + else { + /* not found, go to next record */ + continue; + } + + /* get supported repositories */ + if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_REPOSITORIES)) != NULL) { + /* Found attribute, get value */ + p_ccb->peer_supported_repo = p_attr->attr_value.v.u8; + } + else { + /* not found, clear rfcomm scn and go to next record */ + p_ccb->peer_rfcomm_scn = 0; + continue; + } + + /* get profile version */ + SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_PHONE_ACCESS, &p_ccb->peer_version); + + /* get GOEP L2CAP PSM */ + if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_GOEP_L2CAP_PSM)) != NULL) { + /* Found attribute, get value */ + p_ccb->peer_l2cap_psm = p_attr->attr_value.v.u16; + } + + /* try to get supported features */ + if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_PBAP_SUPPORTED_FEATURES)) != NULL) { + /* found attribute, get value */ + p_ccb->peer_supported_feat = p_attr->attr_value.v.u32; + p_ccb->send_supported_feat = TRUE; + } + else { + /* assume as default value if not found in sdp record */ + p_ccb->peer_supported_feat = BTA_PBAP_DEFAULT_SUPPORTED_FEATURES; + p_ccb->send_supported_feat = FALSE; + } + + /* found what we needed */ + result = TRUE; + break; + } + + APPL_TRACE_DEBUG("%s peer_version:0x%x, supported repositories:0x%x, supported features:0x%x", + __FUNCTION__, p_ccb->peer_version, p_ccb->peer_supported_repo, p_ccb->peer_supported_feat); + + return result; +} + +/******************************************************************************* +** +** Function bta_pba_client_do_disc +** +** Description Do service discovery. +** +** +** Returns TRUE if start service discovery successfully +** +*******************************************************************************/ +BOOLEAN bta_pba_client_do_disc(tBTA_PBA_CLIENT_CCB *p_ccb) +{ + tSDP_UUID uuid_list[1]; + UINT16 num_uuid = 1; + UINT16 attr_list[6]; + UINT8 num_attr = 6; + BOOLEAN db_inited = FALSE; + + /* get proto list and features */ + attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST; + attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST; + attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST; + attr_list[3] = ATTR_ID_GOEP_L2CAP_PSM; + attr_list[4] = ATTR_ID_SUPPORTED_REPOSITORIES; + attr_list[5] = ATTR_ID_PBAP_SUPPORTED_FEATURES; + uuid_list[0].uu.uuid16 = UUID_SERVCLASS_PBAP_PSE; + uuid_list[0].len = LEN_UUID_16; + + if (p_ccb->p_disc_db != NULL) { + APPL_TRACE_WARNING("%s service discovery already in progress", __FUNCTION__); + return FALSE; + } + + /* allocate buffer for sdp database */ + p_ccb->p_disc_db = (tSDP_DISCOVERY_DB *) osi_malloc(BT_DEFAULT_BUFFER_SIZE); + + if (p_ccb->p_disc_db) { + /* set up service discovery database; attr happens to be attr_list len */ + db_inited = SDP_InitDiscoveryDb(p_ccb->p_disc_db, BT_DEFAULT_BUFFER_SIZE, num_uuid, + uuid_list, num_attr, attr_list); + } + + if (db_inited) { + /*start service discovery */ + /* todo: avoid p_ccb being free during sdp */ + db_inited = SDP_ServiceSearchAttributeRequest2(p_ccb->bd_addr, p_ccb->p_disc_db, + bta_pba_client_sdp_cback, p_ccb); + } + + if (!db_inited) { + /*free discover db */ + bta_pba_client_free_db(p_ccb); + APPL_TRACE_ERROR("%s start service discovery failed", __FUNCTION__); + return FALSE; + } + return TRUE; +} + +/******************************************************************************* +** +** Function bta_hf_client_free_db +** +** Description Free discovery database. +** +** +** Returns void +** +*******************************************************************************/ +void bta_pba_client_free_db(tBTA_PBA_CLIENT_CCB *p_ccb) +{ + if (p_ccb->p_disc_db != NULL) { + osi_free(p_ccb->p_disc_db); + p_ccb->p_disc_db = NULL; + } +} + +#endif diff --git a/lib/bt/host/bluedroid/bta/pba/include/bta_pba_client_int.h b/lib/bt/host/bluedroid/bta/pba/include/bta_pba_client_int.h new file mode 100644 index 00000000..5d48eab9 --- /dev/null +++ b/lib/bt/host/bluedroid/bta/pba/include/bta_pba_client_int.h @@ -0,0 +1,177 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "osi/list.h" +#include "common/bt_target.h" +#include "stack/sdp_api.h" +#include "stack/obex_api.h" +#include "bta/bta_sys.h" +#include "bta/bta_api.h" +#include "bta/bta_pba_client_api.h" + +#if BTA_PBA_CLIENT_INCLUDED + +#define PBA_CLIENT_MAX_CONNECTION 2 + +#define PBA_CLIENT_MAX_MTU L2CAP_MTU_SIZE /* RFCOMM is base on L2CAP, its MTU will smaller than this */ +#define PBA_CLIENT_MIN_MTU 255 + +enum { + /* these events are handled by the state machine */ + BTA_PBA_CLIENT_API_OPEN_EVT = BTA_SYS_EVT_START(BTA_ID_PBC), + BTA_PBA_CLIENT_API_CLOSE_EVT, + BTA_PBA_CLIENT_API_REQ_EVT, + BTA_PBA_CLIENT_DISC_RES_EVT, + BTA_PBA_CLIENT_AUTHENTICATE_EVT, + BTA_PBA_CLIENT_CONNECT_EVT, + BTA_PBA_CLIENT_RESPONSE_EVT, + BTA_PBA_CLIENT_RESPONSE_FINAL_EVT, + BTA_PBA_CLIENT_GOEP_CONNECT_EVT, + BTA_PBA_CLIENT_GOEP_DISCONNECT_EVT, + + /* these events are handled outside of the state machine */ + BTA_PBA_CLIENT_API_ENABLE_EVT, + BTA_PBA_CLIENT_API_DISABLE_EVT, + BTA_PBA_CLIENT_API_REGISTER_EVT, + BTA_PBA_CLIENT_API_DEREGISTER_EVT, +}; + +typedef enum { + BTA_PBA_CLIENT_OP_PULL_PHONE_BOOK, + BTA_PBA_CLIENT_OP_SET_PHONE_BOOK, + BTA_PBA_CLIENT_OP_PULL_VCARD_LISTING, + BTA_PBA_CLIENT_OP_PULL_VCARD_ENTRY, +} tBTA_PBA_CLIENT_OP; + +typedef struct { + BT_HDR hdr; + tBTA_PBA_CLIENT_CBACK *p_cback; +} tBTA_PBA_CLIENT_API_ENABLE; + +typedef struct { + BT_HDR hdr; + char name[BTA_SERVICE_NAME_LEN + 1]; +} tBTA_PBA_CLIENT_API_REGISTER; + +typedef struct { + BT_HDR hdr; + BD_ADDR bd_addr; + tBTA_SEC sec_mask; + UINT16 mtu; + UINT32 supported_feat; +} tBTA_PBA_CLIENT_API_OPEN; + +typedef struct { + BT_HDR hdr; + UINT8 operation; + UINT8 flags; + char *name; + UINT16 app_param_len; + UINT8 *app_param; +} tBTA_PBA_CLIENT_API_REQ; + +typedef struct { + BT_HDR hdr; + UINT16 status; +} tBTA_PBA_CLIENT_DISC_RESULT; + +typedef struct { + BT_HDR hdr; + UINT16 our_mtu; + UINT16 peer_mtu; +} tBTA_PBA_CLIENT_GOEP_CONNECT; + +typedef struct { + BT_HDR hdr; + UINT16 reason; +} tBTA_PBA_CLIENT_GOEP_DISCONNECT; + +typedef struct { + BT_HDR hdr; + BT_HDR *pkt; + UINT8 opcode; + BOOLEAN srm_en; + BOOLEAN srm_wait; +} tBTA_PBA_CLIENT_GOEP_RESPONSE; + +typedef union { + BT_HDR hdr; + tBTA_PBA_CLIENT_API_ENABLE api_enable; + tBTA_PBA_CLIENT_API_REGISTER api_register; + tBTA_PBA_CLIENT_API_OPEN api_open; + tBTA_PBA_CLIENT_API_REQ api_req; + tBTA_PBA_CLIENT_DISC_RESULT disc_result; + tBTA_PBA_CLIENT_GOEP_CONNECT goep_connect; + tBTA_PBA_CLIENT_GOEP_DISCONNECT goep_disconnect; + tBTA_PBA_CLIENT_GOEP_RESPONSE goep_response; +} tBTA_PBA_CLIENT_DATA; + +typedef struct { + BD_ADDR bd_addr; /* peer BD address */ + tSDP_DISCOVERY_DB *p_disc_db; /* pointer to discovery database */ + tBTA_SEC sec_mask; /* security mask */ + UINT16 peer_version; /* peer profile version */ + UINT16 peer_l2cap_psm; /* peer l2cap psm */ + UINT8 peer_rfcomm_scn; /* peer rfcomm scn */ + UINT8 peer_supported_repo; /* peer supported repositories */ + UINT32 peer_supported_feat; /* peer supported features */ + UINT32 our_supported_feat; /* we supported features */ + BOOLEAN send_supported_feat; /* whether we should send supported features in connect request */ + UINT16 goep_handle; /* goep connection handle */ + UINT32 goep_cid; /* goep connection id */ + UINT16 max_rx; /* max rx bytes */ + UINT16 max_tx; /* max tx bytes */ + BOOLEAN authenticate; /* whether we are authenticated */ + tBTA_PBA_CLIENT_OP operation; /* ongoing or last operations */ + UINT8 state; /* main state machine */ + UINT8 allocated; /* index + 1 if allocated, otherwise 0 */ +} tBTA_PBA_CLIENT_CCB; + +typedef struct { + tBTA_PBA_CLIENT_CCB ccb[PBA_CLIENT_MAX_CONNECTION]; /* connection control block */ + tBTA_PBA_CLIENT_CBACK *p_cback; /* message callback to upper */ + UINT32 sdp_handle; /* sdp record handle */ + UINT8 trace_level; /* debug trace level */ +} tBTA_PBA_CLIENT_CB; + +#if BTA_DYNAMIC_MEMORY == FALSE +extern tBTA_PBA_CLIENT_CB bta_pba_client_cb; +#else +extern tBTA_PBA_CLIENT_CB *bta_pba_client_cb_ptr; +#define bta_pba_client_cb (*bta_pba_client_cb_ptr) +#endif + +extern void bta_pba_client_api_enable(tBTA_PBA_CLIENT_DATA *p_data); +extern void bta_pba_client_api_disable(tBTA_PBA_CLIENT_DATA *p_data); +extern void bta_pba_client_api_register(tBTA_PBA_CLIENT_DATA *p_data); +extern void bta_pba_client_api_deregister(tBTA_PBA_CLIENT_DATA *p_data); +extern void bta_pba_client_api_open(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data); +extern void bta_pba_client_api_close(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data); +extern void bta_pba_client_api_req(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data); +extern void bta_pba_client_do_connect(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data); +extern void bta_pba_client_authenticate(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data); +extern void bta_pba_client_force_disconnect(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data); + +extern void bta_pba_client_connect(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data); +extern void bta_pba_client_response(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data); +extern void bta_pba_client_response_final(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data); +void bta_pba_client_goep_connect(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data); +void bta_pba_client_goep_disconnect(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data); +void bta_pba_client_free_response(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data); +void bta_pba_client_free_sdp_db(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p_data); + +extern void bta_pba_client_create_record(const char *p_service_name); +extern void bta_pba_client_del_record(void); +extern BOOLEAN bta_pba_client_sdp_find_attr(tBTA_PBA_CLIENT_CCB *p_ccb); +extern BOOLEAN bta_pba_client_do_disc(tBTA_PBA_CLIENT_CCB *p_ccb); +extern void bta_pba_client_free_db(tBTA_PBA_CLIENT_CCB *p_ccb); + +extern void bta_pba_client_sm_execute(tBTA_PBA_CLIENT_CCB *p_ccb, UINT16 event, tBTA_PBA_CLIENT_DATA *p_data); +extern BOOLEAN bta_pba_client_hdl_event(BT_HDR *p_msg); + +#endif diff --git a/lib/bt/host/bluedroid/bta/sdp/bta_sdp.c b/lib/bt/host/bluedroid/bta/sdp/bta_sdp.c index 4deabe9a..71773d98 100644 --- a/lib/bt/host/bluedroid/bta/sdp/bta_sdp.c +++ b/lib/bt/host/bluedroid/bta/sdp/bta_sdp.c @@ -49,10 +49,11 @@ typedef void (*tBTA_SDP_ACTION)(tBTA_SDP_MSG *p_data); /* action function list */ const tBTA_SDP_ACTION bta_sdp_action[] = { - bta_sdp_enable, /* BTA_SDP_API_ENABLE_EVT */ - bta_sdp_search, /* BTA_SDP_API_SEARCH_EVT */ - bta_sdp_create_record, /* BTA_SDP_API_CREATE_RECORD_USER_EVT */ - bta_sdp_remove_record, /* BTA_SDP_API_REMOVE_RECORD_USER_EVT */ + bta_sdp_enable, /* BTA_SDP_API_ENABLE_EVT */ + bta_sdp_search, /* BTA_SDP_API_SEARCH_EVT */ + bta_sdp_create_record, /* BTA_SDP_API_CREATE_RECORD_USER_EVT */ + bta_sdp_remove_record, /* BTA_SDP_API_REMOVE_RECORD_USER_EVT */ + bta_sdp_disable, /* BTA_SDP_API_DISABLE_EVT */ }; /******************************************************************************* diff --git a/lib/bt/host/bluedroid/bta/sdp/bta_sdp_act.c b/lib/bt/host/bluedroid/bta/sdp/bta_sdp_act.c index 70aa00ba..045672f0 100644 --- a/lib/bt/host/bluedroid/bta/sdp/bta_sdp_act.c +++ b/lib/bt/host/bluedroid/bta/sdp/bta_sdp_act.c @@ -40,31 +40,6 @@ #if (SDP_INCLUDED == TRUE) -/***************************************************************************** -** Constants -*****************************************************************************/ - -static const uint8_t UUID_OBEX_OBJECT_PUSH[] = {0x00, 0x00, 0x11, 0x05, 0x00, 0x00, 0x10, 0x00, - 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB - }; -static const uint8_t UUID_PBAP_PSE[] = {0x00, 0x00, 0x11, 0x2F, 0x00, 0x00, 0x10, 0x00, - 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB - }; -static const uint8_t UUID_PBAP_PCE[] = {0x00, 0x00, 0x11, 0x2E, 0x00, 0x00, 0x10, 0x00, - 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB - }; -static const uint8_t UUID_MAP_MAS[] = {0x00, 0x00, 0x11, 0x32, 0x00, 0x00, 0x10, 0x00, - 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB - }; -static const uint8_t UUID_MAP_MNS[] = {0x00, 0x00, 0x11, 0x33, 0x00, 0x00, 0x10, 0x00, - 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB - }; -static const uint8_t UUID_SPP[] = {0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00, - 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB - }; -static const uint8_t UUID_SAP[] = {0x00, 0x00, 0x11, 0x2D, 0x00, 0x00, 0x10, 0x00, - 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB - }; // TODO: // Both the fact that the UUIDs are declared in multiple places, plus the fact // that there is a mess of UUID comparison and shortening methods will have to @@ -140,6 +115,47 @@ static void bta_create_mns_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_RE } } +static void bta_create_dip_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec) +{ + tSDP_DISC_ATTR *p_attr; + UINT16 pversion = -1; + + record->dip.hdr.type = SDP_TYPE_DIP_SERVER; + record->dip.hdr.service_name_length = 0; + record->dip.hdr.service_name = NULL; + record->dip.hdr.rfcomm_channel_number = 0; + record->dip.hdr.l2cap_psm = -1; + record->dip.hdr.profile_version = 0; + + p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_VENDOR_ID); + if (p_attr) { + record->dip.vendor = p_attr->attr_value.v.u16; + } + + p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_VENDOR_ID_SOURCE); + if (p_attr) { + record->dip.vendor_id_source = p_attr->attr_value.v.u16; + } + p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_PRODUCT_ID); + if (p_attr) { + record->dip.product = p_attr->attr_value.v.u16; + } + + p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_PRODUCT_VERSION); + if (p_attr) { + record->dip.version = p_attr->attr_value.v.u16; + } + + p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_PRIMARY_RECORD); + if (p_attr) { + record->dip.primary_record = (BOOLEAN)p_attr->attr_value.v.u8; + } + + if (SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_PNP_INFORMATION, &pversion)) { + record->dip.hdr.profile_version = pversion; + } +} + static void bta_create_mas_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec) { tSDP_DISC_ATTR *p_attr; @@ -328,7 +344,7 @@ static void bta_create_sap_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_RE tSDP_PROTOCOL_ELEM pe; UINT16 pversion = -1; - record->sap.hdr.type = SDP_TYPE_MAP_MAS; + record->sap.hdr.type = SDP_TYPE_SAP_SERVER; record->sap.hdr.service_name_length = 0; record->sap.hdr.service_name = NULL; record->sap.hdr.rfcomm_channel_number = 0; @@ -354,31 +370,40 @@ static void bta_create_raw_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_RE tSDP_DISC_ATTR *p_attr; tSDP_PROTOCOL_ELEM pe; - record->hdr.type = SDP_TYPE_RAW; - record->hdr.service_name_length = 0; - record->hdr.service_name = NULL; - record->hdr.rfcomm_channel_number = -1; - record->hdr.l2cap_psm = -1; - record->hdr.profile_version = -1; + record->raw.hdr.type = SDP_TYPE_RAW; + record->raw.hdr.service_name_length = 0; + record->raw.hdr.service_name = NULL; + record->raw.hdr.rfcomm_channel_number = -1; + record->raw.hdr.l2cap_psm = -1; + record->raw.hdr.profile_version = -1; /* Try to extract a service name */ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME)) != NULL) { - record->pse.hdr.service_name_length = SDP_DISC_ATTR_LEN(p_attr->attr_len_type); - record->pse.hdr.service_name = (char *)p_attr->attr_value.v.array; + record->raw.hdr.service_name_length = SDP_DISC_ATTR_LEN(p_attr->attr_len_type); + record->raw.hdr.service_name = (char *)p_attr->attr_value.v.array; } if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_GOEP_L2CAP_PSM)) != NULL) { - record->hdr.l2cap_psm = p_attr->attr_value.v.u16; + record->raw.hdr.l2cap_psm = p_attr->attr_value.v.u16; } /* Try to extract an RFCOMM channel */ if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) { - record->pse.hdr.rfcomm_channel_number = pe.params[0]; + record->raw.hdr.rfcomm_channel_number = pe.params[0]; } - record->hdr.user1_ptr_len = p_bta_sdp_cfg->p_sdp_db->raw_size; - record->hdr.user1_ptr = p_bta_sdp_cfg->p_sdp_db->raw_data; + record->raw.hdr.user1_ptr_len = p_bta_sdp_cfg->p_sdp_db->raw_used; + record->raw.hdr.user1_ptr = p_bta_sdp_cfg->p_sdp_db->raw_data; } +static bool check_if_uuid16_match(UINT16 uuid16, tBT_UUID *uuid) +{ + // Because it is converted to a short UUID, only uuid16 needs to be checked. + if (uuid->len == 2 && uuid->uu.uuid16 == uuid16) { + return TRUE; + } else { + return FALSE; + } +} /******************************************************************************* ** @@ -415,22 +440,25 @@ static void bta_sdp_search_cback(UINT16 result, void *user_data) /* generate the matching record data pointer */ if (p_rec != NULL) { status = BTA_SDP_SUCCESS; - if (IS_UUID(UUID_MAP_MAS, uuid->uu.uuid128)) { + if (check_if_uuid16_match(UUID_SERVCLASS_PNP_INFORMATION, &su)) { + APPL_TRACE_DEBUG("%s() - found DIP uuid\n", __func__); + bta_create_dip_sdp_record(&evt_data.records[count], p_rec); + } else if (check_if_uuid16_match(UUID_SERVCLASS_MESSAGE_ACCESS, &su)) { APPL_TRACE_DEBUG("%s() - found MAP (MAS) uuid\n", __func__); bta_create_mas_sdp_record(&evt_data.records[count], p_rec); - } else if (IS_UUID(UUID_MAP_MNS, uuid->uu.uuid128)) { + } else if (check_if_uuid16_match(UUID_SERVCLASS_MESSAGE_NOTIFICATION, &su)) { APPL_TRACE_DEBUG("%s() - found MAP (MNS) uuid\n", __func__); bta_create_mns_sdp_record(&evt_data.records[count], p_rec); - } else if (IS_UUID(UUID_PBAP_PSE, uuid->uu.uuid128)) { + } else if (check_if_uuid16_match(UUID_SERVCLASS_PBAP_PSE, &su)) { APPL_TRACE_DEBUG("%s() - found PBAP (PSE) uuid\n", __func__); bta_create_pse_sdp_record(&evt_data.records[count], p_rec); - } else if (IS_UUID(UUID_PBAP_PCE, uuid->uu.uuid128)) { + } else if (check_if_uuid16_match(UUID_SERVCLASS_PBAP_PCE, &su)) { APPL_TRACE_DEBUG("%s() - found PBAP (PCE) uuid\n", __func__); bta_create_pce_sdp_record(&evt_data.records[count], p_rec); - } else if (IS_UUID(UUID_OBEX_OBJECT_PUSH, uuid->uu.uuid128)) { + } else if (check_if_uuid16_match(UUID_SERVCLASS_OBEX_OBJECT_PUSH, &su)) { APPL_TRACE_DEBUG("%s() - found Object Push Server (OPS) uuid\n", __func__); bta_create_ops_sdp_record(&evt_data.records[count], p_rec); - } else if (IS_UUID(UUID_SAP, uuid->uu.uuid128)) { + } else if (check_if_uuid16_match(UUID_SERVCLASS_SAP, &su)) { APPL_TRACE_DEBUG("%s() - found SAP uuid\n", __func__); bta_create_sap_sdp_record(&evt_data.records[count], p_rec); } else { @@ -526,6 +554,10 @@ void bta_sdp_search(tBTA_SDP_MSG *p_data) SDP_InitDiscoveryDb (p_bta_sdp_cfg->p_sdp_db, p_bta_sdp_cfg->sdp_db_size, 1, bta_sdp_search_uuid, 0, NULL); + /* tell SDP to keep the raw data */ + p_bta_sdp_cfg->p_sdp_db->raw_size = p_bta_sdp_cfg->sdp_raw_size; + p_bta_sdp_cfg->p_sdp_db->raw_data = p_bta_sdp_cfg->p_sdp_raw_data; + if (!SDP_ServiceSearchAttributeRequest2(p_data->get_search.bd_addr, p_bta_sdp_cfg->p_sdp_db, bta_sdp_search_cback, (void *)bta_sdp_search_uuid)) { bta_sdp_cb.sdp_active = BTA_SDP_ACTIVE_NONE; @@ -558,7 +590,7 @@ void bta_sdp_create_record(tBTA_SDP_MSG *p_data) APPL_TRACE_DEBUG("%s() event: %d\n", __func__, p_data->record.hdr.event); tBTA_SDP_CREATE_RECORD_USER bta_sdp = {0}; bta_sdp.status = BTA_SDP_SUCCESS; - bta_sdp.handle = (int)p_data->record.user_data; + bta_sdp.handle = -1; if (bta_sdp_cb.p_dm_cback) { bta_sdp_cb.p_dm_cback(BTA_SDP_CREATE_RECORD_USER_EVT, (tBTA_SDP *)&bta_sdp, p_data->record.user_data); } @@ -576,10 +608,30 @@ void bta_sdp_create_record(tBTA_SDP_MSG *p_data) void bta_sdp_remove_record(tBTA_SDP_MSG *p_data) { APPL_TRACE_DEBUG("%s() event: %d\n", __func__, p_data->record.hdr.event); + tBTA_SDP_REMOVE_RECORD_USER bta_sdp; + bta_sdp.status = BTA_SDP_SUCCESS; + bta_sdp.handle = -1; + if (bta_sdp_cb.p_dm_cback) { + bta_sdp_cb.p_dm_cback(BTA_SDP_REMOVE_RECORD_USER_EVT, (tBTA_SDP *)&bta_sdp, p_data->record.user_data); + } +} + +/******************************************************************************* +** +** Function bta_sdp_disable +** +** Description Removes an SDP record +** +** Returns void +** +*******************************************************************************/ +void bta_sdp_disable(tBTA_SDP_MSG *p_data) +{ + APPL_TRACE_DEBUG("%s()\n", __func__); tBTA_SDP bta_sdp; bta_sdp.status = BTA_SDP_SUCCESS; if (bta_sdp_cb.p_dm_cback) { - bta_sdp_cb.p_dm_cback(BTA_SDP_REMOVE_RECORD_USER_EVT, &bta_sdp, p_data->record.user_data); + bta_sdp_cb.p_dm_cback(BTA_SDP_DISABLE_EVT, &bta_sdp, NULL); } } diff --git a/lib/bt/host/bluedroid/bta/sdp/bta_sdp_api.c b/lib/bt/host/bluedroid/bta/sdp/bta_sdp_api.c index cafb1a4a..d46f784b 100644 --- a/lib/bt/host/bluedroid/bta/sdp/bta_sdp_api.c +++ b/lib/bt/host/bluedroid/bta/sdp/bta_sdp_api.c @@ -65,7 +65,9 @@ tBTA_SDP_STATUS BTA_SdpEnable(tBTA_SDP_DM_CBACK *p_cback) #if BTA_DYNAMIC_MEMORY == TRUE /* Malloc buffer for SDP configuration structure */ p_bta_sdp_cfg->p_sdp_db = (tSDP_DISCOVERY_DB *)osi_malloc(p_bta_sdp_cfg->sdp_db_size); - if (p_bta_sdp_cfg->p_sdp_db == NULL) { + p_bta_sdp_cfg->p_sdp_raw_data = (UINT8 *)osi_malloc(p_bta_sdp_cfg->sdp_raw_size); + if (p_bta_sdp_cfg->p_sdp_db == NULL || p_bta_sdp_cfg->p_sdp_raw_data == NULL) { + BTA_SdpCleanup(); return BTA_SDP_FAILURE; } #endif @@ -101,15 +103,34 @@ tBTA_SDP_STATUS BTA_SdpEnable(tBTA_SDP_DM_CBACK *p_cback) *******************************************************************************/ tBTA_SDP_STATUS BTA_SdpDisable(void) { + BT_HDR *p_buf = NULL; tBTA_SDP_STATUS status = BTA_SDP_SUCCESS; + if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_SDP_API_DISABLE_EVT; + bta_sys_sendmsg(p_buf); + status = BTA_SDP_FAILURE; + } + + return status; +} + +tBTA_SDP_STATUS BTA_SdpCleanup(void) +{ bta_sys_deregister(BTA_ID_SDP); #if BTA_DYNAMIC_MEMORY == TRUE /* Free buffer for SDP configuration structure */ - osi_free(p_bta_sdp_cfg->p_sdp_db); - p_bta_sdp_cfg->p_sdp_db = NULL; + if (p_bta_sdp_cfg->p_sdp_db) { + osi_free(p_bta_sdp_cfg->p_sdp_db); + p_bta_sdp_cfg->p_sdp_db = NULL; + } + + if (p_bta_sdp_cfg->p_sdp_raw_data) { + osi_free(p_bta_sdp_cfg->p_sdp_raw_data); + p_bta_sdp_cfg->p_sdp_raw_data = NULL; + } #endif - return (status); + return BTA_SDP_SUCCESS; } /******************************************************************************* diff --git a/lib/bt/host/bluedroid/bta/sdp/bta_sdp_cfg.c b/lib/bt/host/bluedroid/bta/sdp/bta_sdp_cfg.c index 322b25ca..423905bc 100644 --- a/lib/bt/host/bluedroid/bta/sdp/bta_sdp_cfg.c +++ b/lib/bt/host/bluedroid/bta/sdp/bta_sdp_cfg.c @@ -30,16 +30,24 @@ #define BTA_SDP_DB_SIZE 1500 #endif +#ifndef BTA_SDP_RAW_DATA_SIZE +#define BTA_SDP_RAW_DATA_SIZE 1024 +#endif + #if BTA_DYNAMIC_MEMORY == FALSE +static UINT8 bta_sdp_raw_data[BTA_SDP_RAW_DATA_SIZE]; static UINT8 __attribute__ ((aligned(4))) bta_sdp_db_data[BTA_SDP_DB_SIZE]; #endif /* SDP configuration structure */ tBTA_SDP_CFG bta_sdp_cfg = { + BTA_SDP_RAW_DATA_SIZE, BTA_SDP_DB_SIZE, #if BTA_DYNAMIC_MEMORY == FALSE + bta_sdp_raw_data, (tSDP_DISCOVERY_DB *)bta_sdp_db_data /* The data buffer to keep SDP database */ #else + NULL, NULL #endif }; diff --git a/lib/bt/host/bluedroid/bta/sdp/include/bta_sdp_int.h b/lib/bt/host/bluedroid/bta/sdp/include/bta_sdp_int.h index cf0eb99c..f350ae37 100644 --- a/lib/bt/host/bluedroid/bta/sdp/include/bta_sdp_int.h +++ b/lib/bt/host/bluedroid/bta/sdp/include/bta_sdp_int.h @@ -42,6 +42,7 @@ enum { BTA_SDP_API_SEARCH_EVT, BTA_SDP_API_CREATE_RECORD_USER_EVT, BTA_SDP_API_REMOVE_RECORD_USER_EVT, + BTA_SDP_API_DISABLE_EVT, BTA_SDP_MAX_INT_EVT }; @@ -105,6 +106,7 @@ extern void bta_sdp_enable (tBTA_SDP_MSG *p_data); extern void bta_sdp_search (tBTA_SDP_MSG *p_data); extern void bta_sdp_create_record(tBTA_SDP_MSG *p_data); extern void bta_sdp_remove_record(tBTA_SDP_MSG *p_data); +extern void bta_sdp_disable(tBTA_SDP_MSG *p_data); #endif ///SDP_INCLUDED == TRUE diff --git a/lib/bt/host/bluedroid/bta/sys/utl.c b/lib/bt/host/bluedroid/bta/sys/utl.c index c18567cd..94348e85 100644 --- a/lib/bt/host/bluedroid/bta/sys/utl.c +++ b/lib/bt/host/bluedroid/bta/sys/utl.c @@ -170,11 +170,12 @@ void utl_freebuf(void **p) ** p_cod - Pointer to the device class to set to ** ** cmd - the fields of the device class to update. +** BTA_UTL_SET_COD_RESERVED_2 - overwrite the two least significant bits reserved_2 ** BTA_UTL_SET_COD_MAJOR_MINOR, - overwrite major, minor class ** BTA_UTL_SET_COD_SERVICE_CLASS - set the bits in the input ** BTA_UTL_CLR_COD_SERVICE_CLASS - clear the bits in the input -** BTA_UTL_SET_COD_ALL - overwrite major, minor, set the bits in service class -** BTA_UTL_INIT_COD - overwrite major, minor, and service class +** BTA_UTL_SET_COD_ALL - overwrite major, minor, set the bits in service class, reserved_2 remain unchanged +** BTA_UTL_INIT_COD - overwrite major, minor, and service class, reserved_2 remain unchanged ** ** Returns TRUE if successful, Otherwise FALSE ** @@ -183,15 +184,19 @@ BOOLEAN utl_set_device_class(tBTA_UTL_COD *p_cod, UINT8 cmd) { UINT8 *dev; UINT16 service; - UINT8 minor, major; + UINT8 minor, major, reserved_2; DEV_CLASS dev_class; dev = BTM_ReadDeviceClass(); BTM_COD_SERVICE_CLASS( service, dev ); BTM_COD_MINOR_CLASS(minor, dev ); BTM_COD_MAJOR_CLASS(major, dev ); + BTM_COD_RESERVED_2(reserved_2, dev); switch (cmd) { + case BTA_UTL_SET_COD_RESERVED_2: + reserved_2 = p_cod->reserved_2 & BTM_COD_RESERVED_2_MASK; + break; case BTA_UTL_SET_COD_MAJOR_MINOR: minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK; major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK; @@ -226,7 +231,7 @@ BOOLEAN utl_set_device_class(tBTA_UTL_COD *p_cod, UINT8 cmd) } /* convert the fields into the device class type */ - FIELDS_TO_COD(dev_class, minor, major, service); + FIELDS_TO_COD(dev_class, reserved_2, minor, major, service); if (BTM_SetDeviceClass(dev_class) == BTM_SUCCESS) { return TRUE; @@ -252,16 +257,18 @@ BOOLEAN utl_get_device_class(tBTA_UTL_COD *p_cod) { UINT8 *dev; UINT16 service; - UINT8 minor, major; + UINT8 minor, major, reserved_2; dev = BTM_ReadDeviceClass(); BTM_COD_SERVICE_CLASS( service, dev ); BTM_COD_MINOR_CLASS(minor, dev ); BTM_COD_MAJOR_CLASS(major, dev ); + BTM_COD_RESERVED_2(reserved_2, dev ); p_cod->minor = minor; p_cod->major = major; p_cod->service = service; + p_cod->reserved_2 = reserved_2; return TRUE; } diff --git a/lib/bt/host/bluedroid/btc/core/btc_ble_storage.c b/lib/bt/host/bluedroid/btc/core/btc_ble_storage.c index 7df1bfe0..f20a7241 100644 --- a/lib/bt/host/bluedroid/btc/core/btc_ble_storage.c +++ b/lib/bt/host/bluedroid/btc/core/btc_ble_storage.c @@ -15,7 +15,7 @@ #if (SMP_INCLUDED == TRUE) -//the maximum nubmer of bonded devices +//the maximum number of bonded devices #define BONED_DEVICES_MAX_COUNT (BTM_SEC_MAX_DEVICE_RECORDS) static void _btc_storage_save(void) @@ -58,7 +58,7 @@ static void _btc_storage_save(void) addr_section_count ++; iter = btc_config_section_next(iter); } - /*exceeded the maximum nubmer of bonded devices, delete them */ + /*exceeded the maximum number of bonded devices, delete them */ if (need_remove_iter) { while(need_remove_iter != btc_config_section_end()) { const char *need_remove_section = btc_config_section_name(need_remove_iter); @@ -954,6 +954,7 @@ bt_status_t _btc_storage_in_fetch_bonded_ble_device(const char *remote_bd_addr, bt_status_t btc_storage_get_bonded_ble_devices_list(esp_ble_bond_dev_t *bond_dev, int dev_num) { bt_bdaddr_t bd_addr; + int addr_t; char buffer[sizeof(tBTM_LE_KEY_VALUE)] = {0}; btc_config_lock(); @@ -975,6 +976,14 @@ bt_status_t btc_storage_get_bonded_ble_devices_list(esp_ble_bond_dev_t *bond_dev string_to_bdaddr(name, &bd_addr); memcpy(bond_dev->bd_addr, bd_addr.address, sizeof(bt_bdaddr_t)); + //get address type + if (_btc_storage_get_remote_addr_type((bt_bdaddr_t *)bond_dev->bd_addr, &addr_t) == BT_STATUS_SUCCESS) { + bond_dev->bd_addr_type = (uint8_t) addr_t; + } else { + // Set an invalid address type + bond_dev->bd_addr_type = 0xFF; + BTC_TRACE_ERROR("%s, %s get address type fail", __func__, name); + } //resolve the peer device long term key if (_btc_storage_get_ble_bonding_key(&bd_addr, BTM_LE_KEY_PENC, buffer, sizeof(tBTM_LE_PENC_KEYS)) == BT_STATUS_SUCCESS) { bond_dev->bond_key.key_mask |= ESP_BLE_ENC_KEY_MASK; diff --git a/lib/bt/host/bluedroid/btc/core/btc_config.c b/lib/bt/host/bluedroid/btc/core/btc_config.c index f46aef89..e2cce6da 100644 --- a/lib/bt/host/bluedroid/btc/core/btc_config.c +++ b/lib/bt/host/bluedroid/btc/core/btc_config.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -29,6 +29,17 @@ static void btc_key_value_to_string(uint8_t *key_value, char *value_str, int key static osi_mutex_t lock; // protects operations on |config|. static config_t *config; + +int btc_config_file_path_get(char *file_path) +{ + if (file_path == NULL) { + return -1; + } + + strcpy(file_path, CONFIG_FILE_PATH); + return 0; +} + int btc_config_file_path_update(const char *file_path) { if (file_path != NULL && strlen(file_path) < NVS_NS_NAME_MAX_SIZE) { diff --git a/lib/bt/host/bluedroid/btc/core/btc_dm.c b/lib/bt/host/bluedroid/btc/core/btc_dm.c index 7e242a73..782569c2 100644 --- a/lib/bt/host/bluedroid/btc/core/btc_dm.c +++ b/lib/bt/host/bluedroid/btc/core/btc_dm.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -182,11 +182,12 @@ static void btc_dm_remove_ble_bonding_keys(void) btc_storage_remove_ble_bonding_keys(&bd_addr); } +#if BLE_SMP_BOND_NVS_FLASH static void btc_dm_save_ble_bonding_keys(void) { if (!(btc_dm_cb.pairing_cb.ble.is_penc_key_rcvd || btc_dm_cb.pairing_cb.ble.is_pid_key_rcvd || btc_dm_cb.pairing_cb.ble.is_pcsrk_key_rcvd || - btc_dm_cb.pairing_cb.ble.is_lenc_key_rcvd || btc_dm_cb.pairing_cb.ble.is_lcsrk_key_rcvd || btc_dm_cb.pairing_cb.ble.is_lidk_key_rcvd)) { - return ; + btc_dm_cb.pairing_cb.ble.is_lenc_key_rcvd || btc_dm_cb.pairing_cb.ble.is_lcsrk_key_rcvd || btc_dm_cb.pairing_cb.ble.is_lidk_key_rcvd)) { + return; } bt_bdaddr_t bd_addr; @@ -244,13 +245,13 @@ static void btc_dm_save_ble_bonding_keys(void) btc_dm_cb.pairing_cb.ble.is_lidk_key_rcvd = false; } } +#endif static void btc_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) { /* Save link key, if not temporary */ BTC_TRACE_DEBUG("%s, status = %d", __func__, p_auth_cmpl->success); bt_status_t status = BT_STATUS_FAIL; - int addr_type; bt_bdaddr_t bdaddr; bdcpy(bdaddr.address, p_auth_cmpl->bd_addr); bdcpy(btc_dm_cb.pairing_cb.bd_addr, p_auth_cmpl->bd_addr); @@ -266,6 +267,9 @@ static void btc_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) return; } +#if BLE_SMP_BOND_NVS_FLASH + int addr_type; + if (btc_dm_cb.pairing_cb.ble.is_pid_key_rcvd) { // delete unused section in NVS btc_storage_remove_unused_sections(p_auth_cmpl->bd_addr, &btc_dm_cb.pairing_cb.ble.pid_key); @@ -276,6 +280,7 @@ static void btc_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) } btc_storage_set_ble_dev_auth_mode(&bdaddr, p_auth_cmpl->auth_mode, true); btc_dm_save_ble_bonding_keys(); +#endif } else { /*Map the HCI fail reason to bt status */ switch (p_auth_cmpl->fail_reason) { @@ -288,6 +293,9 @@ static void btc_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) status = BT_STATUS_AUTH_REJECTED; break; default: + BTC_TRACE_WARNING ("%s, remove bond in flash bd_addr: %08x%04x", __func__, + (p_auth_cmpl->bd_addr[0] << 24) + (p_auth_cmpl->bd_addr[1] << 16) + (p_auth_cmpl->bd_addr[2] << 8) + p_auth_cmpl->bd_addr[3], + (p_auth_cmpl->bd_addr[4] << 8) + p_auth_cmpl->bd_addr[5]); btc_dm_remove_ble_bonding_keys(); status = BT_STATUS_FAIL; break; @@ -326,6 +334,7 @@ static void btc_dm_link_up_evt(tBTA_DM_LINK_UP *p_link_up) } } +#if (SMP_INCLUDED == TRUE) static void btc_dm_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) { /* Save link key, if not temporary */ @@ -485,6 +494,7 @@ static void btc_dm_pin_req_evt(tBTA_DM_PIN_REQ *p_pin_req) } #endif /// BTC_GAP_BT_INCLUDED == TRUE } +#endif // #if (SMP_INCLUDED == TRUE) #if (CLASSIC_BT_INCLUDED == TRUE) static void btc_dm_sp_cfm_req_evt(tBTA_DM_SP_CFM_REQ *p_cfm_req) @@ -625,6 +635,7 @@ static void btc_dm_pm_mode_chg_evt(tBTA_DM_MODE_CHG *p_mode_chg) msg->act = BTC_GAP_BT_MODE_CHG_EVT; memcpy(param.mode_chg.bda, p_mode_chg->bd_addr, ESP_BD_ADDR_LEN); param.mode_chg.mode = p_mode_chg->mode; + param.mode_chg.interval= p_mode_chg->interval; memcpy(msg->arg, ¶m, sizeof(esp_bt_gap_cb_param_t)); ret = btc_inter_profile_call(msg); @@ -707,10 +718,9 @@ bt_status_t btc_dm_disable_service(tBTA_SERVICE_ID service_id) return BT_STATUS_SUCCESS; } - +#if (BTC_GAP_BT_INCLUDED == TRUE) static void btc_dm_acl_link_stat(tBTA_DM_ACL_LINK_STAT *p_acl_link_stat) { -#if (BTC_GAP_BT_INCLUDED == TRUE) esp_bt_gap_cb_param_t param; esp_bt_gap_cb_event_t event = ESP_BT_GAP_EVT_MAX; bt_bdaddr_t bt_addr; @@ -752,8 +762,8 @@ static void btc_dm_acl_link_stat(tBTA_DM_ACL_LINK_STAT *p_acl_link_stat) if (cb) { cb(event, ¶m); } -#endif } +#endif void btc_dm_sec_cb_handler(btc_msg_t *msg) { @@ -805,6 +815,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) btc_disable_bluetooth_evt(); break; } +#if (SMP_INCLUDED == TRUE) case BTA_DM_PIN_REQ_EVT: BTC_TRACE_DEBUG("BTA_DM_PIN_REQ_EVT"); btc_dm_pin_req_evt(&p_data->pin_req); @@ -818,6 +829,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) case BTA_DM_BOND_CANCEL_CMPL_EVT: BTC_TRACE_DEBUG("BTA_DM_BOND_CANCEL_CMPL_EVT"); break; +#endif // #if (SMP_INCLUDED == TRUE) #if (CLASSIC_BT_INCLUDED == TRUE) case BTA_DM_SP_CFM_REQ_EVT: btc_dm_sp_cfm_req_evt(&p_data->cfm_req); @@ -838,7 +850,10 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) break; #endif /* BTM_OOB_INCLUDED == TRUE */ case BTA_DM_ACL_LINK_STAT_EVT: { +#if (BTC_GAP_BT_INCLUDED == TRUE) + btc_gap_bt_acl_link_num_update(&p_data->acl_link_stat); btc_dm_acl_link_stat(&p_data->acl_link_stat); +#endif break; } case BTA_DM_DEV_UNPAIRED_EVT: { diff --git a/lib/bt/host/bluedroid/btc/core/btc_main.c b/lib/bt/host/bluedroid/btc/core/btc_main.c index 28f70b4b..cee4c251 100644 --- a/lib/bt/host/bluedroid/btc/core/btc_main.c +++ b/lib/bt/host/bluedroid/btc/core/btc_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -60,6 +60,7 @@ static void btc_init_bluetooth(void) #if (BLE_INCLUDED == TRUE) //load the ble local key which has been stored in the flash btc_dm_load_ble_local_keys(); + bta_dm_co_security_param_init(); #endif ///BLE_INCLUDED == TRUE #endif /* #if (SMP_INCLUDED) */ #if BTA_DYNAMIC_MEMORY @@ -121,6 +122,11 @@ uint32_t btc_get_ble_status(void) { uint32_t status = BTC_BLE_STATUS_IDLE; + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + BTC_TRACE_ERROR("%s Bluedroid not enabled", __func__); + return status; + } + #if (BLE_INCLUDED == TRUE) // Number of active advertising extern uint8_t btm_ble_adv_active_count(void); @@ -140,11 +146,29 @@ uint32_t btc_get_ble_status(void) status |= BIT(BTC_BLE_STATUS_CONN); } + // Number of active ACL connection + extern uint8_t btm_ble_acl_active_count(void); + if (btm_ble_acl_active_count()) { + status |= BIT(BTC_BLE_STATUS_CONN); + } + + // Number of active L2C plcb + extern uint8_t l2cu_ble_plcb_active_count(void); + if (l2cu_ble_plcb_active_count()) { + status |= BIT(BTC_BLE_STATUS_CONN); + } + + // Address resolve status + extern uint8_t btm_get_ble_addr_resolve_disable_status(void); + if (btm_get_ble_addr_resolve_disable_status()) { + status |= BIT(BTC_BLE_STATUS_ADDR_RESOLVE_DISABLE); + } + #if (SMP_INCLUDED == TRUE) // Number of recorded devices - extern uint8_t btm_ble_sec_dev_active_count(void); - if (btm_ble_sec_dev_active_count()) { - status |= BIT(BTC_BLE_STATUS_KEYS); + extern uint8_t btm_ble_sec_dev_record_count(void); + if (btm_ble_sec_dev_record_count()) { + status |= BIT(BTC_BLE_STATUS_DEVICE_REC); } // Number of saved bonded devices @@ -170,18 +194,6 @@ uint32_t btc_get_ble_status(void) } #endif - // Number of active ACL connection - extern uint8_t btm_acl_active_count(void); - if (btm_acl_active_count()) { - status |= BIT(BTC_BLE_STATUS_CONN); - } - - // Number of active L2C plcb - extern uint8_t l2cu_plcb_active_count(void); - if (l2cu_plcb_active_count()) { - status |= BIT(BTC_BLE_STATUS_CONN); - } - #if (GATTC_INCLUDED == TRUE) // Number of registered GATTC APP extern uint8_t bta_gattc_cl_rcb_active_count(void); @@ -204,5 +216,12 @@ uint32_t btc_get_ble_status(void) } #endif + #if SMP_INCLUDED == TRUE + extern uint8_t smp_get_state(void); + if (smp_get_state()) { + status |= BIT(BTC_BLE_STATUS_SMP_STATE); + } + #endif + return status; } diff --git a/lib/bt/host/bluedroid/btc/core/btc_util.c b/lib/bt/host/bluedroid/btc/core/btc_util.c index 5e29aba8..e22efce3 100644 --- a/lib/bt/host/bluedroid/btc/core/btc_util.c +++ b/lib/bt/host/bluedroid/btc/core/btc_util.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -349,10 +349,10 @@ esp_bt_status_t btc_hci_to_esp_status(uint8_t hci_status) return esp_status; } -esp_bt_status_t btc_btm_status_to_esp_status (uint8_t btm_status) +esp_bt_status_t btc_btm_status_to_esp_status(uint8_t btm_status) { esp_bt_status_t esp_status = ESP_BT_STATUS_FAIL; - switch(btm_status){ + switch(btm_status) { case BTM_SUCCESS: esp_status = ESP_BT_STATUS_SUCCESS; break; @@ -381,14 +381,18 @@ esp_bt_status_t btc_btm_status_to_esp_status (uint8_t btm_status) esp_status = ESP_BT_STATUS_FAIL; break; default: - esp_status = ESP_BT_STATUS_FAIL; + if (btm_status & BTM_HCI_ERROR) { + esp_status = ESP_BT_STATUS_BASE_FOR_HCI_ERR | (btm_status & 0x7F); + } else { + esp_status = ESP_BT_STATUS_FAIL; + } break; } return esp_status; } -esp_bt_status_t btc_bta_status_to_esp_status (uint8_t bta_status) +esp_bt_status_t btc_bta_status_to_esp_status(uint8_t bta_status) { esp_bt_status_t esp_status = ESP_BT_STATUS_FAIL; switch(bta_status){ @@ -420,3 +424,36 @@ esp_bt_status_t btc_bta_status_to_esp_status (uint8_t bta_status) return esp_status; } + +void bta_to_btc_uuid(esp_bt_uuid_t *p_dest, tBT_UUID *p_src) +{ + p_dest->len = p_src->len; + if (p_src->len == LEN_UUID_16) { + p_dest->uuid.uuid16 = p_src->uu.uuid16; + } else if (p_src->len == LEN_UUID_32) { + p_dest->uuid.uuid32 = p_src->uu.uuid32; + } else if (p_src->len == LEN_UUID_128) { + memcpy(&p_dest->uuid.uuid128, p_src->uu.uuid128, p_dest->len); + } else if (p_src->len == 0) { + /* do nothing for now, there's some scenario will input 0 + such as, receive notify, the descriptor may be 0 */ + } else { + BTC_TRACE_ERROR("%s UUID len is invalid %d\n", __func__, p_src->len); + } +} + +void btc_to_bta_uuid(tBT_UUID *p_dest, esp_bt_uuid_t *p_src) +{ + p_dest->len = p_src->len; + if (p_src->len == LEN_UUID_16) { + p_dest->uu.uuid16 = p_src->uuid.uuid16; + } else if (p_src->len == LEN_UUID_32) { + p_dest->uu.uuid32 = p_src->uuid.uuid32; + } else if (p_src->len == LEN_UUID_128) { + memcpy(&p_dest->uu.uuid128, p_src->uuid.uuid128, p_dest->len); + } else if (p_src->len == 0) { + /* do nothing for now, there's some scenario will input 0 */ + } else { + BTC_TRACE_ERROR("%s UUID len is invalid %d\n", __func__, p_src->len); + } +} diff --git a/lib/bt/host/bluedroid/btc/include/btc/btc_config.h b/lib/bt/host/bluedroid/btc/include/btc/btc_config.h index 8467ced8..6727c0ca 100644 --- a/lib/bt/host/bluedroid/btc/include/btc/btc_config.h +++ b/lib/bt/host/bluedroid/btc/include/btc/btc_config.h @@ -49,4 +49,6 @@ void btc_config_lock(void); void btc_config_unlock(void); int btc_config_file_path_update(const char *file_path); + +int btc_config_file_path_get(char *file_path); #endif diff --git a/lib/bt/host/bluedroid/btc/include/btc/btc_main.h b/lib/bt/host/bluedroid/btc/include/btc/btc_main.h index df20a638..83f87b56 100644 --- a/lib/bt/host/bluedroid/btc/include/btc/btc_main.h +++ b/lib/bt/host/bluedroid/btc/include/btc/btc_main.h @@ -34,12 +34,14 @@ typedef enum { BTC_BLE_STATUS_EXT_ADV, // Extended advertising exist BTC_BLE_STATUS_SCAN, // Scanning exist BTC_BLE_STATUS_CONN, // Connection exist - BTC_BLE_STATUS_KEYS, // Device keys record exist + BTC_BLE_STATUS_DEVICE_REC, // Device record exist BTC_BLE_STATUS_BOND, // Bond info exist BTC_BLE_STATUS_GATTC_CACHE, // GATTC cache exist BTC_BLE_STATUS_GATTC_APP, // GATTC application exist BTC_BLE_STATUS_GATTS_SRVC, // GATTS service exist BTC_BLE_STATUS_PRIVACY, // Privacy enabled + BTC_BLE_STATUS_ADDR_RESOLVE_DISABLE,// Address resolution disable status + BTC_BLE_STATUS_SMP_STATE, // SMP state machine } tBTC_BLE_STATUS; future_t **btc_main_get_future_p(btc_main_future_type_t type); diff --git a/lib/bt/host/bluedroid/btc/include/btc/btc_util.h b/lib/bt/host/bluedroid/btc/include/btc/btc_util.h index deb55990..1b96d6f4 100644 --- a/lib/bt/host/bluedroid/btc/include/btc/btc_util.h +++ b/lib/bt/host/bluedroid/btc/include/btc/btc_util.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -57,8 +57,11 @@ void uuid128_be_to_esp_uuid(esp_bt_uuid_t *u, uint8_t* uuid128); void uuid_to_string_legacy(bt_uuid_t *p_uuid, char *str); esp_bt_status_t btc_hci_to_esp_status(uint8_t hci_status); -esp_bt_status_t btc_btm_status_to_esp_status (uint8_t btm_status); -esp_bt_status_t btc_bta_status_to_esp_status (uint8_t bta_status); +esp_bt_status_t btc_btm_status_to_esp_status(uint8_t btm_status); +esp_bt_status_t btc_bta_status_to_esp_status(uint8_t bta_status); + +void bta_to_btc_uuid(esp_bt_uuid_t *p_dest, tBT_UUID *p_src); +void btc_to_bta_uuid(tBT_UUID *p_dest, esp_bt_uuid_t *p_src); #ifdef __cplusplus } diff --git a/lib/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c b/lib/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c index 3c628d84..f2668e2e 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c +++ b/lib/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c @@ -70,7 +70,7 @@ const UINT8 bta_av_co_cp_scmst[BTA_AV_CP_INFO_LEN] = "\x02\x02\x00"; /* SBC SRC codec capabilities */ const tA2D_SBC_CIE bta_av_co_sbc_caps = { - (A2D_SBC_IE_SAMP_FREQ_44 | A2D_SBC_IE_SAMP_FREQ_48), /* samp_freq */ + (A2D_SBC_IE_SAMP_FREQ_44), /* samp_freq */ (A2D_SBC_IE_CH_MD_MONO | A2D_SBC_IE_CH_MD_STEREO | A2D_SBC_IE_CH_MD_JOINT | A2D_SBC_IE_CH_MD_DUAL), /* ch_mode */ (A2D_SBC_IE_BLOCKS_16 | A2D_SBC_IE_BLOCKS_12 | A2D_SBC_IE_BLOCKS_8 | A2D_SBC_IE_BLOCKS_4), /* block_len */ (A2D_SBC_IE_SUBBAND_4 | A2D_SBC_IE_SUBBAND_8), /* num_subbands */ @@ -91,13 +91,13 @@ const tA2D_SBC_CIE bta_av_co_sbc_sink_caps = { }; #if !defined(BTC_AV_SBC_DEFAULT_SAMP_FREQ) -#define BTC_AV_SBC_DEFAULT_SAMP_FREQ A2D_SBC_IE_SAMP_FREQ_48 +#define BTC_AV_SBC_DEFAULT_SAMP_FREQ A2D_SBC_IE_SAMP_FREQ_44 #endif /* Default SBC codec configuration */ const tA2D_SBC_CIE btc_av_sbc_default_config = { BTC_AV_SBC_DEFAULT_SAMP_FREQ, /* samp_freq */ - A2D_SBC_IE_CH_MD_JOINT, /* ch_mode */ + A2D_SBC_IE_CH_MD_JOINT, /* ch_mode */ A2D_SBC_IE_BLOCKS_16, /* block_len */ A2D_SBC_IE_SUBBAND_8, /* num_subbands */ A2D_SBC_IE_ALLOC_MD_L, /* alloc_mthd */ @@ -122,7 +122,6 @@ static UINT8 bta_av_co_audio_sink_supports_config(UINT8 codec_type, const UINT8 static BOOLEAN bta_av_co_audio_peer_src_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_src_index); - /******************************************************************************* ** ** Function bta_av_co_cp_is_active @@ -245,18 +244,29 @@ BOOLEAN bta_av_co_audio_init(UINT8 *p_codec_type, UINT8 *p_codec_info, UINT8 *p_ UINT16_TO_STREAM(p, BTA_AV_CP_SCMS_T_ID); } while (0); #endif +#if (BTC_AV_EXT_CODEC == TRUE) + /* for external codec, we get codec capability from BTA_AV */ + bta_av_co_cb.codec_caps.id = *p_codec_type; + memcpy(bta_av_co_cb.codec_caps.info, p_codec_info, AVDT_CODEC_SIZE); + bta_av_co_audio_codec_reset(); +#else /* Set up for SBC codec for SRC*/ *p_codec_type = BTA_AV_CODEC_SBC; - /* This should not fail because we are using constants for parameters */ A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &bta_av_co_sbc_caps, p_codec_info); +#endif return TRUE; } else if (tsep == AVDT_TSEP_SNK) { +#if (BTC_AV_EXT_CODEC == TRUE) + /* for external codec, we get codec capability from BTA_AV */ + bta_av_co_cb.codec_caps.id = *p_codec_type; + memcpy(bta_av_co_cb.codec_caps.info, p_codec_info, AVDT_CODEC_SIZE); + bta_av_co_audio_codec_reset(); +#else *p_codec_type = BTA_AV_CODEC_SBC; - /* This should not fail because we are using constants for parameters */ A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &bta_av_co_sbc_sink_caps, p_codec_info); - +#endif /* Codec is valid */ return TRUE; } else { @@ -387,7 +397,7 @@ void bta_av_build_src_cfg (UINT8 *p_pref_cfg, UINT8 *p_src_cap) /* now try to build a preferred one */ /* parse configuration */ if ((status = A2D_ParsSbcInfo(&src_cap, p_src_cap, TRUE)) != 0) { - APPL_TRACE_DEBUG(" Cant parse src cap ret = %d", status); + APPL_TRACE_DEBUG(" Can't parse src cap ret = %d", status); return ; } @@ -1062,12 +1072,12 @@ static BOOLEAN bta_av_co_audio_codec_build_config(const UINT8 *p_codec_caps, UIN memcpy(p_codec_cfg, bta_av_co_cb.codec_cfg.info, BTA_AV_CO_SBC_MAX_BITPOOL_OFF + 1); /* Update the bit pool boundaries with the codec capabilities */ - p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF] = p_codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF]; - p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF] = p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]; + p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF] = BTA_AV_CO_MAX(p_codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF], p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF]); + p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF] = BTA_AV_CO_MIN(p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF], p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]); APPL_TRACE_EVENT("bta_av_co_audio_codec_build_config : bitpool min %d, max %d", p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF], - p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]); + p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]); break; default: APPL_TRACE_ERROR("bta_av_co_audio_codec_build_config: unsupported codec id %d", bta_av_co_cb.codec_cfg.id); @@ -1301,10 +1311,20 @@ static BOOLEAN bta_av_co_audio_peer_src_supports_codec(tBTA_AV_CO_PEER *p_peer, if (p_src_index) { *p_src_index = index; } +#if (BTC_AV_EXT_CODEC == TRUE) + tA2D_SBC_CIE cap_cie; + if (A2D_ParsSbcInfo(&cap_cie, bta_av_co_cb.codec_caps.info, TRUE) != A2D_SUCCESS) { + return FALSE; + } + if (0 == bta_av_sbc_cfg_matches_cap((UINT8 *)p_peer->srcs[index].codec_caps, &cap_cie)) { + return TRUE; + } +#else if (0 == bta_av_sbc_cfg_matches_cap((UINT8 *)p_peer->srcs[index].codec_caps, - (tA2D_SBC_CIE *)&bta_av_co_sbc_sink_caps)) { + (tA2D_SBC_CIE *)&bta_av_co_sbc_sink_caps)) { return TRUE; } +#endif break; default: @@ -1334,7 +1354,11 @@ static UINT8 bta_av_co_audio_sink_supports_config(UINT8 codec_type, const UINT8 switch (codec_type) { case BTA_AV_CODEC_SBC: +#if (BTC_AV_EXT_CODEC == TRUE) + status = bta_av_sbc_cfg_in_external_codec_cap((UINT8 *)p_codec_cfg, (UINT8 *)bta_av_co_cb.codec_caps.info); +#else status = bta_av_sbc_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_SBC_CIE *)&bta_av_co_sbc_sink_caps); +#endif break; case BTA_AV_CODEC_M12: case BTA_AV_CODEC_M24: @@ -1365,7 +1389,11 @@ static UINT8 bta_av_co_audio_media_supports_config(UINT8 codec_type, const UINT8 switch (codec_type) { case BTA_AV_CODEC_SBC: +#if (BTC_AV_EXT_CODEC == TRUE) + status = bta_av_sbc_cfg_in_external_codec_cap((UINT8 *)p_codec_cfg, (UINT8 *)bta_av_co_cb.codec_caps.info); +#else status = bta_av_sbc_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_SBC_CIE *)&bta_av_co_sbc_caps); +#endif break; case BTA_AV_CODEC_M12: case BTA_AV_CODEC_M24: @@ -1478,12 +1506,16 @@ void bta_av_co_audio_codec_reset(void) osi_mutex_global_lock(); FUNC_TRACE(); +#if (BTC_AV_EXT_CODEC == TRUE) + bta_av_co_cb.codec_cfg.id = bta_av_co_cb.codec_caps.id; + bta_av_build_src_cfg(bta_av_co_cb.codec_cfg.info, bta_av_co_cb.codec_caps.info); +#else /* Reset the current configuration to SBC */ bta_av_co_cb.codec_cfg.id = BTC_AV_CODEC_SBC; - if (A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, (tA2D_SBC_CIE *)&btc_av_sbc_default_config, bta_av_co_cb.codec_cfg.info) != A2D_SUCCESS) { APPL_TRACE_ERROR("bta_av_co_audio_codec_reset A2D_BldSbcInfo failed"); } +#endif osi_mutex_global_unlock(); } @@ -1564,7 +1596,6 @@ BOOLEAN bta_av_co_audio_set_codec(const tBTC_AV_MEDIA_FEEDINGS *p_feeding, tBTC_ /* The new config was correctly built */ bta_av_co_cb.codec_cfg = new_cfg; - /* Check all devices support it */ *p_status = BTC_AV_SUCCESS; return bta_av_co_audio_codec_supported(p_status); @@ -1666,13 +1697,16 @@ void bta_av_co_audio_discard_config(tBTA_AV_HNDL hndl) ** Returns Nothing ** *******************************************************************************/ -void bta_av_co_init(void) +void bta_av_co_init(tBTC_AV_CODEC_INFO *codec_caps) { FUNC_TRACE(); /* Reset the control block */ memset(&bta_av_co_cb, 0, sizeof(bta_av_co_cb)); + if (codec_caps) { + memcpy(&bta_av_co_cb.codec_caps, codec_caps, sizeof(tBTC_AV_CODEC_INFO)); + } bta_av_co_cb.codec_cfg_setconfig.id = BTC_AV_CODEC_NONE; #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE) @@ -1685,7 +1719,6 @@ void bta_av_co_init(void) bta_av_co_audio_codec_reset(); } - /******************************************************************************* ** ** Function bta_av_co_peer_cp_supported @@ -1729,7 +1762,7 @@ BOOLEAN bta_av_co_peer_cp_supported(tBTA_AV_HNDL hndl) ** of our exported bitpool range. If set we will set the ** remote preference. ** - ** Returns TRUE if config set, FALSE otherwize + ** Returns TRUE if config set, FALSE otherwise ** *******************************************************************************/ diff --git a/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp.c b/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp.c index 279b1001..86025021 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp.c +++ b/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp.c @@ -49,7 +49,12 @@ void btc_a2dp_on_idle(void) } #endif // BTC_AV_SRC_INCLUDED - bta_av_co_init(); +#if (BTC_AV_EXT_CODEC == TRUE) + tBTC_AV_CODEC_INFO *codec_caps = btc_av_codec_cap_get(); +#else + tBTC_AV_CODEC_INFO *codec_caps = NULL; +#endif + bta_av_co_init(codec_caps); #if BTC_AV_SINK_INCLUDED if (btc_av_get_peer_sep() == AVDT_TSEP_SRC && btc_av_get_service_id() == BTA_A2DP_SINK_SERVICE_ID) { @@ -88,9 +93,11 @@ BOOLEAN btc_a2dp_on_started(tBTA_AV_START *p_av, BOOLEAN pending_start) ack = TRUE; } } else { +#if (BTC_AV_EXT_CODEC == FALSE) /* we were remotely started, make sure codec is setup before datapath is started */ btc_a2dp_source_setup_codec(); +#endif } /* media task is autostarted upon a2dp audiopath connection */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c b/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c index ba264f93..3076e882 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c +++ b/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c @@ -71,8 +71,10 @@ static void btc_a2dp_datapath_open(void) /* Start the media task to encode SBC */ btc_a2dp_source_start_audio_req(); +#if (BTC_AV_EXT_CODEC == FALSE) /* make sure we update any changed sbc encoder params */ btc_a2dp_source_encoder_update(); +#endif } #endif #if (BTC_AV_SINK_INCLUDED == TRUE) diff --git a/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c b/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c index 4a1f060f..d81f0958 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c +++ b/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,12 +30,13 @@ #include "btc_av.h" #include "btc/btc_util.h" #include "esp_a2dp_api.h" -#include "oi_codec_sbc.h" -#include "oi_status.h" #include "osi/future.h" #include -#if (BTC_AV_SINK_INCLUDED == TRUE) +#if (BTC_AV_SINK_INCLUDED == TRUE) && (BTC_AV_EXT_CODEC == FALSE) + +#include "oi_codec_sbc.h" +#include "oi_status.h" /***************************************************************************** ** Constants @@ -85,13 +86,6 @@ typedef struct { void *param; } a2dp_sink_task_evt_t; -typedef struct { - UINT16 num_frames_to_be_processed; - UINT16 len; - UINT16 offset; - UINT16 layer_specific; -} tBT_SBC_HDR; - typedef struct { BOOLEAN rx_flush; /* discards any incoming data when true */ UINT8 channel_count; @@ -121,7 +115,7 @@ static void btc_a2dp_sink_rx_flush(void); static int btc_a2dp_sink_get_track_frequency(UINT8 frequency); static int btc_a2dp_sink_get_track_channel_count(UINT8 channeltype); /* Handle incoming media packets A2DP SINK streaming*/ -static void btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR *p_msg); +static void btc_a2dp_sink_handle_inc_media(BT_HDR *p_msg); static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg); static void btc_a2dp_sink_handle_clear_track(void); static BOOLEAN btc_a2dp_sink_clear_track(void); @@ -346,7 +340,7 @@ void btc_a2dp_sink_reset_decoder(UINT8 *p_av) static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context) { - tBT_SBC_HDR *p_msg; + BT_HDR *p_msg; int nb_of_msgs_to_process = 0; if (fixed_queue_is_empty(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ)) { @@ -362,13 +356,12 @@ static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context) if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON){ return; } - p_msg = (tBT_SBC_HDR *)fixed_queue_dequeue(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ, 0); + p_msg = (BT_HDR *)fixed_queue_dequeue(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ, 0); if ( p_msg == NULL ) { APPL_TRACE_ERROR("Insufficient data in que "); break; } btc_a2dp_sink_handle_inc_media(p_msg); - osi_free(p_msg); nb_of_msgs_to_process--; } APPL_TRACE_DEBUG(" Process Frames - "); @@ -526,25 +519,27 @@ static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg ** Returns void ** *******************************************************************************/ -static void btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR *p_msg) +static void btc_a2dp_sink_handle_inc_media(BT_HDR *p_msg) { UINT8 *sbc_start_frame = ((UINT8 *)(p_msg + 1) + p_msg->offset + 1); int count; UINT32 pcmBytes, availPcmBytes; OI_INT16 *pcmDataPointer = a2dp_sink_local_param.pcmData; /*Will be overwritten on next packet receipt*/ OI_STATUS status; - int num_sbc_frames = p_msg->num_frames_to_be_processed; + int num_sbc_frames = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f; UINT32 sbc_frame_len = p_msg->len - 1; availPcmBytes = sizeof(a2dp_sink_local_param.pcmData); /* XXX: Check if the below check is correct, we are checking for peer to be sink when we are sink */ if (btc_av_get_peer_sep() == AVDT_TSEP_SNK || (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush)) { APPL_TRACE_DEBUG(" State Changed happened in this tick "); + osi_free(p_msg); return; } // ignore data if no one is listening if (!btc_a2dp_control_get_datachnl_stat()) { + osi_free(p_msg); return; } @@ -565,9 +560,9 @@ static void btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR *p_msg) for (count = 0; count < num_sbc_frames && sbc_frame_len != 0; count ++) { pcmBytes = availPcmBytes; status = OI_CODEC_SBC_DecodeFrame(&a2dp_sink_local_param.context, (const OI_BYTE **)&sbc_start_frame, - (OI_UINT32 *)&sbc_frame_len, - (OI_INT16 *)pcmDataPointer, - (OI_UINT32 *)&pcmBytes); + (OI_UINT32 *)&sbc_frame_len, + (OI_INT16 *)pcmDataPointer, + (OI_UINT32 *)&pcmBytes); if (!OI_SUCCESS(status)) { APPL_TRACE_ERROR("Decoding failure: %d\n", status); break; @@ -577,6 +572,7 @@ static void btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR *p_msg) p_msg->offset += (p_msg->len - 1) - sbc_frame_len; p_msg->len = sbc_frame_len + 1; } + osi_free(p_msg); btc_a2d_data_cb_to_app((uint8_t *)a2dp_sink_local_param.pcmData, (sizeof(a2dp_sink_local_param.pcmData) - availPcmBytes)); } @@ -663,35 +659,28 @@ static int btc_a2dp_sink_get_track_channel_count(UINT8 channeltype) *******************************************************************************/ UINT8 btc_a2dp_sink_enque_buf(BT_HDR *p_pkt) { - tBT_SBC_HDR *p_msg; - if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON){ + osi_free(p_pkt); return 0; } - if (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush == TRUE) { /* Flush enabled, do not enque*/ + if (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush == TRUE) { /* Flush enabled, do not enqueue */ + osi_free(p_pkt); return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ); } if (fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ) >= MAX_OUTPUT_A2DP_SNK_FRAME_QUEUE_SZ) { + osi_free(p_pkt); APPL_TRACE_WARNING("Pkt dropped\n"); return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ); } APPL_TRACE_DEBUG("btc_a2dp_sink_enque_buf + "); - /* allocate and Queue this buffer */ - if ((p_msg = (tBT_SBC_HDR *) osi_malloc(sizeof(tBT_SBC_HDR) + - p_pkt->offset + p_pkt->len)) != NULL) { - memcpy(p_msg, p_pkt, (sizeof(BT_HDR) + p_pkt->offset + p_pkt->len)); - p_msg->num_frames_to_be_processed = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f; - APPL_TRACE_VERBOSE("btc_a2dp_sink_enque_buf %d + \n", p_msg->num_frames_to_be_processed); - fixed_queue_enqueue(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ, p_msg, FIXED_QUEUE_MAX_TIMEOUT); - osi_thread_post_event(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event, OSI_THREAD_MAX_TIMEOUT); - } else { - /* let caller deal with a failed allocation */ - APPL_TRACE_WARNING("btc_a2dp_sink_enque_buf No Buffer left - "); - } + // p_msg->num_frames_to_be_processed = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f; + fixed_queue_enqueue(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ, p_pkt, FIXED_QUEUE_MAX_TIMEOUT); + osi_thread_post_event(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event, OSI_THREAD_MAX_TIMEOUT); + return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ); } @@ -749,4 +738,4 @@ static void btc_a2dp_sink_thread_cleanup(UNUSED_ATTR void *context) a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event = NULL; } -#endif /* BTC_AV_SINK_INCLUDED */ +#endif /* (BTC_AV_SINK_INCLUDED == TRUE) && (BTC_AV_EXT_CODEC == FALSE) */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink_ext_coedc.c b/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink_ext_coedc.c new file mode 100644 index 00000000..d2a6164b --- /dev/null +++ b/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink_ext_coedc.c @@ -0,0 +1,286 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "common/bt_target.h" +#include "common/bt_trace.h" +#include +#include +#include "common/bt_defs.h" +#include "osi/allocator.h" +#include "osi/mutex.h" +#include "osi/thread.h" +#include "osi/fixed_queue.h" +#include "stack/a2d_api.h" +#include "bta/bta_av_api.h" +#include "bta/bta_av_ci.h" +#include "btc_av_co.h" +#include "btc_a2dp.h" +#include "btc_a2dp_control.h" +#include "btc_a2dp_sink.h" +#include "btc/btc_manage.h" +#include "btc_av.h" +#include "btc/btc_util.h" +#include "esp_a2dp_api.h" +#include "osi/future.h" +#include + +#if (BTC_AV_SINK_INCLUDED == TRUE) && (BTC_AV_EXT_CODEC == TRUE) + +#define MAX_OUTPUT_A2DP_SNK_FRAME_QUEUE_SZ (25) +#define BTC_A2DP_SNK_DATA_QUEUE_IDX (1) + +enum { + BTC_A2DP_SINK_STATE_OFF = 0, + BTC_A2DP_SINK_STATE_ON = 1, +}; + +typedef struct { + BOOLEAN rx_flush; /* discards any incoming data when true */ + struct osi_event *data_ready_event; + fixed_queue_t *audio_rx_q; +} tBTC_A2DP_SINK_CB; + +typedef struct { + uint16_t expected_seq_num; + bool seq_num_recount; +} a2dp_sink_media_pkt_seq_num_t; + +typedef struct { + tBTC_A2DP_SINK_CB btc_aa_snk_cb; + osi_thread_t *btc_aa_snk_task_hdl; + a2dp_sink_media_pkt_seq_num_t media_pkt_seq_num; +} a2dp_sink_local_param_t; + +static int btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_OFF; +static esp_a2d_sink_audio_data_cb_t bt_aa_snk_audio_data_cb = NULL; + +#if A2D_DYNAMIC_MEMORY == FALSE +static a2dp_sink_local_param_t a2dp_sink_local_param; +#else +static a2dp_sink_local_param_t *a2dp_sink_local_param_ptr; +#define a2dp_sink_local_param (*a2dp_sink_local_param_ptr) +#endif ///A2D_DYNAMIC_MEMORY == FALSE + +static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context); +static void btc_a2dp_sink_handle_inc_media(BT_HDR *p_msg); + +void btc_a2dp_sink_reg_audio_data_cb(esp_a2d_sink_audio_data_cb_t callback) +{ + bt_aa_snk_audio_data_cb = callback; +} + +static inline void btc_a2d_audio_data_cb_to_app(uint16_t conn_hdl, uint8_t *buf, uint8_t *data, uint16_t len, uint16_t number_frame, uint32_t timestamp) +{ + if (bt_aa_snk_audio_data_cb) { + /* AVDT media packet offset is larger than sizeof(esp_a2d_audio_buff_t), it safe to do this */ + esp_a2d_audio_buff_t *audio_buff = (esp_a2d_audio_buff_t *)buf; + audio_buff->buff_size = len; + audio_buff->number_frame = number_frame; + audio_buff->data_len = len; + audio_buff->data = data; + audio_buff->timestamp = timestamp; + bt_aa_snk_audio_data_cb(conn_hdl, audio_buff); + } + else { + osi_free(buf); + } +} + +static void btc_a2dp_sink_rx_flush(void) +{ + while (!fixed_queue_is_empty(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q)) { + osi_free(fixed_queue_dequeue(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q, 0)); + } +} + +bool btc_a2dp_sink_startup(void) +{ + if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_OFF) { + APPL_TRACE_ERROR("a2dp sink already start up"); + return false; + } + +#if A2D_DYNAMIC_MEMORY == TRUE + if ((a2dp_sink_local_param_ptr = (a2dp_sink_local_param_t *)osi_malloc(sizeof(a2dp_sink_local_param_t))) == NULL) { + APPL_TRACE_ERROR("%s malloc failed!", __func__); + return false; + } + memset((void *)a2dp_sink_local_param_ptr, 0, sizeof(a2dp_sink_local_param_t)); +#endif + + a2dp_sink_local_param.btc_aa_snk_task_hdl = btc_get_current_thread(); + + struct osi_event *data_event = osi_event_create(btc_a2dp_sink_data_ready, NULL); + assert (data_event != NULL); + osi_event_bind(data_event, a2dp_sink_local_param.btc_aa_snk_task_hdl, BTC_A2DP_SNK_DATA_QUEUE_IDX); + a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event = data_event; + a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q = fixed_queue_new(QUEUE_SIZE_MAX); + btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_ON; + + btc_a2dp_control_init(); + + return true; +} + +void btc_a2dp_sink_shutdown(void) +{ + if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON) { + APPL_TRACE_ERROR("a2dp sink already shutdown"); + return; + } + + btc_a2dp_control_set_datachnl_stat(FALSE); + + btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_OFF; + + btc_a2dp_control_cleanup(); + + fixed_queue_free(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q, osi_free_func); + + a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q = NULL; + + osi_event_delete(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event); + a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event = NULL; + + a2dp_sink_local_param.btc_aa_snk_task_hdl = NULL; + +#if A2D_DYNAMIC_MEMORY == TRUE + osi_free(a2dp_sink_local_param_ptr); + a2dp_sink_local_param_ptr = NULL; +#endif +} + +void btc_a2dp_sink_on_idle(void) +{ + a2dp_sink_local_param.btc_aa_snk_cb.rx_flush = TRUE; + btc_a2dp_sink_rx_flush(); +} + +void btc_a2dp_sink_on_stopped(tBTA_AV_SUSPEND *p_av) +{ + UNUSED(p_av); + + a2dp_sink_local_param.btc_aa_snk_cb.rx_flush = TRUE; + btc_a2dp_control_set_datachnl_stat(FALSE); + btc_a2dp_sink_rx_flush(); +} + +void btc_a2dp_sink_on_suspended(tBTA_AV_SUSPEND *p_av) +{ + UNUSED(p_av); + + a2dp_sink_local_param.btc_aa_snk_cb.rx_flush = TRUE; + btc_a2dp_sink_rx_flush(); +} + +void btc_a2dp_sink_set_rx_flush(BOOLEAN enable) +{ + if (enable == FALSE) { + a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num = 0x1; + a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount = true; + } + a2dp_sink_local_param.btc_aa_snk_cb.rx_flush = enable; + btc_a2dp_sink_rx_flush(); +} + +static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context) +{ + BT_HDR *p_msg; + int nb_of_msgs_to_process = 0; + + if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON){ + return; + } + + if (!fixed_queue_is_empty(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q)) { + if (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush == TRUE) { + btc_a2dp_sink_rx_flush(); + return; + } + nb_of_msgs_to_process = fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q); + APPL_TRACE_DEBUG("%s nb msgs:%d", __func__, nb_of_msgs_to_process); + while (nb_of_msgs_to_process > 0) { + p_msg = (BT_HDR *)fixed_queue_dequeue(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q, 0); + if ( p_msg == NULL ) { + APPL_TRACE_ERROR("%s insufficient data in queue", __func__); + break; + } + btc_a2dp_sink_handle_inc_media(p_msg); + nb_of_msgs_to_process--; + } + + if (!fixed_queue_is_empty(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q)) { + osi_thread_post_event(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event, OSI_THREAD_MAX_TIMEOUT); + } + } +} + +static void btc_a2dp_sink_handle_inc_media(BT_HDR *p_msg) +{ + UINT8 *sbc_start_frame = ((UINT8 *)(p_msg + 1) + p_msg->offset + 1); + int num_sbc_frames = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f; + UINT32 sbc_frame_len = p_msg->len - 1; + + if (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush) { + osi_free(p_msg); + return; + } + + /* ignore data if no one is listening */ + if (!btc_a2dp_control_get_datachnl_stat()) { + osi_free(p_msg); + return; + } + + if (p_msg->layer_specific != a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num) { + /* Because the sequence number of some devices is not recounted */ + if (!a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount || + a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num != 0x1) { + APPL_TRACE_WARNING("Sequence numbers error, recv:0x%x, expect:0x%x, recount:0x%x", + p_msg->layer_specific, a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num, + a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount); + } + } + a2dp_sink_local_param.media_pkt_seq_num.expected_seq_num = p_msg->layer_specific + 1; + a2dp_sink_local_param.media_pkt_seq_num.seq_num_recount = false; + + APPL_TRACE_DEBUG("Number of sbc frames %d, frame_len %d\n", num_sbc_frames, sbc_frame_len); + + UINT32 timestamp = *((UINT32 *) (p_msg + 1)); + UINT16 conn_hdl = btc_a2d_conn_handle_get(); + btc_a2d_audio_data_cb_to_app(conn_hdl, (uint8_t *)p_msg, sbc_start_frame, sbc_frame_len, num_sbc_frames, timestamp); + /* dont free p_msg here */ +} + +UINT8 btc_a2dp_sink_enque_buf(BT_HDR *p_pkt) +{ + if (btc_a2dp_sink_state != BTC_A2DP_SINK_STATE_ON){ + osi_free(p_pkt); + return 0; + } + + if (a2dp_sink_local_param.btc_aa_snk_cb.rx_flush == TRUE) { + /* Flush enabled, do not enqueue */ + osi_free(p_pkt); + return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q); + } + + if (fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q) >= MAX_OUTPUT_A2DP_SNK_FRAME_QUEUE_SZ) { + osi_free(p_pkt); + APPL_TRACE_WARNING("Pkt dropped\n"); + return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q); + } + + APPL_TRACE_DEBUG("btc_a2dp_sink_enque_buf + "); + + // p_msg->num_frames_to_be_processed = (*((UINT8 *)(p_msg + 1) + p_msg->offset)) & 0x0f; + fixed_queue_enqueue(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q, p_pkt, FIXED_QUEUE_MAX_TIMEOUT); + osi_thread_post_event(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event, OSI_THREAD_MAX_TIMEOUT); + + return fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.audio_rx_q); +} + +#endif diff --git a/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c b/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c index 4fcdd5b7..40b3db00 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c +++ b/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -36,11 +36,12 @@ #include "btc_av.h" #include "btc/btc_util.h" #include "esp_a2dp_api.h" -#include "sbc_encoder.h" #include "osi/future.h" #include -#if BTC_AV_SRC_INCLUDED +#if (BTC_AV_SRC_INCLUDED == TRUE) && (BTC_AV_EXT_CODEC == FALSE) + +#include "sbc_encoder.h" /***************************************************************************** ** BQB global variables @@ -74,21 +75,15 @@ enum { /* Media task tick in milliseconds, must be set to multiple of (1000/TICKS_PER_SEC) */ -#define BTC_MEDIA_TIME_TICK_MS (20) +#define BTC_MEDIA_TIME_TICK_MS (30) #define A2DP_DATA_READ_POLL_MS (BTC_MEDIA_TIME_TICK_MS / 2) #ifndef MAX_PCM_FRAME_NUM_PER_TICK -#define MAX_PCM_FRAME_NUM_PER_TICK 14 // 14 for 20ms +#define MAX_PCM_FRAME_NUM_PER_TICK 21 // 14 for 20ms #endif #define BTC_MEDIA_AA_BUF_SIZE (4096+16) -#if (BTA_AV_CO_CP_SCMS_T == TRUE) -#define BTC_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE + 1) -#else -#define BTC_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE) -#endif - #ifndef BTC_MEDIA_BITRATE_STEP #define BTC_MEDIA_BITRATE_STEP 5 #endif @@ -97,8 +92,8 @@ enum { #define BTC_A2DP_NON_EDR_MAX_RATE 229 #endif -/* Extreme quality quality setting @ 48 khz */ -#define DEFAULT_SBC_BITRATE 672 +/* Middle quality quality setting @ 44.1 khz */ +#define DEFAULT_SBC_BITRATE 328 /* * CONGESTION COMPENSATION CTRL :: @@ -120,7 +115,8 @@ enum { layers we might need to temporarily buffer up data */ /* 5 frames is equivalent to 6.89*5*2.9 ~= 100 ms @ 44.1 khz, 20 ms mediatick */ -#define MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ (50) // 18 for 20ms tick +#define MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ (5) +#define MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ (27) // 18 for 20ms tick #define BTC_A2DP_SRC_DATA_QUEUE_IDX (1) @@ -169,6 +165,10 @@ typedef struct { UINT64 last_frame_us; } a2dp_source_local_param_t; +static BOOLEAN btc_a2dp_source_stop_audio_req(void); +static BOOLEAN btc_a2dp_source_tx_flush_req(void); +static BOOLEAN btc_a2dp_source_audio_feeding_init_req(tBTC_MEDIA_INIT_AUDIO_FEEDING *p_msg); + static void btc_a2dp_source_thread_init(UNUSED_ATTR void *context); static void btc_a2dp_source_thread_cleanup(UNUSED_ATTR void *context); static void btc_a2dp_source_flush_q(fixed_queue_t *p_q); @@ -225,11 +225,6 @@ static inline void btc_aa_cb_to_app(esp_a2d_cb_event_t event, esp_a2d_cb_param_t ** BTC ADAPTATION *****************************************************************************/ -bool btc_a2dp_source_is_streaming(void) -{ - return a2dp_source_local_param.btc_aa_src_cb.is_tx_timer == TRUE; -} - bool btc_a2dp_source_is_task_shutting_down(void) { return btc_a2dp_source_state == BTC_A2DP_SOURCE_STATE_SHUTTING_DOWN; @@ -504,7 +499,7 @@ BOOLEAN btc_a2dp_source_start_audio_req(void) ** Returns TRUE is success ** *******************************************************************************/ -BOOLEAN btc_a2dp_source_stop_audio_req(void) +static BOOLEAN btc_a2dp_source_stop_audio_req(void) { /* * Explicitly check whether the btc_aa_src_ctrl_queue is not NULL to @@ -535,7 +530,7 @@ BOOLEAN btc_a2dp_source_stop_audio_req(void) ** Returns TRUE is success ** *******************************************************************************/ -BOOLEAN btc_a2dp_source_enc_init_req(tBTC_MEDIA_INIT_AUDIO *p_msg) +static BOOLEAN btc_a2dp_source_enc_init_req(tBTC_MEDIA_INIT_AUDIO *p_msg) { tBTC_MEDIA_INIT_AUDIO *p_buf; if (NULL == (p_buf = osi_malloc(sizeof(tBTC_MEDIA_INIT_AUDIO)))) { @@ -558,7 +553,7 @@ BOOLEAN btc_a2dp_source_enc_init_req(tBTC_MEDIA_INIT_AUDIO *p_msg) ** Returns TRUE is success ** *******************************************************************************/ -BOOLEAN btc_a2dp_source_enc_update_req(tBTC_MEDIA_UPDATE_AUDIO *p_msg) +static BOOLEAN btc_a2dp_source_enc_update_req(tBTC_MEDIA_UPDATE_AUDIO *p_msg) { tBTC_MEDIA_UPDATE_AUDIO *p_buf; if (NULL == (p_buf = osi_malloc(sizeof(tBTC_MEDIA_UPDATE_AUDIO)))) { @@ -1450,6 +1445,7 @@ static void btc_a2dp_source_prep_2_send(UINT8 nb_frame) *******************************************************************************/ static void btc_a2dp_source_send_aa_frame(void) { + /* if external codec is used, skip generate audio frame */ UINT8 nb_frame_2_send; /* get the number of frame to send */ @@ -1460,8 +1456,8 @@ static void btc_a2dp_source_send_aa_frame(void) btc_a2dp_source_prep_2_send(nb_frame_2_send); } - /* send it */ - BTC_TRACE_VERBOSE("%s: send %d frames", __FUNCTION__, nb_frame_2_send); + BTC_TRACE_VERBOSE("%s: send %d new frames", __FUNCTION__, nb_frame_2_send); + bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO); } @@ -1538,8 +1534,8 @@ static void btc_a2dp_source_aa_stop_tx(void) when the DUT and the remote device issue SUSPEND simultaneously and due to the processing of the SUSPEND request from the remote, the media path is torn down. If the A2DP HAL happens to wait - for ACK for the initiated SUSPEND, it would never receive it casuing - a block/wait. Due to this acknowledgement, the A2DP HAL is guranteed + for ACK for the initiated SUSPEND, it would never receive it causing + a block/wait. Due to this acknowledgement, the A2DP HAL is guaranteed to get the ACK for any pending command in such cases. */ if (send_ack) { @@ -1646,4 +1642,4 @@ static void btc_a2dp_source_thread_cleanup(UNUSED_ATTR void *context) a2dp_source_local_param.btc_aa_src_cb.poll_data = NULL; } -#endif /* BTC_AV_INCLUDED */ +#endif /* (BTC_AV_SRC_INCLUDED == TRUE) && (BTC_AV_EXT_CODEC == FALSE) */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source_ext_codec.c b/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source_ext_codec.c new file mode 100644 index 00000000..f6a71add --- /dev/null +++ b/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source_ext_codec.c @@ -0,0 +1,235 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "common/bt_target.h" +#include "common/bt_trace.h" +#include +#include +#include +#include "osi/allocator.h" +#include "osi/fixed_queue.h" +#include "stack/a2d_api.h" +#include "bta/bta_av_api.h" +#include "bta/bta_av_ci.h" +#include "btc/btc_manage.h" +#include "btc/btc_common.h" +#include "btc_av_co.h" +#include "btc_a2dp.h" +#include "btc_a2dp_control.h" +#include "btc_a2dp_source.h" +#include "btc_av.h" +#include "esp_a2dp_api.h" +#include + +#if (BTC_AV_SRC_INCLUDED == TRUE) && (BTC_AV_EXT_CODEC == TRUE) + +#define MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ (27) + +enum { + BTC_A2DP_SOURCE_STATE_OFF = 0, + BTC_A2DP_SOURCE_STATE_ON = 1, +}; + +typedef struct { + BOOLEAN stream_started; + BOOLEAN tx_flush; + fixed_queue_t *audio_tx_q; +} a2dp_source_local_param_t; + +static int btc_a2dp_source_state = BTC_A2DP_SOURCE_STATE_OFF; +#if A2D_DYNAMIC_MEMORY == FALSE +static a2dp_source_local_param_t a2dp_source_local_param; +#else +static a2dp_source_local_param_t *a2dp_source_local_param_ptr; +#define a2dp_source_local_param (*a2dp_source_local_param_ptr) +#endif ///A2D_DYNAMIC_MEMORY == FALSE + +static inline void btc_aa_cb_to_app(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) +{ + esp_a2d_cb_t btc_aa_cb = (esp_a2d_cb_t)btc_profile_cb_get(BTC_PID_A2DP); + if (btc_aa_cb) { + btc_aa_cb(event, param); + } +} + +static void btc_a2dp_source_tx_flush(void) +{ + while (!fixed_queue_is_empty(a2dp_source_local_param.audio_tx_q)) { + osi_free(fixed_queue_dequeue(a2dp_source_local_param.audio_tx_q, 0)); + } +} + +static void btc_a2dp_source_tx_stop(void) +{ + if (a2dp_source_local_param.stream_started == TRUE) { + a2dp_source_local_param.stream_started = FALSE; + /* ack to command */ + btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_SUCCESS); + } + + /* flush tx queue */ + btc_a2dp_source_tx_flush(); + a2dp_source_local_param.tx_flush = FALSE; +} + +BOOLEAN btc_a2dp_source_enqueue_audio_frame(BT_HDR *p_buf) +{ + if (btc_a2dp_source_state != BTC_A2DP_SOURCE_STATE_ON) { + APPL_TRACE_WARNING("%s source not start up", __func__); + return FALSE; + } + + if (a2dp_source_local_param.tx_flush) { + APPL_TRACE_WARNING("%s try to send data when tx flush enable", __func__); + return FALSE; + } + + if (fixed_queue_length(a2dp_source_local_param.audio_tx_q) > MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ) { + APPL_TRACE_WARNING("%s audio tx queue overflow: %d", __func__, fixed_queue_length(a2dp_source_local_param.audio_tx_q)); + return FALSE; + } + + fixed_queue_enqueue(a2dp_source_local_param.audio_tx_q, p_buf, FIXED_QUEUE_MAX_TIMEOUT); + bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO); + return TRUE; +} + +void btc_source_report_delay_value(UINT16 delay_value) +{ + esp_a2d_cb_param_t param; + + if (btc_a2dp_source_state != BTC_A2DP_SOURCE_STATE_ON){ + return; + } + + param.a2d_report_delay_value_stat.delay_value = delay_value; + + btc_aa_cb_to_app(ESP_A2D_REPORT_SNK_DELAY_VALUE_EVT, ¶m); +} + +BOOLEAN btc_a2dp_source_start_audio_req(void) +{ + a2dp_source_local_param.stream_started = TRUE; + return TRUE; +} + +BT_HDR *btc_a2dp_source_audio_readbuf(void) +{ + if (btc_a2dp_source_state != BTC_A2DP_SOURCE_STATE_ON || a2dp_source_local_param.tx_flush){ + return NULL; + } + return fixed_queue_dequeue(a2dp_source_local_param.audio_tx_q, 0); +} + +void btc_a2dp_source_set_tx_flush(BOOLEAN enable) +{ + a2dp_source_local_param.tx_flush = enable; + if (enable) { + btc_a2dp_source_tx_flush(); + } +} + +void btc_a2dp_source_on_suspended(tBTA_AV_SUSPEND *p_av) +{ + /* check for status failures */ + if (p_av->status != BTA_AV_SUCCESS) { + if (p_av->initiator == TRUE) { + btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE); + } + } + + /* stop tx, ack to cmd, flush tx queue */ + btc_a2dp_source_tx_stop(); +} + +void btc_a2dp_source_on_stopped(tBTA_AV_SUSPEND *p_av) +{ + /* allow using this api for other than suspend */ + if (p_av != NULL) { + if (p_av->status != BTA_AV_SUCCESS) { + if (p_av->initiator) { + btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE); + } + return; + } + } + + /* stop tx, ack to cmd, flush tx queue */ + btc_a2dp_source_tx_stop(); +} + +void btc_a2dp_source_on_idle(void) +{ + /* stop tx, ack to cmd, flush tx queue */ + btc_a2dp_source_tx_stop(); +} + +bool btc_a2dp_source_is_task_shutting_down(void) +{ + /* always return false, remove this api when internal codec is remove */ + return false; +} + +bool btc_a2dp_source_startup(void) +{ + if (btc_a2dp_source_state != BTC_A2DP_SOURCE_STATE_OFF) { + APPL_TRACE_ERROR("%s A2DP source already start up", __func__); + return false; + } + +#if A2D_DYNAMIC_MEMORY == TRUE + if ((a2dp_source_local_param_ptr = (a2dp_source_local_param_t *)osi_malloc(sizeof(a2dp_source_local_param_t))) == NULL) { + APPL_TRACE_ERROR("%s malloc failed!", __func__); + return false; + } + memset((void *)a2dp_source_local_param_ptr, 0, sizeof(a2dp_source_local_param_t)); +#endif + + btc_a2dp_source_state = BTC_A2DP_SOURCE_STATE_ON; + + a2dp_source_local_param.audio_tx_q = fixed_queue_new(QUEUE_SIZE_MAX); + if(a2dp_source_local_param.audio_tx_q == NULL) { + goto error_exit; + } + + btc_a2dp_control_init(); + + return true; + +error_exit:; + APPL_TRACE_ERROR("%s A2DP source start up failed", __func__); + +#if A2D_DYNAMIC_MEMORY == TRUE + osi_free(a2dp_source_local_param_ptr); + a2dp_source_local_param_ptr = NULL; +#endif + + return false; +} + +void btc_a2dp_source_shutdown(void) +{ + if (btc_a2dp_source_state != BTC_A2DP_SOURCE_STATE_ON) { + APPL_TRACE_ERROR("%s A2DP source already shutdown", __func__); + return; + } + btc_a2dp_source_state = BTC_A2DP_SOURCE_STATE_OFF; + + btc_a2dp_control_cleanup(); + + fixed_queue_free(a2dp_source_local_param.audio_tx_q, osi_free_func); + + a2dp_source_local_param.audio_tx_q = NULL; + a2dp_source_local_param.tx_flush = FALSE; + a2dp_source_local_param.stream_started = FALSE; + +#if A2D_DYNAMIC_MEMORY == TRUE + osi_free(a2dp_source_local_param_ptr); + a2dp_source_local_param_ptr = NULL; +#endif +} + +#endif /* (BTC_AV_SRC_INCLUDED == TRUE) && (BTC_AV_EXT_CODEC == TRUE) */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c b/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c index 4c237b1e..f13d1255 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c +++ b/lib/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,6 +22,7 @@ #include "btc/btc_common.h" #include "btc/btc_manage.h" #include "btc_av.h" +#include "btc_av_co.h" #include "btc_avrc.h" #include "btc/btc_util.h" #include "btc/btc_profile_queue.h" @@ -34,7 +35,7 @@ #if BTC_AV_INCLUDED -// global variable to inidcate avrc is initialized with a2dp +// global variable to indicate avrc is initialized with a2dp bool g_av_with_rc; // global variable to indicate a2dp is initialized bool g_a2dp_on_init; @@ -46,6 +47,9 @@ bool g_a2dp_source_ongoing_deinit; bool g_a2dp_sink_ongoing_deinit; +/* reserve some bytes for media payload header (currently, only SBC, 1 byte) */ +#define BTC_AV_AUDIO_MTU_RESERVE 1 + /***************************************************************************** ** Constants & Macros ******************************************************************************/ @@ -74,6 +78,9 @@ typedef enum { #define BTC_AV_FLAG_PENDING_START 0x4 #define BTC_AV_FLAG_PENDING_STOP 0x8 +#define BTC_AV_SBC_CIE_OFFSET 3 +#define BTC_AV_SBC_CIE_LEN 4 + /***************************************************************************** ** Local type definitions ******************************************************************************/ @@ -81,11 +88,13 @@ typedef enum { typedef struct { int service_id; tBTA_AV_HNDL bta_handle; + UINT16 mtu; bt_bdaddr_t peer_bda; btc_sm_handle_t sm_handle; UINT8 flags; tBTA_AV_EDR edr; UINT8 peer_sep; /* sep type of peer device */ + tBTC_AV_CODEC_INFO codec_caps; #if BTC_AV_SRC_INCLUDED osi_alarm_t *tle_av_open_on_rc; #endif /* BTC_AV_SRC_INCLUDED */ @@ -127,6 +136,8 @@ static btc_av_cb_t *btc_av_cb_ptr = NULL; case BTA_AV_META_MSG_EVT: \ case BTA_AV_RC_FEAT_EVT: \ case BTA_AV_REMOTE_RSP_EVT: \ + case BTA_AV_CA_STATUS_EVT: \ + case BTA_AV_CA_DATA_EVT: \ { \ btc_rc_handler(e, d);\ }break; \ @@ -168,6 +179,7 @@ static void btc_av_event_free_data(btc_msg_t *msg); extern tBTA_AV_CO_FUNCTS bta_av_a2d_cos; extern tBTA_AVRC_CO_FUNCTS bta_avrc_cos; +extern tA2D_SBC_CIE btc_av_sbc_default_config; /***************************************************************************** ** Local helper functions ******************************************************************************/ @@ -220,7 +232,7 @@ UNUSED_ATTR static const char *dump_av_sm_event_name(btc_av_sm_event_t event) CASE_RETURN_STR(BTC_AV_DISCONNECT_REQ_EVT) CASE_RETURN_STR(BTC_AV_START_STREAM_REQ_EVT) CASE_RETURN_STR(BTC_AV_SUSPEND_STREAM_REQ_EVT) - CASE_RETURN_STR(BTC_AV_SINK_CONFIG_REQ_EVT) + CASE_RETURN_STR(BTC_AV_CONFIG_EVT) default: return "UNKNOWN_EVENT"; } } @@ -261,7 +273,7 @@ static void btc_initiate_av_open_tmr_hdlr(void *arg) /***************************************************************************** ** Static functions ******************************************************************************/ -static void btc_report_connection_state(esp_a2d_connection_state_t state, bt_bdaddr_t *bd_addr, int disc_rsn) +static void btc_report_connection_state(esp_a2d_connection_state_t state, bt_bdaddr_t *bd_addr, uint16_t mtu, int disc_rsn) { // todo: add callback for SRC esp_a2d_cb_param_t param; @@ -270,8 +282,15 @@ static void btc_report_connection_state(esp_a2d_connection_state_t state, bt_bda param.conn_stat.state = state; if (bd_addr) { memcpy(param.conn_stat.remote_bda, bd_addr, sizeof(esp_bd_addr_t)); + if (memcmp(bd_addr, &(btc_av_cb.peer_bda), sizeof(bt_bdaddr_t)) == 0) { + param.conn_stat.conn_hdl = btc_av_cb.bta_handle; + } + } + if (state == ESP_A2D_CONNECTION_STATE_CONNECTED) { + param.conn_stat.audio_mtu = mtu; + btc_av_cb.mtu = mtu; } - if (state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) { + else if (state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) { param.conn_stat.disc_rsn = (disc_rsn == 0) ? ESP_A2D_DISC_RSN_NORMAL : ESP_A2D_DISC_RSN_ABNORMAL; } @@ -287,6 +306,9 @@ static void btc_report_audio_state(esp_a2d_audio_state_t state, bt_bdaddr_t *bd_ param.audio_stat.state = state; if (bd_addr) { memcpy(param.audio_stat.remote_bda, bd_addr, sizeof(esp_bd_addr_t)); + if (memcmp(bd_addr, &(btc_av_cb.peer_bda), sizeof(bt_bdaddr_t)) == 0) { + param.audio_stat.conn_hdl = btc_av_cb.bta_handle; + } } btc_a2d_cb_to_app(ESP_A2D_AUDIO_STATE_EVT, ¶m); } @@ -326,6 +348,12 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data) case BTA_AV_REGISTER_EVT: btc_av_cb.bta_handle = ((tBTA_AV *)p_data)->registr.hndl; break; + case BTA_AV_SEP_REG_EVT: + param.a2d_sep_reg_stat.seid = ((tBTA_AV *)p_data)->sep_reg.seid; + param.a2d_sep_reg_stat.reg_state = (((tBTA_AV *)p_data)->sep_reg.reg_state == BTA_AV_SUCCESS) ? ESP_A2D_SEP_REG_SUCCESS : + ESP_A2D_SEP_REG_FAIL; + btc_a2d_cb_to_app(ESP_A2D_SEP_REG_STATE_EVT, ¶m); + break; case BTA_AV_PENDING_EVT: case BTC_AV_CONNECT_REQ_EVT: { @@ -356,7 +384,7 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data) case BTC_AV_DISCONNECT_REQ_EVT: BTC_TRACE_WARNING("No Link At All."); - btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &((btc_av_disconn_req_t *)p_data)->target_bda, 0); + btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &((btc_av_disconn_req_t *)p_data)->target_bda, 0, 0); break; case BTA_AV_RC_OPEN_EVT: @@ -382,6 +410,8 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data) case BTA_AV_META_MSG_EVT: case BTA_AV_RC_FEAT_EVT: case BTA_AV_REMOTE_RSP_EVT: + case BTA_AV_CA_STATUS_EVT: + case BTA_AV_CA_DATA_EVT: btc_rc_handler(event, (tBTA_AV *)p_data); break; @@ -444,7 +474,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) switch (event) { case BTC_SM_ENTER_EVT: /* inform the application that we are entering connecting state */ - btc_report_connection_state(ESP_A2D_CONNECTION_STATE_CONNECTING, &(btc_av_cb.peer_bda), 0); + btc_report_connection_state(ESP_A2D_CONNECTION_STATE_CONNECTING, &(btc_av_cb.peer_bda), 0, 0); break; case BTC_SM_EXIT_EVT: @@ -452,7 +482,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) case BTA_AV_REJECT_EVT: BTC_TRACE_WARNING(" Received BTA_AV_REJECT_EVT \n"); - btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), 0); + btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), 0, 0); btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE); break; @@ -460,13 +490,14 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) tBTA_AV *p_bta_data = (tBTA_AV *)p_data; esp_a2d_connection_state_t conn_stat; btc_sm_state_t av_state; + uint16_t mtu = 0; BTC_TRACE_DEBUG("status:%d, edr 0x%x, peer sep %d\n", p_bta_data->open.status, p_bta_data->open.edr, p_bta_data->open.sep); if (p_bta_data->open.status == BTA_AV_SUCCESS) { btc_av_cb.edr = p_bta_data->open.edr; btc_av_cb.peer_sep = p_bta_data->open.sep; - + mtu = p_bta_data->open.mtu - BTC_AV_AUDIO_MTU_RESERVE; conn_stat = ESP_A2D_CONNECTION_STATE_CONNECTED; av_state = BTC_AV_STATE_OPENED; } else { @@ -476,7 +507,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) av_state = BTC_AV_STATE_IDLE; } /* inform the application of the event */ - btc_report_connection_state(conn_stat, &(btc_av_cb.peer_bda), 0); + btc_report_connection_state(conn_stat, &(btc_av_cb.peer_bda), mtu, 0); /* change state to open/idle based on the status */ btc_sm_change_state(btc_av_cb.sm_handle, av_state); @@ -498,13 +529,12 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) btc_queue_advance(); } break; - case BTC_AV_SINK_CONFIG_REQ_EVT: { - if (btc_av_cb.peer_sep == AVDT_TSEP_SRC) { - esp_a2d_cb_param_t param; - memcpy(param.audio_cfg.remote_bda, &btc_av_cb.peer_bda, sizeof(esp_bd_addr_t)); - memcpy(¶m.audio_cfg.mcc, p_data, sizeof(esp_a2d_mcc_t)); - btc_a2d_cb_to_app(ESP_A2D_AUDIO_CFG_EVT, ¶m); - } + case BTC_AV_CONFIG_EVT: { + esp_a2d_cb_param_t param; + param.audio_cfg.conn_hdl = btc_av_cb.bta_handle; + memcpy(param.audio_cfg.remote_bda, &btc_av_cb.peer_bda, sizeof(esp_bd_addr_t)); + memcpy(¶m.audio_cfg.mcc, p_data, sizeof(esp_a2d_mcc_t)); + btc_a2d_cb_to_app(ESP_A2D_AUDIO_CFG_EVT, ¶m); } break; case BTC_AV_CONNECT_REQ_EVT: @@ -516,7 +546,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) break; } else { BTC_TRACE_DEBUG("%s: Moved from idle by Incoming Connection request\n", __func__); - btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, (bt_bdaddr_t *)p_data, 0); + btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, (bt_bdaddr_t *)p_data, 0, 0); btc_queue_advance(); break; } @@ -619,7 +649,7 @@ static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data) case BTA_AV_CLOSE_EVT: { tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data; /* inform the application that we are disconnecting */ - btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), close->disc_rsn); + btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), 0, close->disc_rsn); btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE); break; } @@ -689,7 +719,9 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data) case BTC_AV_START_STREAM_REQ_EVT: #if BTC_AV_SRC_INCLUDED if (btc_av_cb.peer_sep != AVDT_TSEP_SRC) { +#if (BTC_AV_EXT_CODEC == FALSE) btc_a2dp_source_setup_codec(); +#endif } #endif /* BTC_AV_SRC_INCLUDED */ BTA_AvStart(); @@ -755,7 +787,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data) } /* inform the application that we are disconnecting */ - btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btc_av_cb.peer_bda), 0); + btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btc_av_cb.peer_bda), 0, 0); break; case BTA_AV_CLOSE_EVT: { @@ -763,7 +795,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data) btc_a2dp_on_stopped(NULL); tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data; /* inform the application that we are disconnected */ - btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), + btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), 0, close->disc_rsn); if (btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) { @@ -800,7 +832,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data) } else { BTC_TRACE_DEBUG("%s: Moved to opened by Other Incoming Conn req\n", __func__); btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, - (bt_bdaddr_t *)p_data, ESP_A2D_DISC_RSN_NORMAL); + (bt_bdaddr_t *)p_data, 0, ESP_A2D_DISC_RSN_NORMAL); } btc_queue_advance(); break; @@ -913,7 +945,7 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data) } /* inform the application that we are disconnecting */ - btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btc_av_cb.peer_bda), 0); + btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTING, &(btc_av_cb.peer_bda), 0, 0); /* wait in closing state until fully closed */ btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_CLOSING); @@ -978,7 +1010,7 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data) btc_a2dp_on_stopped(NULL); tBTA_AV_CLOSE *close = (tBTA_AV_CLOSE *)p_data; /* inform the application that we are disconnected */ - btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), + btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), 0, close->disc_rsn); btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE); @@ -1333,7 +1365,7 @@ static void bte_av_callback(tBTA_AV_EVT event, tBTA_AV *p_data) } #if BTC_AV_SINK_INCLUDED -static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data) +static void bte_av_media_sink_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data) { btc_sm_state_t state; UINT8 que_len; @@ -1347,15 +1379,18 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data) que_len = btc_a2dp_sink_enque_buf((BT_HDR *)p_data); BTC_TRACE_DEBUG(" Packets in Que %d\n", que_len); } else { + osi_free(p_data); return; } } - if (event == BTA_AV_MEDIA_SINK_CFG_EVT) { + if (event == BTA_AV_MEDIA_CFG_EVT) { +#if (BTC_AV_EXT_CODEC == FALSE) /* send a command to BT Media Task */ btc_a2dp_sink_reset_decoder((UINT8 *)p_data); +#endif - /* currently only supportes SBC */ + /* currently only supports SBC */ a2d_status = A2D_ParsSbcInfo(&sbc_cie, (UINT8 *)p_data, FALSE); if (a2d_status == A2D_SUCCESS) { btc_msg_t msg; @@ -1363,11 +1398,11 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data) msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_A2DP; - msg.act = BTC_AV_SINK_CONFIG_REQ_EVT; + msg.act = BTC_AV_CONFIG_EVT; memset(&arg, 0, sizeof(btc_av_args_t)); arg.mcc.type = ESP_A2D_MCT_SBC; - memcpy(arg.mcc.cie.sbc, (uint8_t *)p_data + 3, ESP_A2D_CIE_LEN_SBC); + memcpy(&arg.mcc.cie.sbc_info, (uint8_t *)p_data + BTC_AV_SBC_CIE_OFFSET, BTC_AV_SBC_CIE_LEN); btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL); } else { BTC_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d\n", a2d_status); @@ -1376,7 +1411,42 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data) UNUSED(que_len); } #else -static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data) +static void bte_av_media_sink_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data) +{ + UNUSED(event); + UNUSED(p_data); + BTC_TRACE_WARNING("%s : event %u\n", __func__, event); +} +#endif + +#if BTC_AV_SRC_INCLUDED +static void bte_av_media_source_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data) +{ + tA2D_STATUS a2d_status; + tA2D_SBC_CIE sbc_cie; + + if (event == BTA_AV_MEDIA_CFG_EVT) { + /* currently only supports SBC */ + a2d_status = A2D_ParsSbcInfo(&sbc_cie, (UINT8 *)p_data, FALSE); + if (a2d_status == A2D_SUCCESS) { + btc_msg_t msg; + btc_av_args_t arg; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_A2DP; + msg.act = BTC_AV_CONFIG_EVT; + + memset(&arg, 0, sizeof(btc_av_args_t)); + arg.mcc.type = ESP_A2D_MCT_SBC; + memcpy(&arg.mcc.cie.sbc_info, (uint8_t *)p_data + BTC_AV_SBC_CIE_OFFSET, BTC_AV_SBC_CIE_LEN); + btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL); + } else { + BTC_TRACE_ERROR("A2D_ParsSbcInfo fail:%d\n", a2d_status); + } + } +} +#else +static void bte_av_media_source_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data) { UNUSED(event); UNUSED(p_data); @@ -1384,6 +1454,47 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data) } #endif +#if (BTC_AV_EXT_CODEC == TRUE) + +tBTC_AV_CODEC_INFO *btc_av_codec_cap_get(void) +{ + return &btc_av_cb.codec_caps; +} + +static void btc_av_reg_sep(uint8_t tsep, uint8_t seid, esp_a2d_mcc_t *mcc) +{ + tBTA_AV_DATA_CBACK *p_data_cback = NULL; + esp_a2d_cb_param_t param; + + param.a2d_sep_reg_stat.seid = seid; + if (btc_av_cb.sm_handle == NULL || btc_sm_get_state(btc_av_cb.sm_handle) != BTC_AV_STATE_IDLE) { + param.a2d_sep_reg_stat.reg_state = ESP_A2D_SEP_REG_INVALID_STATE; + btc_a2d_cb_to_app(ESP_A2D_SEP_REG_STATE_EVT, ¶m); + BTC_TRACE_WARNING("%s: try to reg sep when a2dp not init or connected", __func__); + } + + if (mcc->type == ESP_A2D_MCT_SBC) { + A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, (tA2D_SBC_CIE *)&btc_av_sbc_default_config, btc_av_cb.codec_caps.info); + /* overwrite sbc cie */ + memcpy(btc_av_cb.codec_caps.info + A2D_SBC_CIE_OFF, &mcc->cie, A2D_SBC_CIE_LEN); + + if (tsep == AVDT_TSEP_SNK) { + p_data_cback = bte_av_media_sink_callback; + } + else { + p_data_cback = bte_av_media_source_callback; + } + BTA_AvRegSEP(BTA_AV_CHNL_AUDIO, seid, tsep, BTA_AV_CODEC_SBC, btc_av_cb.codec_caps.info, p_data_cback); + } + else { + param.a2d_sep_reg_stat.reg_state = ESP_A2D_SEP_REG_UNSUPPORTED; + btc_a2d_cb_to_app(ESP_A2D_SEP_REG_STATE_EVT, ¶m); + BTC_TRACE_WARNING("%s: unsupported codec type %d", __func__, mcc->type); + } +} + +#endif + /******************************************************************************* ** ** Function btc_av_execute_service @@ -1395,7 +1506,15 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data) *******************************************************************************/ bt_status_t btc_av_execute_service(BOOLEAN b_enable, UINT8 tsep) { + tBTA_AV_DATA_CBACK *p_data_cback = NULL; + if (b_enable) { + if (tsep == AVDT_TSEP_SNK) { + p_data_cback = bte_av_media_sink_callback; + } + else { + p_data_cback = bte_av_media_source_callback; + } /* TODO: Removed BTA_SEC_AUTHORIZE since the Java/App does not * handle this request in order to allow incoming connections to succeed. * We need to put this back once support for this is added */ @@ -1409,11 +1528,11 @@ bt_status_t btc_av_execute_service(BOOLEAN b_enable, UINT8 tsep) BTA_AV_FEAT_RCTG | BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_RCCT | BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_DELAY_RPT, bte_av_callback); - BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, bte_av_media_callback, &bta_av_a2d_cos, &bta_avrc_cos, tsep); + BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, p_data_cback, &bta_av_a2d_cos, &bta_avrc_cos, tsep); } else { BTC_TRACE_WARNING("A2DP Enable without AVRC") BTA_AvEnable(BTA_SEC_AUTHENTICATE, BTA_AV_FEAT_NO_SCO_SSPD | BTA_AV_FEAT_DELAY_RPT, bte_av_callback); - BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, bte_av_media_callback, &bta_av_a2d_cos, NULL, tsep); + BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTC_AV_SERVICE_NAME, 0, p_data_cback, &bta_av_a2d_cos, NULL, tsep); } } else { BTA_AvDeregister(btc_av_cb.bta_handle); @@ -1472,6 +1591,11 @@ BOOLEAN btc_av_is_connected(void) return ((state == BTC_AV_STATE_OPENED) || (state == BTC_AV_STATE_STARTED)); } +BOOLEAN btc_av_is_started(void) +{ + return ((btc_sm_get_state(btc_av_cb.sm_handle) == BTC_AV_STATE_STARTED)); +} + /******************************************************************************* * * Function btc_av_get_service_id @@ -1544,15 +1668,17 @@ void btc_a2dp_call_handler(btc_msg_t *msg) btc_av_args_t *arg = (btc_av_args_t *)(msg->arg); switch (msg->act) { #if BTC_AV_SINK_INCLUDED - case BTC_AV_SINK_CONFIG_REQ_EVT: { - btc_sm_dispatch(btc_av_cb.sm_handle, msg->act, (void *)(msg->arg)); - break; - } case BTC_AV_SINK_API_INIT_EVT: { btc_a2d_sink_init(); // todo: callback to application break; } +#if (BTC_AV_EXT_CODEC == TRUE) + case BTC_AV_SINK_API_REG_SEP_EVT: { + btc_av_reg_sep(AVDT_TSEP_SNK, arg->reg_sep.seid, &arg->reg_sep.mcc); + break; + } +#endif case BTC_AV_SINK_API_DEINIT_EVT: { btc_a2d_sink_deinit(); // todo: callback to application @@ -1570,10 +1696,17 @@ void btc_a2dp_call_handler(btc_msg_t *msg) btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_DISCONNECT_REQ_EVT, &disconn_req); break; } +#if (BTC_AV_EXT_CODEC == TRUE) + case BTC_AV_SINK_API_REG_AUDIO_DATA_CB_EVT: { + btc_a2dp_sink_reg_audio_data_cb(arg->audio_data_cb); + break; + } +#else case BTC_AV_SINK_API_REG_DATA_CB_EVT: { btc_a2dp_sink_reg_data_cb(arg->data_cb); break; } +#endif case BTC_AV_SINK_API_SET_DELAY_VALUE_EVT: { btc_a2d_sink_set_delay_value(arg->delay_value); break; @@ -1588,6 +1721,12 @@ void btc_a2dp_call_handler(btc_msg_t *msg) btc_a2d_src_init(); break; } +#if (BTC_AV_EXT_CODEC == TRUE) + case BTC_AV_SRC_API_REG_SEP_EVT: { + btc_av_reg_sep(AVDT_TSEP_SRC, arg->reg_sep.seid, &arg->reg_sep.mcc); + break; + } +#endif case BTC_AV_SRC_API_DEINIT_EVT: { btc_a2d_src_deinit(); break; @@ -1603,10 +1742,12 @@ void btc_a2dp_call_handler(btc_msg_t *msg) btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_DISCONNECT_REQ_EVT, &disconn_req); break; } +#if (BTC_AV_EXT_CODEC == FALSE) case BTC_AV_SRC_API_REG_DATA_CB_EVT: { btc_a2dp_src_reg_data_cb(arg->src_data_cb); break; } +#endif #endif /* BTC_AV_SRC_INCLUDED */ case BTC_AV_API_MEDIA_CTRL_EVT: { btc_a2dp_control_media_ctrl(arg->ctrl); @@ -1632,6 +1773,35 @@ void btc_a2dp_cb_handler(btc_msg_t *msg) btc_av_event_free_data(msg); } +void btc_a2dp_get_profile_status(esp_a2d_profile_status_t *param) +{ + // Not initialized by default + param->a2d_snk_inited = false; + param->a2d_src_inited = false; + +#if A2D_DYNAMIC_MEMORY == TRUE + if (btc_av_cb_ptr) +#endif + { + if (btc_av_cb.sm_handle) { + if (btc_av_cb.service_id == BTA_A2DP_SINK_SERVICE_ID) { + param->a2d_src_inited = false; + param->a2d_snk_inited = true; + } else if (btc_av_cb.service_id == BTA_A2DP_SOURCE_SERVICE_ID) { + param->a2d_src_inited = true; + param->a2d_snk_inited = false; + } else { + param->a2d_snk_inited = false; + param->a2d_src_inited = false; + return; + } + if (btc_av_is_connected()) { + param->conn_num++; + } + } + } +} + #if BTC_AV_SINK_INCLUDED /******************************************************************************* @@ -1730,6 +1900,56 @@ static bt_status_t btc_a2d_src_connect(bt_bdaddr_t *remote_bda) return btc_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, remote_bda, connect_int); } +BOOLEAN btc_a2d_src_audio_mtu_check(uint16_t data_len) +{ + + return (data_len <= btc_av_cb.mtu); +} + +bt_status_t btc_a2d_src_audio_data_send(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf) +{ +#if (BTC_AV_EXT_CODEC == TRUE) + if (conn_hdl != btc_av_cb.bta_handle) { + return BT_STATUS_FAIL; + } + BT_HDR *p_buf = (BT_HDR *)audio_buf; + assert(audio_buf->data - (UINT8 *)(p_buf + 1) >= BTC_AUDIO_BUFF_OFFSET); + /* since p_buf and audio_buf point to the same memory, backup those value before modify p_buf */ + uint16_t number_frame = audio_buf->number_frame; + uint16_t data_len = audio_buf->data_len; + uint32_t timestamp = audio_buf->timestamp; + p_buf->offset = audio_buf->data - (UINT8 *)(p_buf + 1); + p_buf->layer_specific = number_frame; + p_buf->len = data_len; + *((UINT32 *) (p_buf + 1)) = timestamp; + + if (btc_a2dp_source_enqueue_audio_frame(p_buf)) { + return BT_STATUS_SUCCESS; + } +#endif + return BT_STATUS_FAIL; +} + #endif /* BTC_AV_SRC_INCLUDED */ +uint16_t btc_a2d_conn_handle_get(void) +{ + return btc_av_cb.bta_handle; +} + +void btc_av_audio_buff_alloc(uint16_t size, uint8_t **pp_buff, uint8_t **pp_data) +{ + /* todo */ + BT_HDR *p_buf= (BT_HDR *)osi_calloc(sizeof(BT_HDR) + BTC_AUDIO_BUFF_OFFSET + size); + if (p_buf != NULL) { + *pp_buff = (uint8_t *)p_buf; + *pp_data = (uint8_t *)(p_buf + 1) + BTC_AUDIO_BUFF_OFFSET; + } +} + +void btc_av_audio_buff_free(uint8_t *p_buf) +{ + osi_free(p_buf); +} + #endif /* #if BTC_AV_INCLUDED */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/a2dp/include/btc_av_co.h b/lib/bt/host/bluedroid/btc/profile/std/a2dp/include/btc_av_co.h index 34d7a729..9a4f6280 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/a2dp/include/btc_av_co.h +++ b/lib/bt/host/bluedroid/btc/profile/std/a2dp/include/btc_av_co.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -64,6 +64,7 @@ typedef struct { typedef struct { /* Connected peer information */ tBTA_AV_CO_PEER peers[BTA_AV_NUM_STRS]; + tBTC_AV_CODEC_INFO codec_caps; /* Current codec configuration - access to this variable must be protected */ tBTC_AV_CODEC_INFO codec_cfg; tBTC_AV_CODEC_INFO codec_cfg_setconfig; /* remote peer setconfig preference */ @@ -189,8 +190,7 @@ void bta_av_co_audio_discard_config(tBTA_AV_HNDL hndl); ** Returns Nothing ** *******************************************************************************/ -void bta_av_co_init(void); - +void bta_av_co_init(tBTC_AV_CODEC_INFO *codec_caps); /******************************************************************************* ** @@ -211,7 +211,7 @@ BOOLEAN bta_av_co_peer_cp_supported(tBTA_AV_HNDL hndl); ** of our exported bitpool range. If set we will set the ** remote preference. ** - ** Returns TRUE if config set, FALSE otherwize + ** Returns TRUE if config set, FALSE otherwise ** *******************************************************************************/ BOOLEAN bta_av_co_get_remote_bitpool_pref(UINT8 *min, UINT8 *max); diff --git a/lib/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c b/lib/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c index 7e7f1b2b..3ed8a02a 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c +++ b/lib/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -40,7 +40,7 @@ static void btc_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 c ** Static variables ******************************************************************************/ -/* flag indicating wheter TG/CT is initialized */ +/* flag indicating whether TG/CT is initialized */ static uint32_t s_rc_ct_init; static uint32_t s_rc_tg_init; @@ -157,6 +157,11 @@ bool btc_avrc_ct_rn_evt_supported(uint8_t event_id) true : false; } +bool btc_avrc_ct_check_cover_art_support(void) +{ + return (btc_rc_cb.rc_features & BTA_AV_FEAT_COVER_ART); +} + bool btc_avrc_tg_init_p(void) { return (s_rc_tg_init == BTC_RC_TG_INIT_MAGIC); @@ -170,8 +175,7 @@ bool btc_avrc_ct_init_p(void) bool btc_avrc_tg_connected_p(void) { return (s_rc_tg_init == BTC_RC_TG_INIT_MAGIC) && - (btc_rc_cb.rc_connected == TRUE) && - (btc_rc_cb.rc_features & BTA_AV_FEAT_RCCT); + (btc_rc_cb.rc_connected == TRUE); } bool btc_avrc_ct_connected_p(void) @@ -181,6 +185,52 @@ bool btc_avrc_ct_connected_p(void) (btc_rc_cb.rc_features & BTA_AV_FEAT_RCTG); } +void btc_avrc_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + btc_avrc_args_t *dst = (btc_avrc_args_t *)p_dest; + btc_avrc_args_t *src = (btc_avrc_args_t *)p_src; + size_t len; + + switch (msg->act) { +#if BTC_AV_CA_INCLUDED + case BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_EVT: + len = src->ca_get_img.image_descriptor_len; + dst->ca_get_img.image_descriptor = (uint8_t *)osi_malloc(len); + if (dst->ca_get_img.image_descriptor) { + memcpy(dst->ca_get_img.image_descriptor, src->ca_get_img.image_descriptor, len); + } else { + BTC_TRACE_ERROR("%s %d no mem\n", __FUNCTION__, msg->act); + } + break; +#endif + default: + BTC_TRACE_DEBUG("%s Unhandled deep copy %d\n", __FUNCTION__, msg->act); + UNUSED(dst); + UNUSED(src); + UNUSED(len); + break; + } +} + +void btc_avrc_arg_deep_free(btc_msg_t *msg) +{ + btc_avrc_args_t *arg = (btc_avrc_args_t *)msg->arg; + + switch (msg->act) { +#if BTC_AV_CA_INCLUDED + case BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_EVT: + if (arg->ca_get_img.image_descriptor) { + osi_free(arg->ca_get_img.image_descriptor); + } + break; +#endif + default: + BTC_TRACE_DEBUG("%s Unhandled deep free %d\n", __FUNCTION__, msg->act); + UNUSED(arg); + break; + } +} + void btc_avrc_tg_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) { btc_avrc_tg_args_t *dst = (btc_avrc_tg_args_t *) p_dest; @@ -253,10 +303,6 @@ static bool btc_avrc_tg_set_rn_supported_evt(uint16_t evt_set) static inline void btc_avrc_ct_cb_to_app(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param) { - if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) { - return; - } - esp_avrc_ct_cb_t btc_avrc_ct_cb = (esp_avrc_ct_cb_t)btc_profile_cb_get(BTC_PID_AVRC_CT); if (btc_avrc_ct_cb) { btc_avrc_ct_cb(event, param); @@ -265,10 +311,6 @@ static inline void btc_avrc_ct_cb_to_app(esp_avrc_ct_cb_event_t event, esp_avrc_ static inline void btc_avrc_tg_cb_to_app(esp_avrc_tg_cb_event_t event, esp_avrc_tg_cb_param_t *param) { - if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) { - return; - } - esp_avrc_tg_cb_t btc_avrc_tg_cb = (esp_avrc_tg_cb_t)btc_profile_cb_get(BTC_PID_AVRC_TG); if (btc_avrc_tg_cb) { btc_avrc_tg_cb(event, param); @@ -456,7 +498,7 @@ static void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open) btc_avrc_ct_cb_to_app(ESP_AVRC_CT_CONNECTION_STATE_EVT, ¶m); } - if (p_rc_open->peer_features & BTA_AV_FEAT_RCCT) { + if (btc_avrc_tg_init_p()) { esp_avrc_tg_cb_param_t param; memset(¶m, 0, sizeof(esp_avrc_tg_cb_param_t)); param.conn_stat.connected = true; @@ -499,14 +541,28 @@ static void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close) // clean up the state btc_rc_cb.rc_handle = 0; btc_rc_cb.rc_connected = FALSE; - +#if BTC_AV_CA_INCLUDED + bool cover_art_connected = btc_rc_cb.rc_cover_art_connected; + btc_rc_cb.rc_cover_art_connected = FALSE; +#endif btc_rc_cb.rc_features = 0; btc_rc_cb.rc_ct_features = 0; btc_rc_cb.rc_tg_features = 0; memset(btc_rc_cb.rc_addr, 0, sizeof(BD_ADDR)); memset(btc_rc_cb.rc_ntf, 0, sizeof(btc_rc_cb.rc_ntf)); +#if BTC_AV_CA_INCLUDED /* report connection state */ + if (cover_art_connected) { + /* if rc disconnect, cover art disconnect too */ + esp_avrc_ct_cb_param_t param; + memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t)); + param.cover_art_state.state = ESP_AVRC_COVER_ART_DISCONNECTED; + param.cover_art_state.reason = BT_STATUS_FAIL; + btc_avrc_ct_cb_to_app(ESP_AVRC_CT_COVER_ART_STATE_EVT, ¶m); + } +#endif + if (rc_features & BTA_AV_FEAT_RCTG) { esp_avrc_ct_cb_param_t param; memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t)); @@ -515,7 +571,7 @@ static void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close) btc_avrc_ct_cb_to_app(ESP_AVRC_CT_CONNECTION_STATE_EVT, ¶m); } - if (rc_features & BTA_AV_FEAT_RCCT) { + if (btc_avrc_tg_init_p()) { esp_avrc_tg_cb_param_t param; memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t)); param.conn_stat.connected = false; @@ -636,6 +692,18 @@ static void handle_rc_set_absolute_volume_rsp(tAVRC_SET_VOLUME_RSP *rsp) btc_avrc_ct_cb_to_app(ESP_AVRC_CT_SET_ABSOLUTE_VOLUME_RSP_EVT, ¶m); } +static void handle_rc_get_play_status_rsp(tAVRC_GET_PLAY_STATUS_RSP *rsp) +{ + esp_avrc_ct_cb_param_t param; + memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t)); + + param.play_status_rsp.song_length = rsp->song_len; + param.play_status_rsp.song_position = rsp->song_pos; + param.play_status_rsp.play_status = rsp->play_status; + + btc_avrc_ct_cb_to_app(ESP_AVRC_CT_PLAY_STATUS_RSP_EVT, ¶m); +} + /*************************************************************************** * Function handle_rc_metamsg_cmd * @@ -751,7 +819,7 @@ static void btc_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 c btc_rc_cb.rc_ntf[event_id - 1].registered = TRUE; btc_rc_cb.rc_ntf[event_id - 1].label = label; - BTC_TRACE_EVENT("%s: New registerd notification: event_id:0x%x, label:0x%x", + BTC_TRACE_EVENT("%s: New registered notification: event_id:0x%x, label:0x%x", __FUNCTION__, event_id, label); // set up callback @@ -834,6 +902,9 @@ static void handle_rc_metamsg_rsp (tBTA_AV_META_MSG *p_meta_msg) handle_rc_set_absolute_volume_rsp(&avrc_response.volume); } break; + case AVRC_PDU_GET_PLAY_STATUS: + handle_rc_get_play_status_rsp(&avrc_response.get_play_status); + break; default: BTC_TRACE_WARNING("%s: unhandled meta rsp: pdu 0x%x", __FUNCTION__, avrc_response.rsp.pdu); } @@ -941,14 +1012,10 @@ void btc_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data) memcpy(param.conn_stat.remote_bda, btc_rc_cb.rc_addr, sizeof(esp_bd_addr_t)); btc_avrc_ct_cb_to_app(ESP_AVRC_CT_CONNECTION_STATE_EVT, ¶m); } - if ((p_data->rc_feat.peer_features & BTA_AV_FEAT_RCCT) && - !(old_feats & BTA_AV_FEAT_RCCT)) { - esp_avrc_tg_cb_param_t param; - memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t)); - param.conn_stat.connected = true; - memcpy(param.conn_stat.remote_bda, btc_rc_cb.rc_addr, sizeof(esp_bd_addr_t)); - btc_avrc_tg_cb_to_app(ESP_AVRC_CT_CONNECTION_STATE_EVT, ¶m); - } + /** + * @note ESP_AVRC_TG_CONNECTION_STATE_EVT has been reported on rc connect/disconnect event, + * it doesn't rely on the SDP results. + */ } while (0); btc_rc_cb.rc_features = p_data->rc_feat.peer_features; btc_rc_cb.rc_ct_features = p_data->rc_feat.peer_ct_features; @@ -967,6 +1034,36 @@ void btc_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data) handle_rc_passthrough_cmd(&p_data->remote_cmd); } break; +#if BTC_AV_CA_INCLUDED + case BTA_AV_CA_STATUS_EVT: { + btc_rc_cb.rc_cover_art_connected = p_data->ca_status.connected; + esp_avrc_ct_cb_param_t param; + memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t)); + if (p_data->ca_status.connected) { + param.cover_art_state.state = ESP_AVRC_COVER_ART_CONNECTED; + } + else { + param.cover_art_state.state = ESP_AVRC_COVER_ART_DISCONNECTED; + } + param.cover_art_state.reason = p_data->ca_status.reason; + btc_avrc_ct_cb_to_app(ESP_AVRC_CT_COVER_ART_STATE_EVT, ¶m); + } + break; + case BTA_AV_CA_DATA_EVT: { + esp_avrc_ct_cb_param_t param; + memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t)); + param.cover_art_data.status = p_data->ca_data.status; + param.cover_art_data.final = p_data->ca_data.final; + param.cover_art_data.data_len = p_data->ca_data.data_len; + param.cover_art_data.p_data = p_data->ca_data.p_data; + btc_avrc_ct_cb_to_app(ESP_AVRC_CT_COVER_ART_DATA_EVT, ¶m); + /* free the data packet now */ + if (p_data->ca_data.p_hdr != NULL) { + osi_free(p_data->ca_data.p_hdr); + } + } + break; +#endif /* BTC_AV_CA_INCLUDED */ default: BTC_TRACE_DEBUG("Unhandled RC event : 0x%x", event); } @@ -1003,27 +1100,39 @@ BOOLEAN btc_rc_get_connected_peer(BD_ADDR peer_addr) *******************************************************************************/ static void btc_avrc_ct_init(void) { - BTC_TRACE_DEBUG("## %s ##", __FUNCTION__); - if (s_rc_ct_init == BTC_RC_CT_INIT_MAGIC) { - BTC_TRACE_WARNING("%s already initialized", __FUNCTION__); - return; - } + esp_avrc_init_state_t state = ESP_AVRC_INIT_SUCCESS; - /// initialize CT-specific resources - s_rc_ct_init = BTC_RC_CT_INIT_MAGIC; + BTC_TRACE_DEBUG("## %s ##", __FUNCTION__); - /// initialize CT-TG shared resources - if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) { - memset (&btc_rc_cb, 0, sizeof(btc_rc_cb_t)); + do { - if (!g_av_with_rc) { - g_av_with_rc = true; + if (s_rc_ct_init == BTC_RC_CT_INIT_MAGIC) { + BTC_TRACE_WARNING("%s already initialized", __FUNCTION__); + state = ESP_AVRC_INIT_ALREADY; + break; } - if (g_a2dp_on_init) { - BTC_TRACE_WARNING("AVRC Controller is expected to be initialized in advance of A2DP !!!"); + /// initialize CT-TG shared resources + if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) { + if (g_a2dp_on_init) { + BTC_TRACE_WARNING("AVRC Controller is expected to be initialized in advance of A2DP !!!"); + state = ESP_AVRC_INIT_FAIL; + break; + } + memset (&btc_rc_cb, 0, sizeof(btc_rc_cb_t)); + + if (!g_av_with_rc) { + g_av_with_rc = true; + } } - } + + /// initialize CT-specific resources + s_rc_ct_init = BTC_RC_CT_INIT_MAGIC; + } while (0); + + esp_avrc_ct_cb_param_t param = {0}; + param.avrc_ct_init_stat.state = state; + btc_avrc_ct_cb_to_app(ESP_AVRC_CT_PROF_STATE_EVT, ¶m); } @@ -1038,29 +1147,37 @@ static void btc_avrc_ct_init(void) ***************************************************************************/ static void btc_avrc_ct_deinit(void) { + esp_avrc_init_state_t state = ESP_AVRC_DEINIT_SUCCESS; + BTC_TRACE_API("## %s ##", __FUNCTION__); - if (g_a2dp_on_deinit) { - BTC_TRACE_WARNING("A2DP already deinit, AVRC CT shuold deinit in advance of A2DP !!!"); - } + do { + if (g_a2dp_on_deinit) { + BTC_TRACE_WARNING("A2DP already deinit, AVRC CT should deinit in advance of A2DP !!!"); + } - if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) { - BTC_TRACE_WARNING("%s not initialized", __FUNCTION__); - return; - } + if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) { + BTC_TRACE_WARNING("%s not initialized", __FUNCTION__); + state = ESP_AVRC_DEINIT_ALREADY; + break; + } - /// deinit CT-specific resources - s_rc_ct_init = 0; + /// deinit CT-specific resources + s_rc_ct_init = 0; - /// deinit CT-TG shared resources - if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) { - memset (&btc_rc_cb, 0, sizeof(btc_rc_cb_t)); - if (g_av_with_rc) { - g_av_with_rc = false; + /// deinit CT-TG shared resources + if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) { + memset (&btc_rc_cb, 0, sizeof(btc_rc_cb_t)); + if (g_av_with_rc) { + g_av_with_rc = false; + } } - } + BTC_TRACE_API("## %s ## completed", __FUNCTION__); + } while (0); - BTC_TRACE_API("## %s ## completed", __FUNCTION__); + esp_avrc_ct_cb_param_t param = {0}; + param.avrc_ct_init_stat.state = state; + btc_avrc_ct_cb_to_app(ESP_AVRC_CT_PROF_STATE_EVT, ¶m); } static bt_status_t btc_avrc_ct_send_set_player_value_cmd(uint8_t tl, uint8_t attr_id, uint8_t value_id) @@ -1243,6 +1360,38 @@ static bt_status_t btc_avrc_ct_send_metadata_cmd (uint8_t tl, uint8_t attr_mask) return status; } +static bt_status_t btc_avrc_ct_send_get_play_status_cmd(uint8_t tl) +{ + tAVRC_STS status = BT_STATUS_UNSUPPORTED; + +#if (AVRC_METADATA_INCLUDED == TRUE) + CHECK_ESP_RC_CONNECTED; + + tAVRC_COMMAND avrc_cmd = {0}; + BT_HDR *p_msg = NULL; + + avrc_cmd.get_play_status.opcode = AVRC_OP_VENDOR; + avrc_cmd.get_play_status.status = AVRC_STS_NO_ERROR; + avrc_cmd.get_play_status.pdu = AVRC_PDU_GET_PLAY_STATUS; + + if (btc_rc_cb.rc_features & BTA_AV_FEAT_METADATA) { + status = AVRC_BldCommand(&avrc_cmd, &p_msg); + if (status == AVRC_STS_NO_ERROR) { + BTA_AvMetaCmd(btc_rc_cb.rc_handle, tl, AVRC_CMD_STATUS, p_msg); + status = BT_STATUS_SUCCESS; + } + } else { + status = BT_STATUS_FAIL; + BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__); + } + +#else + BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__); +#endif + + return status; +} + static bt_status_t btc_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code, uint8_t key_state) { tAVRC_STS status = BT_STATUS_UNSUPPORTED; @@ -1255,7 +1404,7 @@ static bt_status_t btc_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code BTA_AvRemoteCmd(btc_rc_cb.rc_handle, tl, (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state); status = BT_STATUS_SUCCESS; - BTC_TRACE_API("%s: succesfully sent passthrough command to BTA", __FUNCTION__); + BTC_TRACE_API("%s: successfully sent passthrough command to BTA", __FUNCTION__); } else { status = BT_STATUS_FAIL; BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__); @@ -1267,6 +1416,64 @@ static bt_status_t btc_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code return status; } +#if BTC_AV_CA_INCLUDED + +static void btc_avrc_ct_cover_art_connect(UINT16 mtu) +{ + if (!btc_rc_cb.rc_cover_art_connected) { + BTA_AvCaOpen(btc_rc_cb.rc_handle, mtu); + } + else { + BTC_TRACE_WARNING("%s: cover art already connected", __FUNCTION__); + } + return; +} + +static void btc_avrc_ct_cover_art_disconnect(void) +{ + if (btc_rc_cb.rc_cover_art_connected) { + BTA_AvCaClose(btc_rc_cb.rc_handle); + } + else { + BTC_TRACE_WARNING("%s: cover art not connected", __FUNCTION__); + } + return; +} + +static void btc_avrc_ct_cover_art_get_image_properties(UINT8 *image_handle) +{ + if (btc_rc_cb.rc_cover_art_connected) { + BTA_AvCaGet(btc_rc_cb.rc_handle, BTA_AV_CA_GET_IMAGE_PROPERTIES, image_handle, NULL, 0); + } + else { + BTC_TRACE_WARNING("%s: cover art not connected", __FUNCTION__); + } + return; +} + +static void btc_avrc_ct_cover_art_get_image(UINT8 *image_handle, UINT8 *image_descriptor, UINT16 image_descriptor_len) +{ + if (btc_rc_cb.rc_cover_art_connected) { + BTA_AvCaGet(btc_rc_cb.rc_handle, BTA_AV_CA_GET_IMAGE, image_handle, image_descriptor, image_descriptor_len); + } + else { + BTC_TRACE_WARNING("%s: cover art not connected", __FUNCTION__); + } + return; +} + +static void btc_avrc_ct_cover_art_get_linked_thumbnail(UINT8 *image_handle) +{ + if (btc_rc_cb.rc_cover_art_connected) { + BTA_AvCaGet(btc_rc_cb.rc_handle, BTA_AV_CA_GET_LINKED_THUMBNAIL, image_handle, NULL, 0); + } + else { + BTC_TRACE_WARNING("%s: cover art not connected", __FUNCTION__); + } + return; +} + +#endif /* BTC_AV_CA_INCLUDED */ /******************************************************************************* ** @@ -1279,30 +1486,42 @@ static bt_status_t btc_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code *******************************************************************************/ static void btc_avrc_tg_init(void) { + esp_avrc_init_state_t state = ESP_AVRC_INIT_SUCCESS; + BTC_TRACE_DEBUG("## %s ##", __FUNCTION__); - if (s_rc_tg_init == BTC_RC_TG_INIT_MAGIC) { - BTC_TRACE_WARNING("%s already initialized", __FUNCTION__); - return; - } - /// initialize TG-specific resources - memcpy(s_psth_supported_cmd, cs_psth_dft_supported_cmd, sizeof(s_psth_supported_cmd)); - s_rn_supported_evt = cs_rn_dft_supported_evt; + do { + if (s_rc_tg_init == BTC_RC_TG_INIT_MAGIC) { + BTC_TRACE_WARNING("%s already initialized", __FUNCTION__); + state = ESP_AVRC_INIT_ALREADY; + break; + } - /// initialize CT-TG shared resources - if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) { - memset (&btc_rc_cb, 0, sizeof(btc_rc_cb)); + /// initialize CT-TG shared resources + if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) { + if (g_a2dp_on_init) { + BTC_TRACE_WARNING("AVRC Target is expected to be initialized in advance of A2DP !!!"); + state = ESP_AVRC_INIT_FAIL; + break; + } - if (!g_av_with_rc) { - g_av_with_rc = true; - } + memset (&btc_rc_cb, 0, sizeof(btc_rc_cb)); - if (g_a2dp_on_init) { - BTC_TRACE_WARNING("AVRC Taget is expected to be initialized in advance of A2DP !!!"); + if (!g_av_with_rc) { + g_av_with_rc = true; + } } - } - s_rc_tg_init = BTC_RC_TG_INIT_MAGIC; + /// initialize TG-specific resources + memcpy(s_psth_supported_cmd, cs_psth_dft_supported_cmd, sizeof(s_psth_supported_cmd)); + s_rn_supported_evt = cs_rn_dft_supported_evt; + + s_rc_tg_init = BTC_RC_TG_INIT_MAGIC; + } while (0); + + esp_avrc_tg_cb_param_t param = {0}; + param.avrc_tg_init_stat.state = state; + btc_avrc_tg_cb_to_app(ESP_AVRC_TG_PROF_STATE_EVT, ¶m); } @@ -1317,31 +1536,40 @@ static void btc_avrc_tg_init(void) ***************************************************************************/ static void btc_avrc_tg_deinit(void) { + esp_avrc_init_state_t state = ESP_AVRC_DEINIT_SUCCESS; + BTC_TRACE_API("## %s ##", __FUNCTION__); - if (g_a2dp_on_deinit) { - BTC_TRACE_WARNING("A2DP already deinit, AVRC TG shuold deinit in advance of A2DP !!!"); - } + do { + if (g_a2dp_on_deinit) { + BTC_TRACE_WARNING("A2DP already deinit, AVRC TG should deinit in advance of A2DP !!!"); + } - if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) { - BTC_TRACE_WARNING("%s not initialized", __FUNCTION__); - return; - } + if (s_rc_tg_init != BTC_RC_TG_INIT_MAGIC) { + BTC_TRACE_WARNING("%s not initialized", __FUNCTION__); + state = ESP_AVRC_DEINIT_ALREADY; + break; + } - /// deinit TG-specific resources - memset(s_psth_supported_cmd, 0, sizeof(s_psth_supported_cmd)); - s_rn_supported_evt = 0; - s_rc_tg_init = 0; + /// deinit TG-specific resources + memset(s_psth_supported_cmd, 0, sizeof(s_psth_supported_cmd)); + s_rn_supported_evt = 0; + s_rc_tg_init = 0; - /// deinit CT-TG shared resources - if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) { - memset (&btc_rc_cb, 0, sizeof(btc_rc_cb)); - if (g_av_with_rc) { - g_av_with_rc = false; + /// deinit CT-TG shared resources + if (s_rc_ct_init != BTC_RC_CT_INIT_MAGIC) { + memset (&btc_rc_cb, 0, sizeof(btc_rc_cb)); + if (g_av_with_rc) { + g_av_with_rc = false; + } } - } - BTC_TRACE_API("## %s ## completed", __FUNCTION__); + BTC_TRACE_API("## %s ## completed", __FUNCTION__); + } while (0); + + esp_avrc_tg_cb_param_t param = {0}; + param.avrc_tg_init_stat.state = state; + btc_avrc_tg_cb_to_app(ESP_AVRC_TG_PROF_STATE_EVT, ¶m); } static void btc_avrc_tg_send_rn_rsp(esp_avrc_rn_event_ids_t event_id, esp_avrc_rn_rsp_t rsp, const esp_avrc_rn_param_t *param) @@ -1402,6 +1630,10 @@ void btc_avrc_ct_call_handler(btc_msg_t *msg) btc_avrc_ct_send_metadata_cmd(arg->md_cmd.tl, arg->md_cmd.attr_mask); break; } + case BTC_AVRC_STATUS_API_SND_GET_PLAY_STATUS_EVT: { + btc_avrc_ct_send_get_play_status_cmd(arg->get_play_status_cmd.tl); + break; + } case BTC_AVRC_STATUS_API_SND_GET_RN_CAPS_EVT: { btc_avrc_ct_send_get_rn_caps_cmd(arg->get_caps_cmd.tl); break; @@ -1418,6 +1650,28 @@ void btc_avrc_ct_call_handler(btc_msg_t *msg) btc_avrc_ct_send_set_absolute_volume_cmd(arg->set_abs_vol_cmd.tl, arg->set_abs_vol_cmd.volume); break; } +#if BTC_AV_CA_INCLUDED + case BTC_AVRC_CT_API_COVER_ART_CONNECT_EVT: { + btc_avrc_ct_cover_art_connect(arg->ca_conn.mtu); + break; + } + case BTC_AVRC_CT_API_COVER_ART_DISCONNECT_EVT: { + btc_avrc_ct_cover_art_disconnect(); + break; + } + case BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_PROPERTIES_EVT: { + btc_avrc_ct_cover_art_get_image_properties(arg->ca_get_img_prop.image_handle); + break; + } + case BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_EVT: { + btc_avrc_ct_cover_art_get_image(arg->ca_get_img.image_handle, arg->ca_get_img.image_descriptor, arg->ca_get_img.image_descriptor_len); + break; + } + case BTC_AVRC_CT_API_COVER_ART_GET_LINKED_THUMBNAIL_EVT: { + btc_avrc_ct_cover_art_get_linked_thumbnail(arg->ca_get_lk_thn.image_handle); + break; + } +#endif default: BTC_TRACE_WARNING("%s : unhandled event: %d\n", __FUNCTION__, msg->act); } @@ -1455,4 +1709,25 @@ void btc_avrc_tg_call_handler(btc_msg_t *msg) btc_avrc_tg_arg_deep_free(msg); } +void btc_avrc_get_profile_status(esp_avrc_profile_status_t *param) +{ + param->avrc_ct_inited = false; + param->avrc_tg_inited = false; + +#if AVRC_DYNAMIC_MEMORY == TRUE + if (btc_rc_cb_ptr) +#endif + { + if (btc_avrc_tg_init_p()) { + param->avrc_tg_inited = true; + } + if (btc_avrc_ct_init_p()) { + param->avrc_ct_inited = true; + } + if (btc_rc_cb.rc_cover_art_connected) { + param->ct_cover_art_conn_num++; + } + } +} + #endif /* #if BTC_AV_INCLUDED */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/cte/btc_ble_cte.c b/lib/bt/host/bluedroid/btc/profile/std/cte/btc_ble_cte.c new file mode 100644 index 00000000..a4f4377c --- /dev/null +++ b/lib/bt/host/bluedroid/btc/profile/std/cte/btc_ble_cte.c @@ -0,0 +1,395 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "osi/allocator.h" + +#include "bta/bta_api.h" +#include "bta/bta_dm_co.h" +#include "btc/btc_task.h" +#include "btc/btc_util.h" +#if (BLE_FEAT_CTE_EN == TRUE) +#include "btc_ble_cte.h" + +static inline void btc_cte_ble_cb_to_app(esp_ble_cte_cb_event_t event, esp_ble_cte_cb_param_t *param) +{ + esp_ble_cte_cb_t btc_cte_ble_cb = (esp_ble_cte_cb_t)btc_profile_cb_get(BTC_PID_BLE_CTE); + if (btc_cte_ble_cb) { + btc_cte_ble_cb(event, param); + } +} + +static void btc_ble_cte_callback(tBTM_BLE_CTE_EVENT event, + tBTM_BLE_CTE_CB_PARAMS *params) +{ + esp_ble_cte_cb_param_t param; + bt_status_t ret; + btc_msg_t msg; + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_BLE_CTE; + + BTC_TRACE_DEBUG("%s event %d\n", __func__, event); + + switch(event) { +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + case BTA_BLE_CTE_SET_TRANS_PARAMS_EVT: + msg.act = ESP_BLE_CTE_SET_CONNLESS_TRANS_PARAMS_CMPL_EVT; + param.set_trans_params_cmpl.status = btc_btm_status_to_esp_status(params->cte_trans_params_cmpl.status); + break; + case BTA_BLE_CTE_SET_TRANS_ENABLE_EVT: + msg.act = ESP_BLE_CTE_SET_CONNLESS_TRANS_ENABLE_CMPL_EVT; + param.set_trans_enable_cmpl.status = btc_btm_status_to_esp_status(params->cte_trans_params_cmpl.status); + break; + case BTA_BLE_CTE_SET_IQ_SAMP_ENABLE_EVT: + msg.act = ESP_BLE_CTE_SET_CONNLESS_IQ_SAMPLING_ENABLE_CMPL_EVT; + param.iq_sampling_enable_cmpl.status = btc_btm_status_to_esp_status(params->cte_iq_samp_en_cmpl.status); + param.iq_sampling_enable_cmpl.sync_handle = params->cte_iq_samp_en_cmpl.sync_handle; + break; +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + case BTA_BLE_CTE_SET_CONN_RECV_PARAMS_EVT: + msg.act = ESP_BLE_CTE_SET_CONN_RECV_PARAMS_CMPL_EVT; + param.conn_recv_params_cmpl.status = btc_btm_status_to_esp_status(params->cte_recv_params_cmpl.status); + param.conn_recv_params_cmpl.conn_handle = params->cte_recv_params_cmpl.conn_handle; + break; + case BTA_BLE_CTE_SET_CONN_TRANS_PARAMS_EVT: + msg.act = ESP_BLE_CTE_SET_CONN_TRANS_PARAMS_CMPL_EVT; + param.conn_trans_params_cmpl.status = btc_btm_status_to_esp_status(params->cte_conn_trans_params_cmpl.status); + param.conn_trans_params_cmpl.conn_handle = params->cte_conn_trans_params_cmpl.conn_handle; + break; + case BTA_BLE_CTE_SET_CONN_REQ_ENABLE_EVT: + msg.act = ESP_BLE_CTE_SET_CONN_REQ_ENABLE_CMPL_EVT; + param.conn_req_en_cmpl.status = btc_btm_status_to_esp_status(params->cte_conn_req_en_cmpl.status); + param.conn_req_en_cmpl.conn_handle = params->cte_conn_req_en_cmpl.conn_handle; + break; + case BTA_BLE_CTE_SET_CONN_RSP_ENABLE_EVT: + msg.act = ESP_BLE_CTE_SET_CONN_RSP_ENABLE_CMPL_EVT; + param.conn_rsp_en_cmpl.status = btc_btm_status_to_esp_status(params->cte_conn_rsp_en_cmpl.status); + param.conn_rsp_en_cmpl.conn_handle = params->cte_conn_rsp_en_cmpl.conn_handle; + break; +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + case BTA_BLE_CTE_READ_ANT_INFOR_EVT: + msg.act = ESP_BLE_CTE_READ_ANT_INFOR_CMPL_EVT; + param.read_ant_infor_cmpl.status = btc_btm_status_to_esp_status(params->cte_read_ant_infor_cmpl.status); + param.read_ant_infor_cmpl.supported_switching_sampling_rates = params->cte_read_ant_infor_cmpl.supported_switching_sampling_rates; + param.read_ant_infor_cmpl.num_antennae = params->cte_read_ant_infor_cmpl.num_ant; + param.read_ant_infor_cmpl.max_switching_pattern_len = params->cte_read_ant_infor_cmpl.max_switching_pattern_len; + param.read_ant_infor_cmpl.max_cte_len = params->cte_read_ant_infor_cmpl.max_cte_len; + break; +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + case BTA_BLE_CTE_CONNLESS_IQ_REPORT_EVT: + msg.act = ESP_BLE_CTE_CONNLESS_IQ_REPORT_EVT; + param.connless_iq_rpt.sync_handle = params->cte_connless_iq_rpt.sync_handle; + param.connless_iq_rpt.channel_idx = params->cte_connless_iq_rpt.channel_idx; + param.connless_iq_rpt.rssi = params->cte_connless_iq_rpt.rssi; + param.connless_iq_rpt.rssi_ant_id = params->cte_connless_iq_rpt.rssi_ant_id; + param.connless_iq_rpt.cte_type = params->cte_connless_iq_rpt.cte_type; + param.connless_iq_rpt.slot_dur = params->cte_connless_iq_rpt.slot_dur; + param.connless_iq_rpt.pkt_status = params->cte_connless_iq_rpt.pkt_status; + param.connless_iq_rpt.periodic_evt_counter = params->cte_connless_iq_rpt.periodic_evt_counter; + param.connless_iq_rpt.sample_count = params->cte_connless_iq_rpt.sample_count; + param.connless_iq_rpt.i_sample = &(params->cte_connless_iq_rpt.i_sample[0]); + param.connless_iq_rpt.q_sample = &(params->cte_connless_iq_rpt.q_sample[0]); + break; +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + case BTA_BLE_CTE_CONN_IQ_REPORT_EVT: + msg.act = ESP_BLE_CTE_CONN_IQ_REPORT_EVT; + param.conn_iq_rpt.conn_handle = params->cte_conn_iq_rpt.conn_handle; + param.conn_iq_rpt.data_channel_idx = params->cte_conn_iq_rpt.data_channel_idx; + param.conn_iq_rpt.rssi = params->cte_conn_iq_rpt.rssi; + param.conn_iq_rpt.rssi_ant_id = params->cte_conn_iq_rpt.rssi_ant_id; + param.conn_iq_rpt.cte_type = params->cte_conn_iq_rpt.cte_type; + param.conn_iq_rpt.slot_dur = params->cte_conn_iq_rpt.slot_dur; + param.conn_iq_rpt.pkt_status = params->cte_conn_iq_rpt.pkt_status; + param.conn_iq_rpt.conn_evt_counter = params->cte_conn_iq_rpt.conn_evt_counter; + param.conn_iq_rpt.sample_count = params->cte_conn_iq_rpt.sample_count; + param.conn_iq_rpt.i_sample = ¶ms->cte_conn_iq_rpt.i_sample[0]; + param.conn_iq_rpt.q_sample = ¶ms->cte_conn_iq_rpt.q_sample[0]; + break; + case BTA_BLE_CTE_REQUEST_FAILED_EVT: + msg.act = ESP_BLE_CTE_REQUEST_FAILED_EVT; + param.req_failed_evt.reason = btc_btm_status_to_esp_status(params->cte_req_failed.status); + param.req_failed_evt.conn_handle = params->cte_req_failed.conn_handle; + break; +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + default: + break; + } + + ret = btc_transfer_context(&msg, ¶m, + sizeof(esp_ble_cte_cb_param_t), btc_ble_cte_cb_deep_copy, btc_ble_cte_cb_deep_free); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } +} + +void btc_ble_cte_cb_handler(btc_msg_t *msg) +{ + BTC_TRACE_DEBUG("%s act %d \n", __func__, msg->act); + esp_ble_cte_cb_param_t *param = (esp_ble_cte_cb_param_t *)msg->arg; + + if (msg->act < ESP_BLE_CTE_EVT_MAX) { + btc_cte_ble_cb_to_app(msg->act, param); + } else { + BTC_TRACE_ERROR("%s, unknown msg->act = %d", __func__, msg->act); + } + + btc_ble_cte_cb_deep_free(msg); + +} + +void btc_ble_cte_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ +#if ((BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) || (BLE_FEAT_CTE_CONNECTION_EN == TRUE)) + btc_ble_cte_args_t *src = (btc_ble_cte_args_t *)p_src; + btc_ble_cte_args_t *dst = (btc_ble_cte_args_t *)p_dest; +#endif // #if ((BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) || (BLE_FEAT_CTE_CONNECTION_EN == TRUE)) + switch (msg->act) { +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + case BTC_CTE_ACT_SET_TRANS_PARAMS: + if (src->cte_trans_params.switching_pattern_len && src->cte_trans_params.antenna_ids) { + dst->cte_trans_params.antenna_ids = osi_malloc(src->cte_trans_params.switching_pattern_len); + if (dst->cte_trans_params.antenna_ids) { + memcpy(dst->cte_trans_params.antenna_ids, src->cte_trans_params.antenna_ids, src->cte_trans_params.switching_pattern_len); + } else { + BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act); + } + } + break; + case BTC_CTE_ACT_SET_IQ_SAMPLING_EN: + if (src->cte_iq_sampling_en.switching_pattern_len && src->cte_iq_sampling_en.antenna_ids) { + dst->cte_iq_sampling_en.antenna_ids = osi_malloc(src->cte_iq_sampling_en.switching_pattern_len); + if (dst->cte_iq_sampling_en.antenna_ids) { + memcpy(dst->cte_iq_sampling_en.antenna_ids, src->cte_iq_sampling_en.antenna_ids, src->cte_iq_sampling_en.switching_pattern_len); + } else { + BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act); + } + } + break; +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + case BTC_CTE_ACT_SET_CONN_CTE_RECV_PARAMS: + if (src->cte_recv_params.switching_pattern_len && src->cte_recv_params.antenna_ids) { + dst->cte_recv_params.antenna_ids = osi_malloc(src->cte_recv_params.switching_pattern_len); + if (dst->cte_recv_params.antenna_ids) { + memcpy(dst->cte_recv_params.antenna_ids, src->cte_recv_params.antenna_ids, src->cte_recv_params.switching_pattern_len); + } else { + BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act); + } + } + break; + case BTC_CTE_ACT_SET_CONN_CTE_TRANS_PARAMS: + if (src->cte_conn_trans_params.switching_pattern_len && src->cte_conn_trans_params.antenna_ids) { + dst->cte_conn_trans_params.antenna_ids = osi_malloc(src->cte_conn_trans_params.switching_pattern_len); + if (dst->cte_conn_trans_params.antenna_ids) { + memcpy(dst->cte_conn_trans_params.antenna_ids, src->cte_conn_trans_params.antenna_ids, src->cte_conn_trans_params.switching_pattern_len); + } else { + BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act); + } + } + break; +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + default: + BTC_TRACE_ERROR("Unhandled deep copy %d\n", msg->act); + break; + } +} + +void btc_ble_cte_arg_deep_free(btc_msg_t *msg) +{ + BTC_TRACE_DEBUG("%s \n", __func__); + switch (msg->act) { +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + case BTC_CTE_ACT_SET_TRANS_PARAMS: { + uint8_t *antenna_ids = ((btc_ble_cte_args_t *)msg->arg)->cte_trans_params.antenna_ids; + if (antenna_ids) { + osi_free(antenna_ids); + } + break; + } + case BTC_CTE_ACT_SET_IQ_SAMPLING_EN: { + uint8_t *antenna_ids = ((btc_ble_cte_args_t *)msg->arg)->cte_iq_sampling_en.antenna_ids; + if (antenna_ids) { + osi_free(antenna_ids); + } + break; + } +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + case BTC_CTE_ACT_SET_CONN_CTE_RECV_PARAMS: { + uint8_t *antenna_ids = ((btc_ble_cte_args_t *)msg->arg)->cte_recv_params.antenna_ids; + if (antenna_ids) { + osi_free(antenna_ids); + } + break; + } + case BTC_CTE_ACT_SET_CONN_CTE_TRANS_PARAMS: { + uint8_t *antenna_ids = ((btc_ble_cte_args_t *)msg->arg)->cte_conn_trans_params.antenna_ids; + if (antenna_ids) { + osi_free(antenna_ids); + } + break; + } +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + default: + BTC_TRACE_DEBUG("Unhandled deep free %d\n", msg->act); + break; + } +} + +void btc_ble_cte_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + esp_ble_cte_cb_param_t *src = (esp_ble_cte_cb_param_t *)p_src; + esp_ble_cte_cb_param_t *dst = (esp_ble_cte_cb_param_t *) p_dest; + + switch (msg->act) { +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + case ESP_BLE_CTE_CONNLESS_IQ_REPORT_EVT: + if (src->connless_iq_rpt.sample_count) { + dst->connless_iq_rpt.i_sample = osi_malloc(src->connless_iq_rpt.sample_count); + if (dst->connless_iq_rpt.i_sample) { + memcpy(dst->connless_iq_rpt.i_sample, &(src->connless_iq_rpt.i_sample[0]), + src->connless_iq_rpt.sample_count); + } else { + BTC_TRACE_ERROR("%s, i_sample malloc failed\n", __func__); + } + dst->connless_iq_rpt.q_sample = osi_malloc(src->connless_iq_rpt.sample_count); + if (dst->connless_iq_rpt.q_sample) { + memcpy(dst->connless_iq_rpt.q_sample, &(src->connless_iq_rpt.q_sample[0]), + src->connless_iq_rpt.sample_count); + } else { + BTC_TRACE_ERROR("%s, q_sample malloc failed\n", __func__); + } + } + break; +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + case ESP_BLE_CTE_CONN_IQ_REPORT_EVT: + if (src->conn_iq_rpt.sample_count) { + dst->conn_iq_rpt.i_sample = osi_malloc(src->conn_iq_rpt.sample_count); + if (dst->conn_iq_rpt.i_sample) { + memcpy(dst->conn_iq_rpt.i_sample, src->conn_iq_rpt.i_sample, + src->conn_iq_rpt.sample_count); + } else { + BTC_TRACE_ERROR("%s, i_sample malloc failed\n", __func__); + } + dst->conn_iq_rpt.q_sample = osi_malloc(src->conn_iq_rpt.sample_count); + if (dst->conn_iq_rpt.q_sample) { + memcpy(dst->conn_iq_rpt.q_sample, src->conn_iq_rpt.q_sample, + src->conn_iq_rpt.sample_count); + } else { + BTC_TRACE_ERROR("%s, q_sample malloc failed\n", __func__); + } + } + break; +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + default: + BTC_TRACE_DEBUG("%s, Unhandled deep copy %d\n", __func__, msg->act); + break; + } +} + +void btc_ble_cte_cb_deep_free(btc_msg_t *msg) +{ + BTC_TRACE_DEBUG("%s", __func__); + switch (msg->act) { +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + case ESP_BLE_CTE_CONNLESS_IQ_REPORT_EVT: { + esp_ble_cte_cb_param_t *params = (esp_ble_cte_cb_param_t *)msg->arg; + uint8_t *i_sample = &(params->connless_iq_rpt.i_sample[0]); + uint8_t *q_sample = &(params->connless_iq_rpt.q_sample[0]); + if (i_sample) { + osi_free(i_sample); + } + if (q_sample) { + osi_free(q_sample); + } + break; + } +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + case ESP_BLE_CTE_CONN_IQ_REPORT_EVT: { + esp_ble_cte_cb_param_t *params = (esp_ble_cte_cb_param_t *)msg->arg; + uint8_t *i_sample = params->conn_iq_rpt.i_sample; + uint8_t *q_sample = params->conn_iq_rpt.q_sample; + if (i_sample) { + osi_free(i_sample); + } + if (q_sample) { + osi_free(q_sample); + } + break; + } +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + default: + BTC_TRACE_DEBUG("Unhandled deep free %d", msg->act); + break; + } +} + +void btc_ble_cte_call_handler(btc_msg_t *msg) +{ +#if ((BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) || (BLE_FEAT_CTE_CONNECTION_EN == TRUE)) + btc_ble_cte_args_t *arg = (btc_ble_cte_args_t *)msg->arg; +#endif // #if ((BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) || (BLE_FEAT_CTE_CONNECTION_EN == TRUE)) + BTC_TRACE_DEBUG("%s act %d\n", __FUNCTION__, msg->act); + + switch (msg->act) { +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + case BTC_CTE_ACT_SET_TRANS_PARAMS: + struct cte_set_trans_params_arg *cte_trans_params = &arg->cte_trans_params; + BTA_DmBleCteSetConnectionlessTransParams(cte_trans_params->adv_handle, cte_trans_params->cte_len, cte_trans_params->cte_type, + cte_trans_params->cte_count, cte_trans_params->switching_pattern_len, cte_trans_params->antenna_ids); + break; + case BTC_CTE_ACT_SET_TRANS_ENABLE: + BTA_DmBleCteSetConnectionlessTransEnable(arg->cte_trans_enable.adv_handle, arg->cte_trans_enable.cte_enable); + break; + case BTC_CTE_ACT_SET_IQ_SAMPLING_EN: + struct cte_iq_sampling_en_arg *iq_sampling_en = &arg->cte_iq_sampling_en; + BTA_DmBleCteSetConnectionlessIqSamplingEnable(iq_sampling_en->sync_handle, iq_sampling_en->sampling_en, iq_sampling_en->slot_dur, + iq_sampling_en->max_sampled_ctes, iq_sampling_en->switching_pattern_len, iq_sampling_en->antenna_ids); + break; +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + case BTC_CTE_ACT_SET_CONN_CTE_RECV_PARAMS: + struct cte_recv_params_arg *recv_params = &arg->cte_recv_params; + BTA_DmBleCteSetConnectionReceiveParams(recv_params->conn_handle, recv_params->sampling_en, recv_params->slot_dur, + recv_params->switching_pattern_len, recv_params->antenna_ids); + break; + case BTC_CTE_ACT_SET_CONN_CTE_TRANS_PARAMS: + struct cte_set_conn_trans_params_arg *trans_params = &arg->cte_conn_trans_params; + BTA_DmBleCteSetConnectionTransParams(trans_params->conn_handle, trans_params->cte_types, trans_params->switching_pattern_len, trans_params->antenna_ids); + break; + case BTC_CTE_ACT_SET_CONN_CTE_REQUEST_EN: + struct cte_req_en_arg *cte_req_en = &arg->cte_req_en; + BTA_DmBleCteSetConnectionRequestEnable(cte_req_en->conn_handle, cte_req_en->enable, cte_req_en->cte_req_interval, + cte_req_en->req_cte_len, cte_req_en->req_cte_Type); + break; + case BTC_CTE_ACT_SET_CONN_CTE_RESPONSE_EN: + BTA_DmBleCteSetConnectionRspEnable(arg->cte_rsp_en.conn_handle, arg->cte_rsp_en.enable); + break; +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + case BTC_CTE_ACT_READ_ANTENNA_INFOR: + BTA_DmBleCteReadAntInfor(); + break; + default: + break; + } + + btc_ble_cte_arg_deep_free(msg); +} + +//register connection parameter update callback +void btc_cte_callback_init(void) +{ + BTM_BleCteRegisterCallback(btc_ble_cte_callback); +} + +#endif ///BLE_FEAT_CTE_EN == TRUE diff --git a/lib/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c b/lib/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c index 53d0b835..e2872ce5 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c +++ b/lib/bt/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,6 +30,7 @@ #if (BLE_INCLUDED == TRUE) #if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_ADV_EN == TRUE) #if BTC_DYNAMIC_MEMORY == FALSE static tBTA_BLE_ADV_DATA gl_bta_adv_data; static tBTA_BLE_ADV_DATA gl_bta_scan_rsp_data; @@ -37,33 +38,22 @@ static tBTA_BLE_ADV_DATA gl_bta_scan_rsp_data; tBTA_BLE_ADV_DATA *gl_bta_adv_data_ptr; tBTA_BLE_ADV_DATA *gl_bta_scan_rsp_data_ptr; #endif +#endif // #if (BLE_42_ADV_EN == TRUE) #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) -#if SCAN_QUEUE_CONGEST_CHECK -static list_t *adv_filter_list; -static osi_mutex_t adv_list_lock; -bool btc_check_adv_list(uint8_t * addr, uint8_t addr_type); -uint32_t btc_get_adv_list_length(void); -void btc_adv_list_refresh(void); -void btc_adv_list_lock(void); -void btc_adv_list_unlock(void); -static uint16_t btc_adv_list_count = 0; - -#define BTC_ADV_LIST_MAX_LENGTH 50 -#define BTC_ADV_LIST_MAX_COUNT 200 -#endif - #define BTC_GAP_BLE_ADV_RPT_QUEUE_IDX (1) #define BTC_GAP_BLE_ADV_RPT_BATCH_SIZE (10) #define BTC_GAP_BLE_ADV_RPT_QUEUE_LEN_MAX (200) #if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_SCAN_EN == TRUE) typedef struct { struct pkt_queue *adv_rpt_queue; struct osi_event *adv_rpt_ready; } btc_gap_ble_env_t; static btc_gap_ble_env_t btc_gap_ble_env; +#endif // #if (BLE_42_SCAN_EN == TRUE) #endif static inline void btc_gap_ble_cb_to_app(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) @@ -102,6 +92,7 @@ static void btc_gap_ble_get_dev_name_callback(UINT8 status, char *name) } #if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_ADV_EN == TRUE) static void btc_gap_adv_point_cleanup(void **buf) { if (NULL == *buf) { @@ -476,25 +467,7 @@ static void btc_stop_adv_callback(uint8_t status) BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } - -static void btc_clear_adv_callback(uint8_t status) -{ - esp_ble_gap_cb_param_t param; - bt_status_t ret; - btc_msg_t msg = {0}; - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_GAP_BLE; - msg.act = ESP_GAP_BLE_ADV_CLEAR_COMPLETE_EVT; - param.adv_clear_cmpl.status = btc_hci_to_esp_status(status); - - ret = btc_transfer_context(&msg, ¶m, - sizeof(esp_ble_gap_cb_param_t), NULL, NULL); - - if (ret != BT_STATUS_SUCCESS) { - BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); - } -} +#endif // #if (BLE_42_ADV_EN == TRUE) void btc_update_duplicate_exceptional_list_callback(tBTA_STATUS status, uint8_t subcode, uint32_t length, uint8_t *device_info) { @@ -525,6 +498,7 @@ static void btc_ble_update_duplicate_exceptional_list(uint8_t subcode, uint32_t BTA_DmUpdateDuplicateExceptionalList(subcode, info_type, device_info, p_update_duplicate_ignore_list_cback); } +#if (BLE_42_ADV_EN == TRUE) static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params, tBTA_START_ADV_CMPL_CBACK start_adv_cback) { tBLE_BD_ADDR peer_addr; @@ -575,8 +549,9 @@ static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params, tBT &peer_addr, start_adv_cback); } +#endif // #if (BLE_42_ADV_EN == TRUE) - +#if (BLE_42_SCAN_EN == TRUE) static void btc_scan_params_callback(tGATT_IF gatt_if, tBTM_STATUS status) { esp_ble_gap_cb_param_t param; @@ -641,20 +616,6 @@ static void btc_gap_ble_adv_pkt_handler(void *arg) static void btc_process_adv_rpt_pkt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data) { -#if SCAN_QUEUE_CONGEST_CHECK - if(btc_check_queue_is_congest()) { - BTC_TRACE_DEBUG("BtcQueue is congested"); - if(btc_get_adv_list_length() > BTC_ADV_LIST_MAX_LENGTH || btc_adv_list_count > BTC_ADV_LIST_MAX_COUNT) { - btc_adv_list_refresh(); - btc_adv_list_count = 0; - } - if(btc_check_adv_list(p_data->inq_res.bd_addr, p_data->inq_res.ble_addr_type)) { - return; - } - } - btc_adv_list_count ++; -#endif - // drop ADV packets if data queue length goes above threshold btc_gap_ble_env_t *p_env = &btc_gap_ble_env; if (pkt_queue_length(p_env->adv_rpt_queue) >= BTC_GAP_BLE_ADV_RPT_QUEUE_LEN_MAX) { @@ -770,10 +731,8 @@ static void btc_stop_scan_callback(tBTA_STATUS status) if (ret != BT_STATUS_SUCCESS) { BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } -#if SCAN_QUEUE_CONGEST_CHECK - btc_adv_list_refresh(); -#endif } +#endif // #if (BLE_42_SCAN_EN == TRUE) #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) void btc_update_conn_param_callback (UINT8 status, BD_ADDR bd_addr, tBTM_LE_UPDATE_CONN_PRAMS *update_conn_params) { @@ -957,8 +916,31 @@ static void btc_read_ble_rssi_cmpl_callback(void *p_data) } } +static void btc_ble_read_channel_map_callback(void *p_data) +{ + tBTA_BLE_CH_MAP_RESULTS *result = (tBTA_BLE_CH_MAP_RESULTS *)p_data; + esp_ble_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg = {0}; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BLE; + msg.act = ESP_GAP_BLE_READ_CHANNEL_MAP_COMPLETE_EVT; + + param.read_ble_channel_map_cmpl.status = btc_btm_status_to_esp_status(result->status); + memcpy(param.read_ble_channel_map_cmpl.channel_map, result->channel_map, 5); + memcpy(param.read_ble_channel_map_cmpl.remote_addr, result->rem_bda, sizeof(BD_ADDR)); + + ret = btc_transfer_context(&msg, ¶m, sizeof(esp_ble_gap_cb_param_t), NULL, NULL); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } +} + + #if (BLE_50_FEATURE_SUPPORT == TRUE) -static void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, +void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, tBTA_DM_BLE_5_GAP_CB_PARAMS *params) { esp_ble_gap_cb_param_t param; @@ -986,62 +968,86 @@ static void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, param.set_perf_phy.status = btc_btm_status_to_esp_status(params->set_perf_phy.status); break; } +#if (BLE_50_EXTEND_ADV_EN == TRUE) case BTA_DM_BLE_5_GAP_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT: msg.act = ESP_GAP_BLE_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT; param.ext_adv_set_rand_addr.status = btc_btm_status_to_esp_status(params->set_ext_rand_addr.status); + param.ext_adv_set_rand_addr.instance = params->set_ext_rand_addr.instance; break; case BTA_DM_BLE_5_GAP_EXT_ADV_SET_PARAMS_COMPLETE_EVT: { msg.act = ESP_GAP_BLE_EXT_ADV_SET_PARAMS_COMPLETE_EVT; - param.ext_adv_set_rand_addr.status = btc_btm_status_to_esp_status(params->set_params.status); + param.ext_adv_set_params.status = btc_btm_status_to_esp_status(params->set_params.status); + param.ext_adv_set_params.instance = params->set_params.instance; break; } case BTA_DM_BLE_5_GAP_EXT_ADV_DATA_SET_COMPLETE_EVT: { msg.act = ESP_GAP_BLE_EXT_ADV_DATA_SET_COMPLETE_EVT; param.ext_adv_data_set.status = btc_btm_status_to_esp_status(params->adv_data_set.status); + param.ext_adv_data_set.instance = params->adv_data_set.instance; break; } case BTA_DM_BLE_5_GAP_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT: { msg.act = ESP_GAP_BLE_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT; param.scan_rsp_set.status = btc_btm_status_to_esp_status(params->scan_rsp_data_set.status); + param.scan_rsp_set.instance = params->scan_rsp_data_set.instance; break; } case BTA_DM_BLE_5_GAP_EXT_ADV_START_COMPLETE_EVT: { msg.act = ESP_GAP_BLE_EXT_ADV_START_COMPLETE_EVT; param.ext_adv_start.status = btc_btm_status_to_esp_status(params->adv_start.status); + for (UINT8 i = 0; i < params->adv_start.instance_num; i++) { + param.ext_adv_start.instance[i] = params->adv_start.instance[i]; + } + + param.ext_adv_start.instance_num = params->adv_start.instance_num; break; } case BTA_DM_BLE_5_GAP_EXT_ADV_STOP_COMPLETE_EVT: msg.act = ESP_GAP_BLE_EXT_ADV_STOP_COMPLETE_EVT; param.ext_adv_stop.status = btc_btm_status_to_esp_status(params->adv_start.status); + for (UINT8 i = 0; i < params->adv_start.instance_num; i++) { + param.ext_adv_stop.instance[i] = params->adv_start.instance[i]; + } + param.ext_adv_stop.instance_num = params->adv_start.instance_num; break; case BTA_DM_BLE_5_GAP_EXT_ADV_SET_REMOVE_COMPLETE_EVT: msg.act = ESP_GAP_BLE_EXT_ADV_SET_REMOVE_COMPLETE_EVT; param.ext_adv_remove.status = btc_btm_status_to_esp_status(params->adv_start.status); + param.ext_adv_remove.instance = params->adv_start.instance[0]; break; case BTA_DM_BLE_5_GAP_EXT_ADV_SET_CLEAR_COMPLETE_EVT: msg.act = ESP_GAP_BLE_EXT_ADV_SET_CLEAR_COMPLETE_EVT; param.ext_adv_clear.status = btc_btm_status_to_esp_status(params->adv_start.status); break; +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) + +#if (BLE_50_PERIODIC_ADV_EN == TRUE) case BTA_DM_BLE_5_GAP_PERIODIC_ADV_SET_PARAMS_COMPLETE_EVT: { msg.act = ESP_GAP_BLE_PERIODIC_ADV_SET_PARAMS_COMPLETE_EVT; param.peroid_adv_set_params.status = btc_btm_status_to_esp_status(params->per_adv_set_params.status); + param.peroid_adv_set_params.instance = params->per_adv_set_params.instance; break; } case BTA_DM_BLE_5_GAP_PERIODIC_ADV_DATA_SET_COMPLETE_EVT: { msg.act = ESP_GAP_BLE_PERIODIC_ADV_DATA_SET_COMPLETE_EVT; param.period_adv_data_set.status = btc_btm_status_to_esp_status(params->per_adv_data_set.status); + param.period_adv_data_set.instance = params->per_adv_data_set.instance; break; } case BTA_DM_BLE_5_GAP_PERIODIC_ADV_START_COMPLETE_EVT: { msg.act = ESP_GAP_BLE_PERIODIC_ADV_START_COMPLETE_EVT; param.period_adv_start.status = btc_btm_status_to_esp_status(params->per_adv_start.status); + param.period_adv_start.instance = params->per_adv_start.instance; break; } case BTA_DM_BLE_5_GAP_PERIODIC_ADV_STOP_COMPLETE_EVT: { msg.act = ESP_GAP_BLE_PERIODIC_ADV_STOP_COMPLETE_EVT; param.period_adv_stop.status = btc_btm_status_to_esp_status(params->per_adv_stop.status); + param.period_adv_stop.instance = params->per_adv_stop.instance; break; } +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) case BTA_DM_BLE_5_GAP_PERIODIC_ADV_CREATE_SYNC_COMPLETE_EVT: { msg.act = ESP_GAP_BLE_PERIODIC_ADV_CREATE_SYNC_COMPLETE_EVT; param.period_adv_create_sync.status = btc_btm_status_to_esp_status(params->per_adv_sync_create.status); @@ -1072,6 +1078,9 @@ static void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, param.period_adv_clear_dev.status = btc_btm_status_to_esp_status(params->per_adv_clear_dev.status); break; } +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) + +#if (BLE_50_EXTEND_SCAN_EN == TRUE) case BTA_DM_BLE_5_GAP_SET_EXT_SCAN_PARAMS_COMPLETE_EVT: { msg.act = ESP_GAP_BLE_SET_EXT_SCAN_PARAMS_COMPLETE_EVT; param.set_ext_scan_params.status = btc_btm_status_to_esp_status(params->ext_scan.status); @@ -1087,6 +1096,7 @@ static void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, param.ext_scan_stop.status = btc_btm_status_to_esp_status(params->scan_stop.status); break; } +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) case BTA_DM_BLE_5_GAP_PREFER_EXT_CONN_PARAMS_SET_COMPLETE_EVT: { msg.act = ESP_GAP_BLE_PREFER_EXT_CONN_PARAMS_SET_COMPLETE_EVT; param.ext_conn_params_set.status = btc_btm_status_to_esp_status(params->ext_conn_set_params.status); @@ -1099,6 +1109,7 @@ static void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, param.phy_update.tx_phy = params->phy_update.tx_phy; param.phy_update.rx_phy = params->phy_update.rx_phy; break; +#if (BLE_50_EXTEND_SCAN_EN == TRUE) case BTA_DM_BLE_5_GAP_EXT_ADV_REPORT_EVT: msg.act = ESP_GAP_BLE_EXT_ADV_REPORT_EVT; memcpy(¶m.ext_adv_report.params, ¶ms->ext_adv_report, sizeof(esp_ble_gap_ext_adv_report_t)); @@ -1110,6 +1121,8 @@ static void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, case BTA_DM_BLE_5_GAP_SCAN_TIMEOUT_EVT: msg.act = ESP_GAP_BLE_SCAN_TIMEOUT_EVT; break; +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) case BTA_DM_BLE_5_GAP_ADV_TERMINATED_EVT: { param.adv_terminate.status = params->adv_term.status; param.adv_terminate.adv_instance = params->adv_term.adv_handle; @@ -1125,16 +1138,24 @@ static void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, memcpy(param.scan_req_received.scan_addr, params->scan_req.scan_addr, sizeof(BD_ADDR)); break; } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) case BTA_DM_BLE_5_GAP_CHANNEL_SELETE_ALGORITHM_EVT: { msg.act = ESP_GAP_BLE_CHANNEL_SELECT_ALGORITHM_EVT; param.channel_sel_alg.conn_handle = params->channel_sel.conn_handle; param.channel_sel_alg.channel_sel_alg = params->channel_sel.channel_sel_alg; break; } +#if (BLE_50_EXTEND_SYNC_EN == TRUE) case BTA_DM_BLE_5_GAP_PERIODIC_ADV_REPORT_EVT: { msg.act = ESP_GAP_BLE_PERIODIC_ADV_REPORT_EVT; - memcpy(¶m.period_adv_report, ¶ms->period_adv_report, - sizeof(esp_ble_gap_periodic_adv_report_t)); + param.period_adv_report.params.sync_handle = params->period_adv_report.sync_handle; + param.period_adv_report.params.tx_power = params->period_adv_report.tx_power; + param.period_adv_report.params.rssi = params->period_adv_report.rssi; + #if (BLE_FEAT_CTE_EN == TRUE) + param.period_adv_report.params.cte_type = params->period_adv_report.cte_type; + #endif // #if (BLE_FEAT_CTE_EN == TRUE) + param.period_adv_report.params.data_status = params->period_adv_report.data_status; + param.period_adv_report.params.data_length = params->period_adv_report.data_length; if (params->period_adv_report.data) { memcpy(param.period_adv_report.params.data, params->period_adv_report.data, params->period_adv_report.data_length); @@ -1159,6 +1180,8 @@ static void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, param.periodic_adv_sync_estab.adv_clk_accuracy = params->sync_estab.adv_clk_accuracy; break; } +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) + #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) case BTA_BLE_GAP_PERIODIC_ADV_RECV_ENABLE_COMPLETE_EVT: msg.act = ESP_GAP_BLE_PERIODIC_ADV_RECV_ENABLE_COMPLETE_EVT; @@ -1193,6 +1216,76 @@ static void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, param.past_received.adv_clk_accuracy = params->past_recv.adv_clk_accuracy; break; #endif +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + case BTA_BLE_GAP_ENH_READ_TRANS_POWER_LEVEL_EVT: + msg.act = ESP_GAP_BLE_ENH_READ_TRANS_PWR_LEVEL_EVT; + param.enh_trans_pwr_level_cmpl.status = btc_btm_status_to_esp_status(params->enh_trans_pwr_level_cmpl.status); + param.enh_trans_pwr_level_cmpl.conn_handle = params->enh_trans_pwr_level_cmpl.conn_handle; + param.enh_trans_pwr_level_cmpl.phy = params->enh_trans_pwr_level_cmpl.phy; + param.enh_trans_pwr_level_cmpl.cur_tx_pwr_level = params->enh_trans_pwr_level_cmpl.cur_tx_pwr_level; + param.enh_trans_pwr_level_cmpl.max_tx_pwr_level = params->enh_trans_pwr_level_cmpl.max_tx_pwr_level; + break; + case BTA_BLE_GAP_READ_REMOTE_TRANS_POWER_LEVEL_EVT: + msg.act = ESP_GAP_BLE_READ_REMOTE_TRANS_PWR_LEVEL_EVT; + param.read_remote_trans_pwr_level_cmpl.status = btc_btm_status_to_esp_status(params->remote_pwr_level_cmpl.status); + break; + case BTA_BLE_GAP_SET_PATH_LOSS_REPORTING_PARAMS_EVT: + msg.act = ESP_GAP_BLE_SET_PATH_LOSS_RPTING_PARAMS_EVT; + param.set_path_loss_rpting_params.status = btc_btm_status_to_esp_status(params->path_loss_rpting_params.status); + param.set_path_loss_rpting_params.conn_handle = params->path_loss_rpting_params.conn_handle; + break; + case BTA_BLE_GAP_SET_PATH_LOSS_REPORTING_ENABLE_EVT: + msg.act = ESP_GAP_BLE_SET_PATH_LOSS_RPTING_ENABLE_EVT; + param.set_path_loss_rpting_enable.status = btc_btm_status_to_esp_status(params->path_loss_rpting_enable.status); + param.set_path_loss_rpting_enable.conn_handle = params->path_loss_rpting_enable.conn_handle; + break; + case BTA_BLE_GAP_SET_TRANS_POWER_REPORTING_ENABLE_EVT: + msg.act = ESP_GAP_BLE_SET_TRANS_PWR_RPTING_ENABLE_EVT; + param.set_trans_pwr_rpting_enable.status = btc_btm_status_to_esp_status(params->trans_pwr_rpting_enable.status); + param.set_trans_pwr_rpting_enable.conn_handle = params->trans_pwr_rpting_enable.conn_handle; + break; + case BTA_BLE_GAP_PATH_LOSS_THRESHOLD_EVT: + msg.act = ESP_GAP_BLE_PATH_LOSS_THRESHOLD_EVT; + param.path_loss_thres_evt.conn_handle = params->path_loss_thres_evt.conn_handle; + param.path_loss_thres_evt.cur_path_loss = params->path_loss_thres_evt.cur_path_loss; + param.path_loss_thres_evt.zone_entered = params->path_loss_thres_evt.zone_entered; + break; + case BTA_BLE_GAP_TRANMIT_POWER_REPORTING_EVT: + msg.act = ESP_GAP_BLE_TRANS_PWR_RPTING_EVT; + param.trans_power_report_evt.status = btc_btm_status_to_esp_status(params->trans_pwr_report_evt.status); + param.trans_power_report_evt.conn_handle = params->trans_pwr_report_evt.conn_handle; + param.trans_power_report_evt.reason = params->trans_pwr_report_evt.reason; + param.trans_power_report_evt.phy = params->trans_pwr_report_evt.phy; + param.trans_power_report_evt.tx_power_level = params->trans_pwr_report_evt.tx_power_level; + param.trans_power_report_evt.tx_power_level_flag = params->trans_pwr_report_evt.tx_power_level_flag; + param.trans_power_report_evt.delta = params->trans_pwr_report_evt.delta; + break; +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) + case BTA_BLE_GAP_SET_DEFAULT_SUBRATE_EVT: + msg.act = ESP_GAP_BLE_SET_DEFAULT_SUBRATE_COMPLETE_EVT; + param.set_default_subrate_evt.status = btc_btm_status_to_esp_status(params->status); + break; + case BTA_BLE_GAP_SUBRATE_REQUEST_EVT: + msg.act = ESP_GAP_BLE_SUBRATE_REQUEST_COMPLETE_EVT; + param.subrate_req_cmpl_evt.status = btc_btm_status_to_esp_status(params->status); + break; + case BTA_BLE_GAP_SUBRATE_CHANGE_EVT: + msg.act = ESP_GAP_BLE_SUBRATE_CHANGE_EVT; + param.subrate_change_evt.status = btc_btm_status_to_esp_status(params->subrate_change_evt.status); + param.subrate_change_evt.conn_handle = params->subrate_change_evt.conn_handle; + param.subrate_change_evt.subrate_factor = params->subrate_change_evt.subrate_factor; + param.subrate_change_evt.peripheral_latency = params->subrate_change_evt.peripheral_latency; + param.subrate_change_evt.continuation_number = params->subrate_change_evt.continuation_number; + param.subrate_change_evt.supervision_timeout = params->subrate_change_evt.supervision_timeout; + break; +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) + case BTA_BLE_GAP_SET_HOST_FEATURE_EVT: + msg.act = ESP_GAP_BLE_SET_HOST_FEATURE_CMPL_EVT; + param.host_feature.status = btc_btm_status_to_esp_status(params->status); + break; +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) default: break; } @@ -1206,6 +1299,7 @@ static void btc_ble_5_gap_callback(tBTA_DM_BLE_5_GAP_EVENT event, } #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) void btc_dtm_tx_start_callback(void *p1) { UINT8 status; @@ -1260,7 +1354,9 @@ void btc_dtm_rx_start_callback(void *p1) } } } +#endif // #if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) +#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) void btc_dtm_stop_callback(void *p1) { UINT8 status; @@ -1289,6 +1385,46 @@ void btc_dtm_stop_callback(void *p1) } } } +#endif // #if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) + +static void btc_ble_set_privacy_mode_callback(UINT8 status) +{ + esp_ble_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg = {0}; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BLE; + msg.act = ESP_GAP_BLE_SET_PRIVACY_MODE_COMPLETE_EVT; + + param.set_privacy_mode_cmpl.status = btc_btm_status_to_esp_status(status); + + ret = btc_transfer_context(&msg, ¶m, sizeof(esp_ble_gap_cb_param_t), NULL, NULL); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } +} + +#if (BLE_VENDOR_HCI_EN == TRUE) +static void btc_clear_adv_callback(uint8_t status) +{ + esp_ble_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg = {0}; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BLE; + msg.act = ESP_GAP_BLE_ADV_CLEAR_COMPLETE_EVT; + param.adv_clear_cmpl.status = btc_hci_to_esp_status(status); + + ret = btc_transfer_context(&msg, ¶m, + sizeof(esp_ble_gap_cb_param_t), NULL, NULL); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } +} static void btc_ble_vendor_hci_cmd_complete_callback(tBTA_VSC_CMPL *p_param) { @@ -1326,7 +1462,7 @@ static void btc_ble_vendor_hci_cmd_complete_callback(tBTA_VSC_CMPL *p_param) } } -static void btc_ble_set_privacy_mode_callback(UINT8 status) +static void btc_ble_set_csa_support_callback(UINT8 status) { esp_ble_gap_cb_param_t param; bt_status_t ret; @@ -1334,9 +1470,9 @@ static void btc_ble_set_privacy_mode_callback(UINT8 status) msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_GAP_BLE; - msg.act = ESP_GAP_BLE_SET_PRIVACY_MODE_COMPLETE_EVT; + msg.act = ESP_GAP_BLE_SET_CSA_SUPPORT_COMPLETE_EVT; - param.set_privacy_mode_cmpl.status = btc_btm_status_to_esp_status(status); + param.set_csa_support_cmpl.status = btc_btm_status_to_esp_status(status); ret = btc_transfer_context(&msg, ¶m, sizeof(esp_ble_gap_cb_param_t), NULL, NULL); @@ -1345,20 +1481,89 @@ static void btc_ble_set_privacy_mode_callback(UINT8 status) } } +static void btc_ble_set_vendor_evt_mask_callback(UINT8 status) +{ + esp_ble_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg = {0}; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BLE; + msg.act = ESP_GAP_BLE_SET_VENDOR_EVT_MASK_COMPLETE_EVT; + + param.set_vendor_evt_mask_cmpl.status = btc_btm_status_to_esp_status(status); + + ret = btc_transfer_context(&msg, ¶m, sizeof(esp_ble_gap_cb_param_t), NULL, NULL); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } +} + +static void btc_ble_vendor_hci_event_callback(UINT8 subevt_code, UINT8 param_len, UINT8 *params) +{ + esp_ble_gap_cb_param_t param = {0}; + bt_status_t ret; + btc_msg_t msg = {0}; + esp_ble_vendor_evt_param_t *evt_param = ¶m.vendor_hci_evt.param; + bool copy_param = false; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BLE; + msg.act = ESP_GAP_BLE_VENDOR_HCI_EVT; + + param.vendor_hci_evt.subevt_code = subevt_code; + param.vendor_hci_evt.param_len = 0; + param.vendor_hci_evt.param_buf = NULL; + switch (subevt_code) { + case BLE_VENDOR_PDU_RECV_EVT: + param.vendor_hci_evt.subevt_code = ESP_BLE_VENDOR_PDU_RECV_EVT; + STREAM_TO_UINT8(evt_param->pdu_recv.type, params); + STREAM_TO_UINT8(evt_param->pdu_recv.handle, params); + STREAM_TO_UINT8(evt_param->pdu_recv.addr_type, params); + STREAM_TO_BDADDR(evt_param->pdu_recv.peer_addr, params); + break; + case BLE_VENDOR_CHMAP_UPDATE_EVT: + param.vendor_hci_evt.subevt_code = ESP_BLE_VENDOR_CHAN_MAP_UPDATE_EVT; + STREAM_TO_UINT8(evt_param->chan_map_update.status, params); + STREAM_TO_UINT16(evt_param->chan_map_update.conn_handle, params); + REVERSE_STREAM_TO_ARRAY(evt_param->chan_map_update.ch_map, params, ESP_GAP_BLE_CHANNELS_LEN); + break; + case BLE_VENDOR_SLEEP_WAKEUP_EVT: + param.vendor_hci_evt.subevt_code = ESP_BLE_VENDOR_SLEEP_WAKEUP_EVT; + // No parameters + break; + default: + copy_param = true; + break; + } + + if (copy_param) { + param.vendor_hci_evt.param_len = param_len; + param.vendor_hci_evt.param_buf = (param_len) ? params : NULL; + ret = btc_transfer_context(&msg, ¶m, sizeof(esp_ble_gap_cb_param_t), btc_gap_ble_cb_deep_copy, btc_gap_ble_cb_deep_free); + } else { + ret = btc_transfer_context(&msg, ¶m, sizeof(esp_ble_gap_cb_param_t), NULL, NULL); + } + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } +} +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) + void btc_get_whitelist_size(uint16_t *length) { BTM_BleGetWhiteListSize(length); return; } #if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_SCAN_EN == TRUE) static void btc_ble_start_scanning(uint32_t duration, tBTA_DM_SEARCH_CBACK *results_cb, tBTA_START_STOP_SCAN_CMPL_CBACK *start_scan_cb) { if ((results_cb != NULL) && (start_scan_cb != NULL)) { -#if SCAN_QUEUE_CONGEST_CHECK - btc_adv_list_refresh(); -#endif //Start scan the device BTA_DmBleScan(true, duration, results_cb, start_scan_cb); } else { @@ -1371,18 +1576,17 @@ static void btc_ble_stop_scanning(tBTA_START_STOP_SCAN_CMPL_CBACK *stop_scan_cb) uint8_t duration = 0; BTA_DmBleScan(false, duration, NULL, stop_scan_cb); } +#endif // #if (BLE_42_SCAN_EN == TRUE) +#if (BLE_42_ADV_EN == TRUE) static void btc_ble_stop_advertising(tBTA_START_STOP_ADV_CMPL_CBACK *stop_adv_cb) { bool stop_adv = false; BTA_DmBleBroadcast(stop_adv, stop_adv_cb); } +#endif // #if (BLE_42_ADV_EN == TRUE) -static void btc_ble_clear_advertising(tBTA_CLEAR_ADV_CMPL_CBACK *clear_adv_cb) -{ - BTA_DmBleClearAdv(clear_adv_cb); -} #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) static void btc_ble_update_conn_params(BD_ADDR bd_addr, uint16_t min_int, uint16_t max_int, uint16_t latency, uint16_t timeout) @@ -1491,7 +1695,7 @@ static void btc_gap_ble_set_channels(esp_gap_ble_channels channels) BTA_DmBleSetChannels(channels, btc_gap_ble_set_channels_cmpl_callback); } -#if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_DTM_TEST_EN == TRUE) static void btc_ble_dtm_tx_start(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) { BTA_DmBleDtmTxStart(tx_channel, len_of_data, pkt_payload, p_dtm_cmpl_cback); @@ -1502,9 +1706,9 @@ static void btc_ble_dtm_rx_start(uint8_t rx_channel, tBTA_DTM_CMD_CMPL_CBACK *p_ BTA_DmBleDtmRxStart(rx_channel, p_dtm_cmpl_cback); } -#endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) +#endif // #if (BLE_42_DTM_TEST_EN == TRUE) -#if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_DTM_TEST_EN == TRUE) static void btc_ble_dtm_enhance_tx_start(uint8_t tx_channel, uint8_t len_of_data, uint8_t pkt_payload, uint8_t phy, tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) { BTA_DmBleDtmEnhTxStart(tx_channel, len_of_data, pkt_payload, phy, p_dtm_cmpl_cback); @@ -1515,14 +1719,22 @@ static void btc_ble_dtm_enhance_rx_start(uint8_t rx_channel, uint8_t phy, uint8_ BTA_DmBleDtmEnhRxStart(rx_channel, phy, modulation_index, p_dtm_cmpl_cback); } -#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) +void btc_get_periodic_list_size(uint8_t *size) +{ + BTM_BleGetPeriodicAdvListSize(size); + return; +} +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) static void btc_ble_dtm_stop(tBTA_DTM_CMD_CMPL_CBACK *p_dtm_cmpl_cback) { BTA_DmBleDtmStop(p_dtm_cmpl_cback); } - +#endif // #if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) static void btc_ble_set_privacy_mode(uint8_t addr_type, BD_ADDR addr, uint8_t privacy_mode, @@ -1549,6 +1761,7 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) { switch (msg->act) { #if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_ADV_EN == TRUE) case BTC_GAP_BLE_ACT_CFG_ADV_DATA: { btc_ble_gap_args_t *src = (btc_ble_gap_args_t *)p_src; btc_ble_gap_args_t *dst = (btc_ble_gap_args_t *) p_dest; @@ -1594,6 +1807,7 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) } break; } +#endif // #if (BLE_42_ADV_EN == TRUE) #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) case BTC_GAP_BLE_SET_SECURITY_PARAM_EVT: { btc_ble_gap_args_t *src = (btc_ble_gap_args_t *)p_src; @@ -1647,6 +1861,7 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) break; } #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) case BTC_GAP_BLE_CFG_EXT_ADV_DATA_RAW: case BTC_GAP_BLE_CFG_EXT_SCAN_RSP_DATA_RAW: { btc_ble_5_gap_args_t *src = (btc_ble_5_gap_args_t *)p_src; @@ -1664,6 +1879,8 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) } break; } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) case BTC_GAP_BLE_CFG_PERIODIC_ADV_DATA_RAW: { btc_ble_5_gap_args_t *src = (btc_ble_5_gap_args_t *)p_src; btc_ble_5_gap_args_t *dst = (btc_ble_5_gap_args_t *)p_dest; @@ -1680,6 +1897,8 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) } break; } +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) case BTC_GAP_BLE_EXT_ADV_START: { btc_ble_5_gap_args_t *src = (btc_ble_5_gap_args_t *)p_src; btc_ble_5_gap_args_t *dst = (btc_ble_5_gap_args_t *)p_dest; @@ -1706,7 +1925,9 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) } break; } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_VENDOR_HCI_EN == TRUE) case BTC_GAP_BLE_ACT_VENDOR_HCI_CMD_EVT: { btc_ble_gap_args_t *src = (btc_ble_gap_args_t *)p_src; btc_ble_gap_args_t *dst = (btc_ble_gap_args_t *)p_dest; @@ -1720,6 +1941,7 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) } break; } +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) case BTC_GAP_BLE_ACT_SET_DEV_NAME:{ btc_ble_gap_args_t *src = (btc_ble_gap_args_t *)p_src; btc_ble_gap_args_t *dst = (btc_ble_gap_args_t *)p_dest; @@ -1756,6 +1978,18 @@ void btc_gap_ble_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) } break; } + case ESP_GAP_BLE_VENDOR_HCI_EVT: { + if (src->vendor_hci_evt.param_len) { + dst->vendor_hci_evt.param_buf = osi_malloc(src->vendor_hci_evt.param_len); + if (dst->vendor_hci_evt.param_buf) { + memcpy(dst->vendor_hci_evt.param_buf, src->vendor_hci_evt.param_buf, + src->vendor_hci_evt.param_len); + } else { + BTC_TRACE_ERROR("%s, malloc failed\n", __func__); + } + } + break; + } default: BTC_TRACE_ERROR("%s, Unhandled deep copy %d\n", __func__, msg->act); break; @@ -1767,6 +2001,7 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg) BTC_TRACE_DEBUG("%s \n", __func__); switch (msg->act) { #if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_ADV_EN == TRUE) case BTC_GAP_BLE_ACT_CFG_ADV_DATA: { esp_ble_adv_data_t *adv = &((btc_ble_gap_args_t *)msg->arg)->cfg_adv_data.adv_data; if (adv->p_service_data) { @@ -1796,6 +2031,7 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg) } break; } +#endif // #if (BLE_42_ADV_EN == TRUE) #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) case BTC_GAP_BLE_SET_SECURITY_PARAM_EVT: { uint8_t *value = ((btc_ble_gap_args_t *)msg->arg)->set_security_param.value; @@ -1823,6 +2059,7 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg) break; } #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) case BTC_GAP_BLE_CFG_EXT_ADV_DATA_RAW: case BTC_GAP_BLE_CFG_EXT_SCAN_RSP_DATA_RAW: { uint8_t *value = ((btc_ble_5_gap_args_t *)msg->arg)->ext_adv_cfg_data.data; @@ -1831,6 +2068,8 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg) } break; } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) case BTC_GAP_BLE_CFG_PERIODIC_ADV_DATA_RAW: { uint8_t *value = ((btc_ble_5_gap_args_t *)msg->arg)->periodic_adv_cfg_data.data; if (value) { @@ -1838,6 +2077,8 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg) } break; } +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) case BTC_GAP_BLE_EXT_ADV_START: { esp_ble_gap_ext_adv_t *value = ((btc_ble_5_gap_args_t *)msg->arg)->ext_adv_start.ext_adv; if (value) { @@ -1852,7 +2093,9 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg) } break; } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_VENDOR_HCI_EN == TRUE) case BTC_GAP_BLE_ACT_VENDOR_HCI_CMD_EVT: { uint8_t *p_param_buf = ((btc_ble_gap_args_t *)msg->arg)->vendor_cmd_send.p_param_buf; if (p_param_buf) { @@ -1860,6 +2103,7 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg) } break; } +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) case BTC_GAP_BLE_ACT_SET_DEV_NAME:{ char *p_name = ((btc_ble_gap_args_t *)msg->arg)->set_dev_name.device_name; if (p_name) { @@ -1892,6 +2136,13 @@ void btc_gap_ble_cb_deep_free(btc_msg_t *msg) } break; } + case ESP_GAP_BLE_VENDOR_HCI_EVT: { + void *value = ((esp_ble_gap_cb_param_t *)msg->arg)->vendor_hci_evt.param_buf; + if (value) { + osi_free(value); + } + break; + } default: BTC_TRACE_DEBUG("Unhandled deep free %d", msg->act); break; @@ -1909,6 +2160,7 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) switch (msg->act) { #if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_ADV_EN == TRUE) case BTC_GAP_BLE_ACT_CFG_ADV_DATA: { if (arg->cfg_adv_data.adv_data.set_scan_rsp == false) { btc_ble_set_adv_data(&arg->cfg_adv_data.adv_data, btc_adv_data_callback); @@ -1917,6 +2169,8 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) } break; } +#endif // #if (BLE_42_ADV_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) case BTC_GAP_BLE_ACT_SET_SCAN_PARAM: btc_ble_set_scan_params(&arg->set_scan_param.scan_params, btc_scan_params_callback); break; @@ -1926,15 +2180,15 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) case BTC_GAP_BLE_ACT_STOP_SCAN: btc_ble_stop_scanning(btc_stop_scan_callback); break; +#endif // #if (BLE_42_SCAN_EN == TRUE) +#if (BLE_42_ADV_EN == TRUE) case BTC_GAP_BLE_ACT_START_ADV: btc_ble_start_advertising(&arg->start_adv.adv_params, btc_start_adv_callback); break; case BTC_GAP_BLE_ACT_STOP_ADV: btc_ble_stop_advertising(btc_stop_adv_callback); break; - case BTC_GAP_BLE_ACT_CLEAR_ADV: - btc_ble_clear_advertising(btc_clear_adv_callback); - break; +#endif // #if (BLE_42_ADV_EN == TRUE) #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) case BTC_GAP_BLE_ACT_UPDATE_CONN_PARAM: btc_ble_update_conn_params(arg->conn_update_params.conn_params.bda, @@ -1982,6 +2236,9 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) case BTC_GAP_BLE_ACT_READ_RSSI: BTA_DmReadRSSI(arg->read_rssi.remote_addr, BTA_TRANSPORT_LE, btc_read_ble_rssi_cmpl_callback); break; + case BTC_GAP_BLE_READ_CHANNEL_MAP: + BTA_DmBleReadChannelMap(arg->read_channel_map.bd_addr, btc_ble_read_channel_map_callback); + break; #if (BLE_42_FEATURE_SUPPORT == TRUE) case BTC_GAP_BLE_ACT_SET_CONN_PARAMS: BTA_DmSetBlePrefConnParams(arg->set_conn_params.bd_addr, arg->set_conn_params.min_conn_int, @@ -1996,6 +2253,7 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) BTA_DmGetDeviceName(btc_gap_ble_get_dev_name_callback, BT_DEVICE_TYPE_BLE); break; #if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_ADV_EN == TRUE) case BTC_GAP_BLE_ACT_CFG_ADV_DATA_RAW: btc_ble_set_adv_data_raw(arg->cfg_adv_data_raw.raw_adv, arg->cfg_adv_data_raw.raw_adv_len, @@ -2006,6 +2264,7 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) arg->cfg_scan_rsp_data_raw.raw_scan_rsp_len, btc_scan_rsp_data_raw_callback); break; +#endif // #if (BLE_42_ADV_EN == TRUE) case BTC_GAP_BLE_UPDATE_DUPLICATE_SCAN_EXCEPTIONAL_LIST: btc_ble_update_duplicate_exceptional_list(arg->update_duplicate_exceptional_list.subcode, arg->update_duplicate_exceptional_list.info_type, @@ -2151,6 +2410,7 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) arg_5->set_def_phy.rx_phy_mask, arg_5->set_def_phy.phy_options); break; +#if (BLE_50_EXTEND_ADV_EN == TRUE) case BTC_GAP_BLE_SET_EXT_ADV_RAND_ADDR: BTA_DmBleGapExtAdvSetRandaddr(arg_5->ext_adv_set_rand_addr.instance, arg_5->ext_adv_set_rand_addr.rand_addr); break; @@ -2226,6 +2486,8 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) case BTC_GAP_BLE_EXT_ADV_SET_CLEAR: BTA_DmBleGapExtAdvSetClear(); break; +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) case BTC_GAP_BLE_SET_PERIODIC_ADV_PARAMS: { tBTA_DM_BLE_Periodic_Adv_Params params = {0}; params.interval_min = arg_5->peridic_adv_set_params.params.interval_min; @@ -2251,6 +2513,8 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) BTC_TRACE_DEBUG("BTC_GAP_BLE_PERIODIC_ADV_STOP"); BTA_DmBleGapPeriodicAdvEnable(FALSE, arg_5->periodic_adv_stop.instance); break; +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) case BTC_GAP_BLE_PERIODIC_ADV_CREATE_SYNC: { tBTA_DM_BLE_Periodic_Sync_Params params = {0}; params.filter_policy = arg_5->periodic_adv_create_sync.params.filter_policy; @@ -2258,10 +2522,13 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) params.addr_type = arg_5->periodic_adv_create_sync.params.addr_type; params.skip = arg_5->periodic_adv_create_sync.params.skip; params.sync_timeout = arg_5->periodic_adv_create_sync.params.sync_timeout; - #if (CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH) +#if (BLE_FEAT_CTE_EN == TRUE) + params.sync_cte_type = arg_5->periodic_adv_create_sync.params.sync_cte_type; +#endif // #if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_CREATE_SYNC_ENH == TRUE) params.reports_disabled = arg_5->periodic_adv_create_sync.params.reports_disabled; params.filter_duplicates = arg_5->periodic_adv_create_sync.params.filter_duplicates; - #endif +#endif // (BLE_FEAT_CREATE_SYNC_ENH == TRUE) memcpy(params.addr, arg_5->periodic_adv_create_sync.params.addr, sizeof(BD_ADDR)); BTC_TRACE_DEBUG("BTC_GAP_BLE_PERIODIC_ADV_CREATE_SYNC"); @@ -2292,6 +2559,9 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) BTC_TRACE_DEBUG("BTC_GAP_BLE_PERIODIC_CLEAR_DEV"); BTA_DmBleGapPeriodicAdvClearDev(); break; +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) + +#if (BLE_50_EXTEND_SCAN_EN == TRUE) case BTC_GAP_BLE_SET_EXT_SCAN_PARAMS: { tBTA_DM_BLE_EXT_SCAN_PARAMS params = {0}; params.own_addr_type = arg_5->set_ext_scan_params.params.own_addr_type; @@ -2322,6 +2592,7 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) BTC_TRACE_DEBUG("BTC_GAP_BLE_STOP_EXT_SCAN"); BTA_DmBleGapExtScan(FALSE, 0, 0); break; +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) case BTC_GAP_BLE_SET_EXT_PEFER_CONNET_PARAMS: BTC_TRACE_DEBUG("BTC_GAP_BLE_SET_EXT_PEFER_CONNET_PARAMS"); BTA_DmBleGapPreferExtConnectParamsSet(arg_5->set_ext_conn_params.addr, @@ -2355,35 +2626,81 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) (tBTA_DM_BLE_PAST_PARAMS *)&arg_5->set_periodic_adv_sync_trans_params.params); break; #endif -#if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_DTM_TEST_EN == TRUE) case BTC_GAP_BLE_DTM_TX_START: btc_ble_dtm_tx_start(arg->dtm_tx_start.tx_channel, arg->dtm_tx_start.len_of_data, arg->dtm_tx_start.pkt_payload, btc_dtm_tx_start_callback); break; case BTC_GAP_BLE_DTM_RX_START: btc_ble_dtm_rx_start(arg->dtm_rx_start.rx_channel, btc_dtm_rx_start_callback); break; -#endif // if (BLE_42_FEATURE_SUPPORT == TRUE) +#endif // #if (BLE_42_DTM_TEST_EN == TRUE) +#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) case BTC_GAP_BLE_DTM_STOP: btc_ble_dtm_stop(btc_dtm_stop_callback); break; -#if (BLE_50_FEATURE_SUPPORT == TRUE) +#endif // #if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) +#if (BLE_50_DTM_TEST_EN == TRUE) case BTC_GAP_BLE_DTM_ENH_TX_START: btc_ble_dtm_enhance_tx_start(arg_5->dtm_enh_tx_start.tx_channel, arg_5->dtm_enh_tx_start.len_of_data, arg_5->dtm_enh_tx_start.pkt_payload, arg_5->dtm_enh_tx_start.phy, btc_dtm_tx_start_callback); break; case BTC_GAP_BLE_DTM_ENH_RX_START: btc_ble_dtm_enhance_rx_start(arg_5->dtm_enh_rx_start.rx_channel, arg_5->dtm_enh_rx_start.phy, arg_5->dtm_enh_rx_start.modulation_index, btc_dtm_rx_start_callback); break; -#endif // if (BLE_50_FEATURE_SUPPORT == TRUE) +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) + case BTC_GAP_BLE_SET_PRIVACY_MODE: + btc_ble_set_privacy_mode(arg->set_privacy_mode.addr_type, arg->set_privacy_mode.addr, + arg->set_privacy_mode.privacy_mode, btc_ble_set_privacy_mode_callback); + break; +#if (BLE_VENDOR_HCI_EN == TRUE) + case BTC_GAP_BLE_ACT_CLEAR_ADV: + BTA_DmBleClearAdv(btc_clear_adv_callback); + break; case BTC_GAP_BLE_ACT_VENDOR_HCI_CMD_EVT: BTA_DmsendVendorHciCmd(arg->vendor_cmd_send.opcode, arg->vendor_cmd_send.param_len, arg->vendor_cmd_send.p_param_buf, btc_ble_vendor_hci_cmd_complete_callback); break; - case BTC_GAP_BLE_SET_PRIVACY_MODE: - btc_ble_set_privacy_mode(arg->set_privacy_mode.addr_type, arg->set_privacy_mode.addr, - arg->set_privacy_mode.privacy_mode, btc_ble_set_privacy_mode_callback); + case BTC_GAP_BLE_SET_CSA_SUPPORT: + BTA_DmBleGapSetCsaSupport(arg->set_csa_support.csa_select, btc_ble_set_csa_support_callback); + break; + case BTC_GAP_BLE_ACT_SET_VENDOR_EVT_MASK: + BTA_DmBleGapSetVendorEventMask(arg->set_vendor_evt_mask.evt_mask, btc_ble_set_vendor_evt_mask_callback); + break; +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + case BTC_GAP_BLE_ENH_READ_TRANS_POWER_LEVEL: + BTA_DmBleGapEnhReadTransPwrLevel(arg_5->enh_read_trans_pwr_level.conn_handle, arg_5->enh_read_trans_pwr_level.phy); + break; + case BTC_GAP_BLE_READ_REM_TRANS_POWER_LEVEL: + BTA_DmBleGapReadRemoteTransPwrLevel(arg_5->read_rem_trans_pwr_level.conn_handle, arg_5->read_rem_trans_pwr_level.phy); + break; + case BTC_GAP_BLE_SET_PATH_LOSS_REPORT_PARAMS: + BTA_DmBleGapSetPathLossRptParams(arg_5->set_path_loss_rpt_params.conn_handle, arg_5->set_path_loss_rpt_params.high_threshold, arg_5->set_path_loss_rpt_params.high_hysteresis, + arg_5->set_path_loss_rpt_params.low_threshold, arg_5->set_path_loss_rpt_params.low_hysteresis, arg_5->set_path_loss_rpt_params.min_time_spent); + break; + case BTC_GAP_BLE_SET_PATH_LOSS_REPORTING_EN: + BTA_DmBleGapSetPathLossRptEnable(arg_5->set_path_loss_rpt_en.conn_handle, arg_5->set_path_loss_rpt_en.enable); + break; + case BTC_GAP_BLE_SET_TRANS_POWER_REPORTING_EN: + BTA_DmBleGapSetTransPwrRptEnable(arg_5->set_trans_pwr_rpting_en.conn_handle, arg_5->set_trans_pwr_rpting_en.local_enable, arg_5->set_trans_pwr_rpting_en.remote_enable); + break; +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) + case BTC_GAP_BLE_SET_DEFALT_SUBRATE: + BTA_DmBleGapSetDefaultSubrate(arg_5->default_subrate_param.subrate_min, arg_5->default_subrate_param.subrate_max, arg_5->default_subrate_param.max_latency, + arg_5->default_subrate_param.continuation_number, arg_5->default_subrate_param.supervision_timeout); break; + case BTC_GAP_BLE_SUBRATE_REQUEST: + BTA_DmBleGapSubrateReqest(arg_5->subrate_req_param.conn_handle, arg_5->subrate_req_param.subrate_min, arg_5->subrate_req_param.subrate_max, + arg_5->subrate_req_param.max_latency, arg_5->subrate_req_param.continuation_number, arg_5->subrate_req_param.supervision_timeout); + break; +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) + case BTC_GAP_ACT_SET_HOST_FEATURE: + BTA_DmBleGapSetHostFeature(arg_5->set_host_feature_params.bit_num, arg_5->set_host_feature_params.bit_val); + break; +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) default: break; } @@ -2399,11 +2716,15 @@ void btc_gap_callback_init(void) #if (BLE_50_FEATURE_SUPPORT == TRUE) BTM_BleGapRegisterCallback(btc_ble_5_gap_callback); #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_VENDOR_HCI_EN == TRUE) + BTM_BleRegisterVendorHciEventCallback(btc_ble_vendor_hci_event_callback); +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) } bool btc_gap_ble_init(void) { #if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_SCAN_EN == TRUE) btc_gap_ble_env_t *p_env = &btc_gap_ble_env; p_env->adv_rpt_queue = pkt_queue_create(); assert(p_env->adv_rpt_queue != NULL); @@ -2411,6 +2732,7 @@ bool btc_gap_ble_init(void) p_env->adv_rpt_ready = osi_event_create(btc_gap_ble_adv_pkt_handler, NULL); assert(p_env->adv_rpt_ready != NULL); osi_event_bind(p_env->adv_rpt_ready, btc_get_current_thread(), BTC_GAP_BLE_ADV_RPT_QUEUE_IDX); +#endif // #if (BLE_42_SCAN_EN == TRUE) #endif return true; } @@ -2418,6 +2740,7 @@ bool btc_gap_ble_init(void) void btc_gap_ble_deinit(void) { #if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_SCAN_EN == TRUE) btc_gap_ble_env_t *p_env = &btc_gap_ble_env; osi_event_delete(p_env->adv_rpt_ready); @@ -2425,105 +2748,11 @@ void btc_gap_ble_deinit(void) pkt_queue_destroy(p_env->adv_rpt_queue, NULL); p_env->adv_rpt_queue = NULL; - +#endif // #if (BLE_42_SCAN_EN == TRUE) +#if (BLE_42_ADV_EN == TRUE) btc_cleanup_adv_data(&gl_bta_adv_data); btc_cleanup_adv_data(&gl_bta_scan_rsp_data); +#endif // #if (BLE_42_ADV_EN == TRUE) #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) } - -#if SCAN_QUEUE_CONGEST_CHECK -void btc_adv_list_free(void *data) -{ - osi_free(data); -} - -void btc_adv_list_init(void) -{ - osi_mutex_new(&adv_list_lock); - adv_filter_list = list_new(btc_adv_list_free); -} - -void btc_adv_list_deinit(void) -{ - osi_mutex_free(&adv_list_lock); - if(adv_filter_list) { - list_free(adv_filter_list); - adv_filter_list = NULL; - } -} -void btc_adv_list_add_packet(void * data) -{ - if(!data) { - BTC_TRACE_ERROR("%s data is NULL", __func__); - return; - } - btc_adv_list_lock(); - list_prepend(adv_filter_list, data); - btc_adv_list_unlock(); -} - -uint32_t btc_get_adv_list_length(void) -{ - if(!adv_filter_list) { - BTC_TRACE_ERROR("%s adv_filter_list is NULL", __func__); - return 0; - } - btc_adv_list_lock(); - size_t length = list_length(adv_filter_list); - btc_adv_list_unlock(); - - return length; -} - -void btc_adv_list_refresh(void) -{ - if(!adv_filter_list) { - BTC_TRACE_ERROR("%s adv_filter_list is NULL", __func__); - return ; - } - btc_adv_list_lock(); - list_clear(adv_filter_list); - btc_adv_list_unlock(); -} - -bool btc_check_adv_list(uint8_t * addr, uint8_t addr_type) -{ - bool found = false; - if(!adv_filter_list || !addr) { - BTC_TRACE_ERROR("%s adv_filter_list is NULL", __func__); - return found; - } - - btc_adv_list_lock(); - for (const list_node_t *node = list_begin(adv_filter_list); node != list_end(adv_filter_list); node = list_next(node)) { - btc_adv_packet_t *packet = (btc_adv_packet_t *)list_node(node); - if(!bdcmp(addr, packet->addr) && packet->addr_type == addr_type) { - found = true; - break; - } - } - btc_adv_list_unlock(); - if(!found) { - btc_adv_packet_t *adv_packet = osi_malloc(sizeof(btc_adv_packet_t)); - if(adv_packet) { - adv_packet->addr_type = addr_type; - bdcpy(adv_packet->addr, addr); - btc_adv_list_add_packet(adv_packet); - } else { - BTC_TRACE_ERROR("%s adv_packet malloc failed", __func__); - } - } - return found; -} - -void btc_adv_list_lock(void) -{ - osi_mutex_lock(&adv_list_lock, OSI_MUTEX_MAX_TIMEOUT); -} - -void btc_adv_list_unlock(void) -{ - osi_mutex_unlock(&adv_list_lock); -} -#endif #endif ///BLE_INCLUDED == TRUE diff --git a/lib/bt/host/bluedroid/btc/profile/std/gap/btc_gap_bt.c b/lib/bt/host/bluedroid/btc/profile/std/gap/btc_gap_bt.c index 9e9d7b01..e1278954 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/gap/btc_gap_bt.c +++ b/lib/bt/host/bluedroid/btc/profile/std/gap/btc_gap_bt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -24,14 +24,27 @@ #define BTC_STORAGE_FILL_PROPERTY(p_prop, t, l, p_v) \ (p_prop)->type = t;(p_prop)->len = l; (p_prop)->val = (p_v); +typedef struct { + esp_bt_gap_discovery_state_t disc_stat; + esp_bt_connection_mode_t conn_mode; + esp_bt_discovery_mode_t disc_mode; + uint8_t bredr_acl_link_num; + uint16_t handle[MAX_ACL_CONNECTIONS]; +} gap_bt_local_param_t; + +#if BTC_GAP_BT_DYNAMIC_MEMORY == FALSE +static gap_bt_local_param_t gap_bt_local_param; +#else +static gap_bt_local_param_t *gap_bt_local_param_ptr; +#define gap_bt_local_param (*gap_bt_local_param_ptr) +#endif + static void bte_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data); static void bte_dm_search_services_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data); static void bte_dm_remote_service_record_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data); static void search_services_copy_cb(btc_msg_t *msg, void *p_dest, void *p_src); static void search_service_record_copy_cb(btc_msg_t *msg, void *p_dest, void *p_src); -static bool btc_gap_bt_inquiry_in_progress = false; - static inline void btc_gap_bt_cb_to_app(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) { esp_bt_gap_cb_t cb = (esp_bt_gap_cb_t)btc_profile_cb_get(BTC_PID_GAP_BT); @@ -45,6 +58,9 @@ static void btc_bt_set_scan_mode(esp_bt_connection_mode_t c_mode, esp_bt_discove tBTA_DM_DISC disc_mode; tBTA_DM_CONN conn_mode; + gap_bt_local_param.conn_mode = c_mode; + gap_bt_local_param.disc_mode = d_mode; + switch (c_mode) { case ESP_BT_NON_CONNECTABLE: conn_mode = BTA_DM_NON_CONN; @@ -93,7 +109,7 @@ static void btc_gap_bt_start_discovery(btc_gap_bt_args_t *arg) /* TODO: Filter device by BDA needs to be implemented here */ /* Will be enabled to TRUE once inquiry busy level has been received */ - btc_gap_bt_inquiry_in_progress = FALSE; + gap_bt_local_param.disc_stat = ESP_BT_GAP_DISCOVERY_STOPPED; /* find nearby devices */ BTA_DmSearch(&inq_params, services, bte_search_devices_evt); @@ -374,7 +390,7 @@ static void btc_gap_bt_search_devices_evt(tBTA_DM_SEARCH_PARAM *p_data) * if inquiry is in progress, then we don't want to act on this cancel_cmpl_evt * but instead wait for the cancel_cmpl_evt_via the busy level */ - if (btc_gap_bt_inquiry_in_progress == false) { + if (gap_bt_local_param.disc_stat == ESP_BT_GAP_DISCOVERY_STOPPED) { esp_bt_gap_cb_param_t param; param.disc_st_chg.state = ESP_BT_GAP_DISCOVERY_STOPPED; btc_gap_bt_cb_to_app(ESP_BT_GAP_DISC_STATE_CHANGED_EVT, ¶m); @@ -585,6 +601,7 @@ static void btc_gap_bt_set_cod(btc_gap_bt_args_t *arg) { tBTA_UTL_COD p_cod; esp_bt_cod_t *cod = &(arg->set_cod.cod); + p_cod.reserved_2 = cod->reserved_2; p_cod.minor = cod->minor << 2; p_cod.major = cod->major; p_cod.service = cod->service << 5; @@ -602,6 +619,7 @@ esp_err_t btc_gap_bt_get_cod(esp_bt_cod_t *cod) BTC_TRACE_ERROR("%s get class of device failed!",__func__); return ESP_BT_STATUS_FAIL; } + cod->reserved_2 = p_cod.reserved_2; cod->minor = p_cod.minor >> 2; cod->major = p_cod.major; cod->service = p_cod.service >> 5; @@ -1156,15 +1174,15 @@ void btc_gap_bt_busy_level_updated(uint8_t bl_flags) if (bl_flags == BTM_BL_INQUIRY_STARTED) { param.disc_st_chg.state = ESP_BT_GAP_DISCOVERY_STARTED; btc_gap_bt_cb_to_app(ESP_BT_GAP_DISC_STATE_CHANGED_EVT, ¶m); - btc_gap_bt_inquiry_in_progress = true; + gap_bt_local_param.disc_stat = ESP_BT_GAP_DISCOVERY_STARTED; } else if (bl_flags == BTM_BL_INQUIRY_CANCELLED) { param.disc_st_chg.state = ESP_BT_GAP_DISCOVERY_STOPPED; btc_gap_bt_cb_to_app(ESP_BT_GAP_DISC_STATE_CHANGED_EVT, ¶m); - btc_gap_bt_inquiry_in_progress = false; + gap_bt_local_param.disc_stat = ESP_BT_GAP_DISCOVERY_STOPPED; } else if (bl_flags == BTM_BL_INQUIRY_COMPLETE) { /* The Inquiry Complete event is not transported to app layer, since the app only cares about the Name Discovery Complete event */ - btc_gap_bt_inquiry_in_progress = false; + gap_bt_local_param.disc_stat = ESP_BT_GAP_DISCOVERY_STOPPED; } } @@ -1305,4 +1323,76 @@ void btc_gap_bt_cb_handler(btc_msg_t *msg) } btc_gap_bt_cb_deep_free(msg); } + +void btc_gap_bt_init(void) +{ +#if BTC_GAP_BT_DYNAMIC_MEMORY == TRUE + if ((gap_bt_local_param_ptr = (gap_bt_local_param_t *)osi_malloc(sizeof(gap_bt_local_param_t))) == NULL) { + BTC_TRACE_ERROR("%s malloc failed\n", __func__); + return; + } + memset((void *)gap_bt_local_param_ptr, 0, sizeof(gap_bt_local_param_t)); +#else + memset(&gap_bt_local_param, 0, sizeof(gap_bt_local_param_t)); +#endif +} + +void btc_gap_bt_deinit(void) +{ +#if BTC_GAP_BT_DYNAMIC_MEMORY == TRUE + if (gap_bt_local_param_ptr) { + osi_free(gap_bt_local_param_ptr); + gap_bt_local_param_ptr = NULL; + } +#endif +} + +static void btc_gap_bt_acl_link_handle_store(uint16_t handle) +{ + for (int i = 0; i < MAX_ACL_CONNECTIONS; i++) { + if (gap_bt_local_param.handle[i] == 0) { + gap_bt_local_param.handle[i] = handle; + gap_bt_local_param.bredr_acl_link_num++; + break; + } + } + + if (gap_bt_local_param.bredr_acl_link_num > MAX_ACL_CONNECTIONS) { + assert(0); + } +} + +static void btc_gap_bt_acl_link_handle_remove(uint16_t handle) +{ + for (int i = 0; i < MAX_ACL_CONNECTIONS; i++) { + if (gap_bt_local_param.handle[i] == handle) { + gap_bt_local_param.handle[i] = 0; + gap_bt_local_param.bredr_acl_link_num--; + break; + } + } + + if (gap_bt_local_param.bredr_acl_link_num > MAX_ACL_CONNECTIONS) { + assert(0); + } +} + +void btc_gap_bt_acl_link_num_update(tBTA_DM_ACL_LINK_STAT *p_acl_link_stat) +{ + if (p_acl_link_stat->event == BTA_ACL_LINK_STAT_CONN_CMPL && + p_acl_link_stat->link_act.conn_cmpl.status == HCI_SUCCESS) { + btc_gap_bt_acl_link_handle_store(p_acl_link_stat->link_act.conn_cmpl.handle); + } else if (p_acl_link_stat->event == BTA_ACL_LINK_STAT_DISCONN_CMPL) { + btc_gap_bt_acl_link_handle_remove(p_acl_link_stat->link_act.disconn_cmpl.handle); + } +} + +void btc_gap_bt_status_get(esp_bt_gap_profile_status_t *param) +{ + param->disc_stat = gap_bt_local_param.disc_stat; + param->conn_mode = gap_bt_local_param.conn_mode; + param->disc_mode = gap_bt_local_param.disc_mode; + param->bredr_acl_link_num = gap_bt_local_param.bredr_acl_link_num; +} + #endif /* (BTC_GAP_BT_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/gatt/btc_gatt_util.c b/lib/bt/host/bluedroid/btc/profile/std/gatt/btc_gatt_util.c index bca8ea66..9d4d108b 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/gatt/btc_gatt_util.c +++ b/lib/bt/host/bluedroid/btc/profile/std/gatt/btc_gatt_util.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -82,23 +82,6 @@ void btc128_to_bta_uuid(tBT_UUID *p_dest, uint8_t *p_src) /******************************************************************************* * BTC -> BTA conversion functions *******************************************************************************/ - -void btc_to_bta_uuid(tBT_UUID *p_dest, esp_bt_uuid_t *p_src) -{ - p_dest->len = p_src->len; - if (p_src->len == LEN_UUID_16) { - p_dest->uu.uuid16 = p_src->uuid.uuid16; - } else if (p_src->len == LEN_UUID_32) { - p_dest->uu.uuid32 = p_src->uuid.uuid32; - } else if (p_src->len == LEN_UUID_128) { - memcpy(&p_dest->uu.uuid128, p_src->uuid.uuid128, p_dest->len); - } else if (p_src->len == 0) { - /* do nothing for now, there's some scenario will input 0 */ - } else { - BTC_TRACE_ERROR("%s UUID len is invalid %d\n", __func__, p_src->len); - } -} - void btc_to_bta_gatt_id(tBTA_GATT_ID *p_dest, esp_gatt_id_t *p_src) { p_dest->inst_id = p_src->inst_id; @@ -115,23 +98,6 @@ void btc_to_bta_srvc_id(tBTA_GATT_SRVC_ID *p_dest, esp_gatt_srvc_id_t *p_src) /******************************************************************************* * BTA -> BTC conversion functions *******************************************************************************/ -void bta_to_btc_uuid(esp_bt_uuid_t *p_dest, tBT_UUID *p_src) -{ - p_dest->len = p_src->len; - if (p_src->len == LEN_UUID_16) { - p_dest->uuid.uuid16 = p_src->uu.uuid16; - } else if (p_src->len == LEN_UUID_32) { - p_dest->uuid.uuid32 = p_src->uu.uuid32; - } else if (p_src->len == LEN_UUID_128) { - memcpy(&p_dest->uuid.uuid128, p_src->uu.uuid128, p_dest->len); - } else if (p_src->len == 0) { - /* do nothing for now, there's some scenario will input 0 - such as, receive notify, the descriptor may be 0 */ - } else { - BTC_TRACE_ERROR("%s UUID len is invalid %d\n", __func__, p_src->len); - } -} - void bta_to_btc_gatt_id(esp_gatt_id_t *p_dest, tBTA_GATT_ID *p_src) { p_dest->inst_id = p_src->inst_id; diff --git a/lib/bt/host/bluedroid/btc/profile/std/gatt/btc_gattc.c b/lib/bt/host/bluedroid/btc/profile/std/gatt/btc_gattc.c index e69eed48..86221e3c 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/gatt/btc_gattc.c +++ b/lib/bt/host/bluedroid/btc/profile/std/gatt/btc_gattc.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 @@ -212,9 +212,12 @@ static void btc_gattc_app_unregister(btc_ble_gattc_args_t *arg) static void btc_gattc_open(btc_ble_gattc_args_t *arg) { tBTA_GATT_TRANSPORT transport = BTA_GATT_TRANSPORT_LE; - BTA_GATTC_Open(arg->open.gattc_if, arg->open.remote_bda, + + BTA_GATTC_Enh_Open(arg->open.gattc_if, arg->open.remote_bda, arg->open.remote_addr_type, arg->open.is_direct, - transport, arg->open.is_aux); + transport, arg->open.is_aux, arg->open.own_addr_type, + arg->open.phy_mask, (void *)&arg->open.phy_1m_conn_params, + (void *)&arg->open.phy_2m_conn_params, (void *)&arg->open.phy_coded_conn_params); } static void btc_gattc_close(btc_ble_gattc_args_t *arg) diff --git a/lib/bt/host/bluedroid/btc/profile/std/gatt/btc_gatts.c b/lib/bt/host/bluedroid/btc/profile/std/gatt/btc_gatts.c index df9a4ceb..7eab806e 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/gatt/btc_gatts.c +++ b/lib/bt/host/bluedroid/btc/profile/std/gatt/btc_gatts.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -469,7 +469,7 @@ static esp_gatt_status_t btc_gatts_check_valid_attr_tab(esp_gatts_attr_db_t *gat if(gatts_attr_db[i+1].att_desc.uuid_length != ESP_UUID_LEN_16 && gatts_attr_db[i+1].att_desc.uuid_length != ESP_UUID_LEN_32 && gatts_attr_db[i+1].att_desc.uuid_length != ESP_UUID_LEN_128) { - BTC_TRACE_ERROR("%s, The Charateristic uuid length = %d is invalid", __func__,\ + BTC_TRACE_ERROR("%s, The Characteristic uuid length = %d is invalid", __func__,\ gatts_attr_db[i+1].att_desc.uuid_length); return ESP_GATT_INVALID_ATTR_LEN; } @@ -481,7 +481,7 @@ static esp_gatt_status_t btc_gatts_check_valid_attr_tab(esp_gatts_attr_db_t *gat uuid == ESP_GATT_UUID_CHAR_SRVR_CONFIG || uuid == ESP_GATT_UUID_CHAR_PRESENT_FORMAT || uuid == ESP_GATT_UUID_CHAR_AGG_FORMAT || uuid == ESP_GATT_UUID_CHAR_VALID_RANGE || uuid == ESP_GATT_UUID_EXT_RPT_REF_DESCR || uuid == ESP_GATT_UUID_RPT_REF_DESCR) { - BTC_TRACE_ERROR("%s, The charateristic value uuid = %d is invalid", __func__, uuid); + BTC_TRACE_ERROR("%s, The characteristic value uuid = %d is invalid", __func__, uuid); return ESP_GATT_INVALID_PDU; } } @@ -694,6 +694,7 @@ void btc_gatts_call_handler(btc_msg_t *msg) } param.rsp.status = 0; + param.rsp.conn_id = BTC_GATT_GET_CONN_ID(arg->send_rsp.conn_id); btc_gatts_cb_to_app(ESP_GATTS_RESPONSE_EVT, BTC_GATT_GET_GATT_IF(arg->send_rsp.conn_id), ¶m); break; } diff --git a/lib/bt/host/bluedroid/btc/profile/std/hf_ag/bta_ag_co.c b/lib/bt/host/bluedroid/btc/profile/std/hf_ag/bta_ag_co.c index 6000f832..2f095ab3 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/hf_ag/bta_ag_co.c +++ b/lib/bt/host/bluedroid/btc/profile/std/hf_ag/bta_ag_co.c @@ -35,9 +35,11 @@ * CONST ********************************************************************************/ #if (BTM_SCO_HCI_INCLUDED == TRUE) +#if (BTC_HFP_EXT_CODEC == FALSE) #include "oi_codec_sbc.h" #include "oi_status.h" #include "sbc_encoder.h" +#endif #if (PLC_INCLUDED == TRUE) #include "sbc_plc.h" @@ -58,21 +60,39 @@ static bta_hf_ct_plc_t *bta_hf_ct_plc_ptr; #define HF_SBC_DEC_RAW_DATA_SIZE 240 #define HF_SBC_ENC_RAW_DATA_SIZE 240 +// H2: Header with synchronization word and sequence number +#define BTA_HF_H2_HEADER_SYNC_WORD 0x0801 +#define BTA_HF_H2_HEADER_SYNC_WORD_MASK 0x0FFF +#define BTA_HF_H2_HEADER_BIT0_MASK (1 << 0) +#define BTA_HF_H2_HEADER_BIT1_MASK (1 << 1) +#define BTA_HF_H2_HEADER_SN0_BIT_OFFSET1 12 +#define BTA_HF_H2_HEADER_SN0_BIT_OFFSET2 13 +#define BTA_HF_H2_HEADER_SN1_BIT_OFFSET1 14 +#define BTA_HF_H2_HEADER_SN1_BIT_OFFSET2 15 + +#define BTA_HF_H2_HEADER_SYNC_WORD_CHECK(p) ((*((uint16_t *)p) & BTA_HF_H2_HEADER_SYNC_WORD_MASK) == BTA_HF_H2_HEADER_SYNC_WORD) + /* BTA-AG-CO control block to map bdaddr to BTA handle */ typedef struct { +#if (BTC_HFP_EXT_CODEC == FALSE) OI_CODEC_SBC_DECODER_CONTEXT decoder_context; OI_UINT32 decoder_context_data[HF_SBC_DEC_CONTEXT_DATA_LEN]; OI_INT16 decode_raw_data[HF_SBC_DEC_RAW_DATA_SIZE]; SBC_ENC_PARAMS encoder; - UINT8 sequence_number; bool is_bad_frame; bool decode_first_pkt; - OI_BYTE decode_msbc_data[BTM_MSBC_FRAME_SIZE]; bool encode_first_pkt; + OI_BYTE decode_msbc_data[BTM_MSBC_FRAME_SIZE]; OI_BYTE encode_msbc_data[BTM_MSBC_FRAME_SIZE]; +#else + UINT8 sequence_number; + BOOLEAN rx_first_pkt; + BOOLEAN is_bad_frame; + UINT8 rx_half_msbc_data[BTM_MSBC_FRAME_SIZE/2]; +#endif } bta_ag_co_cb_t; #if HFP_DYNAMIC_MEMORY == FALSE @@ -151,7 +171,7 @@ void bta_ag_ci_rx_write(UINT16 handle, char *p_data, UINT16 len) ** Function bta_ag_ci_slc_ready ** ** Description This function is called to notify AG that SLC is up at -** the application. This funcion is only used when the app +** the application. This function is only used when the app ** is running in pass-through mode. ** ** Returns void @@ -179,18 +199,9 @@ void bta_ag_ci_slc_ready(UINT16 handle) ** Returns void ** *******************************************************************************/ -static void bta_ag_h2_header(UINT16 *p_buf) +void bta_ag_h2_header(UINT16 *p_buf) { - // H2: Header with synchronization word and sequence number -#define BTA_HF_H2_HEADER 0x0801 -#define BTA_HF_H2_HEADER_BIT0_MASK (1 << 0) -#define BTA_HF_H2_HEADER_BIT1_MASK (1 << 1) -#define BTA_HF_H2_HEADER_SN0_BIT_OFFSET1 12 -#define BTA_HF_H2_HEADER_SN0_BIT_OFFSET2 13 -#define BTA_HF_H2_HEADER_SN1_BIT_OFFSET1 14 -#define BTA_HF_H2_HEADER_SN1_BIT_OFFSET2 15 - - UINT16 h2_header = BTA_HF_H2_HEADER; + UINT16 h2_header = BTA_HF_H2_HEADER_SYNC_WORD; UINT8 h2_header_sn0 = bta_ag_co_cb.sequence_number & BTA_HF_H2_HEADER_BIT0_MASK; UINT8 h2_header_sn1 = bta_ag_co_cb.sequence_number & BTA_HF_H2_HEADER_BIT1_MASK; h2_header |= (h2_header_sn0 << BTA_HF_H2_HEADER_SN0_BIT_OFFSET1 @@ -202,6 +213,19 @@ static void bta_ag_h2_header(UINT16 *p_buf) *p_buf = h2_header; } +#if (BTC_HFP_EXT_CODEC == TRUE) + +static void bta_ag_pkt_state_reset(void) +{ + bta_ag_co_cb.sequence_number = 0; + bta_ag_co_cb.rx_first_pkt = TRUE; + bta_ag_co_cb.is_bad_frame = FALSE; +} + +#endif + +#if (BTC_HFP_EXT_CODEC == FALSE) + /******************************************************************************* ** ** Function bta_hf_dec_init @@ -217,6 +241,7 @@ static void bta_hf_dec_init(void) sbc_plc_init(&(bta_hf_ct_plc.plc_state)); #endif ///(PLC_INCLUDED == TRUE) + OI_STATUS status = OI_CODEC_SBC_DecoderReset(&bta_ag_co_cb.decoder_context, bta_ag_co_cb.decoder_context_data, HF_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32), 1, 1, FALSE, TRUE); if (!OI_SUCCESS(status)) { @@ -326,15 +351,21 @@ static void bta_ag_decode_msbc_frame(UINT8 **data, UINT8 *length, BOOLEAN is_bad APPL_TRACE_ERROR("Frame decode error: %d", status); break; } -#endif ///(PLC_INCLUDED == TRUE) if (OI_SUCCESS(status)) { btc_hf_incoming_data_cb_to_app((const uint8_t *)(bta_hf_ct_plc.sbc_plc_out), sbc_raw_data_size); } +#else + if (OI_SUCCESS(status)) { + btc_hf_incoming_data_cb_to_app((const uint8_t *)(bta_ag_co_cb.decode_raw_data), sbc_raw_data_size); + } +#endif } +#endif + /******************************************************************************* - * BTA AG SCO CO FUNCITONS + * BTA AG SCO CO FUNCTIONS ********************************************************************************/ /******************************************************************************* ** @@ -418,8 +449,12 @@ void bta_ag_sco_co_open(UINT16 handle, tBTM_SCO_AIR_MODE_TYPE air_mode, UINT8 in } #endif ///(PLC_INCLUDED == TRUE) #endif /// (HFP_DYNAMIC_MEMORY == TRUE) +#if (BTC_HFP_EXT_CODEC == TRUE) + bta_ag_pkt_state_reset(); +#else bta_hf_dec_init(); bta_hf_enc_init(); +#endif return; } else { return; // Nothing to do @@ -476,6 +511,8 @@ void bta_ag_sco_co_close(void) hf_inout_pkt_size = 0; } +#if (BTC_HFP_EXT_CODEC == FALSE) + /******************************************************************************* ** ** Function bta_ag_sco_co_out_data @@ -525,7 +562,7 @@ uint32_t bta_ag_sco_co_out_data(UINT8 *p_buf) //Never run to here. } } else { - APPL_TRACE_ERROR("%s invaild air mode: %d", __FUNCTION__, hf_air_mode); + APPL_TRACE_ERROR("%s invalid air mode: %d", __FUNCTION__, hf_air_mode); } return 0; } @@ -546,6 +583,65 @@ void bta_ag_sco_co_in_data(BT_HDR *p_buf, tBTM_SCO_DATA_FLAG status) STREAM_SKIP_UINT16(p); STREAM_TO_UINT8(pkt_size, p); +#if (BTC_HFP_EXT_CODEC == TRUE) + if (hf_air_mode == BTM_SCO_AIR_MODE_CVSD) { + btc_hf_audio_data_cb_to_app((uint8_t *)p_buf, (uint8_t *)p, pkt_size, status != BTM_SCO_DATA_CORRECT); + } + else if (hf_air_mode == BTM_SCO_AIR_MODE_TRANSPNT) { + if (pkt_size != hf_inout_pkt_size) { + bta_ag_co_cb.is_bad_frame = true; + } + if (status != BTM_SCO_DATA_CORRECT) { + bta_ag_co_cb.is_bad_frame = true; + } + if (hf_inout_pkt_size == BTM_MSBC_FRAME_SIZE / 2) { + if (pkt_size > BTM_MSBC_FRAME_SIZE / 2) { + pkt_size = BTM_MSBC_FRAME_SIZE / 2; + } + if (bta_ag_co_cb.rx_first_pkt){ + memcpy(bta_ag_co_cb.rx_half_msbc_data, p, pkt_size); + osi_free(p_buf); + } else { + BT_HDR *p_new_buf = osi_calloc(sizeof(BT_HDR) + BTM_MSBC_FRAME_SIZE); + p_new_buf->offset = 0; + UINT8 *p_data = (UINT8 *)(p_new_buf + 1) + p_new_buf->offset; + memcpy(p_data, bta_ag_co_cb.rx_half_msbc_data, BTM_MSBC_FRAME_SIZE / 2); + memcpy(p_data + BTM_MSBC_FRAME_SIZE / 2, p, pkt_size); + osi_free(p_buf); + if (BTA_HF_H2_HEADER_SYNC_WORD_CHECK(p_data)) { + /* H2 header sync word found, skip */ + p_data += 2; + } + else if (!bta_ag_co_cb.is_bad_frame){ + /* not a bad frame, assume as H1 header */ + p_data += 1; + } + btc_hf_audio_data_cb_to_app((uint8_t *)p_new_buf, (uint8_t *)p_data, BTM_MSBC_FRAME_SIZE, bta_ag_co_cb.is_bad_frame); + bta_ag_co_cb.is_bad_frame = false; + memset(bta_ag_co_cb.decode_msbc_data, 0, BTM_MSBC_FRAME_SIZE); + } + bta_ag_co_cb.rx_first_pkt = !bta_ag_co_cb.rx_first_pkt; + } + else if (hf_inout_pkt_size == BTM_MSBC_FRAME_SIZE) { + if (pkt_size > BTM_MSBC_FRAME_SIZE) { + pkt_size = BTM_MSBC_FRAME_SIZE; + } + if (BTA_HF_H2_HEADER_SYNC_WORD_CHECK(p)) { + /* H2 header sync word found, skip */ + p += 2; + } + else if (!bta_ag_co_cb.is_bad_frame){ + /* not a bad frame, assume as H1 header */ + p += 1; + } + btc_hf_audio_data_cb_to_app((uint8_t *)p_buf, (uint8_t *)p, pkt_size, bta_ag_co_cb.is_bad_frame); + bta_ag_co_cb.is_bad_frame = false; + } + else { + osi_free(p_buf); + } + } +#else if (hf_air_mode == BTM_SCO_AIR_MODE_CVSD) { // CVSD if(status != BTM_SCO_DATA_CORRECT) { @@ -583,8 +679,12 @@ void bta_ag_sco_co_in_data(BT_HDR *p_buf, tBTM_SCO_DATA_FLAG status) //Never run to here. } } else { - APPL_TRACE_ERROR("%s invaild air mode: %d", __FUNCTION__, hf_air_mode); + APPL_TRACE_ERROR("%s invalid air mode: %d", __FUNCTION__, hf_air_mode); } + osi_free(p_buf); +#endif } +#endif + #endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */ #endif /* #if (BTA_AG_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c b/lib/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c index 99f7a19f..b7df3635 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c +++ b/lib/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -236,12 +236,15 @@ static void bte_hf_evt(tBTA_AG_EVT event, tBTA_AG *param) else if (BTA_AG_OPEN_EVT == event) { param_len = sizeof(tBTA_AG_OPEN); } - else if ((BTA_AG_CLOSE_EVT == event) || (BTA_AG_AUDIO_OPEN_EVT == event) || (BTA_AG_AUDIO_CLOSE_EVT == event)) { + else if ((BTA_AG_CLOSE_EVT == event)) { param_len = sizeof(tBTA_AG_HDR); } else if (BTA_AG_CONN_EVT == event) { param_len = sizeof(tBTA_AG_CONN); } + else if ((BTA_AG_AUDIO_OPEN_EVT == event) || (BTA_AG_AUDIO_CLOSE_EVT == event) || (BTA_AG_AUDIO_MSBC_OPEN_EVT == event)) { + param_len = sizeof(tBTA_AG_AUDIO_STAT); + } else if (param) { param_len = sizeof(tBTA_AG_VAL); } @@ -265,6 +268,26 @@ void btc_hf_reg_data_cb(esp_hf_incoming_data_cb_t recv, esp_hf_outgoing_data_cb_ hf_local_param[0].btc_hf_outgoing_data_cb = send; } +void btc_hf_reg_audio_data_cb(esp_hf_ag_audio_data_cb_t callback) +{ + hf_local_param[0].btc_hf_audio_data_cb = callback; +} + +void btc_hf_audio_data_cb_to_app(uint8_t *buf, uint8_t *data, uint16_t len, bool is_bad_frame) +{ + if (hf_local_param[0].btc_hf_audio_data_cb) { + /* we always have sizeof(BT_HDR) bytes free space before data, it is enough for esp_hf_audio_buff_t */ + esp_hf_audio_buff_t *audio_buff = (esp_hf_audio_buff_t *)buf; + audio_buff->buff_size = len; + audio_buff->data_len = len; + audio_buff->data = data; + hf_local_param[0].btc_hf_audio_data_cb(hf_local_param[0].btc_hf_cb.sync_conn_hdl, audio_buff, is_bad_frame); + } + else { + osi_free(buf); + } +} + void btc_hf_incoming_data_cb_to_app(const uint8_t *data, uint32_t len) { int idx = 0; @@ -316,6 +339,19 @@ bt_status_t btc_hf_init(void) { int idx = 0; +#if HFP_DYNAMIC_MEMORY == TRUE + if (hf_local_param) +#endif + { + if (hf_local_param[idx].btc_hf_cb.initialized) { + esp_hf_cb_param_t param = { + .prof_stat.state = ESP_HF_INIT_ALREADY, + }; + btc_hf_cb_to_app(ESP_HF_PROF_STATE_EVT, ¶m); + return BT_STATUS_SUCCESS; + } + } + BTC_TRACE_DEBUG("%s - max_hf_clients=%d", __func__, btc_max_hf_clients); #if HFP_DYNAMIC_MEMORY == TRUE @@ -338,8 +374,9 @@ bt_status_t btc_hf_init(void) #endif clear_phone_state(); memset(&hf_local_param[idx].btc_hf_cb, 0, sizeof(btc_hf_cb_t)); - // custom initialization here - hf_local_param[idx].btc_hf_cb.initialized = true; + for (int i = 0; i < BTC_HF_NUM_CB; i++) { + hf_local_param[i].btc_hf_cb.sync_conn_hdl = ESP_INVALID_CONN_HANDLE; + } // set audio path #if (BT_CONTROLLER_INCLUDED == TRUE) #if BTM_SCO_HCI_INCLUDED @@ -349,14 +386,30 @@ bt_status_t btc_hf_init(void) #endif esp_bredr_sco_datapath_set(data_path); #endif + return BT_STATUS_SUCCESS; } void btc_hf_deinit(void) { BTC_TRACE_EVENT("%s", __FUNCTION__); + + int idx = 0; + +#if HFP_DYNAMIC_MEMORY == TRUE + if (hf_local_param) +#endif + { + if (!hf_local_param[idx].btc_hf_cb.initialized) { + esp_hf_cb_param_t param = { + .prof_stat.state = ESP_HF_DEINIT_ALREADY, + }; + btc_hf_cb_to_app(ESP_HF_PROF_STATE_EVT, ¶m); + return; + } + } + btc_dm_disable_service(BTA_HFP_SERVICE_ID); - hf_local_param[0].btc_hf_cb.initialized = false; } static void btc_hf_cb_release(void) @@ -922,6 +975,20 @@ bt_status_t btc_hf_ci_sco_data(void) return status; } +bool btc_hf_ag_audio_data_send(uint16_t sync_conn_hdl, uint8_t *p_buff_start, uint8_t *p_data, uint8_t data_len) +{ +#if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTA_HFP_EXT_CODEC == TRUE) + /* currently, sync_conn_hdl is not used */ + int idx = btc_hf_latest_connected_idx(); + CHECK_HF_SLC_CONNECTED(idx); + if (idx != BTC_HF_INVALID_IDX) { + BTA_AgAudioDataSend(hf_local_param[idx].btc_hf_cb.handle, p_buff_start, p_data, data_len); + return true; + } +#endif + return false; +} + /************************************************************************************ ** Memory malloc and release ************************************************************************************/ @@ -1239,6 +1306,13 @@ void btc_hf_call_handler(btc_msg_t *msg) btc_hf_reg_data_cb(arg->reg_data_cb.recv, arg->reg_data_cb.send); break; } + + case BTC_HF_REGISTER_AUDIO_DATA_CALLBACK_EVT: + { + btc_hf_reg_audio_data_cb(arg->reg_audio_data_cb.callback); + break; + } + case BTC_HF_REQUEST_PKT_STAT_EVT: { btc_hf_pkt_stat_nums_get(arg->pkt_sync_hd.sync_conn_handle); @@ -1268,7 +1342,18 @@ void btc_hf_cb_handler(btc_msg_t *msg) break; case BTA_AG_DISABLE_EVT: { - btc_hf_cb_release(); + idx = 0; +#if HFP_DYNAMIC_MEMORY == TRUE + if (hf_local_param) +#endif + { + if (hf_local_param[idx].btc_hf_cb.initialized) { + hf_local_param[idx].btc_hf_cb.initialized = false; + btc_hf_cb_release(); + param.prof_stat.state = ESP_HF_DEINIT_SUCCESS; + btc_hf_cb_to_app(ESP_HF_PROF_STATE_EVT, ¶m); + } + } break; } case BTA_AG_REGISTER_EVT: @@ -1278,6 +1363,11 @@ void btc_hf_cb_handler(btc_msg_t *msg) hf_local_param[idx].btc_hf_cb.handle = p_data->reg.hdr.handle; BTC_TRACE_DEBUG("%s: BTA_AG_REGISTER_EVT," "hf_local_param[%d].btc_hf_cb.handle = %d", __FUNCTION__, idx, hf_local_param[idx].btc_hf_cb.handle); + if (!hf_local_param[idx].btc_hf_cb.initialized) { + param.prof_stat.state = ESP_HF_INIT_SUCCESS; + btc_hf_cb_to_app(ESP_HF_PROF_STATE_EVT, ¶m); + } + hf_local_param[idx].btc_hf_cb.initialized = true; break; } @@ -1368,7 +1458,9 @@ void btc_hf_cb_handler(btc_msg_t *msg) do { param.audio_stat.state = ESP_HF_AUDIO_STATE_CONNECTED; memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t)); + hf_local_param[idx].btc_hf_cb.sync_conn_hdl = p_data->hdr.sync_conn_handle; param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle; + param.audio_stat.preferred_frame_size = p_data->audio_stat.preferred_frame_size; btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, ¶m); } while(0); break; @@ -1381,7 +1473,9 @@ void btc_hf_cb_handler(btc_msg_t *msg) do { param.audio_stat.state = ESP_HF_AUDIO_STATE_CONNECTED_MSBC; memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t)); + hf_local_param[idx].btc_hf_cb.sync_conn_hdl = p_data->hdr.sync_conn_handle; param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle; + param.audio_stat.preferred_frame_size = p_data->audio_stat.preferred_frame_size; btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, ¶m); } while (0); break; @@ -1392,6 +1486,7 @@ void btc_hf_cb_handler(btc_msg_t *msg) CHECK_HF_IDX(idx); do { param.audio_stat.state = ESP_HF_AUDIO_STATE_DISCONNECTED; + hf_local_param[idx].btc_hf_cb.sync_conn_hdl = ESP_INVALID_CONN_HANDLE; memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda, sizeof(esp_bd_addr_t)); param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle; btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, ¶m); @@ -1623,4 +1718,26 @@ void btc_hf_cb_handler(btc_msg_t *msg) break; } } + +void btc_hf_get_profile_status(esp_hf_profile_status_t *param) +{ + param->hfp_ag_inited = false; // Not initialized by default + +#if HFP_DYNAMIC_MEMORY == TRUE + if (hf_local_param) +#endif + { + for (int idx = 0; idx < BTC_HF_NUM_CB; idx++) { + if (hf_local_param[idx].btc_hf_cb.initialized) { + param->hfp_ag_inited = true; + if (hf_local_param[idx].btc_hf_cb.connection_state == ESP_HF_CONNECTION_STATE_SLC_CONNECTED) { + param->slc_conn_num++; + if (hf_local_param[idx].btc_hf_cb.sync_conn_hdl != ESP_INVALID_CONN_HANDLE) { + param->sync_conn_num++; + } + } + } + } + } +} #endif // #if (BTC_HF_INCLUDED == TRUE) diff --git a/lib/bt/host/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c b/lib/bt/host/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c index 555e7137..c785c739 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c +++ b/lib/bt/host/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,9 +14,23 @@ #if (BTM_SCO_HCI_INCLUDED == TRUE) +#if (BTC_HFP_EXT_CODEC == FALSE) #include "oi_codec_sbc.h" #include "oi_status.h" #include "sbc_encoder.h" +#endif + +// H2: Header with synchronization word and sequence number +#define BTA_HF_H2_HEADER_SYNC_WORD 0x0801 +#define BTA_HF_H2_HEADER_SYNC_WORD_MASK 0x0FFF +#define BTA_HF_H2_HEADER_BIT0_MASK (1 << 0) +#define BTA_HF_H2_HEADER_BIT1_MASK (1 << 1) +#define BTA_HF_H2_HEADER_SN0_BIT_OFFSET1 12 +#define BTA_HF_H2_HEADER_SN0_BIT_OFFSET2 13 +#define BTA_HF_H2_HEADER_SN1_BIT_OFFSET1 14 +#define BTA_HF_H2_HEADER_SN1_BIT_OFFSET2 15 + +#define BTA_HF_H2_HEADER_SYNC_WORD_CHECK(p) ((*((uint16_t *)p) & BTA_HF_H2_HEADER_SYNC_WORD_MASK) == BTA_HF_H2_HEADER_SYNC_WORD) #if (PLC_INCLUDED == TRUE) #include "sbc_plc.h" @@ -44,18 +58,23 @@ static bta_hf_ct_plc_t *bta_hf_ct_plc_ptr; /* BTA-HF-CO control block to map bdaddr to BTA handle */ typedef struct { +#if (BTC_HFP_EXT_CODEC == FALSE) OI_CODEC_SBC_DECODER_CONTEXT decoder_context; OI_UINT32 decoder_context_data[HF_SBC_DEC_CONTEXT_DATA_LEN]; OI_INT16 decode_raw_data[HF_SBC_DEC_RAW_DATA_SIZE]; - SBC_ENC_PARAMS encoder; - UINT8 sequence_number; bool is_bad_frame; bool decode_first_pkt; - OI_BYTE decode_msbc_data[BTM_MSBC_FRAME_SIZE]; bool encode_first_pkt; + OI_BYTE decode_msbc_data[BTM_MSBC_FRAME_SIZE]; OI_BYTE encode_msbc_data[BTM_MSBC_FRAME_SIZE]; +#else + UINT8 sequence_number; + BOOLEAN rx_first_pkt; + BOOLEAN is_bad_frame; + UINT8 rx_half_msbc_data[BTM_MSBC_FRAME_SIZE/2]; +#endif } bta_hf_client_co_cb_t; #if HFP_DYNAMIC_MEMORY == FALSE @@ -118,6 +137,8 @@ tBTA_HFP_SCO_ROUTE_TYPE bta_hf_client_sco_co_init(UINT32 rx_bw, UINT32 tx_bw, return BTA_HFP_SCO_ROUTE_HCI; } +#if (BTC_HFP_EXT_CODEC == FALSE) + /******************************************************************************* ** ** Function bta_hf_dec_init @@ -168,6 +189,19 @@ static void bta_hf_enc_init(void) { SBC_Encoder_Init(&(bta_hf_client_co_cb.encoder)); } +#endif + +#if (BTC_HFP_EXT_CODEC == TRUE) + +void bta_hf_pkt_state_reset(void) +{ + bta_hf_client_co_cb.sequence_number = 0; + bta_hf_client_co_cb.rx_first_pkt = TRUE; + bta_hf_client_co_cb.is_bad_frame = FALSE; +} + +#endif + /******************************************************************************* ** ** Function bta_hf_client_sco_co_open @@ -204,8 +238,12 @@ void bta_hf_client_sco_co_open(UINT16 handle, UINT8 air_mode, UINT8 inout_pkt_si #endif /// (HFP_DYNAMIC_MEMORY == TRUE) +#if (BTC_HFP_EXT_CODEC == TRUE) + bta_hf_pkt_state_reset(); +#else bta_hf_dec_init(); bta_hf_enc_init(); +#endif return; } else { @@ -280,18 +318,9 @@ void bta_hf_client_sco_co_close(void) ** Returns void ** *******************************************************************************/ -static void bta_hf_client_h2_header(UINT16 *p_buf) +void bta_hf_client_h2_header(UINT16 *p_buf) { - // H2: Header with synchronization word and sequence number -#define BTA_HF_H2_HEADER 0x0801 -#define BTA_HF_H2_HEADER_BIT0_MASK (1 << 0) -#define BTA_HF_H2_HEADER_BIT1_MASK (1 << 1) -#define BTA_HF_H2_HEADER_SN0_BIT_OFFSET1 12 -#define BTA_HF_H2_HEADER_SN0_BIT_OFFSET2 13 -#define BTA_HF_H2_HEADER_SN1_BIT_OFFSET1 14 -#define BTA_HF_H2_HEADER_SN1_BIT_OFFSET2 15 - - UINT16 h2_header = BTA_HF_H2_HEADER; + UINT16 h2_header = BTA_HF_H2_HEADER_SYNC_WORD; UINT8 h2_header_sn0 = bta_hf_client_co_cb.sequence_number & BTA_HF_H2_HEADER_BIT0_MASK; UINT8 h2_header_sn1 = bta_hf_client_co_cb.sequence_number & BTA_HF_H2_HEADER_BIT1_MASK; h2_header |= (h2_header_sn0 << BTA_HF_H2_HEADER_SN0_BIT_OFFSET1 @@ -304,6 +333,8 @@ static void bta_hf_client_h2_header(UINT16 *p_buf) *p_buf = h2_header; } +#if (BTC_HFP_EXT_CODEC == FALSE) + /******************************************************************************* ** ** Function bta_hf_client_sco_co_out_data @@ -364,7 +395,7 @@ uint32_t bta_hf_client_sco_co_out_data(UINT8 *p_buf) } else { - APPL_TRACE_ERROR("%s invaild air mode: %d", __FUNCTION__, hf_air_mode); + APPL_TRACE_ERROR("%s invalid air mode: %d", __FUNCTION__, hf_air_mode); } return 0; } @@ -439,6 +470,8 @@ static void bta_hf_client_decode_msbc_frame(UINT8 **data, UINT8 *length, BOOLEAN } } +#endif + /******************************************************************************* ** ** Function bta_hf_client_sco_co_in_data @@ -450,12 +483,77 @@ static void bta_hf_client_decode_msbc_frame(UINT8 **data, UINT8 *length, BOOLEAN *******************************************************************************/ void bta_hf_client_sco_co_in_data(BT_HDR *p_buf, tBTM_SCO_DATA_FLAG status) { + if (hf_air_mode != BTM_SCO_AIR_MODE_CVSD && hf_air_mode != BTM_SCO_AIR_MODE_TRANSPNT) { + APPL_TRACE_ERROR("%s invalid air mode: %d", __FUNCTION__, hf_air_mode); + osi_free(p_buf); + return; + } + UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset; UINT8 pkt_size = 0; STREAM_SKIP_UINT16(p); STREAM_TO_UINT8 (pkt_size, p); +#if (BTC_HFP_EXT_CODEC == TRUE) + if (hf_air_mode == BTM_SCO_AIR_MODE_CVSD) { + btc_hf_client_audio_data_cb_to_app((uint8_t *)p_buf, (uint8_t *)p, pkt_size, status != BTM_SCO_DATA_CORRECT); + } + else if (hf_air_mode == BTM_SCO_AIR_MODE_TRANSPNT) { + if (pkt_size != hf_inout_pkt_size) { + bta_hf_client_co_cb.is_bad_frame = true; + } + if (status != BTM_SCO_DATA_CORRECT) { + bta_hf_client_co_cb.is_bad_frame = true; + } + if (hf_inout_pkt_size == BTM_MSBC_FRAME_SIZE / 2) { + if (pkt_size > BTM_MSBC_FRAME_SIZE / 2) { + pkt_size = BTM_MSBC_FRAME_SIZE / 2; + } + if (bta_hf_client_co_cb.rx_first_pkt){ + memcpy(bta_hf_client_co_cb.rx_half_msbc_data, p, pkt_size); + osi_free(p_buf); + } else { + BT_HDR *p_new_buf = osi_calloc(sizeof(BT_HDR) + BTM_MSBC_FRAME_SIZE); + p_new_buf->offset = 0; + UINT8 *p_data = (UINT8 *)(p_new_buf + 1) + p_new_buf->offset; + memcpy(p_data, bta_hf_client_co_cb.rx_half_msbc_data, BTM_MSBC_FRAME_SIZE / 2); + memcpy(p_data + BTM_MSBC_FRAME_SIZE / 2, p, pkt_size); + osi_free(p_buf); + if (BTA_HF_H2_HEADER_SYNC_WORD_CHECK(p_data)) { + /* H2 header sync word found, skip */ + p_data += 2; + } + else if (!bta_hf_client_co_cb.is_bad_frame){ + /* not a bad frame, assume as H1 header */ + p_data += 1; + } + btc_hf_client_audio_data_cb_to_app((uint8_t *)p_new_buf, (uint8_t *)p_data, BTM_MSBC_FRAME_SIZE, bta_hf_client_co_cb.is_bad_frame); + bta_hf_client_co_cb.is_bad_frame = false; + memset(bta_hf_client_co_cb.rx_half_msbc_data, 0, BTM_MSBC_FRAME_SIZE); + } + bta_hf_client_co_cb.rx_first_pkt = !bta_hf_client_co_cb.rx_first_pkt; + } + else if (hf_inout_pkt_size == BTM_MSBC_FRAME_SIZE) { + if (pkt_size > BTM_MSBC_FRAME_SIZE) { + pkt_size = BTM_MSBC_FRAME_SIZE; + } + if (BTA_HF_H2_HEADER_SYNC_WORD_CHECK(p)) { + /* H2 header sync word found, skip */ + p += 2; + } + else if (!bta_hf_client_co_cb.is_bad_frame){ + /* not a bad frame, assume as H1 header */ + p += 1; + } + btc_hf_client_audio_data_cb_to_app((uint8_t *)p_buf, (uint8_t *)p, pkt_size, bta_hf_client_co_cb.is_bad_frame); + bta_hf_client_co_cb.is_bad_frame = false; + } + else { + osi_free(p_buf); + } + } +#else if (hf_air_mode == BTM_SCO_AIR_MODE_CVSD) { // CVSD if(status != BTM_SCO_DATA_CORRECT){ @@ -496,8 +594,10 @@ void bta_hf_client_sco_co_in_data(BT_HDR *p_buf, tBTM_SCO_DATA_FLAG status) //Never run to here. } } else { - APPL_TRACE_ERROR("%s invaild air mode: %d", __FUNCTION__, hf_air_mode); + APPL_TRACE_ERROR("%s invalid air mode: %d", __FUNCTION__, hf_air_mode); } + osi_free(p_buf); +#endif } #endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c b/lib/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c index 67973bc2..cac3afb5 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c +++ b/lib/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -114,6 +114,7 @@ static inline void btc_hf_client_cb_to_app(esp_hf_client_cb_event_t event, esp_h static void clear_state(void) { memset(&hf_client_local_param.btc_hf_client_cb, 0, sizeof(btc_hf_client_cb_t)); + hf_client_local_param.btc_hf_client_cb.sync_conn_hdl = ESP_INVALID_CONN_HANDLE; } static BOOLEAN is_connected(bt_bdaddr_t *bd_addr) @@ -132,6 +133,26 @@ void btc_hf_client_reg_data_cb(esp_hf_client_incoming_data_cb_t recv, hf_client_local_param.btc_hf_client_outgoing_data_cb = send; } +static void btc_hf_client_reg_audio_data_cb(esp_hf_client_audio_data_cb_t callback) +{ + hf_client_local_param.btc_hf_client_audio_data_cb = callback; +} + +void btc_hf_client_audio_data_cb_to_app(uint8_t *buf, uint8_t *data, uint16_t len, bool is_bad_frame) +{ + if (hf_client_local_param.btc_hf_client_audio_data_cb) { + /* we always have sizeof(BT_HDR) bytes free space before data, it is enough for esp_hf_audio_buff_t */ + esp_hf_audio_buff_t *audio_buff = (esp_hf_audio_buff_t *)buf; + audio_buff->buff_size = len; + audio_buff->data_len = len; + audio_buff->data = data; + hf_client_local_param.btc_hf_client_audio_data_cb(hf_client_local_param.btc_hf_client_cb.sync_conn_hdl, audio_buff, is_bad_frame); + } + else { + osi_free(buf); + } +} + void btc_hf_client_incoming_data_cb_to_app(const uint8_t *data, uint32_t len) { // todo: critical section protection @@ -169,12 +190,18 @@ bt_status_t btc_hf_client_init(void) { BTC_TRACE_EVENT("%s", __FUNCTION__); + if (hf_client_local_param.btc_hf_client_cb.initialized) { + esp_hf_client_cb_param_t param = { + .prof_stat.state = ESP_HF_INIT_ALREADY, + }; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_PROF_STATE_EVT, ¶m); + return BT_STATUS_SUCCESS; + } + btc_dm_enable_service(BTA_HFP_HS_SERVICE_ID); clear_state(); - hf_client_local_param.btc_hf_client_cb.initialized = true; - #if (BT_CONTROLLER_INCLUDED == TRUE) #if BTM_SCO_HCI_INCLUDED uint8_t data_path = ESP_SCO_DATA_PATH_HCI; @@ -232,9 +259,15 @@ void btc_hf_client_deinit( void ) { BTC_TRACE_EVENT("%s", __FUNCTION__); - btc_dm_disable_service(BTA_HFP_HS_SERVICE_ID); + if (!hf_client_local_param.btc_hf_client_cb.initialized) { + esp_hf_client_cb_param_t param = { + .prof_stat.state = ESP_HF_DEINIT_ALREADY, + }; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_PROF_STATE_EVT, ¶m); + return; + } - hf_client_local_param.btc_hf_client_cb.initialized = false; + btc_dm_disable_service(BTA_HFP_HS_SERVICE_ID); } /******************************************************************************* @@ -852,10 +885,21 @@ void btc_hf_client_cb_handler(btc_msg_t *msg) switch (event) { case BTA_HF_CLIENT_ENABLE_EVT: + break; case BTA_HF_CLIENT_DISABLE_EVT: + if (hf_client_local_param.btc_hf_client_cb.initialized) { + param.prof_stat.state = ESP_HF_DEINIT_SUCCESS, + btc_hf_client_cb_to_app(ESP_HF_CLIENT_PROF_STATE_EVT, ¶m); + } + hf_client_local_param.btc_hf_client_cb.initialized = false; break; case BTA_HF_CLIENT_REGISTER_EVT: hf_client_local_param.btc_hf_client_cb.handle = p_data->reg.handle; + if (!hf_client_local_param.btc_hf_client_cb.initialized) { + param.prof_stat.state = ESP_HF_INIT_SUCCESS, + btc_hf_client_cb_to_app(ESP_HF_CLIENT_PROF_STATE_EVT, ¶m); + } + hf_client_local_param.btc_hf_client_cb.initialized = true; break; case BTA_HF_CLIENT_OPEN_EVT: if (p_data->open.status == BTA_HF_CLIENT_SUCCESS) @@ -1053,7 +1097,9 @@ void btc_hf_client_cb_handler(btc_msg_t *msg) param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_CONNECTED; memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda, sizeof(esp_bd_addr_t)); + hf_client_local_param.btc_hf_client_cb.sync_conn_hdl = p_data->hdr.sync_conn_handle; param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle; + param.audio_stat.preferred_frame_size = p_data->audio_stat.preferred_frame_size; btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, ¶m); } while (0); break; @@ -1062,7 +1108,9 @@ void btc_hf_client_cb_handler(btc_msg_t *msg) param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_CONNECTED_MSBC; memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda, sizeof(esp_bd_addr_t)); + hf_client_local_param.btc_hf_client_cb.sync_conn_hdl = p_data->hdr.sync_conn_handle; param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle; + param.audio_stat.preferred_frame_size = p_data->audio_stat.preferred_frame_size; btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, ¶m); } while (0); break; @@ -1071,7 +1119,9 @@ void btc_hf_client_cb_handler(btc_msg_t *msg) param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_DISCONNECTED; memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda, sizeof(esp_bd_addr_t)); + hf_client_local_param.btc_hf_client_cb.sync_conn_hdl = ESP_INVALID_CONN_HANDLE; param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle; + param.audio_stat.preferred_frame_size = 0; btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, ¶m); } while (0); break; @@ -1160,6 +1210,9 @@ void btc_hf_client_call_handler(btc_msg_t *msg) case BTC_HF_CLIENT_REGISTER_DATA_CALLBACK_EVT: btc_hf_client_reg_data_cb(arg->reg_data_cb.recv, arg->reg_data_cb.send); break; + case BTC_HF_CLIENT_REGISTER_AUDIO_DATA_CALLBACK_EVT: + btc_hf_client_reg_audio_data_cb(arg->reg_audio_data_cb.callback); + break; case BTC_HF_CLIENT_SEND_NREC_EVT: btc_hf_client_send_nrec(); break; @@ -1177,4 +1230,24 @@ void btc_hf_client_call_handler(btc_msg_t *msg) } } +void btc_hf_client_get_profile_status(esp_hf_client_profile_status_t *param) +{ + param->hf_client_inited = false; // Not initialized by default + +#if HFP_DYNAMIC_MEMORY == TRUE + if (hf_client_local_param_ptr) +#endif + { + if (hf_client_local_param.btc_hf_client_cb.initialized) { + param->hf_client_inited = true; + if (hf_client_local_param.btc_hf_client_cb.state == ESP_HF_CLIENT_CONNECTION_STATE_SLC_CONNECTED) { + param->slc_conn_num++; + if (hf_client_local_param.btc_hf_client_cb.sync_conn_hdl != ESP_INVALID_CONN_HANDLE) { + param->sync_conn_num++; + } + } + } + } +} + #endif /* #if (BTC_HF_CLIENT_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c b/lib/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c index 0d99c030..82ff2b8d 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c +++ b/lib/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c @@ -844,6 +844,7 @@ void btc_hd_cb_handler(btc_msg_t *msg) // } // btc_storage_set_hidd((bt_bdaddr_t *)&p_data->conn.bda); btc_hd_cb.status = BTC_HD_CONNECTED; + btc_hd_cb.in_use = TRUE; } else if (p_data->conn.conn_status == BTA_HD_CONN_STATE_DISCONNECTED) { btc_hd_cb.status = BTC_HD_DISCONNECTED; } @@ -903,14 +904,10 @@ void btc_hd_cb_handler(btc_msg_t *msg) btc_hd_cb_to_app(ESP_HIDD_INTR_DATA_EVT, ¶m); break; case BTA_HD_VC_UNPLUG_EVT: { - bt_bdaddr_t *bd_addr = (bt_bdaddr_t *)&p_data->conn.bda; - if (bta_dm_check_if_only_hd_connected(p_data->conn.bda)) { - BTC_TRACE_DEBUG("%s: Removing bonding as only HID profile connected", __func__); - BTA_DmRemoveDevice((uint8_t *)&p_data->conn.bda, BT_TRANSPORT_BR_EDR); - } else { - BTC_TRACE_DEBUG("%s: Only removing HID data as some other profiles connected", __func__); - btc_hd_remove_device(*bd_addr); - } +#if BTC_HID_REMOVE_DEVICE_BONDING + BTC_TRACE_DEBUG("%s: Removing bonding information", __func__); + BTA_DmRemoveDevice((uint8_t *)&p_data->conn.bda, BT_TRANSPORT_BR_EDR); +#endif if (btc_hd_cb.status == BTC_HD_DISCONNECTING || btc_hd_cb.status == BTC_HD_CONNECTING || btc_hd_cb.status == BTC_HD_CONNECTED) { @@ -920,6 +917,8 @@ void btc_hd_cb_handler(btc_msg_t *msg) btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, ¶m); } + btc_hd_cb.in_use = FALSE; + param.vc_unplug.status = p_data->conn.status; param.vc_unplug.conn_status = p_data->conn.conn_status; btc_hd_cb_to_app(ESP_HIDD_VC_UNPLUG_EVT, ¶m); @@ -963,4 +962,22 @@ void btc_hd_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) } } +void btc_hd_get_profile_status(esp_hidd_profile_status_t *param) +{ + if (is_hidd_init()) { + param->hidd_inited = true; + if (btc_hd_cb.status == BTC_HD_CONNECTED) { + param->conn_num++; + } + if (btc_hd_cb.in_use) { + param->plug_vc_dev_num++; + } + if (btc_hd_cb.app_registered) { + param->reg_app_num++; + } + } else { + param->hidd_inited = false; + } +} + #endif // HID_DEV_INCLUDED==TRUE diff --git a/lib/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c b/lib/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c index 1d6f2020..55fe3f69 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c +++ b/lib/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c @@ -1372,7 +1372,10 @@ void btc_hh_cb_handler(btc_msg_t *msg) */ if (p_dev->local_vup) { p_dev->local_vup = false; +#if BTC_HID_REMOVE_DEVICE_BONDING BTA_DmRemoveDevice(p_dev->bd_addr, BT_TRANSPORT_BR_EDR); +#endif + btc_hh_remove_device(p_dev->bd_addr); } btc_hh_cb.status = (BTC_HH_STATUS)BTC_HH_DEV_DISCONNECTED; @@ -1406,8 +1409,9 @@ void btc_hh_cb_handler(btc_msg_t *msg) // [boblane] if (p_dev->local_vup) { p_dev->local_vup = false; +#if BTC_HID_REMOVE_DEVICE_BONDING BTA_DmRemoveDevice(p_dev->bd_addr, BT_TRANSPORT_BR_EDR); - } else { +#endif btc_hh_remove_device(p_dev->bd_addr); } param.unplug.status = p_data->dev_status.status; @@ -1571,4 +1575,21 @@ void btc_hh_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) } } +void btc_hh_get_profile_status(esp_hidh_profile_status_t *param) +{ + if (is_hidh_init()) { + param->hidh_inited = true; + if (btc_hh_cb.status == BTC_HH_DEV_CONNECTED) { + param->conn_num++; + } + for (int i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) { + if (memcmp(btc_hh_cb.added_devices[i].bd_addr, bd_addr_null, BD_ADDR_LEN) != 0) { + param->plug_vc_dev_num++; + } + } + } else { + param->hidh_inited = false; + } +} + #endif // HID_HOST_INCLUDED == TRUE diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/bt_sdp.h b/lib/bt/host/bluedroid/btc/profile/std/include/bt_sdp.h index 63ca09a8..69fac9d6 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/bt_sdp.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/bt_sdp.h @@ -34,55 +34,48 @@ typedef enum { SDP_TYPE_PBAP_PSE, // Phone Book Profile - Server SDP_TYPE_PBAP_PCE, // Phone Book Profile - Client SDP_TYPE_OPP_SERVER, // Object Push Profile - SDP_TYPE_SAP_SERVER // SIM Access Profile + SDP_TYPE_SAP_SERVER, // SIM Access Profile + SDP_TYPE_DIP_SERVER, // Device Identification Profile } bluetooth_sdp_types; -typedef struct _bluetooth_sdp_hdr { - bluetooth_sdp_types type; - esp_bt_uuid_t uuid; - uint32_t service_name_length; - char *service_name; - int32_t rfcomm_channel_number; - int32_t l2cap_psm; - int32_t profile_version; -} bluetooth_sdp_hdr; - /** * Some signals need additional pointers, hence we introduce a * generic way to handle these pointers. */ typedef struct _bluetooth_sdp_hdr_overlay { bluetooth_sdp_types type; - esp_bt_uuid_t bt_uuid; - uint32_t service_name_length; - char *service_name; - int32_t rfcomm_channel_number; - int32_t l2cap_psm; - int32_t profile_version; - - // User pointers, only used for some signals - see bluetooth_sdp_ops_record - int user1_ptr_len; - uint8_t *user1_ptr; - int user2_ptr_len; - uint8_t *user2_ptr; + esp_bt_uuid_t uuid; + uint32_t service_name_length; + char *service_name; + int32_t rfcomm_channel_number; + int32_t l2cap_psm; + int32_t profile_version; + int user1_ptr_len; + uint8_t *user1_ptr; + int user2_ptr_len; // not used + uint8_t *user2_ptr; // not used } bluetooth_sdp_hdr_overlay; +typedef struct _bluetooth_sdp_raw_record { + bluetooth_sdp_hdr_overlay hdr; +} bluetooth_sdp_raw_record; + typedef struct _bluetooth_sdp_mas_record { bluetooth_sdp_hdr_overlay hdr; - uint32_t mas_instance_id; - uint32_t supported_features; - uint32_t supported_message_types; + uint32_t mas_instance_id; + uint32_t supported_features; + uint32_t supported_message_types; } bluetooth_sdp_mas_record; typedef struct _bluetooth_sdp_mns_record { bluetooth_sdp_hdr_overlay hdr; - uint32_t supported_features; + uint32_t supported_features; } bluetooth_sdp_mns_record; typedef struct _bluetooth_sdp_pse_record { bluetooth_sdp_hdr_overlay hdr; - uint32_t supported_features; - uint32_t supported_repositories; + uint32_t supported_features; + uint32_t supported_repositories; } bluetooth_sdp_pse_record; typedef struct _bluetooth_sdp_pce_record { @@ -91,22 +84,33 @@ typedef struct _bluetooth_sdp_pce_record { typedef struct _bluetooth_sdp_ops_record { bluetooth_sdp_hdr_overlay hdr; - int supported_formats_list_len; - uint8_t supported_formats_list[SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH]; + int supported_formats_list_len; + uint8_t supported_formats_list[SDP_OPP_SUPPORTED_FORMATS_MAX_LENGTH]; } bluetooth_sdp_ops_record; typedef struct _bluetooth_sdp_sap_record { bluetooth_sdp_hdr_overlay hdr; } bluetooth_sdp_sap_record; +typedef struct _bluetooth_sdp_dip_record { + bluetooth_sdp_hdr_overlay hdr; + uint16_t vendor; + uint16_t vendor_id_source; + uint16_t product; + uint16_t version; + bool primary_record; +} bluetooth_sdp_dip_record; + typedef union { - bluetooth_sdp_hdr_overlay hdr; - bluetooth_sdp_mas_record mas; - bluetooth_sdp_mns_record mns; - bluetooth_sdp_pse_record pse; - bluetooth_sdp_pce_record pce; - bluetooth_sdp_ops_record ops; - bluetooth_sdp_sap_record sap; + bluetooth_sdp_hdr_overlay hdr; + bluetooth_sdp_raw_record raw; + bluetooth_sdp_mas_record mas; + bluetooth_sdp_mns_record mns; + bluetooth_sdp_pse_record pse; + bluetooth_sdp_pce_record pce; + bluetooth_sdp_ops_record ops; + bluetooth_sdp_sap_record sap; + bluetooth_sdp_dip_record dip; } bluetooth_sdp_record; #endif /* __BT_SDP_H__ */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_a2dp_source.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_a2dp_source.h index f7ce1cbc..3f0e79f8 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/btc_a2dp_source.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_a2dp_source.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,6 +23,7 @@ /******************************************************************************* ** Data types *******************************************************************************/ +#if (BTC_AV_EXT_CODEC == FALSE) /* tBTC_MEDIA_INIT_AUDIO msg structure */ typedef struct { @@ -50,6 +51,8 @@ typedef struct { tBTC_AV_MEDIA_FEEDINGS feeding; } tBTC_MEDIA_INIT_AUDIO_FEEDING; +#endif + /******************************************************************************* ** Public functions *******************************************************************************/ @@ -76,29 +79,6 @@ bool btc_a2dp_source_startup(void); *******************************************************************************/ void btc_a2dp_source_shutdown(void); -/******************************************************************************* - ** - ** Function btc_a2dp_source_enc_init_req - ** - ** Description Request to initialize the media task encoder - ** - ** Returns TRUE is success - ** - *******************************************************************************/ -BOOLEAN btc_a2dp_source_enc_init_req(tBTC_MEDIA_INIT_AUDIO *p_msg); - -/******************************************************************************* - ** - ** Function btc_a2dp_source_enc_udpate_req - ** - ** Description Request to update the media task encoder - ** - ** Returns TRUE is success - ** - *******************************************************************************/ -BOOLEAN btc_a2dp_source_enc_update_req(tBTC_MEDIA_UPDATE_AUDIO *p_msg); - - /******************************************************************************* ** ** Function btc_a2dp_source_start_audio_req @@ -110,28 +90,6 @@ BOOLEAN btc_a2dp_source_enc_update_req(tBTC_MEDIA_UPDATE_AUDIO *p_msg); *******************************************************************************/ BOOLEAN btc_a2dp_source_start_audio_req(void); -/******************************************************************************* - ** - ** Function btc_a2dp_source_stop_audio_req - ** - ** Description Request to stop audio encoding task - ** - ** Returns TRUE is success - ** - *******************************************************************************/ -BOOLEAN btc_a2dp_source_stop_audio_req(void); - -/******************************************************************************* - ** - ** Function btc_a2dp_source_tx_flush_req - ** - ** Description Request to flush audio encoding pipe - ** - ** Returns TRUE is success - ** - *******************************************************************************/ -BOOLEAN btc_a2dp_source_tx_flush_req(void); - /******************************************************************************* ** ** Function btc_a2dp_source_audio_readbuf @@ -143,27 +101,6 @@ BOOLEAN btc_a2dp_source_tx_flush_req(void); *******************************************************************************/ BT_HDR *btc_a2dp_source_audio_readbuf(void); -/******************************************************************************* - ** - ** Function btc_a2dp_source_audio_feeding_init_req - ** - ** Description Request to initialize audio feeding - ** - ** Returns TRUE if success - ** - *******************************************************************************/ - -BOOLEAN btc_a2dp_source_audio_feeding_init_req(tBTC_MEDIA_INIT_AUDIO_FEEDING *p_msg); - -/******************************************************************************* - ** - ** Function btc_a2dp_source_is_streaming - ** - ** Description Check whether A2DP source is in streaming state - ** - *******************************************************************************/ -bool btc_a2dp_source_is_streaming(void); - /******************************************************************************* ** ** Function btc_a2dp_source_is_task_shutting_down @@ -206,21 +143,23 @@ void btc_a2dp_source_on_suspended(tBTA_AV_SUSPEND *p_av); /******************************************************************************* ** - ** Function btc_a2dp_source_setup_codec + ** Function btc_a2dp_source_set_tx_flush ** - ** Description initialize the encoder parameters + ** Description enable/disable discarding of transmitted frames ** *******************************************************************************/ -void btc_a2dp_source_setup_codec(void); +void btc_a2dp_source_set_tx_flush(BOOLEAN enable); + +#if (BTC_AV_EXT_CODEC == FALSE) /******************************************************************************* ** - ** Function btc_a2dp_source_set_tx_flush + ** Function btc_a2dp_source_setup_codec ** - ** Description enable/disable discarding of transmitted frames + ** Description initialize the encoder parameters ** *******************************************************************************/ -void btc_a2dp_source_set_tx_flush(BOOLEAN enable); +void btc_a2dp_source_setup_codec(void); /******************************************************************************* ** @@ -231,6 +170,8 @@ void btc_a2dp_source_set_tx_flush(BOOLEAN enable); *******************************************************************************/ void btc_a2dp_source_encoder_update(void); +#endif + /***************************************************************************** ** ** Function btc_source_report_delay_value @@ -240,6 +181,19 @@ void btc_a2dp_source_encoder_update(void); *******************************************************************************/ void btc_source_report_delay_value(UINT16 delay_value); +#if (BTC_AV_EXT_CODEC == TRUE) + +/***************************************************************************** +** +** Function btc_a2dp_source_enqueue_audio_frame +** +** Description Enqueue source audio frame to tx queue +** +*******************************************************************************/ +BOOLEAN btc_a2dp_source_enqueue_audio_frame(BT_HDR *p_buf); + +#endif + #endif /* #if BTC_AV_SRC_INCLUDED */ #endif /* __BTC_A2DP_SOURCE_H__ */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_av.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_av.h index 3dd2ebe6..f23ff670 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/btc_av.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_av.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,11 +22,21 @@ #include "btc/btc_task.h" #include "btc/btc_common.h" #include "btc/btc_sm.h" +#include "btc_av_api.h" #include "bta/bta_av_api.h" +#include "bta/bta_av_sbc.h" #if (BTC_AV_INCLUDED == TRUE) -// global variable to inidcate avrc is initialized with a2dp +#if (BTA_AV_CO_CP_SCMS_T == TRUE) +#define BTC_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE + 1) +#else +#define BTC_MEDIA_AA_SBC_OFFSET (AVDT_MEDIA_OFFSET + BTA_AV_SBC_HDR_SIZE) +#endif + +#define BTC_AUDIO_BUFF_OFFSET BTC_MEDIA_AA_SBC_OFFSET + +// global variable to indicate avrc is initialized with a2dp extern bool g_av_with_rc; // global variable to indicate a2dp is initialized extern bool g_a2dp_on_init; @@ -51,21 +61,24 @@ typedef enum { BTC_AV_DISCONNECT_REQ_EVT, BTC_AV_START_STREAM_REQ_EVT, BTC_AV_SUSPEND_STREAM_REQ_EVT, - BTC_AV_SINK_CONFIG_REQ_EVT, + BTC_AV_CONFIG_EVT, } btc_av_sm_event_t; typedef enum { #if BTC_AV_SINK_INCLUDED BTC_AV_SINK_API_INIT_EVT = 0, + BTC_AV_SINK_API_REG_SEP_EVT, BTC_AV_SINK_API_DEINIT_EVT, BTC_AV_SINK_API_CONNECT_EVT, BTC_AV_SINK_API_DISCONNECT_EVT, BTC_AV_SINK_API_REG_DATA_CB_EVT, + BTC_AV_SINK_API_REG_AUDIO_DATA_CB_EVT, BTC_AV_SINK_API_SET_DELAY_VALUE_EVT, BTC_AV_SINK_API_GET_DELAY_VALUE_EVT, #endif /* BTC_AV_SINK_INCLUDED */ #if BTC_AV_SRC_INCLUDED BTC_AV_SRC_API_INIT_EVT, + BTC_AV_SRC_API_REG_SEP_EVT, BTC_AV_SRC_API_DEINIT_EVT, BTC_AV_SRC_API_CONNECT_EVT, BTC_AV_SRC_API_DISCONNECT_EVT, @@ -77,14 +90,14 @@ typedef enum { /* btc_av_args_t */ typedef union { #if BTC_AV_SINK_INCLUDED - // BTC_AV_SINK_CONFIG_REQ_EVT -- internal event - esp_a2d_mcc_t mcc; // BTC_AV_SINK_API_CONNECT_EVT bt_bdaddr_t connect; // BTC_AV_SINK_API_DISCONNECT_EVT bt_bdaddr_t disconn; // BTC_AV_SINK_API_REG_DATA_CB_EVT esp_a2d_sink_data_cb_t data_cb; + // BTC_AV_SINK_API_REG_AUDIO_DATA_CB_EVT + esp_a2d_sink_audio_data_cb_t audio_data_cb; // BTC_AV_SINK_API_SET_DELAY_VALUE_EVT uint16_t delay_value; #endif /* BTC_AV_SINK_INCLUDED */ @@ -96,6 +109,13 @@ typedef union { // BTC_AV_SRC_API_DISCONNECT_EVT bt_bdaddr_t src_disconn; #endif /* BTC_AV_SRC_INCLUDED */ + // BTC_AV_CONFIG_EVT + esp_a2d_mcc_t mcc; + // BTC_AV_SINK_API_REG_SEP_EVT or BTC_AV_SRC_API_REG_SEP_EVT + struct { + uint8_t seid; + esp_a2d_mcc_t mcc; + } reg_sep; // BTC_AV_API_MEDIA_CTRL_EVT esp_a2d_media_ctrl_t ctrl; } btc_av_args_t; @@ -108,8 +128,36 @@ void btc_a2dp_call_handler(btc_msg_t *msg); void btc_a2dp_cb_handler(btc_msg_t *msg); +void btc_a2dp_get_profile_status(esp_a2d_profile_status_t *param); + void btc_a2dp_sink_reg_data_cb(esp_a2d_sink_data_cb_t callback); +/******************************************************************************* +** +** Function btc_a2dp_sink_reg_audio_data_cb +** +** Description Register a2dp sink audio data callback +** +** Returns None +** +*******************************************************************************/ +void btc_a2dp_sink_reg_audio_data_cb(esp_a2d_sink_audio_data_cb_t callback); + +#if (BTC_AV_EXT_CODEC == TRUE) + +/******************************************************************************* +** +** Function btc_av_codec_cap_get +** +** Description Get external codec capability +** +** Returns Pointer to codec capability +** +*******************************************************************************/ +tBTC_AV_CODEC_INFO *btc_av_codec_cap_get(void); + +#endif + void btc_a2dp_src_reg_data_cb(esp_a2d_source_data_cb_t callback); /******************************************************************************* ** @@ -172,6 +220,16 @@ void btc_dispatch_sm_event(btc_av_sm_event_t event, void *p_data, int len); BOOLEAN btc_av_is_connected(void); +/******************************************************************************* +** +** Function btc_av_is_started +** +** Description Checks if av is started +** +** Returns BOOLEAN +** +*******************************************************************************/ +BOOLEAN btc_av_is_started(void); /******************************************************************************* * @@ -225,4 +283,60 @@ uint8_t btc_av_get_service_id(void); #endif ///BTC_AV_INCLUDED == TRUE +/******************************************************************************* +** +** Function btc_a2d_conn_handle_get +** +** Description Get connection handle from btc_av_cb +** +** Returns Void +** +*******************************************************************************/ +uint16_t btc_a2d_conn_handle_get(void); + +/******************************************************************************* +** +** Function btc_av_audio_buff_alloc +** +** Description Allocate audio buffer with specific size +** +** Returns Void +** +*******************************************************************************/ +void btc_av_audio_buff_alloc(uint16_t size, uint8_t **pp_buff, uint8_t **pp_data); + +/******************************************************************************* +** +** Function btc_av_audio_buff_free +** +** Description Free audio buffer +** +** Returns Void +** +*******************************************************************************/ +void btc_av_audio_buff_free(uint8_t *p_buf); + +/******************************************************************************* +** +** Function btc_a2d_src_audio_mtu_check +** +** Description Checks if data length is valid, not bigger than mtu +** +** Returns BOOLEAN +** +*******************************************************************************/ +BOOLEAN btc_a2d_src_audio_mtu_check(uint16_t data_len); + +/******************************************************************************* +** +** Function btc_a2d_src_audio_data_send +** +** Description Send audio data to lower layer, audio buffer is consumed +** only when operation is success +** +** Returns BT_STATUS_SUCCESS if success, otherwise, BT_STATUS_FAIL +** +*******************************************************************************/ +bt_status_t btc_a2d_src_audio_data_send(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf); + #endif /* __BTC_AV_H__ */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_av_api.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_av_api.h index 72ee3bb7..57d14fbf 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/btc_av_api.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_av_api.h @@ -23,6 +23,9 @@ #include "stack/a2d_sbc.h" #if (BTC_AV_INCLUDED == TRUE) +#ifdef __cplusplus +extern "C" { +#endif /***************************************************************************** ** Constants and data types *****************************************************************************/ diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_avrc.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_avrc.h index 83200ae1..c44a5e48 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/btc_avrc.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_avrc.h @@ -37,9 +37,17 @@ typedef enum { BTC_AVRC_STATUS_API_SND_META_EVT, BTC_AVRC_STATUS_API_SND_PLAY_STATUS_EVT, BTC_AVRC_STATUS_API_SND_GET_RN_CAPS_EVT, + BTC_AVRC_STATUS_API_SND_GET_PLAY_STATUS_EVT, BTC_AVRC_NOTIFY_API_SND_REG_NOTIFY_EVT, BTC_AVRC_CTRL_API_SND_SET_PLAYER_SETTING_EVT, - BTC_AVRC_CTRL_API_SND_SET_ABSOLUTE_VOLUME_EVT + BTC_AVRC_CTRL_API_SND_SET_ABSOLUTE_VOLUME_EVT, +#if BTC_AV_CA_INCLUDED + BTC_AVRC_CT_API_COVER_ART_CONNECT_EVT, + BTC_AVRC_CT_API_COVER_ART_DISCONNECT_EVT, + BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_PROPERTIES_EVT, + BTC_AVRC_CT_API_COVER_ART_GET_IMAGE_EVT, + BTC_AVRC_CT_API_COVER_ART_GET_LINKED_THUMBNAIL_EVT, +#endif } btc_avrc_act_t; typedef struct { @@ -69,6 +77,10 @@ typedef struct { uint8_t tl; } get_caps_cmd_t; +typedef struct { + uint8_t tl; +} get_play_status_cmd_t; + #define BTC_AVRC_MIN_VOLUME 0x00 #define BTC_AVRC_MAX_VOLUME 0x7f @@ -77,6 +89,28 @@ typedef struct { uint8_t volume; } set_abs_vol_cmd_t; +#if BTC_AV_CA_INCLUDED + +typedef struct { + uint16_t mtu; +} ca_conn_t; + +typedef struct { + uint8_t image_handle[7]; +} ca_get_img_prop_t; + +typedef struct { + uint8_t image_handle[7]; + uint16_t image_descriptor_len; + uint8_t *image_descriptor; +} ca_get_img_t; + +typedef struct { + uint8_t image_handle[7]; +} ca_get_lk_thn_t; + +#endif /* BTC_AV_CA_INCLUDED */ + /* btc_avrc_args_t */ typedef union { pt_cmd_t pt_cmd; @@ -84,7 +118,14 @@ typedef union { rn_cmd_t rn_cmd; ps_cmd_t ps_cmd; get_caps_cmd_t get_caps_cmd; + get_play_status_cmd_t get_play_status_cmd; set_abs_vol_cmd_t set_abs_vol_cmd; +#if BTC_AV_CA_INCLUDED + ca_conn_t ca_conn; + ca_get_img_prop_t ca_get_img_prop; + ca_get_img_t ca_get_img; + ca_get_lk_thn_t ca_get_lk_thn; +#endif } btc_avrc_args_t; /* btc_avrc_tg_act_t */ @@ -124,6 +165,9 @@ typedef struct { typedef struct { BOOLEAN rc_connected; +#if BTC_AV_CA_INCLUDED + BOOLEAN rc_cover_art_connected; +#endif UINT8 rc_handle; tBTA_AV_FEAT rc_features; UINT16 rc_ct_features; @@ -162,6 +206,8 @@ BOOLEAN btc_rc_get_connected_peer(BD_ADDR peer_addr); ********************************************************************************/ void btc_avrc_ct_call_handler(btc_msg_t *msg); void btc_avrc_tg_call_handler(btc_msg_t *msg); +void btc_avrc_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); +void btc_avrc_arg_deep_free(btc_msg_t *msg); void btc_avrc_tg_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); void btc_avrc_tg_arg_deep_free(btc_msg_t *msg); @@ -179,6 +225,8 @@ uint16_t btc_avrc_tg_get_rn_supported_evt(void); bool btc_avrc_tg_check_rn_supported_evt(uint16_t evt_set); bool btc_avrc_tg_rn_evt_supported(uint8_t event_id); bool btc_avrc_ct_rn_evt_supported(uint8_t event_id); +bool btc_avrc_ct_check_cover_art_support(void); +void btc_avrc_get_profile_status(esp_avrc_profile_status_t *param); #endif ///BTC_AV_INCLUDED == TRUE diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_ble_cte.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_ble_cte.h new file mode 100644 index 00000000..659bfb31 --- /dev/null +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_ble_cte.h @@ -0,0 +1,98 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __BTC_CTE_BLE_H__ +#define __BTC_CTE_BLE_H__ + +#if (BLE_FEAT_CTE_EN == TRUE) +#include "esp_bt_defs.h" +#include "esp_ble_cte_api.h" +#include "btc/btc_manage.h" + +typedef enum { +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + BTC_CTE_ACT_SET_TRANS_PARAMS, + BTC_CTE_ACT_SET_TRANS_ENABLE, + BTC_CTE_ACT_SET_IQ_SAMPLING_EN, +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + BTC_CTE_ACT_SET_CONN_CTE_RECV_PARAMS, + BTC_CTE_ACT_SET_CONN_CTE_TRANS_PARAMS, + BTC_CTE_ACT_SET_CONN_CTE_REQUEST_EN, + BTC_CTE_ACT_SET_CONN_CTE_RESPONSE_EN, +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + BTC_CTE_ACT_READ_ANTENNA_INFOR, +} btc_cte_ble_act_t; + +/* btc_ble_cte_args_t */ +typedef union { +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + struct cte_set_trans_params_arg { + uint8_t adv_handle; + uint8_t cte_len; + uint8_t cte_type; + uint8_t cte_count; + uint8_t switching_pattern_len; + uint8_t *antenna_ids; + } cte_trans_params; + + struct cte_set_trans_enable_arg { + uint8_t adv_handle; + uint8_t cte_enable; + } cte_trans_enable; + + struct cte_iq_sampling_en_arg { + uint16_t sync_handle; + uint8_t sampling_en; + uint8_t slot_dur; + uint8_t max_sampled_ctes; + uint8_t switching_pattern_len; + uint8_t *antenna_ids; + } cte_iq_sampling_en; +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + struct cte_recv_params_arg { + uint16_t conn_handle; + uint8_t sampling_en; + uint8_t slot_dur; + uint8_t switching_pattern_len; + uint8_t *antenna_ids; + } cte_recv_params; + + struct cte_set_conn_trans_params_arg { + uint16_t conn_handle; + uint8_t cte_types; + uint8_t switching_pattern_len; + uint8_t *antenna_ids; + } cte_conn_trans_params; + + struct cte_req_en_arg { + uint16_t conn_handle; + uint8_t enable; + uint16_t cte_req_interval; + uint8_t req_cte_len; + uint8_t req_cte_Type; + } cte_req_en; +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + + struct cte_rsp_en_arg { + uint16_t conn_handle; + uint8_t enable; + } cte_rsp_en; + +} btc_ble_cte_args_t; + +void btc_ble_cte_call_handler(btc_msg_t *msg); +void btc_ble_cte_cb_handler(btc_msg_t *msg); +void btc_ble_cte_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); +void btc_ble_cte_arg_deep_free(btc_msg_t *msg); +void btc_ble_cte_cb_deep_free(btc_msg_t *msg); +void btc_ble_cte_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); +void btc_cte_callback_init(void); + +#endif // #if (BLE_FEAT_CTE_EN == TRUE) + +#endif /* __BTC_CTE_BLE_H__ */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h index e540116d..03b1e088 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_gap_ble.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,15 +11,23 @@ #include "esp_gap_ble_api.h" #if BTC_DYNAMIC_MEMORY == TRUE +#if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_ADV_EN == TRUE) #include "bta/bta_api.h" extern tBTA_BLE_ADV_DATA *gl_bta_adv_data_ptr; extern tBTA_BLE_ADV_DATA *gl_bta_scan_rsp_data_ptr; #define gl_bta_adv_data (*gl_bta_adv_data_ptr) #define gl_bta_scan_rsp_data (*gl_bta_scan_rsp_data_ptr) +#endif // #if (BLE_42_ADV_EN == TRUE) +#endif // BLE_42_FEATURE_SUPPORT #endif #define BLE_ISVALID_PARAM(x, min, max) (((x) >= (min) && (x) <= (max))) +#define BLE_VENDOR_PDU_RECV_EVT (0xC0) +#define BLE_VENDOR_CHMAP_UPDATE_EVT (0xC1) +#define BLE_VENDOR_SLEEP_WAKEUP_EVT (0xC3) + typedef enum { #if (BLE_42_FEATURE_SUPPORT == TRUE) BTC_GAP_BLE_ACT_CFG_ADV_DATA = 0, @@ -62,6 +70,7 @@ typedef enum { BTC_GAP_BLE_READ_PHY, BTC_GAP_BLE_SET_PREFERED_DEF_PHY, BTC_GAP_BLE_SET_DEF_PHY, +#if (BLE_50_EXTEND_ADV_EN == TRUE) BTC_GAP_BLE_SET_EXT_ADV_RAND_ADDR, BTC_GAP_BLE_SET_EXT_ADV_PARAMS, BTC_GAP_BLE_CFG_EXT_ADV_DATA_RAW, @@ -70,23 +79,32 @@ typedef enum { BTC_GAP_BLE_EXT_ADV_STOP, BTC_GAP_BLE_EXT_ADV_SET_REMOVE, BTC_GAP_BLE_EXT_ADV_SET_CLEAR, +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) BTC_GAP_BLE_SET_PERIODIC_ADV_PARAMS, BTC_GAP_BLE_CFG_PERIODIC_ADV_DATA_RAW, BTC_GAP_BLE_PERIODIC_ADV_START, BTC_GAP_BLE_PERIODIC_ADV_STOP, +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) BTC_GAP_BLE_PERIODIC_ADV_CREATE_SYNC, BTC_GAP_BLE_PERIODIC_ADV_SYNC_CANCEL, BTC_GAP_BLE_PERIODIC_ADV_SYNC_TERMINATE, BTC_GAP_BLE_PERIODIC_ADV_ADD_DEV_TO_LIST, BTC_GAP_BLE_PERIODIC_REMOVE_ADD_DEV_FROM_LIST, BTC_GAP_BLE_PERIODIC_CLEAR_DEV, +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if (BLE_50_EXTEND_SCAN_EN == TRUE) BTC_GAP_BLE_SET_EXT_SCAN_PARAMS, BTC_GAP_BLE_START_EXT_SCAN, BTC_GAP_BLE_STOP_EXT_SCAN, +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) BTC_GAP_BLE_SET_EXT_PEFER_CONNET_PARAMS, +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_DTM_TEST_EN == TRUE) BTC_GAP_BLE_DTM_ENH_TX_START, BTC_GAP_BLE_DTM_ENH_RX_START, -#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) BTC_GAP_BLE_ACT_GET_DEV_NAME, #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) BTC_GAP_BLE_PERIODIC_ADV_RECV_ENABLE, @@ -94,18 +112,35 @@ typedef enum { BTC_GAP_BLE_PERIODIC_ADV_SET_INFO_TRANS, BTC_GAP_BLE_SET_PERIODIC_ADV_SYNC_TRANS_PARAMS, #endif //#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) -#if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_42_DTM_TEST_EN == TRUE) BTC_GAP_BLE_DTM_TX_START, BTC_GAP_BLE_DTM_RX_START, -#endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) +#endif // #if (BLE_42_DTM_TEST_EN == TRUE) BTC_GAP_BLE_DTM_STOP, -#if (BLE_42_FEATURE_SUPPORT == TRUE) +#if (BLE_VENDOR_HCI_EN == TRUE) BTC_GAP_BLE_ACT_CLEAR_ADV, -#endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) + BTC_GAP_BLE_ACT_VENDOR_HCI_CMD_EVT, + BTC_GAP_BLE_SET_CSA_SUPPORT, + BTC_GAP_BLE_ACT_SET_VENDOR_EVT_MASK, +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) BTC_GAP_BLE_ACT_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT, BTC_GAP_BLE_ACT_ADD_DEVICE_TO_RESOLVING_LIST, - BTC_GAP_BLE_ACT_VENDOR_HCI_CMD_EVT, BTC_GAP_BLE_SET_PRIVACY_MODE, +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + BTC_GAP_BLE_ENH_READ_TRANS_POWER_LEVEL, + BTC_GAP_BLE_READ_REM_TRANS_POWER_LEVEL, + BTC_GAP_BLE_SET_PATH_LOSS_REPORT_PARAMS, + BTC_GAP_BLE_SET_PATH_LOSS_REPORTING_EN, + BTC_GAP_BLE_SET_TRANS_POWER_REPORTING_EN, +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) + BTC_GAP_BLE_SET_DEFALT_SUBRATE, + BTC_GAP_BLE_SUBRATE_REQUEST, +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) + BTC_GAP_ACT_SET_HOST_FEATURE, +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + BTC_GAP_BLE_READ_CHANNEL_MAP, } btc_gap_ble_act_t; /* btc_ble_gap_args_t */ @@ -254,6 +289,7 @@ typedef union { struct set_channels_args { esp_gap_ble_channels channels; } set_channels; +#if (BLE_42_DTM_TEST_EN == TRUE) struct dtm_tx_start_args { uint8_t tx_channel; uint8_t len_of_data; @@ -262,6 +298,7 @@ typedef union { struct dtm_rx_start_args { uint8_t rx_channel; } dtm_rx_start; +#endif // #if (BLE_42_DTM_TEST_EN == TRUE) //BTC_DEV_VENDOR_HCI_CMD_EVT struct vendor_cmd_send_args { uint16_t opcode; @@ -274,6 +311,17 @@ typedef union { esp_bd_addr_t addr; uint8_t privacy_mode; } set_privacy_mode; + // BTC_GAP_BLE_SET_CSA_SUPPORT + struct set_csa_support_args { + uint8_t csa_select; + } set_csa_support; + // BTC_GAP_BLE_ACT_SET_VENDOR_EVT_MASK + struct set_vendor_evt_mask_args { + uint32_t evt_mask; + } set_vendor_evt_mask; + struct read_channel_map_args { + esp_bd_addr_t bd_addr; + } read_channel_map; } btc_ble_gap_args_t; #if (BLE_50_FEATURE_SUPPORT == TRUE) @@ -294,7 +342,7 @@ typedef union { esp_ble_gap_phy_mask_t rx_phy_mask; uint16_t phy_options; } set_def_phy; - +#if (BLE_50_EXTEND_ADV_EN == TRUE) struct ext_adv_set_rand_addr_args { uint8_t instance; esp_bd_addr_t rand_addr; @@ -330,7 +378,9 @@ typedef union { struct ext_adv_set_remove_args { uint8_t instance; } ext_adv_set_remove; +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) struct peridic_adv_set_params_args { uint8_t instance; esp_ble_gap_periodic_adv_params_t params; @@ -351,6 +401,7 @@ typedef union { struct periodic_adv_stop_args { uint8_t instance; } periodic_adv_stop; +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) struct periodic_adv_create_sync_args { esp_ble_gap_periodic_adv_sync_params_t params; @@ -428,12 +479,70 @@ typedef union { uint8_t phy; uint8_t modulation_index; } dtm_enh_rx_start; +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + // BTC_GAP_BLE_ENH_READ_TRANS_POWER_LEVEL + struct enh_read_trans_pwr_level_args { + uint8_t conn_handle; + uint8_t phy; + } enh_read_trans_pwr_level; + // BTC_GAP_BLE_READ_REM_TRANS_POWER_LEVEL + struct read_rem_trans_pwr_level_args { + uint8_t conn_handle; + uint8_t phy; + } read_rem_trans_pwr_level; + // BTC_GAP_BLE_SET_PATH_LOSS_REPORT_PARAMS + struct set_path_loss_rpt_params_args { + uint16_t conn_handle; + uint8_t high_threshold; + uint8_t high_hysteresis; + uint8_t low_threshold; + uint8_t low_hysteresis; + uint16_t min_time_spent; + } set_path_loss_rpt_params; + // BTC_GAP_BLE_SET_PATH_LOSS_REPORTING_EN + struct set_path_loss_rpt_en_args { + uint16_t conn_handle; + uint8_t enable; + } set_path_loss_rpt_en; + // BTC_GAP_BLE_SET_TRANS_POWER_REPORTING_EN + struct set_trans_pwr_rpting_en_args { + uint16_t conn_handle; + uint8_t local_enable; + uint8_t remote_enable; + } set_trans_pwr_rpting_en; +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) + // BTC_GAP_BLE_SET_DEFALT_SUBRATE + struct default_subrate_param_args { + uint16_t subrate_min; + uint16_t subrate_max; + uint16_t max_latency; + uint16_t continuation_number; + uint16_t supervision_timeout; + } default_subrate_param; + // BTC_GAP_BLE_SUBRATE_REQUEST + struct subrate_req_param_args { + uint16_t conn_handle; + uint16_t subrate_min; + uint16_t subrate_max; + uint16_t max_latency; + uint16_t continuation_number; + uint16_t supervision_timeout; + } subrate_req_param; +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + struct set_host_feature_arg { + uint16_t bit_num; + uint8_t bit_val; + } set_host_feature_params; } btc_ble_5_gap_args_t; #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) void btc_gap_ble_call_handler(btc_msg_t *msg); void btc_gap_ble_cb_handler(btc_msg_t *msg); void btc_get_whitelist_size(uint16_t *length); +#if (BLE_50_EXTEND_SYNC_EN == TRUE) +void btc_get_periodic_list_size(uint8_t *length); +#endif //#if (BLE_50_EXTEND_SYNC_EN == TRUE) void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); void btc_gap_ble_arg_deep_free(btc_msg_t *msg); void btc_gap_ble_cb_deep_free(btc_msg_t *msg); diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_gap_bt.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_gap_bt.h index 6855449c..b35e6425 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/btc_gap_bt.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_gap_bt.h @@ -13,6 +13,7 @@ #include "esp_gap_bt_api.h" #include "btc/btc_task.h" #include "bta/utl.h" +#include "bta/bta_api.h" #if (BTC_GAP_BT_INCLUDED == TRUE) typedef enum { @@ -192,8 +193,12 @@ void btc_gap_bt_cb_handler(btc_msg_t *msg); void btc_gap_bt_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); void btc_gap_bt_arg_deep_free(btc_msg_t *msg); void btc_gap_bt_busy_level_updated(uint8_t bl_flags); +void btc_gap_bt_init(void); +void btc_gap_bt_deinit(void); +void btc_gap_bt_acl_link_num_update(tBTA_DM_ACL_LINK_STAT *p_acl_link_stat); esp_err_t btc_gap_bt_get_cod(esp_bt_cod_t *cod); +void btc_gap_bt_status_get(esp_bt_gap_profile_status_t *param); #endif /* #if BTC_GAP_BT_INCLUDED */ #endif /* __BTC_GAP_BT_H__ */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_gatt_util.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_gatt_util.h index 3eb38abd..487708e6 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/btc_gatt_util.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_gatt_util.h @@ -9,6 +9,7 @@ #include "stack/bt_types.h" #include "bta/bta_gatt_api.h" +#include "btc/btc_util.h" #include "esp_bt_defs.h" #include "esp_gatt_defs.h" #include "esp_gattc_api.h" @@ -18,12 +19,10 @@ #define BTC_GATT_GET_GATT_IF(conn_id) ((uint8_t)(conn_id)) void btc128_to_bta_uuid(tBT_UUID *p_dest, uint8_t *p_src); -void btc_to_bta_uuid(tBT_UUID *p_dest, esp_bt_uuid_t *p_src); void btc_to_bta_gatt_id(tBTA_GATT_ID *p_dest, esp_gatt_id_t *p_src); void btc_to_bta_srvc_id(tBTA_GATT_SRVC_ID *p_dest, esp_gatt_srvc_id_t *p_src); void btc_to_bta_response(tBTA_GATTS_RSP *rsp_struct, esp_gatt_rsp_t *p_rsp); -void bta_to_btc_uuid(esp_bt_uuid_t *p_dest, tBT_UUID *p_src); void bta_to_btc_gatt_id(esp_gatt_id_t *p_dest, tBTA_GATT_ID *p_src); void bta_to_btc_srvc_id(esp_gatt_srvc_id_t *p_dest, tBTA_GATT_SRVC_ID *p_src); diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_gattc.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_gattc.h index eeebb427..1c8ef828 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/btc_gattc.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_gattc.h @@ -57,6 +57,11 @@ typedef union { esp_ble_addr_type_t remote_addr_type; bool is_direct; bool is_aux; + esp_ble_addr_type_t own_addr_type; + esp_ble_phy_mask_t phy_mask; + esp_ble_conn_params_t phy_1m_conn_params; + esp_ble_conn_params_t phy_2m_conn_params; + esp_ble_conn_params_t phy_coded_conn_params; } open; //BTC_GATTC_ACT_CLOSE, struct close_arg { diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_hd.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_hd.h index 313930a4..15b59393 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/btc_hd.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_hd.h @@ -55,6 +55,7 @@ typedef struct { bool app_registered; bool service_dereg_active; bool forced_disc; + bool in_use; tBTA_HD_APP_INFO app_info; tBTA_HD_QOS_INFO in_qos; tBTA_HD_QOS_INFO out_qos; @@ -97,13 +98,11 @@ void btc_hd_call_handler(btc_msg_t *msg); void btc_hd_cb_handler(btc_msg_t *msg); -// extern btc_hd_cb_t btc_hd_cb; -// extern void btc_hd_remove_device(bt_bdaddr_t bd_addr); -// extern void btc_hd_service_registration(); - void btc_hd_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); void btc_hd_cb_arg_deep_free(btc_msg_t *msg); +void btc_hd_get_profile_status(esp_hidd_profile_status_t *param); + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_hf_ag.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_hf_ag.h index 5cecdd99..e2706193 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/btc_hf_ag.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_hf_ag.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -57,6 +57,7 @@ typedef enum BTC_HF_END_CALL_EVT, //REG BTC_HF_REGISTER_DATA_CALLBACK_EVT, + BTC_HF_REGISTER_AUDIO_DATA_CALLBACK_EVT, BTC_HF_REQUEST_PKT_STAT_EVT } btc_hf_act_t; @@ -189,6 +190,11 @@ typedef union esp_hf_outgoing_data_cb_t send; } reg_data_cb; + // BTC_HF_REGISTER_AUDIO_DATA_CALLBACK_EVT + struct ag_reg_audio_data_callback { + esp_hf_ag_audio_data_cb_t callback; + } reg_audio_data_cb; + // BTC_HF_REQUEST_PKT_STAT_EVT struct ag_req_pkt_stat_sync_handle { UINT16 sync_conn_handle; @@ -211,6 +217,7 @@ typedef struct { bool initialized; UINT16 handle; + UINT16 sync_conn_hdl; bt_bdaddr_t connected_bda; tBTA_AG_PEER_FEAT peer_feat; tBTA_AG_CHLD_FEAT chld_feat; @@ -231,6 +238,7 @@ typedef struct btc_hf_cb_t btc_hf_cb; esp_hf_incoming_data_cb_t btc_hf_incoming_data_cb; esp_hf_outgoing_data_cb_t btc_hf_outgoing_data_cb; + esp_hf_ag_audio_data_cb_t btc_hf_audio_data_cb; } hf_local_param_t; #if HFP_DYNAMIC_MEMORY == TRUE @@ -247,6 +255,8 @@ void btc_hf_cb_handler(btc_msg_t *msg); //handle the event from bta void btc_hf_incoming_data_cb_to_app(const uint8_t *data, uint32_t len); +void btc_hf_audio_data_cb_to_app(uint8_t *buf, uint8_t *data, uint16_t len, bool is_bad_frame); + uint32_t btc_hf_outgoing_data_cb_to_app(uint8_t *data, uint32_t len); void btc_hf_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); @@ -255,6 +265,9 @@ void btc_hf_arg_deep_free(btc_msg_t *msg); bt_status_t btc_hf_ci_sco_data(void); +bool btc_hf_ag_audio_data_send(uint16_t sync_conn_hdl, uint8_t *p_buff_start, uint8_t *p_data, uint8_t data_len); + +void btc_hf_get_profile_status(esp_hf_profile_status_t *param); #endif // BTC_HF_INCLUDED == TRUE #endif /* __BTC_HF_AG_H__ */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_hf_client.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_hf_client.h index 4f10371b..7211d87c 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/btc_hf_client.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_hf_client.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -49,6 +49,7 @@ typedef enum { BTC_HF_CLIENT_SEND_DTMF_EVT, BTC_HF_CLIENT_REQUEST_LAST_VOICE_TAG_NUMBER_EVT, BTC_HF_CLIENT_REGISTER_DATA_CALLBACK_EVT, + BTC_HF_CLIENT_REGISTER_AUDIO_DATA_CALLBACK_EVT, BTC_HF_CLIENT_SEND_NREC_EVT, BTC_HF_CLIENT_SEND_XAPL_EVT, BTC_HF_CLIENT_SEND_IPHONEACCEV_EVT, @@ -107,6 +108,11 @@ typedef union { esp_hf_client_outgoing_data_cb_t send; } reg_data_cb; + // BTC_HF_CLIENT_REGISTER_AUDIO_DATA_CALLBACK_EVT + struct hf_client_reg_audio_data_callback { + esp_hf_client_audio_data_cb_t callback; + } reg_audio_data_cb; + //BTC_HF_CLIENT_SEND_XAPL_EVT struct send_xapl_args { char information[ESP_BT_HF_AT_SEND_XAPL_LEN + 1]; @@ -134,6 +140,7 @@ typedef struct { bool initialized; UINT16 handle; + UINT16 sync_conn_hdl; bt_bdaddr_t connected_bda; esp_hf_client_connection_state_t state; esp_hf_vr_state_t vr_state; @@ -147,6 +154,7 @@ typedef struct btc_hf_client_cb_t btc_hf_client_cb; esp_hf_client_incoming_data_cb_t btc_hf_client_incoming_data_cb; esp_hf_client_outgoing_data_cb_t btc_hf_client_outgoing_data_cb; + esp_hf_client_audio_data_cb_t btc_hf_client_audio_data_cb; }hf_client_local_param_t; #if HFP_DYNAMIC_MEMORY == TRUE @@ -155,16 +163,20 @@ extern hf_client_local_param_t *hf_client_local_param_ptr; #endif /******************************************************************************* -** BTC HF AG API +** BTC HF CLIENT API ********************************************************************************/ void btc_hf_client_call_handler(btc_msg_t *msg); void btc_hf_client_cb_handler(btc_msg_t *msg); +void btc_hf_client_audio_data_cb_to_app(uint8_t *buf, uint8_t *data, uint16_t len, bool is_bad_frame); + void btc_hf_client_incoming_data_cb_to_app(const uint8_t *data, uint32_t len); uint32_t btc_hf_client_outgoing_data_cb_to_app(uint8_t *data, uint32_t len); + +void btc_hf_client_get_profile_status(esp_hf_client_profile_status_t *param); #endif ///BTC_HF_CLIENT_INCLUDED == TRUE #endif /* __BTC_HF_CLIENT_H__ */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_hh.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_hh.h index ae6faefc..f1158c6f 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/btc_hh.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_hh.h @@ -186,4 +186,6 @@ void btc_hh_cb_arg_deep_free(btc_msg_t *msg); bool btc_hh_add_added_dev(BD_ADDR bd_addr, uint16_t attr_mask); +void btc_hh_get_profile_status(esp_hidh_profile_status_t *param); + #endif /* BTC_HH_H */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_iso_ble.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_iso_ble.h new file mode 100644 index 00000000..4e734b12 --- /dev/null +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_iso_ble.h @@ -0,0 +1,222 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __BTC_ISO_BLE_H__ +#define __BTC_ISO_BLE_H__ + +#if (BLE_FEAT_ISO_EN == TRUE) +#include "esp_bt_defs.h" +#include "esp_ble_iso_api.h" +#include "btc/btc_manage.h" + +struct btc_iso_cis_params { + uint8_t cis_id; + uint16_t max_sdu_c_to_p; + uint16_t max_sdu_p_to_c; + uint8_t phy_c_to_p; + uint8_t phy_p_to_c; + uint8_t rtn_c_to_p; + uint8_t rtn_p_to_c; +} __attribute__((packed)); + +struct btc_iso_cis_params_test { + uint8_t cis_id; + uint8_t nse; + uint16_t max_sdu_c_to_p; + uint16_t max_sdu_p_to_c; + uint16_t max_pdu_c_to_p; + uint16_t max_pdu_p_to_c; + uint8_t phy_c_to_p; + uint8_t phy_p_to_c; + uint8_t bn_c_to_p; + uint8_t bn_p_to_c; +} __attribute__((packed)); + +struct btc_iso_cis_hdls { + uint16_t cis_hdl; + uint16_t acl_hdl; +}__attribute__((packed)); + +typedef enum { +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + BTC_ISO_ACT_BIG_CREATE, + BTC_ISO_ACT_BIG_CREATE_TEST, + BTC_ISO_ACT_BIG_TERMINATE, +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + BTC_ISO_ACT_BIG_SYNC_CREATE, + BTC_ISO_ACT_BIG_SYNC_TERMINATE, +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + BTC_ISO_ACT_SET_DATA_PATH, + BTC_ISO_ACT_REMOVE_DATA_PATH, + BTC_ISO_ACT_READ_ISO_TX_SYNC, + BTC_ISO_ACT_READ_ISO_LINK_QUALITY, +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + BTC_ISO_ACT_SET_CIG_PARAMS, + BTC_ISO_ACT_SET_CIG_PARAMS_TEST, + BTC_ISO_ACT_CREATE_CIS, + BTC_ISO_ACT_REMOVE_CIG, +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + BTC_ISO_ACT_ACCEPT_CIS_REQ, + BTC_ISO_ACT_REJECT_CIS_REQ, +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_EN == TRUE) + BTC_ISO_ACT_DISCON_CIS, +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) +} btc_iso_ble_act_t; + +/* btc_ble_iso_args_t */ +typedef union { +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + struct iso_big_create_args { + uint8_t big_handle; + uint8_t adv_handle; + uint8_t num_bis; + uint32_t sdu_interval; + uint16_t max_sdu; + uint16_t max_transport_latency; + uint8_t rtn; + uint8_t phy; + uint8_t packing; + uint8_t framing; + uint8_t encryption; + uint8_t broadcast_code[16]; + } iso_big_creat_params; + + struct iso_big_create_test_args { + uint8_t big_handle; + uint8_t adv_handle; + uint8_t num_bis; + uint32_t sdu_interval; + uint16_t iso_interval; + uint8_t nse; + uint16_t max_sdu; + uint16_t max_pdu; + uint8_t phy; + uint8_t packing; + uint8_t framing; + uint8_t bn; + uint8_t irc; + uint8_t pto; + uint8_t encryption; + uint8_t broadcast_code[16]; + } iso_big_creat_test_params; + + struct iso_big_terminate_args { + uint8_t big_handle; + uint8_t reason; + } iso_big_terminate_params; +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + struct iso_big_sync_creat_arg { + uint8_t big_handle; + uint16_t sync_handle; + uint8_t encryption; + uint8_t bc_code[16]; + uint8_t mse; + uint16_t big_sync_timeout; + uint8_t num_bis; + uint8_t bis[BLE_ISO_BIS_MAX_COUNT]; + } iso_big_sync_creat_params; + + struct iso_big_sync_terminate_arg { + uint8_t big_handle; + } iso_big_sync_terminate_params; +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + struct iso_set_data_path_arg { + uint16_t conn_handle; + uint8_t data_path_dir; + uint8_t data_path_id; + uint8_t coding_fmt; + uint16_t company_id; + uint16_t vs_codec_id; + uint32_t controller_delay; + uint8_t codec_cfg_len; + uint8_t *codec_cfg; + } iso_set_data_path_params; + + struct iso_remove_data_path_arg { + uint16_t conn_handle; + uint8_t data_path_dir; + } iso_remove_data_path_params; + + struct iso_read_tx_sync_arg { + uint16_t iso_handle; + } iso_read_tx_sync_params; + + struct iso_read_link_quality_arg { + uint16_t iso_handle; + } iso_read_link_quality_params; + +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + struct set_cig_params_arg { + uint8_t cig_id; + uint32_t sdu_int_c_to_p; + uint32_t sdu_int_p_to_c; + uint8_t worse_case_SCA; + uint8_t packing; + uint8_t framing; + uint16_t mtl_c_to_p; + uint16_t mtl_p_to_c; + uint8_t cis_cnt; + struct btc_iso_cis_params cis_params[BLE_ISO_CIS_MAX_COUNT]; + } set_cig_params; + + struct set_cig_params_test_arg { + uint8_t cig_id; + uint32_t sdu_int_c_to_p; + uint32_t sdu_int_p_to_c; + uint8_t ft_c_to_p; + uint8_t ft_p_to_c; + uint16_t iso_interval; + uint8_t worse_case_SCA; + uint8_t packing; + uint8_t framing; + uint8_t cis_cnt; + struct btc_iso_cis_params_test cis_params_test[ESP_BLE_MAX_CIS_NUM]; + } set_cig_params_test; + + struct creat_cis_arg { + uint8_t cis_count; + struct btc_iso_cis_hdls cis_hdls[BLE_ISO_CIS_MAX_COUNT]; + } creat_cis_params; + struct remove_cig_arg { + uint8_t cig_id; + } remove_cig_params; +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + struct accept_cis_req_arg { + uint16_t cis_handle; + } accept_cis_req_params; + + struct reject_cis_req_arg { + uint16_t cis_handle; + uint8_t reason; + } reject_cis_req_params; +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_EN == TRUE) + struct discon_cis_arg { + uint16_t cis_handle; + uint8_t reason; + } discon_cis_params; +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) +} btc_ble_iso_args_t; + +void btc_iso_ble_call_handler(btc_msg_t *msg); +void btc_iso_ble_cb_handler(btc_msg_t *msg); +void btc_iso_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); +void btc_iso_ble_arg_deep_free(btc_msg_t *msg); +void btc_iso_ble_cb_deep_free(btc_msg_t *msg); +void btc_iso_ble_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); +void btc_iso_callback_init(void); + +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + +#endif /* __BTC_ISO_BLE_H__ */ diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_l2cap.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_l2cap.h index 83708dbb..bf61852d 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/btc_l2cap.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_l2cap.h @@ -24,6 +24,8 @@ typedef enum { BTC_L2CAP_ACT_CONNECT, BTC_L2CAP_ACT_START_SRV, BTC_L2CAP_ACT_STOP_SRV, + BTC_L2CAP_ACT_VFS_REGISTER, + BTC_L2CAP_ACT_VFS_UNREGISTER, } btc_l2cap_act_t; /* btc_l2cap_args_t */ @@ -65,8 +67,8 @@ typedef union { void btc_l2cap_call_handler(btc_msg_t *msg); void btc_l2cap_cb_handler(btc_msg_t *msg); -esp_err_t btc_l2cap_vfs_register(void); -esp_err_t btc_l2cap_vfs_unregister(void); + +void btc_l2cap_get_protocol_status(esp_bt_l2cap_protocol_status_t *param); #endif ///defined BTC_L2CAP_INCLUDED && BTC_L2CAP_INCLUDED == TRUE #endif ///__BTC_L2CAP_H__ diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_pba_client.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_pba_client.h new file mode 100644 index 00000000..0a718fa3 --- /dev/null +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_pba_client.h @@ -0,0 +1,90 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "common/bt_defs.h" +#include "esp_pbac_api.h" + +#if BTC_PBA_CLIENT_INCLUDED + +typedef enum { + BTC_PBA_CLIENT_INIT_EVT = 0, + BTC_PBA_CLIENT_DEINIT_EVT, + BTC_PBA_CLIENT_CONNECT_EVT, + BTC_PBA_CLIENT_DISCONNECT_EVT, + BTC_PBA_CLIENT_PULL_PHONE_BOOK_EVT, + BTC_PBA_CLIENT_SET_PHONE_BOOK_EVT, + BTC_PBA_CLIENT_SET_PHONE_BOOK2_EVT, + BTC_PBA_CLIENT_PULL_VCARD_LISTING_EVT, + BTC_PBA_CLIENT_PULL_VCARD_ENTRY_EVT +} BTC_PBA_CLIENT_EVT; + +/* equal to BTA max conn */ +#define BTC_PBA_CLIENT_MAX_CONN_NUM 2 + +typedef struct { + uint16_t handle; + bt_bdaddr_t bd_addr; + char *path; + uint16_t path_len; + uint16_t path_pos; + bool busy; +} btc_pba_client_ccb_t; + +typedef struct { + btc_pba_client_ccb_t ccb[BTC_PBA_CLIENT_MAX_CONN_NUM]; +} btc_pba_client_cb_t; + +typedef union { + // BTC_PBA_CLIENT_CONNECT_EVT + struct pba_client_connect_arg { + bt_bdaddr_t bd_addr; + } connect; + + // BTC_PBA_CLIENT_DISCONNECT_EVT + struct pba_client_disconnect_arg { + uint16_t handle; + } disconnect; + + // BTC_PBA_CLIENT_PULL_PHONE_BOOK_EVT + struct pba_client_pull_phone_book_arg { + uint16_t handle; + char *name; + bool include_app_param; + esp_pbac_pull_phone_book_app_param_t app_param; + } pull_phone_book; + + // BTC_PBA_CLIENT_SET_PHONE_BOOK_EVT + struct pba_client_set_phone_book_arg { + uint16_t handle; + uint8_t flags; + char *name; + } set_phone_book; + + // BTC_PBA_CLIENT_PULL_VCARD_LISTING_EVT + struct pba_client_pull_vcard_listing_arg { + uint16_t handle; + char *name; + bool include_app_param; + esp_pbac_pull_vcard_listing_app_param_t app_param; + } pull_vcard_listing; + + // BTC_PBA_CLIENT_PULL_VCARD_ENTRY_EVT + struct pba_client_pull_vcard_entry_arg { + uint16_t handle; + char *name; + bool include_app_param; + esp_pbac_pull_vcard_entry_app_param_t app_param; + } pull_vcard_entry; +} btc_pba_client_args_t; + +void btc_pba_client_call_handler(btc_msg_t *msg); +void btc_pba_client_cb_handler(btc_msg_t *msg); +void btc_pba_client_args_deep_free(btc_msg_t *msg); +void btc_pba_client_args_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); + +#endif diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_sdp.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_sdp.h index 60772fa3..234c79b8 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/btc_sdp.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_sdp.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,8 +12,9 @@ #include "common/bt_target.h" #include "bta/bta_sdp_api.h" #include "bt_sdp.h" +#include "esp_sdp_api.h" -#if (defined BTC_SDP_INCLUDED && BTC_SDP_INCLUDED == TRUE) +#if (defined BTC_SDP_COMMON_INCLUDED && BTC_SDP_COMMON_INCLUDED == TRUE) typedef enum { BTC_SDP_ACT_INIT = 0, @@ -32,9 +33,9 @@ typedef union { } search; //BTC_SDP_ACT_CREATE_RECORD - struct creat_record_arg { + struct create_record_arg { bluetooth_sdp_record *record; - } creat_record; + } create_record; //BTC_SDP_ACT_REMOVE_RECORD struct remove_record_arg { @@ -49,5 +50,7 @@ void btc_sdp_arg_deep_free(btc_msg_t *msg); void btc_sdp_call_handler(btc_msg_t *msg); void btc_sdp_cb_handler(btc_msg_t *msg); -#endif ///defined BTC_SDP_INCLUDED && BTC_SDP_INCLUDED == TRUE +void btc_sdp_get_protocol_status(esp_sdp_protocol_status_t *param); + +#endif ///defined BTC_SDP_COMMON_INCLUDED && BTC_SDP_COMMON_INCLUDED == TRUE #endif ///__BTC_SDP_H__ diff --git a/lib/bt/host/bluedroid/btc/profile/std/include/btc_spp.h b/lib/bt/host/bluedroid/btc/profile/std/include/btc_spp.h index b3498132..5082a135 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/include/btc_spp.h +++ b/lib/bt/host/bluedroid/btc/profile/std/include/btc_spp.h @@ -90,5 +90,6 @@ void btc_spp_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); void btc_spp_arg_deep_free(btc_msg_t *msg); esp_err_t spp_send_data_to_btc(uint32_t handle, int len, uint8_t *p_data, esp_spp_mode_t spp_mode); +void btc_spp_get_profile_status(esp_spp_profile_status_t *param); #endif ///defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE #endif ///__BTC_SPP_H__ diff --git a/lib/bt/host/bluedroid/btc/profile/std/iso/btc_iso_ble.c b/lib/bt/host/bluedroid/btc/profile/std/iso/btc_iso_ble.c new file mode 100644 index 00000000..825d9563 --- /dev/null +++ b/lib/bt/host/bluedroid/btc/profile/std/iso/btc_iso_ble.c @@ -0,0 +1,384 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "osi/allocator.h" + +#include "bta/bta_api.h" +#include "bta/bta_dm_co.h" +#include "btc/btc_task.h" +#include "btc/btc_util.h" +#if (BLE_FEAT_ISO_EN == TRUE) +#include "btc_iso_ble.h" +#include "esp_ble_iso_api.h" + +static inline void btc_iso_ble_cb_to_app(esp_ble_iso_cb_event_t event, esp_ble_iso_cb_param_t *param) +{ + esp_ble_iso_cb_t btc_iso_ble_cb = (esp_ble_iso_cb_t)btc_profile_cb_get(BTC_PID_ISO_BLE); + if (btc_iso_ble_cb) { + btc_iso_ble_cb(event, param); + } +} + +static void btc_ble_iso_callback(tBTM_BLE_ISO_EVENT event, + tBTM_BLE_ISO_CB_PARAMS *params) +{ + esp_ble_iso_cb_param_t param; + bt_status_t ret; + btc_msg_t msg; + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_ISO_BLE; + + switch(event) { +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + case BTA_BLE_ISO_BIG_CREATE_COMPLETE_EVT: + msg.act = ESP_BLE_ISO_BIG_CREATE_CMPL_EVT; + param.create_big_cmpl.status = btc_btm_status_to_esp_status(params->btm_big_cmpl.status); + param.create_big_cmpl.big_handle = params->btm_big_cmpl.big_handle; + param.create_big_cmpl.big_sync_delay = params->btm_big_cmpl.big_sync_delay; + param.create_big_cmpl.transport_latency = params->btm_big_cmpl.transport_latency; + param.create_big_cmpl.phy = params->btm_big_cmpl.phy; + param.create_big_cmpl.nse = params->btm_big_cmpl.nse; + param.create_big_cmpl.bn = params->btm_big_cmpl.bn; + param.create_big_cmpl.pto = params->btm_big_cmpl.pto; + param.create_big_cmpl.irc = params->btm_big_cmpl.irc; + param.create_big_cmpl.max_pdu = params->btm_big_cmpl.max_pdu; + param.create_big_cmpl.iso_interval = params->btm_big_cmpl.iso_interval; + param.create_big_cmpl.num_bis = params->btm_big_cmpl.num_bis; + for (uint8_t i = 0; i < params->btm_big_cmpl.num_bis; i++) + { + param.create_big_cmpl.bis_handle[i] = params->btm_big_cmpl.bis_handle[i]; + } + break; + case BTA_BLE_ISO_BIG_TERMINATE_COMPLETE_EVT: + msg.act = ESP_BLE_ISO_BIG_TERMINATE_CMPL_EVT; + param.term_big_cmpl.status = btc_btm_status_to_esp_status(params->btm_big_term.status); + param.term_big_cmpl.big_handle = params->btm_big_term.big_handle; + param.term_big_cmpl.reason = params->btm_big_term.reason; + break; +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + case BTA_BLE_ISO_BIG_SYNC_ESTABLISHED_EVT: + msg.act = ESP_BLE_ISO_BIG_SYNC_ESTABLISHED_EVT; + param.big_sync_estab.status = btc_btm_status_to_esp_status(params->btm_big_sync_estab.status); + param.big_sync_estab.big_handle = params->btm_big_sync_estab.big_handle; + param.big_sync_estab.transport_latency = params->btm_big_sync_estab.transport_latency_big; + param.big_sync_estab.nse = params->btm_big_sync_estab.nse; + param.big_sync_estab.bn = params->btm_big_sync_estab.bn; + param.big_sync_estab.pto = params->btm_big_sync_estab.pto; + param.big_sync_estab.irc = params->btm_big_sync_estab.irc; + param.big_sync_estab.max_pdu = params->btm_big_sync_estab.max_pdu; + param.big_sync_estab.iso_interval = params->btm_big_sync_estab.iso_interval; + param.big_sync_estab.num_bis = params->btm_big_sync_estab.num_bis; + for (uint8_t i = 0; i < params->btm_big_sync_estab.num_bis; i++) + { + param.big_sync_estab.bis_handle[i] = params->btm_big_sync_estab.bis_handle[i]; + } + break; + case BTA_BLE_ISO_BIG_SYNC_LOST_EVT: + msg.act = ESP_BLE_ISO_BIG_SYNC_LOST_EVT; + param.big_sync_lost.big_handle = params->btm_big_sync_lost.big_handle; + param.big_sync_lost.reason = params->btm_big_sync_lost.reason; + break; + case BTA_BLE_ISO_BIG_SYNC_TERMINATE_COMPLETE_EVT: + msg.act = ESP_BLE_ISO_BIG_SYNC_TERMINATE_CMPL_EVT; + param.term_big_sync.status = btc_btm_status_to_esp_status(params->btm_big_sync_ter.status); + param.term_big_sync.big_handle = params->btm_big_sync_ter.big_hdl; + break; + case BTA_BLE_ISO_BIGINFO_ADV_REPORT_EVT: + msg.act = ESP_BLE_ISO_BIGINFO_ADV_REPORT_EVT; + param.biginfo_report.sync_handle = params->btm_biginfo_report.sync_handle; + param.biginfo_report.num_bis = params->btm_biginfo_report.num_bis; + param.biginfo_report.nse = params->btm_biginfo_report.nse; + param.biginfo_report.iso_interval = params->btm_biginfo_report.iso_interval; + param.biginfo_report.bn = params->btm_biginfo_report.bn; + param.biginfo_report.pto = params->btm_biginfo_report.pto; + param.biginfo_report.irc = params->btm_biginfo_report.irc; + param.biginfo_report.max_pdu = params->btm_biginfo_report.max_pdu; + param.biginfo_report.sdu_interval = params->btm_biginfo_report.sdu_interval; + param.biginfo_report.max_sdu = params->btm_biginfo_report.max_sdu; + param.biginfo_report.phy = params->btm_biginfo_report.phy; + param.biginfo_report.framing = params->btm_biginfo_report.framing; + param.biginfo_report.encryption = params->btm_biginfo_report.encryption; + break; +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + case BTA_BLE_ISO_DATA_PATH_UPFATE_EVT: + msg.act = ESP_BLE_ISO_ISO_DATA_PATH_UPDATE_EVT; + param.data_path.op_type = params->btm_data_path_update.op_type; + param.data_path.status = btc_btm_status_to_esp_status(params->btm_data_path_update.status); + param.data_path.iso_hdl = params->btm_data_path_update.conn_hdl; + break; + case BTA_BLE_ISO_READ_TX_SYNC_EVT: + msg.act = ESP_BLE_ISO_READ_ISO_TX_SYNC_CMPL_EVT; + param.read_tx_sync.status = btc_btm_status_to_esp_status(params->btm_read_tx_sync.status); + param.read_tx_sync.iso_hdl = params->btm_read_tx_sync.conn_hdl; + param.read_tx_sync.pkt_seq_num = params->btm_read_tx_sync.pkt_seq_num; + param.read_tx_sync.tx_time_stamp = params->btm_read_tx_sync.tx_time_stamp; + param.read_tx_sync.time_offset = params->btm_read_tx_sync.time_offset; + break; + case BTA_BLE_ISO_READ_LINK_QUALITY_EVT: + msg.act = ESP_BLE_ISO_READ_LINK_QUALITY_CMPL_EVT; + param.read_link_quality.status = btc_btm_status_to_esp_status(params->btm_read_link_quality.status); + param.read_link_quality.iso_hdl = params->btm_read_link_quality.conn_hdl; + param.read_link_quality.tx_unacked_pkts = params->btm_read_link_quality.tx_unacked_pkts; + param.read_link_quality.tx_flushed_pkts = params->btm_read_link_quality.tx_flushed_pkts; + param.read_link_quality.tx_last_subevt_pkts = params->btm_read_link_quality.tx_last_subevt_pkts; + param.read_link_quality.retransmitted_pkts = params->btm_read_link_quality.retransmitted_pkts; + param.read_link_quality.crc_error_pkts = params->btm_read_link_quality.crc_error_pkts; + param.read_link_quality.rx_unreceived_pkts = params->btm_read_link_quality.rx_unreceived_pkts; + param.read_link_quality.duplicate_pkts = params->btm_read_link_quality.duplicate_pkts; + break; +#if (BLE_FEAT_ISO_CIG_EN == TRUE) + case BTA_BLE_ISO_CIS_ESTABLISHED_EVT: + msg.act = ESP_BLE_ISO_CIS_ESTABLISHED_EVT; + param.cis_estab.status = btc_btm_status_to_esp_status(params->btm_cis_established_evt.status); + param.cis_estab.cis_handle = params->btm_cis_established_evt.conn_handle; + param.cis_estab.cig_sync_delay = params->btm_cis_established_evt.cig_sync_delay; + param.cis_estab.cis_sync_delay = params->btm_cis_established_evt.cis_sync_delay; + param.cis_estab.trans_lat_c_to_p = params->btm_cis_established_evt.trans_lat_c_to_p; + param.cis_estab.trans_lat_p_to_c = params->btm_cis_established_evt.trans_lat_p_to_c; + param.cis_estab.phy_c_to_p = params->btm_cis_established_evt.phy_c_to_p; + param.cis_estab.phy_p_to_c = params->btm_cis_established_evt.phy_p_to_c; + param.cis_estab.nse = params->btm_cis_established_evt.nse; + param.cis_estab.bn_c_to_p = params->btm_cis_established_evt.bn_c_to_p; + param.cis_estab.bn_p_to_c = params->btm_cis_established_evt.bn_p_to_c; + param.cis_estab.ft_c_to_p = params->btm_cis_established_evt.ft_c_to_p; + param.cis_estab.ft_p_to_c = params->btm_cis_established_evt.ft_p_to_c; + param.cis_estab.max_pdu_c_to_p = params->btm_cis_established_evt.max_pdu_c_to_p; + param.cis_estab.max_pdu_p_to_c = params->btm_cis_established_evt.max_pdu_p_to_c; + param.cis_estab.iso_interval = params->btm_cis_established_evt.iso_interval; +#if (BLE_FEAT_ISO_60_EN == TRUE) + param.cis_estab.sub_interval = params->btm_cis_established_evt.sub_interval; + param.cis_estab.max_sdu_c_to_p = params->btm_cis_established_evt.max_sdu_c_to_p; + param.cis_estab.max_sdu_p_to_c = params->btm_cis_established_evt.max_sdu_p_to_c; + param.cis_estab.sdu_int_c_to_p = params->btm_cis_established_evt.sdu_int_c_to_p; + param.cis_estab.sdu_int_p_to_c = params->btm_cis_established_evt.sdu_int_p_to_c; + param.cis_estab.framing = params->btm_cis_established_evt.framing; +#endif // #if (BLE_FEAT_ISO_60_EN == TRUE) + break; + case BTA_BLE_ISO_CIS_DISCONNECTED_EVT: + msg.act = ESP_BLE_ISO_CIS_DISCONNECTED_EVT; + param.cis_disconnected.cis_handle = params->btm_cis_disconnectd_evt.cis_handle; + param.cis_disconnected.reason = params->btm_cis_disconnectd_evt.reason; + break; +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + case BTM_BLE_ISO_CIS_REQUEST_EVT: + msg.act = ESP_BLE_ISO_CIS_REQUEST_EVT; + param.cis_request.acl_handle = params->btm_cis_request_evt.acl_handle; + param.cis_request.cis_handle = params->btm_cis_request_evt.cis_handle; + param.cis_request.cig_id = params->btm_cis_request_evt.cig_id; + param.cis_request.cis_id = params->btm_cis_request_evt.cis_id; + break; +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + case BTA_BLE_ISO_SET_CIG_PARAMS_EVT: + msg.act = ESP_BLE_ISO_SET_CIG_PARAMS_CMPL_EVT; + param.set_cig_params.status = btc_btm_status_to_esp_status(params->btm_set_cig_params.status); + param.set_cig_params.cig_id = params->btm_set_cig_params.cig_id; + param.set_cig_params.cis_count = params->btm_set_cig_params.cis_count; + memcpy(¶m.set_cig_params.cis_hdl[0], ¶ms->btm_set_cig_params.conn_hdl[0], params->btm_set_cig_params.cis_count * 2); + break; + case BTA_BLE_ISO_CREATE_CIS_EVT: + msg.act = ESP_BLE_ISO_CREATE_CIS_CMPL_EVT; + param.create_cis.status = btc_btm_status_to_esp_status(params->status); + break; + case BTA_BLE_ISO_REMOVE_CIG_EVT: + msg.act = ESP_BLE_ISO_REMOVE_CIG_CMPL_EVT; + param.remove_cig.status = btc_btm_status_to_esp_status(params->btm_remove_cig.status); + param.remove_cig.cig_id = params->btm_remove_cig.cig_id; + break; +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + case BTA_BLE_ISO_ACCEPT_CIS_REQ_EVT: + msg.act = ESP_BLE_ISO_ACCEPT_CIS_REQ_CMPL_EVT; + param.accept_req.status = btc_btm_status_to_esp_status(params->status); + break; + case BTA_BLE_ISO_REJECT_CIS_REQ_EVT: + msg.act = ESP_BLE_ISO_REJECT_CIS_REQ_CMPL_EVT; + param.reject_req.status = btc_btm_status_to_esp_status(params->btm_reject_cis_req.status); + param.reject_req.cis_handle = params->btm_reject_cis_req.cis_handle; + break; +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + default: + break; + } + + ret = btc_transfer_context(&msg, ¶m, + sizeof(esp_ble_iso_cb_param_t), NULL, NULL); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } +} + +void btc_iso_ble_cb_handler(btc_msg_t *msg) +{ + BTC_TRACE_DEBUG("%s act %d \n", __func__, msg->act); + esp_ble_iso_cb_param_t *param = (esp_ble_iso_cb_param_t *)msg->arg; + + if (msg->act < ESP_BLE_ISO_EVT_MAX) { + btc_iso_ble_cb_to_app(msg->act, param); + } else { + BTC_TRACE_ERROR("%s, unknown msg->act = %d", __func__, msg->act); + } + + btc_iso_ble_cb_deep_free(msg); + +} + +void btc_iso_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + btc_ble_iso_args_t *src = (btc_ble_iso_args_t *)p_src; + btc_ble_iso_args_t *dst = (btc_ble_iso_args_t *)p_dest; + + switch (msg->act) { + case BTC_ISO_ACT_SET_DATA_PATH: { + if (src->iso_set_data_path_params.codec_cfg_len && src->iso_set_data_path_params.codec_cfg) { + dst->iso_set_data_path_params.codec_cfg = osi_malloc(src->iso_set_data_path_params.codec_cfg_len); + if (dst->iso_set_data_path_params.codec_cfg) { + memcpy(dst->iso_set_data_path_params.codec_cfg, src->iso_set_data_path_params.codec_cfg, src->iso_set_data_path_params.codec_cfg_len); + } else { + BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act); + } + } + break; + } + default: + BTC_TRACE_ERROR("Unhandled deep copy %d\n", msg->act); + break; + } +} + +void btc_iso_ble_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + // esp_ble_iso_cb_param_t *src = (esp_ble_iso_cb_param_t *)p_src; + // esp_ble_iso_cb_param_t *dst = (esp_ble_iso_cb_param_t *) p_dest; + + switch (msg->act) { + default: + BTC_TRACE_ERROR("%s, Unhandled deep copy %d\n", __func__, msg->act); + break; + } +} + +void btc_iso_ble_arg_deep_free(btc_msg_t *msg) +{ + BTC_TRACE_DEBUG("%s \n", __func__); + switch (msg->act) { + + case BTC_ISO_ACT_SET_DATA_PATH: { + uint8_t *p_codec_cfg = ((btc_ble_iso_args_t *)msg->arg)->iso_set_data_path_params.codec_cfg; + if (p_codec_cfg) { + osi_free(p_codec_cfg); + } + break; + } + default: + BTC_TRACE_DEBUG("Unhandled deep free %d\n", msg->act); + break; + } +} + +void btc_iso_ble_cb_deep_free(btc_msg_t *msg) +{ + BTC_TRACE_DEBUG("%s", __func__); + switch (msg->act) { + default: + BTC_TRACE_DEBUG("Unhandled deep free %d", msg->act); + break; + } +} + +void btc_iso_ble_call_handler(btc_msg_t *msg) +{ + btc_ble_iso_args_t *arg = (btc_ble_iso_args_t *)msg->arg; + BTC_TRACE_DEBUG("%s act %d\n", __FUNCTION__, msg->act); + + switch (msg->act) { +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + case BTC_ISO_ACT_BIG_CREATE: + BTA_DmBleGapIsoBigCreate((tBTA_DM_BLE_BIG_CREATE_PARAMS *)&arg->iso_big_creat_params); + break; + case BTC_ISO_ACT_BIG_CREATE_TEST: + BTA_DmBleGapIsoBigCreateTest((tBTA_DM_BLE_BIG_CREATE_TEST_PARAMS *)&arg->iso_big_creat_test_params); + break; + case BTC_ISO_ACT_BIG_TERMINATE: + BTA_DmBleGapIsoBigTerminate((tBTA_DM_BLE_BIG_TERMINATE_PARAMS *)&arg->iso_big_terminate_params); + break; +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + case BTC_ISO_ACT_BIG_SYNC_CREATE: + BTA_DmBleGapIsoBigSyncCreate((tBTA_DM_BLE_BIG_SYNC_CREATE_PARAMS *)&arg->iso_big_sync_creat_params); + break; + case BTC_ISO_ACT_BIG_SYNC_TERMINATE: + BTA_DmBleGapIsoBigSyncTerminate((tBTA_DM_BLE_BIG_SYNC_TERMINATE_PARAMS *)&arg->iso_big_sync_terminate_params); + break; +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + case BTC_ISO_ACT_SET_DATA_PATH: + BTA_DmBleGapIsoDataPathSet((tBTA_DM_BLE_ISO_SET_DATA_PATH_PARAMS *)&arg->iso_set_data_path_params); + break; + case BTC_ISO_ACT_REMOVE_DATA_PATH: + BTA_DmBleGapIsoDataPathRemove((tBTA_DM_BLE_ISO_REMOVE_DATA_PATH_PARAMS *)&arg->iso_remove_data_path_params); + break; + case BTC_ISO_ACT_READ_ISO_TX_SYNC: + BTA_DmBleGapIsoReadTxSync(arg->iso_read_tx_sync_params.iso_handle); + break; + case BTC_ISO_ACT_READ_ISO_LINK_QUALITY: + break; +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + case BTC_ISO_ACT_SET_CIG_PARAMS: { + struct set_cig_params_arg *set_cig_params = (struct set_cig_params_arg *)arg; + BTA_DmBleIsoSetCigParams(set_cig_params->cig_id, set_cig_params->sdu_int_c_to_p, set_cig_params->sdu_int_p_to_c, + set_cig_params->worse_case_SCA, set_cig_params->packing, set_cig_params->framing, + set_cig_params->mtl_c_to_p, set_cig_params->mtl_p_to_c, set_cig_params->cis_cnt, + (uint8_t *)&set_cig_params->cis_params[0]); + break; + } + case BTC_ISO_ACT_SET_CIG_PARAMS_TEST: + struct set_cig_params_test_arg *set_cig_params_test = (struct set_cig_params_test_arg *)arg; + BTA_DmBleIsoSetCigParamsTest(set_cig_params_test->cig_id, set_cig_params_test->sdu_int_c_to_p, set_cig_params_test->sdu_int_p_to_c, + set_cig_params_test->ft_c_to_p, set_cig_params_test->ft_p_to_c, set_cig_params_test->iso_interval, + set_cig_params_test->worse_case_SCA, set_cig_params_test->packing, set_cig_params_test->framing, + set_cig_params_test->cis_cnt, (uint8_t *)&set_cig_params_test->cis_params_test[0]); + break; + case BTC_ISO_ACT_CREATE_CIS: { + struct creat_cis_arg * create_cis = (struct creat_cis_arg *)arg; + BTA_DmBleIsoCreateCis(create_cis->cis_count, (uint8_t *)&create_cis->cis_hdls[0]); + break; + } + case BTC_ISO_ACT_REMOVE_CIG: + BTA_DmBleIsoRemoveCig(arg->remove_cig_params.cig_id); + break; +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + case BTC_ISO_ACT_ACCEPT_CIS_REQ: + BTA_DmBleIsoAcceptCisReq(arg->accept_cis_req_params.cis_handle); + break; + case BTC_ISO_ACT_REJECT_CIS_REQ: + BTA_DmBleIsoRejectCisReq(arg->reject_cis_req_params.cis_handle, arg->reject_cis_req_params.reason); + break; +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_EN == TRUE) + case BTC_ISO_ACT_DISCON_CIS: + BTA_DmBleIsoDisconCis(arg->discon_cis_params.cis_handle, arg->discon_cis_params.reason); + break; +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) + default: + break; + } + + btc_iso_ble_arg_deep_free(msg); +} + +//register connection parameter update callback +void btc_iso_callback_init(void) +{ + BTM_BleIsoRegisterCallback(btc_ble_iso_callback); +} + +#endif ///BLE_FEAT_ISO_EN == TRUE diff --git a/lib/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c b/lib/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c index 5cd777c5..9155784f 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c +++ b/lib/bt/host/bluedroid/btc/profile/std/l2cap/btc_l2cap.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -72,7 +72,6 @@ typedef struct { uint8_t service_uuid[16]; } l2cap_slot_t; - typedef struct { l2cap_slot_t *l2cap_slots[BTA_JV_MAX_L2C_CONN + 1]; uint32_t l2cap_slot_id; @@ -81,7 +80,12 @@ typedef struct { esp_vfs_id_t l2cap_vfs_id; } l2cap_local_param_t; +#if L2CAP_DYNAMIC_MEMORY == FALSE static l2cap_local_param_t l2cap_local_param; +#else +static l2cap_local_param_t *l2cap_local_param_ptr; +#define l2cap_local_param (*l2cap_local_param_ptr) +#endif /* L2CAP default options for OBEX connections */ static const tL2CAP_FCR_OPTS obex_l2c_fcr_opts_def = @@ -103,13 +107,15 @@ static const tL2CAP_ERTM_INFO obex_l2c_etm_opt = OBX_FCR_TX_POOL_ID }; - #if L2CAP_DYNAMIC_MEMORY == FALSE #define is_l2cap_init() (l2cap_local_param.l2cap_slot_mutex != NULL) #else #define is_l2cap_init() (&l2cap_local_param != NULL && l2cap_local_param.l2cap_slot_mutex != NULL) #endif +static void btc_l2cap_vfs_register(void); +static void btc_l2cap_vfs_unregister(void); + static void l2cap_osi_free(void *p) { osi_free(p); @@ -281,7 +287,7 @@ static void close_timeout_handler(void *arg) status = btc_transfer_context(&msg, slot->alarm_arg, sizeof(tBTA_JV), NULL, NULL); if (slot->alarm_arg) { - free(slot->alarm_arg); + osi_free(slot->alarm_arg); slot->alarm_arg = NULL; } @@ -355,12 +361,20 @@ static void *btc_l2cap_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d // to do break; case BTA_JV_FREE_SCN_EVT: - slot = l2cap_find_slot_by_id(id); - if (slot) { - l2cap_free_slot(slot); - } else { - BTC_TRACE_ERROR("%s unable to find L2CAP slot, event:%d!", __func__, event); - p_data->free_scn.status = ESP_BT_L2CAP_NO_CONNECTION; + if (user_data) { + id = ((tBTA_JV_FREE_SCN_USER_DATA *)user_data)->slot_id; + slot = l2cap_find_slot_by_id(id); + if (slot) { + if (((tBTA_JV_FREE_SCN_USER_DATA *)user_data)->server_status != BTA_JV_SERVER_CONNECTED) { + l2cap_free_slot(slot); + } else { + // Currently running in btu task, free in btc task. It will be free when handling the disconnect event. + } + } else { + BTC_TRACE_ERROR("%s unable to find L2CAP slot, event:%d!", __func__, event); + p_data->free_scn.status = ESP_BT_L2CAP_NO_CONNECTION; + } + osi_free(user_data); } break; default: @@ -458,6 +472,7 @@ static void btc_l2cap_init(void) static void btc_l2cap_uninit(void) { esp_bt_l2cap_status_t ret = ESP_BT_L2CAP_SUCCESS; + tBTA_JV_SERVER_STATUS server_status = BTA_JV_SERVER_RUNNING; do { if (!is_l2cap_init()) { @@ -468,7 +483,8 @@ static void btc_l2cap_uninit(void) osi_mutex_lock(&l2cap_local_param.l2cap_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); // first, remove all connection for (size_t i = 1; i <= BTA_JV_MAX_L2C_CONN; i++) { - if (l2cap_local_param.l2cap_slots[i] != NULL && !l2cap_local_param.l2cap_slots[i]->is_server) { + if (l2cap_local_param.l2cap_slots[i] != NULL && l2cap_local_param.l2cap_slots[i]->connected) { + server_status = BTA_JV_SERVER_CONNECTED; BTA_JvL2capClose(l2cap_local_param.l2cap_slots[i]->handle, (tBTA_JV_L2CAP_CBACK *)btc_l2cap_inter_cb, (void *)l2cap_local_param.l2cap_slots[i]->id); } @@ -481,8 +497,17 @@ static void btc_l2cap_uninit(void) (void *)l2cap_local_param.l2cap_slots[i]->id); } + tBTA_JV_FREE_SCN_USER_DATA *user_data = osi_malloc(sizeof(tBTA_JV_FREE_SCN_USER_DATA)); + if (user_data) { + user_data->server_status = server_status; + user_data->slot_id = l2cap_local_param.l2cap_slots[i]->id; + } else { + BTC_TRACE_ERROR("%s unable to malloc user data!", __func__); + assert(0); + } + BTA_JvFreeChannel(l2cap_local_param.l2cap_slots[i]->psm, BTA_JV_CONN_TYPE_L2CAP, - (tBTA_JV_RFCOMM_CBACK *)btc_l2cap_inter_cb, (void *)l2cap_local_param.l2cap_slots[i]->id); + (tBTA_JV_RFCOMM_CBACK *)btc_l2cap_inter_cb, (void *)user_data); } } BTA_JvDisable((tBTA_JV_L2CAP_CBACK *)btc_l2cap_inter_cb); @@ -547,7 +572,8 @@ static void btc_l2cap_stop_srv(btc_l2cap_args_t *arg) esp_bt_l2cap_status_t ret = ESP_BT_L2CAP_SUCCESS; bool is_remove_all = false; uint8_t i, j, srv_cnt = 0; - uint8_t *srv_psm_arr = osi_malloc(BTA_JV_MAX_L2C_CONN); + uint16_t *srv_psm_arr = osi_malloc(BTA_JV_MAX_L2C_CONN); + tBTA_JV_SERVER_STATUS server_status = BTA_JV_SERVER_RUNNING; if (arg->stop_srv.psm == BTC_L2CAP_INVALID_PSM) { is_remove_all = true; @@ -594,6 +620,7 @@ static void btc_l2cap_stop_srv(btc_l2cap_args_t *arg) if (l2cap_local_param.l2cap_slots[i] != NULL && l2cap_local_param.l2cap_slots[i]->connected && l2cap_local_param.l2cap_slots[i]->handle != 0xffff && l2cap_local_param.l2cap_slots[i]->psm == srv_psm_arr[j]) { + server_status = BTA_JV_SERVER_CONNECTED; BTA_JvL2capClose(l2cap_local_param.l2cap_slots[i]->handle, (tBTA_JV_L2CAP_CBACK *)btc_l2cap_inter_cb, (void *)l2cap_local_param.l2cap_slots[i]->id); } @@ -606,14 +633,19 @@ static void btc_l2cap_stop_srv(btc_l2cap_args_t *arg) if (l2cap_local_param.l2cap_slots[i] != NULL && l2cap_local_param.l2cap_slots[i]->is_server && l2cap_local_param.l2cap_slots[i]->handle != 0xffff && l2cap_local_param.l2cap_slots[i]->psm == srv_psm_arr[j]) { - - if (l2cap_local_param.l2cap_slots[i]->handle > 0) { - BTA_JvL2capStopServer(l2cap_local_param.l2cap_slots[i]->psm, - (void *)l2cap_local_param.l2cap_slots[i]->id); + BTA_JvL2capStopServer(l2cap_local_param.l2cap_slots[i]->psm, + (void *)l2cap_local_param.l2cap_slots[i]->id); + + tBTA_JV_FREE_SCN_USER_DATA *user_data = osi_malloc(sizeof(tBTA_JV_FREE_SCN_USER_DATA)); + if (user_data) { + user_data->server_status = server_status; + user_data->slot_id = l2cap_local_param.l2cap_slots[i]->id; + } else { + BTC_TRACE_ERROR("%s unable to malloc user data!", __func__); + assert(0); } - BTA_JvFreeChannel(l2cap_local_param.l2cap_slots[i]->psm, BTA_JV_CONN_TYPE_L2CAP, - (tBTA_JV_RFCOMM_CBACK *)btc_l2cap_inter_cb, (void *)l2cap_local_param.l2cap_slots[i]->id); + (tBTA_JV_RFCOMM_CBACK *)btc_l2cap_inter_cb, (void *)user_data); } } } @@ -756,6 +788,12 @@ void btc_l2cap_call_handler(btc_msg_t *msg) case BTC_L2CAP_ACT_STOP_SRV: btc_l2cap_stop_srv(arg); break; + case BTC_L2CAP_ACT_VFS_REGISTER: + btc_l2cap_vfs_register(); + break; + case BTC_L2CAP_ACT_VFS_UNREGISTER: + btc_l2cap_vfs_unregister(); + break; default: BTC_TRACE_ERROR("%s: Unhandled event (%d)!\n", __FUNCTION__, msg->act); break; @@ -832,7 +870,7 @@ void btc_l2cap_cb_handler(btc_msg_t *msg) // if rx still has data, delay free slot if (slot->close_alarm == NULL && slot->rx.queue && fixed_queue_length(slot->rx.queue) > 0) { tBTA_JV *p_arg = NULL; - if ((p_arg = malloc(sizeof(tBTA_JV))) == NULL) { + if ((p_arg = osi_malloc(sizeof(tBTA_JV))) == NULL) { param.close.status = ESP_BT_L2CAP_NO_RESOURCE; osi_mutex_unlock(&l2cap_local_param.l2cap_slot_mutex); BTC_TRACE_ERROR("%s unable to malloc slot close_alarm arg!", __func__); @@ -842,7 +880,7 @@ void btc_l2cap_cb_handler(btc_msg_t *msg) slot->alarm_arg = (void *)p_arg; if ((slot->close_alarm = osi_alarm_new("slot", close_timeout_handler, (void *)slot, VFS_CLOSE_TIMEOUT)) == NULL) { - free(p_arg); + osi_free(p_arg); slot->alarm_arg = NULL; param.close.status = ESP_BT_L2CAP_NO_RESOURCE; osi_mutex_unlock(&l2cap_local_param.l2cap_slot_mutex); @@ -850,7 +888,7 @@ void btc_l2cap_cb_handler(btc_msg_t *msg) break; } if (osi_alarm_set(slot->close_alarm, VFS_CLOSE_TIMEOUT) != OSI_ALARM_ERR_PASS) { - free(p_arg); + osi_free(p_arg); slot->alarm_arg = NULL; osi_alarm_free(slot->close_alarm); param.close.status = ESP_BT_L2CAP_BUSY; @@ -906,7 +944,6 @@ void btc_l2cap_cb_handler(btc_msg_t *msg) fixed_queue_enqueue(slot->rx.queue, p_data_buf, FIXED_QUEUE_MAX_TIMEOUT); } else { osi_free(p_data_buf); - break; } } osi_mutex_unlock(&l2cap_local_param.l2cap_slot_mutex); @@ -945,12 +982,11 @@ void btc_l2cap_cb_handler(btc_msg_t *msg) break; // to do disconnect } memset(p_data_buf, 0, count + sizeof(BT_HDR)); - p_data_buf->len = BTA_JvL2capRead(p_data->data_ind.handle, slot->id, p_data_buf->data, count); + p_data_buf->len = BTA_JvL2capRead(p_data->l2c_read.handle, slot->id, p_data_buf->data, count); if (p_data_buf->len > 0) { fixed_queue_enqueue(slot->rx.queue, p_data_buf, FIXED_QUEUE_MAX_TIMEOUT); } else { osi_free(p_data_buf); - break; } } osi_mutex_unlock(&l2cap_local_param.l2cap_slot_mutex); @@ -1060,7 +1096,7 @@ static ssize_t l2cap_vfs_write(int fd, const void * data, size_t size) if (!enqueue_status) { BTC_TRACE_DEBUG("%s tx_len:%d, fd:%d\n", __func__, fixed_queue_length(slot->tx.queue), fd); osi_mutex_unlock(&l2cap_local_param.l2cap_slot_mutex); - //block untill under water level, be closed or time out + //block until under water level, be closed or time out tx_event_group_val = xEventGroupWaitBits(l2cap_local_param.tx_event_group, SLOT_WRITE_BIT(serial) | SLOT_CLOSE_BIT(serial), pdTRUE, pdFALSE, VFS_WRITE_TIMEOUT / portTICK_PERIOD_MS); @@ -1201,14 +1237,14 @@ static ssize_t l2cap_vfs_read(int fd, void * dst, size_t size) return item_size; } -esp_err_t btc_l2cap_vfs_register(void) +static void btc_l2cap_vfs_register(void) { - esp_err_t ret = ESP_OK; + esp_bt_l2cap_status_t ret = ESP_BT_L2CAP_SUCCESS; do { if (!is_l2cap_init()) { BTC_TRACE_ERROR("%s L2CAP have not been init\n", __func__); - ret = ESP_FAIL; + ret = ESP_BT_L2CAP_NEED_INIT; break; } @@ -1225,33 +1261,54 @@ esp_err_t btc_l2cap_vfs_register(void) // No FD range is registered here: l2cap_vfs_id is used to register/unregister // file descriptors if (esp_vfs_register_with_id(&vfs, NULL, &l2cap_local_param.l2cap_vfs_id) != ESP_OK) { - ret = ESP_FAIL; + ret = ESP_BT_L2CAP_FAILURE; break; } } while (0); - return ret; + esp_bt_l2cap_cb_param_t param = {0}; + param.vfs_register.status = ret; + btc_l2cap_cb_to_app(ESP_BT_L2CAP_VFS_REGISTER_EVT, ¶m); } -esp_err_t btc_l2cap_vfs_unregister(void) +static void btc_l2cap_vfs_unregister(void) { - esp_err_t ret = ESP_OK; + esp_bt_l2cap_status_t ret = ESP_BT_L2CAP_SUCCESS; + do { if (!is_l2cap_init()) { BTC_TRACE_ERROR("%s L2CAP have not been init\n", __func__); - ret = ESP_FAIL; + ret = ESP_BT_L2CAP_NEED_INIT; break; } if (l2cap_local_param.l2cap_vfs_id != -1) { if (esp_vfs_unregister_with_id(l2cap_local_param.l2cap_vfs_id) != ESP_OK) { - ret = ESP_FAIL; + ret = ESP_BT_L2CAP_FAILURE; } } l2cap_local_param.l2cap_vfs_id = -1; } while (0); - return ret; + esp_bt_l2cap_cb_param_t param = {0}; + param.vfs_unregister.status = ret; + btc_l2cap_cb_to_app(ESP_BT_L2CAP_VFS_UNREGISTER_EVT, ¶m); +} + +void btc_l2cap_get_protocol_status(esp_bt_l2cap_protocol_status_t *param) +{ + if (is_l2cap_init()) { + param->l2cap_inited = true; + osi_mutex_lock(&l2cap_local_param.l2cap_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); + for (size_t i = 1; i <= BTA_JV_MAX_L2C_CONN; i++) { + if (l2cap_local_param.l2cap_slots[i] != NULL && l2cap_local_param.l2cap_slots[i]->connected) { + param->conn_num++; + } + } + osi_mutex_unlock(&l2cap_local_param.l2cap_slot_mutex); + } else { + param->l2cap_inited = false; + } } #endif ///defined BTC_L2CAP_INCLUDED && BTC_L2CAP_INCLUDED == TRUE diff --git a/lib/bt/host/bluedroid/btc/profile/std/pba/btc_pba_client.c b/lib/bt/host/bluedroid/btc/profile/std/pba/btc_pba_client.c new file mode 100644 index 00000000..ede18df3 --- /dev/null +++ b/lib/bt/host/bluedroid/btc/profile/std/pba/btc_pba_client.c @@ -0,0 +1,968 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "osi/allocator.h" + +#include "bta/bta_api.h" +#include "bta/bta_pba_defs.h" +#include "bta/bta_pba_client_api.h" +#include "btc/btc_profile_queue.h" +#include "btc/btc_manage.h" +#include "btc/btc_task.h" +#include "btc_pba_client.h" +#include "esp_pbac_api.h" + +#if BTC_PBA_CLIENT_INCLUDED + +#define BTC_PBA_CLIENT_SECURITY (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT) + +static bool s_btc_pba_client_init = 0; + +btc_pba_client_cb_t btc_pba_client_cb; + +static void bte_pba_client_evt(tBTA_PBA_CLIENT_EVT event, tBTA_PBA_CLIENT *p_data) +{ + bt_status_t status; + int param_len = 0; + bool ignore = false; + + switch (event) { + case BTA_PBA_CLIENT_CONN_OPEN_EVT: + case BTA_PBA_CLIENT_CONN_CLOSE_EVT: + param_len = sizeof(tBTA_PBA_CLIENT_CONN); + break; + case BTA_PBA_CLIENT_PULL_PHONE_BOOK_RSP_EVT: + case BTA_PBA_CLIENT_SET_PHONE_BOOK_RSP_EVT: + case BTA_PBA_CLIENT_PULL_VCARD_LISTING_RSP_EVT: + case BTA_PBA_CLIENT_PULL_VCARD_ENTRY_RSP_EVT: + param_len = sizeof(tBTA_PBA_CLIENT_RESPONSE); + break; + case BTA_PBA_CLIENT_REGISTER_EVT: + param_len = 0; + break; + case BTA_PBA_CLIENT_DISABLE_EVT: + param_len = 0; + break; + case BTA_PBA_CLIENT_ENABLE_EVT: + case BTA_PBA_CLIENT_DEREGISTER_EVT: + default: + ignore = true; + break; + } + + if (ignore) { + return; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_PBA_CLIENT; + msg.act = event; + + status = btc_transfer_context(&msg, p_data, param_len, NULL, NULL); + if (status != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("context transfer failed"); + } +} + +static void btc_pba_client_callback_to_app(esp_pbac_event_t event, esp_pbac_param_t *param) +{ + esp_pbac_callback_t callback = (esp_pbac_callback_t)btc_profile_cb_get(BTC_PID_PBA_CLIENT); + if (callback) { + callback(event, param); + } +} + +static void btc_pba_client_init(void) +{ + if (!s_btc_pba_client_init) { + s_btc_pba_client_init = true; + memset(&btc_pba_client_cb, 0, sizeof(btc_pba_client_cb_t)); + /* enable pba client */ + BTA_PbaClientEnable(bte_pba_client_evt); + /* register sdp record */ + BTA_PbaClientRegister("Phonebook Access PCE"); + } +} + +static void btc_pba_client_deinit(void) +{ + if (s_btc_pba_client_init) { + s_btc_pba_client_init = false; + /* deregister sdp record */ + BTA_PbaClientDeregister(); + /* disable pba client */ + BTA_PbaClientDisable(); + } +} + +static BOOLEAN is_connected(bt_bdaddr_t *bd_addr) +{ + for (int i = 0; i < BTC_PBA_CLIENT_MAX_CONN_NUM; ++i) { + if (btc_pba_client_cb.ccb[i].handle != 0 && bdcmp(bd_addr->address, btc_pba_client_cb.ccb[i].bd_addr.address) == 0) { + return TRUE; + } + } + + return FALSE; +} + +static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid) +{ + if (is_connected(bd_addr)) { + return BT_STATUS_BUSY; + } + + BTA_PbaClientOpen(bd_addr->address, BTC_PBA_CLIENT_SECURITY, (uint32_t)BTC_PBA_SUPPORTED_FEAT, (uint16_t)BTC_PBA_PREFERRED_MTU); + + return BT_STATUS_SUCCESS; +} + +static void btc_pba_client_connect(bt_bdaddr_t *bd_addr) +{ + if (!s_btc_pba_client_init) { + return; + } + + btc_queue_connect(UUID_SERVCLASS_PBAP_PCE, bd_addr, connect_int); +} + +static void btc_pba_client_disconnect(uint16_t handle) +{ + do { + if (!s_btc_pba_client_init) { + break; + } + + if (handle == 0 || handle > BTC_PBA_CLIENT_MAX_CONN_NUM) { + /* invalid handle value */ + break; + } + + btc_pba_client_ccb_t *p_ccb = &btc_pba_client_cb.ccb[handle - 1]; + if (p_ccb->handle != handle) { + /* not connect */ + break; + } + + BTA_PbaClientClose(handle); + } while (0); +} + +static bool btc_pba_client_pull_phone_book(uint16_t handle, char *name, bool include_app_param, esp_pbac_pull_phone_book_app_param_t *app_param) +{ + bt_status_t err = BT_STATUS_FAIL; + uint8_t *app_param_buff = NULL; + uint16_t app_param_len = 0; + + do { + if (!s_btc_pba_client_init) { + /* pba client not init */ + err = BT_STATUS_NOT_READY; + break; + } + + if (handle == 0 || handle > BTC_PBA_CLIENT_MAX_CONN_NUM) { + /* invalid handle value */ + err = BT_STATUS_PARM_INVALID; + break; + } + + btc_pba_client_ccb_t *p_ccb = &btc_pba_client_cb.ccb[handle - 1]; + if (p_ccb->handle != handle) { + /* not connect */ + err = BT_STATUS_PARM_INVALID; + break; + } + + if (p_ccb->busy) { + /* busy */ + err = BT_STATUS_BUSY; + break; + } + + if (include_app_param) { + app_param_buff = osi_malloc(BTA_PBAP_PULL_PHONE_BOOK_APP_PARAM_BUFF_SIZE_MIN); + if (app_param_buff == NULL) { + err = BT_STATUS_NOMEM; + break; + } + uint8_t *p = app_param_buff; + if (app_param->include_property_selector) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_PROPERTY_SELECTOR); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_PROPERTY_SELECTOR); + UINT64_TO_BE_STREAM(p, app_param->property_selector); + } + if (app_param->include_format) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_FORMAT); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_FORMAT); + UINT8_TO_BE_STREAM(p, app_param->format); + } + if (app_param->include_max_list_count) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_MAX_LIST_COUNT); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_MAX_LIST_COUNT); + UINT16_TO_BE_STREAM(p, app_param->max_list_count); + } + if (app_param->include_list_start_offset) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LIST_START_OFFSET); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_LIST_START_OFFSET); + UINT16_TO_BE_STREAM(p, app_param->list_start_offset); + } + if (app_param->include_reset_new_missed_calls) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_RESET_NEW_MISSED_CALLS); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_RESET_NEW_MISSED_CALLS); + UINT8_TO_BE_STREAM(p, app_param->reset_new_missed_calls); + } + if (app_param->include_vcard_selector) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_VCARD_SELECTOR); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_VCARD_SELECTOR); + UINT64_TO_BE_STREAM(p, app_param->vcard_selector); + } + if (app_param->include_vcard_selector_operator) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_VCARD_SELECTOR_OPERATOR); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_VCARD_SELECTOR_OPERATOR); + UINT8_TO_BE_STREAM(p, app_param->vcard_selector_operator); + } + app_param_len = p - app_param_buff; + assert(app_param_len <= BTA_PBAP_PULL_PHONE_BOOK_APP_PARAM_BUFF_SIZE_MIN); + if (app_param_len == 0) { + /* user give us an empty app param, allow but not recommend */ + osi_free(app_param_buff); + app_param_buff = NULL; + } + } + + p_ccb->busy = true; + BTA_PbaClientPullPhoneBook(handle, name, app_param_buff, app_param_len); + err = BT_STATUS_SUCCESS; + } while (0); + + if (err != BT_STATUS_SUCCESS) { + BTC_TRACE_WARNING("%s failed, handle: %d, reason: %d", __FUNCTION__, handle, err); + return false; + } + + return true; +} + +static bool btc_pba_client_set_phone_book(uint16_t handle, uint8_t flags, char *name) +{ + bt_status_t err = BT_STATUS_FAIL; + + do { + if (!s_btc_pba_client_init) { + /* pba client not init */ + err = BT_STATUS_NOT_READY; + break; + } + + if (handle == 0 || handle > BTC_PBA_CLIENT_MAX_CONN_NUM) { + /* invalid handle value */ + err = BT_STATUS_PARM_INVALID; + break; + } + + btc_pba_client_ccb_t *p_ccb = &btc_pba_client_cb.ccb[handle - 1]; + if (p_ccb->handle != handle) { + /* not connect */ + err = BT_STATUS_PARM_INVALID; + break; + } + + if (p_ccb->busy) { + /* busy */ + err = BT_STATUS_BUSY; + break; + } + + p_ccb->busy = true; + BTA_PbaClientSetPhoneBook(handle, flags, (char *)name); + err = BT_STATUS_SUCCESS; + } while (0); + + if (err != BT_STATUS_SUCCESS) { + BTC_TRACE_WARNING("%s failed, handle: %d, reason: %d", __FUNCTION__, handle, err); + return false; + } + + return true; +} + +static bool btc_pba_client_set_phone_book2(uint16_t handle, char *path) +{ + bt_status_t err = BT_STATUS_FAIL; + + do { + if (!s_btc_pba_client_init) { + /* pba client not init */ + err = BT_STATUS_NOT_READY; + break; + } + + if (handle == 0 || handle > BTC_PBA_CLIENT_MAX_CONN_NUM) { + /* invalid handle value */ + err = BT_STATUS_PARM_INVALID; + break; + } + + btc_pba_client_ccb_t *p_ccb = &btc_pba_client_cb.ccb[handle - 1]; + if (p_ccb->handle != handle) { + /* not connect */ + err = BT_STATUS_PARM_INVALID; + break; + } + + if (p_ccb->busy) { + /* busy */ + err = BT_STATUS_BUSY; + break; + } + + p_ccb->busy = true; + if (path != NULL) { + p_ccb->path_len = strlen(path) + 1; + /* ignore the first slash */ + if (path[0] == '/') { + p_ccb->path_pos = 1; + } + else { + p_ccb->path_pos = 0; + } + /* since we use absolute path, treat empty path as go to ROOT */ + if (p_ccb->path_len == p_ccb->path_pos + 1) { + p_ccb->path_len = 0; + p_ccb->path_pos = 0; + osi_free(path); + path = NULL; + } + else { + p_ccb->path = path; + } + } + /* anyway, go to ROOT first */ + char *empty_name = osi_malloc(1); + assert(empty_name != NULL); + *empty_name = '\0'; + BTA_PbaClientSetPhoneBook(handle, ESP_PBAC_SET_PHONE_BOOK_FLAGS_ROOT, empty_name); + err = BT_STATUS_SUCCESS; + } while (0); + + if (err != BT_STATUS_SUCCESS) { + BTC_TRACE_WARNING("%s failed, handle: %d, reason: %d", __FUNCTION__, handle, err); + return false; + } + + return true; +} + +static bool btc_pba_client_pull_vcard_listing(uint16_t handle, char *name, bool include_app_param, esp_pbac_pull_vcard_listing_app_param_t *app_param) +{ + bt_status_t err = BT_STATUS_FAIL; + uint8_t *app_param_buff = NULL; + uint16_t app_param_len = 0; + + do { + if (!s_btc_pba_client_init) { + /* pba client not init */ + err = BT_STATUS_NOT_READY; + break; + } + + if (handle == 0 || handle > BTC_PBA_CLIENT_MAX_CONN_NUM) { + /* invalid handle value */ + err = BT_STATUS_PARM_INVALID; + break; + } + + btc_pba_client_ccb_t *p_ccb = &btc_pba_client_cb.ccb[handle - 1]; + if (p_ccb->handle != handle) { + /* not connect */ + err = BT_STATUS_PARM_INVALID; + break; + } + + if (p_ccb->busy) { + /* busy */ + err = BT_STATUS_BUSY; + break; + } + + if (include_app_param) { + uint8_t search_value_len = 0; + if (app_param->include_search_value) { + search_value_len = strlen(app_param->search_value) + 1; + } + app_param_buff = osi_malloc(BTA_PBAP_PULL_VCARD_LISTING_APP_PARAM_BUFF_SIZE_MIN + search_value_len); + if (app_param_buff == NULL) { + err = BT_STATUS_NOMEM; + break; + } + + uint8_t *p = app_param_buff; + if (app_param->include_order) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_ORDER); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_ORDER); + UINT8_TO_BE_STREAM(p, app_param->order); + } + if (app_param->include_search_value) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_SEARCH_VALUE); + UINT8_TO_BE_STREAM(p, search_value_len); + memcpy(p, app_param->search_value, search_value_len); + p += search_value_len; + } + if (app_param->include_search_property) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_SEARCH_PROPERTY); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_SEARCH_PROPERTY); + UINT8_TO_BE_STREAM(p, app_param->search_property); + } + if (app_param->include_max_list_count) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_MAX_LIST_COUNT); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_MAX_LIST_COUNT); + UINT16_TO_BE_STREAM(p, app_param->max_list_count); + } + if (app_param->include_list_start_offset) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LIST_START_OFFSET); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_LIST_START_OFFSET); + UINT16_TO_BE_STREAM(p, app_param->list_start_offset); + } + if (app_param->include_reset_new_missed_calls) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_RESET_NEW_MISSED_CALLS); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_RESET_NEW_MISSED_CALLS); + UINT8_TO_BE_STREAM(p, app_param->reset_new_missed_calls); + } + if (app_param->include_vcard_selector) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_VCARD_SELECTOR); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_VCARD_SELECTOR); + UINT64_TO_BE_STREAM(p, app_param->vcard_selector); + } + if (app_param->include_vcard_selector_operator) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_VCARD_SELECTOR_OPERATOR); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_VCARD_SELECTOR_OPERATOR); + UINT8_TO_BE_STREAM(p, app_param->vcard_selector_operator); + } + app_param_len = p - app_param_buff; + assert(app_param_len <= BTA_PBAP_PULL_VCARD_LISTING_APP_PARAM_BUFF_SIZE_MIN + search_value_len); + if (app_param_len == 0) { + /* user give us an empty app param, allow but not recommend */ + osi_free(app_param_buff); + app_param_buff = NULL; + } + /* free search_value (allocated by deep_copy) */ + if (app_param->include_search_value && app_param->search_value) { + osi_free(app_param->search_value); + app_param->search_value = NULL; + } + } + + p_ccb->busy = true; + BTA_PbaClientPullvCardListing(handle, (char *)name, app_param_buff, app_param_len); + err = BT_STATUS_SUCCESS; + } while (0); + + if (err != BT_STATUS_SUCCESS) { + BTC_TRACE_WARNING("%s failed, handle: %d, reason: %d", __FUNCTION__, handle, err); + return false; + } + + return true; +} + +static bool btc_pba_client_pull_vcard_entry(uint16_t handle, char *name, bool include_app_param, esp_pbac_pull_vcard_entry_app_param_t *app_param) +{ + bt_status_t err = BT_STATUS_FAIL; + uint8_t *app_param_buff = NULL; + uint16_t app_param_len = 0; + + do { + if (!s_btc_pba_client_init) { + /* pba client not init */ + err = BT_STATUS_NOT_READY; + break; + } + + if (handle == 0 || handle > BTC_PBA_CLIENT_MAX_CONN_NUM) { + /* invalid handle value */ + err = BT_STATUS_PARM_INVALID; + break; + } + + btc_pba_client_ccb_t *p_ccb = &btc_pba_client_cb.ccb[handle - 1]; + if (p_ccb->handle != handle) { + /* not connect */ + err = BT_STATUS_PARM_INVALID; + break; + } + + if (p_ccb->busy) { + /* busy */ + err = BT_STATUS_BUSY; + break; + } + + if (include_app_param) { + app_param_buff = osi_malloc(BTA_PBAP_PULL_VCARD_ENTRY_APP_PARAM_BUFF_SIZE_MIN); + if (app_param_buff == NULL) { + err = BT_STATUS_NOMEM; + break; + } + uint8_t *p = app_param_buff; + if (app_param->include_property_selector) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_PROPERTY_SELECTOR); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_PROPERTY_SELECTOR); + UINT64_TO_BE_STREAM(p, app_param->property_selector); + } + if (app_param->include_format) { + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_FORMAT); + UINT8_TO_BE_STREAM(p, BTA_PBAP_APP_PARAM_LENGTH_FORMAT); + UINT8_TO_BE_STREAM(p, app_param->format); + } + app_param_len = p - app_param_buff; + assert(app_param_len <= BTA_PBAP_PULL_VCARD_ENTRY_APP_PARAM_BUFF_SIZE_MIN); + if (app_param_len == 0) { + /* user give us an empty app param, allow but not recommend */ + osi_free(app_param_buff); + app_param_buff = NULL; + } + } + + p_ccb->busy = true; + BTA_PbaClientPullvCardEntry(handle, (char *)name, app_param_buff, app_param_len); + err = BT_STATUS_SUCCESS; + } while (0); + + if (err != BT_STATUS_SUCCESS) { + BTC_TRACE_WARNING("%s failed, handle: %d, reason: %d", __FUNCTION__, handle, err); + return false; + } + + return true; +} + +void btc_pba_client_args_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + btc_pba_client_args_t *dst = (btc_pba_client_args_t *)p_dest; + btc_pba_client_args_t *src = (btc_pba_client_args_t *)p_src; + size_t len; + + switch (msg->act) { + case BTC_PBA_CLIENT_PULL_PHONE_BOOK_EVT: + len = strlen(src->pull_phone_book.name) + 1; + dst->pull_phone_book.name = (char *)osi_malloc(len); + if (dst->pull_phone_book.name) { + memcpy(dst->pull_phone_book.name, src->pull_phone_book.name, len); + } else { + BTC_TRACE_ERROR("%s %d no mem\n", __FUNCTION__, msg->act); + } + break; + case BTC_PBA_CLIENT_PULL_VCARD_LISTING_EVT: + len = strlen(src->pull_vcard_listing.name) + 1; + dst->pull_vcard_listing.name = (char *)osi_malloc(len); + if (dst->pull_vcard_listing.name) { + memcpy(dst->pull_vcard_listing.name, src->pull_vcard_listing.name, len); + } else { + BTC_TRACE_ERROR("%s %d no mem\n", __FUNCTION__, msg->act); + } + if (src->pull_vcard_listing.include_app_param && src->pull_vcard_listing.app_param.include_search_value) { + len = strlen(src->pull_vcard_listing.app_param.search_value) + 1; + dst->pull_vcard_listing.app_param.search_value = (char *)osi_malloc(len); + if (dst->pull_vcard_listing.app_param.search_value) { + memcpy(dst->pull_vcard_listing.app_param.search_value, src->pull_vcard_listing.app_param.search_value, len); + } else { + BTC_TRACE_ERROR("%s %d no mem\n", __FUNCTION__, msg->act); + } + } + break; + case BTC_PBA_CLIENT_PULL_VCARD_ENTRY_EVT: + len = strlen(src->pull_vcard_entry.name) + 1; + dst->pull_vcard_entry.name = (char *)osi_malloc(len); + if (dst->pull_vcard_entry.name) { + memcpy(dst->pull_vcard_entry.name, src->pull_vcard_entry.name, len); + } else { + BTC_TRACE_ERROR("%s %d no mem\n", __FUNCTION__, msg->act); + } + break; + case BTC_PBA_CLIENT_SET_PHONE_BOOK_EVT: + case BTC_PBA_CLIENT_SET_PHONE_BOOK2_EVT: + /* set phone book name may be NULL */ + if (src->set_phone_book.name) { + len = strlen(src->set_phone_book.name) + 1; + dst->set_phone_book.name = (char *)osi_malloc(len); + if (dst->set_phone_book.name) { + memcpy(dst->set_phone_book.name, src->set_phone_book.name, len); + } else { + BTC_TRACE_ERROR("%s %d no mem\n", __FUNCTION__, msg->act); + } + } + break; + default: + BTC_TRACE_DEBUG("%s Unhandled deep copy %d\n", __FUNCTION__, msg->act); + UNUSED(dst); + UNUSED(src); + UNUSED(len); + break; + } +} + +void btc_pba_client_args_deep_free(btc_msg_t *msg) +{ + btc_pba_client_args_t *arg = (btc_pba_client_args_t *)msg->arg; + + switch (msg->act) { + case BTC_PBA_CLIENT_PULL_PHONE_BOOK_EVT: + if (arg->pull_phone_book.name) { + osi_free(arg->pull_phone_book.name); + } + break; + case BTC_PBA_CLIENT_PULL_VCARD_LISTING_EVT: + if (arg->pull_vcard_listing.name) { + osi_free(arg->pull_vcard_listing.name); + } + if (arg->pull_vcard_listing.include_app_param + && arg->pull_vcard_listing.app_param.include_search_value + && arg->pull_vcard_listing.app_param.search_value) { + osi_free(arg->pull_vcard_listing.app_param.search_value); + } + break; + case BTC_PBA_CLIENT_PULL_VCARD_ENTRY_EVT: + if (arg->pull_vcard_entry.name) { + osi_free(arg->pull_vcard_entry.name); + } + break; + case BTC_PBA_CLIENT_SET_PHONE_BOOK_EVT: + case BTC_PBA_CLIENT_SET_PHONE_BOOK2_EVT: + if (arg->set_phone_book.name) { + osi_free(arg->set_phone_book.name); + } + break; + default: + BTC_TRACE_DEBUG("%s Unhandled deep free %d\n", __FUNCTION__, msg->act); + UNUSED(arg); + break; + } +} + +void btc_pba_client_call_handler(btc_msg_t *msg) +{ + bool ret = true; + btc_pba_client_args_t *arg = (btc_pba_client_args_t *)(msg->arg); + switch (msg->act) { + case BTC_PBA_CLIENT_INIT_EVT: + btc_pba_client_init(); + break; + case BTC_PBA_CLIENT_DEINIT_EVT: + btc_pba_client_deinit(); + break; + case BTC_PBA_CLIENT_CONNECT_EVT: + btc_pba_client_connect(&arg->connect.bd_addr); + break; + case BTC_PBA_CLIENT_DISCONNECT_EVT: + btc_pba_client_disconnect(arg->disconnect.handle); + break; + case BTC_PBA_CLIENT_PULL_PHONE_BOOK_EVT: + ret = btc_pba_client_pull_phone_book(arg->pull_phone_book.handle, arg->pull_phone_book.name, arg->pull_phone_book.include_app_param, &arg->pull_phone_book.app_param); + break; + case BTC_PBA_CLIENT_SET_PHONE_BOOK_EVT: + ret = btc_pba_client_set_phone_book(arg->set_phone_book.handle, arg->set_phone_book.flags, arg->set_phone_book.name); + break; + case BTC_PBA_CLIENT_SET_PHONE_BOOK2_EVT: + ret = btc_pba_client_set_phone_book2(arg->set_phone_book.handle, arg->set_phone_book.name); + break; + case BTC_PBA_CLIENT_PULL_VCARD_LISTING_EVT: + ret = btc_pba_client_pull_vcard_listing(arg->pull_vcard_listing.handle, arg->pull_vcard_listing.name, arg->pull_vcard_listing.include_app_param, &arg->pull_vcard_listing.app_param); + break; + case BTC_PBA_CLIENT_PULL_VCARD_ENTRY_EVT: + ret = btc_pba_client_pull_vcard_entry(arg->pull_vcard_entry.handle, arg->pull_vcard_entry.name, arg->pull_vcard_entry.include_app_param, &arg->pull_vcard_entry.app_param); + break; + default: + BTC_TRACE_WARNING("unknown pba client action %i", msg->act); + break; + } + + if (!ret) { + /* operation failed, do deep free */ + btc_pba_client_args_deep_free(msg); + } +} + +static void parse_pull_phone_book_app_param(esp_pbac_param_t *param, uint8_t *app_param, uint16_t app_param_len) +{ + if (app_param == NULL || app_param_len == 0) { + return; + } + uint8_t *ptr = app_param; + while(ptr < app_param + app_param_len) { + switch (*ptr) + { + case BTA_PBAP_APP_PARAM_PHONE_BOOK_SIZE: + param->pull_phone_book_rsp.include_phone_book_size = 1; + ptr += BTA_PBAP_APP_PARAM_HEADER_LENGTH; + BE_STREAM_TO_UINT16(param->pull_phone_book_rsp.phone_book_size, ptr); + break; + case BTA_PBAP_APP_PARAM_NEW_MISSED_CALLS: + param->pull_phone_book_rsp.include_new_missed_calls = 1; + ptr += BTA_PBAP_APP_PARAM_HEADER_LENGTH; + BE_STREAM_TO_UINT8(param->pull_phone_book_rsp.new_missed_calls, ptr); + break; + case BTA_PBAP_APP_PARAM_PRIMARY_FOLDER_VERSION: + param->pull_phone_book_rsp.include_primary_folder_version = 1; + ptr += BTA_PBAP_APP_PARAM_HEADER_LENGTH; + /* don't copy */ + param->pull_phone_book_rsp.primary_folder_version = ptr; + ptr += BTA_PBAP_APP_PARAM_LENGTH_PRIMARY_FOLDER_VERSION; + break; + case BTA_PBAP_APP_PARAM_SECONDARY_FOLDER_VERSION: + param->pull_phone_book_rsp.include_secondary_folder_version = 1; + ptr += BTA_PBAP_APP_PARAM_HEADER_LENGTH; + /* don't copy */ + param->pull_phone_book_rsp.secondary_folder_version = ptr; + ptr += BTA_PBAP_APP_PARAM_LENGTH_SECONDARY_FOLDER_VERSION; + break; + case BTA_PBAP_APP_PARAM_DATABASE_IDENTIFIER: + param->pull_phone_book_rsp.include_database_identifier = 1; + ptr += BTA_PBAP_APP_PARAM_HEADER_LENGTH; + /* don't copy */ + param->pull_phone_book_rsp.database_identifier = ptr; + ptr += BTA_PBAP_APP_PARAM_LENGTH_DATABASE_IDENTIFIER; + break; + default: + goto error; + break; + } + } +error: + return; +} + +static void parse_pull_vcard_listing_app_param(esp_pbac_param_t *param, uint8_t *app_param, uint16_t app_param_len) +{ + if (app_param == NULL || app_param_len == 0) { + return; + } + uint8_t *ptr = app_param; + while(ptr < app_param + app_param_len) { + switch (*ptr) + { + case BTA_PBAP_APP_PARAM_PHONE_BOOK_SIZE: + param->pull_vcard_listing_rsp.include_phone_book_size = 1; + ptr += BTA_PBAP_APP_PARAM_HEADER_LENGTH; + BE_STREAM_TO_UINT16(param->pull_vcard_listing_rsp.phone_book_size, ptr); + break; + case BTA_PBAP_APP_PARAM_NEW_MISSED_CALLS: + param->pull_vcard_listing_rsp.include_new_missed_calls = 1; + ptr += BTA_PBAP_APP_PARAM_HEADER_LENGTH; + BE_STREAM_TO_UINT8(param->pull_vcard_listing_rsp.new_missed_calls, ptr); + break; + case BTA_PBAP_APP_PARAM_PRIMARY_FOLDER_VERSION: + param->pull_vcard_listing_rsp.include_primary_folder_version = 1; + ptr += BTA_PBAP_APP_PARAM_HEADER_LENGTH; + /* don't copy */ + param->pull_vcard_listing_rsp.primary_folder_version = ptr; + ptr += BTA_PBAP_APP_PARAM_LENGTH_PRIMARY_FOLDER_VERSION; + break; + case BTA_PBAP_APP_PARAM_SECONDARY_FOLDER_VERSION: + param->pull_vcard_listing_rsp.include_secondary_folder_version = 1; + ptr += BTA_PBAP_APP_PARAM_HEADER_LENGTH; + /* don't copy */ + param->pull_vcard_listing_rsp.secondary_folder_version = ptr; + ptr += BTA_PBAP_APP_PARAM_LENGTH_SECONDARY_FOLDER_VERSION; + break; + case BTA_PBAP_APP_PARAM_DATABASE_IDENTIFIER: + param->pull_vcard_listing_rsp.include_database_identifier = 1; + ptr += BTA_PBAP_APP_PARAM_HEADER_LENGTH; + /* don't copy */ + param->pull_vcard_listing_rsp.database_identifier = ptr; + ptr += BTA_PBAP_APP_PARAM_LENGTH_DATABASE_IDENTIFIER; + break; + default: + goto error; + break; + } + } +error: + return; +} + +static void parse_pull_vcard_entry_app_param(esp_pbac_param_t *param, uint8_t *app_param, uint16_t app_param_len) +{ + if (app_param == NULL || app_param_len == 0) { + return; + } + uint8_t *ptr = app_param; + while(ptr < app_param + app_param_len) { + switch (*ptr) + { + case BTA_PBAP_APP_PARAM_DATABASE_IDENTIFIER: + param->pull_vcard_entry_rsp.include_database_identifier = 1; + ptr += BTA_PBAP_APP_PARAM_HEADER_LENGTH; + /* don't copy */ + param->pull_vcard_entry_rsp.database_identifier = ptr; + ptr += BTA_PBAP_APP_PARAM_LENGTH_DATABASE_IDENTIFIER; + break; + default: + goto error; + break; + } + } +error: + return; +} + +static uint16_t get_next_dir_len_from_path(char *path, uint16_t path_len, uint16_t path_pos) +{ + uint16_t ret = 0; + for (int i = path_pos; i < path_len; ++i) { + if (path[i] == '/' || path[i] == '\0') { + break; + } + else { + ++ret; + } + } + return ret; +} + +void btc_pba_client_cb_handler(btc_msg_t *msg) +{ + uint16_t event = msg->act; + tBTA_PBA_CLIENT *p_data = (tBTA_PBA_CLIENT *)msg->arg; + btc_pba_client_ccb_t *p_ccb = NULL; + esp_pbac_param_t param = {0}; + + switch (event) { + case BTA_PBA_CLIENT_CONN_OPEN_EVT: + if (p_data->conn.error == BTA_PBA_CLIENT_NO_ERROR) { + /* allocate ccb */ + p_ccb = &btc_pba_client_cb.ccb[p_data->conn.handle - 1]; + p_ccb->handle = p_data->conn.handle; + bdcpy(p_ccb->bd_addr.address, p_data->conn.bd_addr); + p_ccb->busy = false; + param.conn_stat.connected = true; + param.conn_stat.peer_supported_repo = p_data->conn.peer_supported_repo; + param.conn_stat.peer_supported_feat = p_data->conn.peer_supported_feat; + param.conn_stat.reason = BTA_PBA_CLIENT_NO_ERROR; + } + else { + param.conn_stat.connected = false; + /* error codes are compatible */ + param.conn_stat.reason = p_data->conn.error; + } + bdcpy(param.conn_stat.remote_bda, p_data->conn.bd_addr); + param.conn_stat.handle = p_data->conn.handle; + btc_pba_client_callback_to_app(ESP_PBAC_CONNECTION_STATE_EVT, ¶m); + btc_queue_advance(); + break; + case BTA_PBA_CLIENT_CONN_CLOSE_EVT: + if (p_data->conn.handle != 0) { + /* clear ccb */ + p_ccb = &btc_pba_client_cb.ccb[p_data->conn.handle - 1]; + if (p_ccb->path) { + osi_free(p_ccb->path); + } + memset(p_ccb, 0, sizeof(btc_pba_client_ccb_t)); + } + param.conn_stat.connected = false; + bdcpy(param.conn_stat.remote_bda, p_data->conn.bd_addr); + param.conn_stat.handle = p_data->conn.handle; + /* error codes are compatible */ + param.conn_stat.reason = p_data->conn.error; + btc_pba_client_callback_to_app(ESP_PBAC_CONNECTION_STATE_EVT, ¶m); + btc_queue_advance(); + break; + case BTA_PBA_CLIENT_PULL_PHONE_BOOK_RSP_EVT: + if (p_data->response.final) { + p_ccb = &btc_pba_client_cb.ccb[p_data->response.handle - 1]; + p_ccb->busy = false; + } + param.pull_phone_book_rsp.handle = p_data->response.handle; + param.pull_phone_book_rsp.final = p_data->response.final; + param.pull_phone_book_rsp.result = p_data->response.status; + param.pull_phone_book_rsp.data = p_data->response.data; + param.pull_phone_book_rsp.data_len = p_data->response.data_len; + parse_pull_phone_book_app_param(¶m, p_data->response.app_param, p_data->response.app_param_len); + btc_pba_client_callback_to_app(ESP_PBAC_PULL_PHONE_BOOK_RESPONSE_EVT, ¶m); + if (p_data->response.pkt != NULL) { + osi_free(p_data->response.pkt); + } + break; + case BTA_PBA_CLIENT_SET_PHONE_BOOK_RSP_EVT: + p_ccb = &btc_pba_client_cb.ccb[p_data->response.handle - 1]; + if (p_data->response.status == BTA_PBA_CLIENT_NO_ERROR && p_ccb->path_pos < p_ccb->path_len) { + /* since path_len is not zero, path should not be NULL, use asset to check */ + assert(p_ccb->path != NULL); + uint16_t dir_name_len = get_next_dir_len_from_path(p_ccb->path, p_ccb->path_len, p_ccb->path_pos); + if (dir_name_len > 0) { + char *dir_name = osi_malloc(dir_name_len + 1); + assert(dir_name != NULL); + memcpy(dir_name, p_ccb->path + p_ccb->path_pos, dir_name_len); + dir_name[dir_name_len] = '\0'; + p_ccb->path_pos += dir_name_len + 1; + BTA_PbaClientSetPhoneBook(p_data->response.handle, ESP_PBAC_SET_PHONE_BOOK_FLAGS_DOWN, dir_name); + /* break here, don't report event to upper */ + break; + } + } + /* set path done or failed, clear status */ + p_ccb->path_len = 0; + p_ccb->path_pos = 0; + if (p_ccb->path) { + osi_free(p_ccb->path); + p_ccb->path = NULL; + } + p_ccb->busy = false; + param.set_phone_book_rsp.handle = p_data->response.handle; + param.set_phone_book_rsp.result = p_data->response.status; + btc_pba_client_callback_to_app(ESP_PBAC_SET_PHONE_BOOK_RESPONSE_EVT, ¶m); + if (p_data->response.pkt != NULL) { + osi_free(p_data->response.pkt); + } + break; + case BTA_PBA_CLIENT_PULL_VCARD_LISTING_RSP_EVT: + if (p_data->response.final) { + p_ccb = &btc_pba_client_cb.ccb[p_data->response.handle - 1]; + p_ccb->busy = false; + } + param.pull_vcard_listing_rsp.handle = p_data->response.handle; + param.pull_vcard_listing_rsp.final = p_data->response.final; + param.pull_vcard_listing_rsp.result = p_data->response.status; + param.pull_vcard_listing_rsp.data = p_data->response.data; + param.pull_vcard_listing_rsp.data_len = p_data->response.data_len; + parse_pull_vcard_listing_app_param(¶m, p_data->response.app_param, p_data->response.app_param_len); + btc_pba_client_callback_to_app(ESP_PBAC_PULL_VCARD_LISTING_RESPONSE_EVT, ¶m); + if (p_data->response.pkt != NULL) { + osi_free(p_data->response.pkt); + } + break; + case BTA_PBA_CLIENT_PULL_VCARD_ENTRY_RSP_EVT: + if (p_data->response.final) { + p_ccb = &btc_pba_client_cb.ccb[p_data->response.handle - 1]; + p_ccb->busy = false; + } + param.pull_vcard_entry_rsp.handle = p_data->response.handle; + param.pull_vcard_entry_rsp.final = p_data->response.final; + param.pull_vcard_entry_rsp.result = p_data->response.status; + param.pull_vcard_entry_rsp.data = p_data->response.data; + param.pull_vcard_entry_rsp.data_len = p_data->response.data_len; + parse_pull_vcard_entry_app_param(¶m, p_data->response.app_param, p_data->response.app_param_len); + btc_pba_client_callback_to_app(ESP_PBAC_PULL_VCARD_ENTRY_RESPONSE_EVT, ¶m); + if (p_data->response.pkt != NULL) { + osi_free(p_data->response.pkt); + } + break; + case BTA_PBA_CLIENT_REGISTER_EVT: + /* init process: Enable -> Register */ + btc_pba_client_callback_to_app(ESP_PBAC_INIT_EVT, NULL); + break; + case BTA_PBA_CLIENT_DISABLE_EVT: + /* deinit process: Deregister -> Disable */ + btc_pba_client_callback_to_app(ESP_PBAC_DEINIT_EVT, NULL); + break; + default: + BTC_TRACE_WARNING("%s: unknown event (%d)", __func__, event); + break; + } +} + +#endif diff --git a/lib/bt/host/bluedroid/btc/profile/std/sdp/btc_sdp.c b/lib/bt/host/bluedroid/btc/profile/std/sdp/btc_sdp.c index 6eaf6cfb..23ee72eb 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/sdp/btc_sdp.c +++ b/lib/bt/host/bluedroid/btc/profile/std/sdp/btc_sdp.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,6 +9,7 @@ #include "btc_sdp.h" #include "btc/btc_manage.h" #include "btc/btc_task.h" +#include "btc/btc_util.h" #include "bta/bta_sdp_api.h" #include "bta/bta_sys.h" #include "bta/utl.h" @@ -17,7 +18,7 @@ #include "osi/allocator.h" #include "esp_sdp_api.h" -#if (defined BTC_SDP_INCLUDED && BTC_SDP_INCLUDED == TRUE) +#if (defined BTC_SDP_COMMON_INCLUDED && BTC_SDP_COMMON_INCLUDED == TRUE) typedef enum { SDP_RECORD_FREE = 0, @@ -25,12 +26,21 @@ typedef enum { } sdp_state_t; typedef struct { - sdp_state_t state; + uint8_t di : 1; + uint8_t primary_di : 1; + uint8_t reserved : 6; +} sdp_flag_t; + +typedef struct { + uint8_t state; + sdp_flag_t flag; int sdp_handle; - bluetooth_sdp_record* record_data; + esp_bt_uuid_t uuid; + void* record_data; } sdp_slot_t; typedef struct { + bool search_allowed; sdp_slot_t *sdp_slots[SDP_MAX_RECORDS]; osi_mutex_t sdp_slot_mutex; } sdp_local_param_t; @@ -48,6 +58,21 @@ static sdp_local_param_t *sdp_local_param_ptr; #define is_sdp_init() (&sdp_local_param != NULL && sdp_local_param.sdp_slot_mutex != NULL) #endif +static void btc_sdp_cleanup(void) +{ +#if SDP_DYNAMIC_MEMORY == TRUE + if (sdp_local_param_ptr) { +#endif + if (sdp_local_param.sdp_slot_mutex) { + osi_mutex_free(&sdp_local_param.sdp_slot_mutex); + sdp_local_param.sdp_slot_mutex = NULL; + } +#if SDP_DYNAMIC_MEMORY == TRUE + osi_free(sdp_local_param_ptr); + sdp_local_param_ptr = NULL; + } +#endif +} static inline void btc_sdp_cb_to_app(esp_sdp_cb_event_t event, esp_sdp_cb_param_t *param) { @@ -57,46 +82,33 @@ static inline void btc_sdp_cb_to_app(esp_sdp_cb_event_t event, esp_sdp_cb_param_ } } -static void sdp_disable_handler(void) +static int get_sdp_record_size(bluetooth_sdp_record* in_record) { - btc_msg_t msg; - bt_status_t status; - - msg.sig = BTC_SIG_API_CB; - msg.pid = BTC_PID_SDP; - msg.act = BTA_SDP_DISENABLE_EVT; - - status = btc_transfer_context(&msg, NULL, 0, NULL, NULL); - - if (status != BT_STATUS_SUCCESS) { - BTC_TRACE_ERROR("%s btc_transfer_context failed", __func__); - } -} - -static int get_sdp_records_size(bluetooth_sdp_record* in_record, int count) -{ - bluetooth_sdp_record* record = in_record; + bluetooth_sdp_record *record = in_record; int records_size = 0; - for(int i = 0; i < count; i++) { - record = &in_record[i]; + switch (record->hdr.type) { + case SDP_TYPE_DIP_SERVER: + records_size = sizeof(bluetooth_sdp_record); + break; + + default: records_size += sizeof(bluetooth_sdp_record); records_size += record->hdr.service_name_length; - if(record->hdr.service_name_length > 0){ + if (record->hdr.service_name_length > 0) { records_size++; /* + '\0' termination of string */ } - records_size += record->hdr.user1_ptr_len; - records_size += record->hdr.user2_ptr_len; + break; } return records_size; } -static void set_sdp_handle(int id, int handle) +static void set_sdp_slot_info(int id, int sdp_handle, esp_bt_uuid_t *uuid) { sdp_slot_t *slot = NULL; - BTC_TRACE_DEBUG("%s() id=%d to handle=0x%08x", __func__, id, handle); + BTC_TRACE_DEBUG("%s() id=%d to sdp_handle=0x%08x", __func__, id, sdp_handle); if(id >= SDP_MAX_RECORDS) { BTC_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id); @@ -104,34 +116,68 @@ static void set_sdp_handle(int id, int handle) } osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - slot = sdp_local_param.sdp_slots[id]; - if (slot == NULL) { - osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); - BTC_TRACE_ERROR("%s() id=%d to handle=0x%08x, set failed", __func__, id, handle); - return; - } - slot->sdp_handle = handle; + + do { + slot = sdp_local_param.sdp_slots[id]; + if (slot == NULL) { + BTC_TRACE_ERROR("%s() id = %d ", __func__, id); + break; + } + + if (slot->state != SDP_RECORD_ALLOCED) { + BTC_TRACE_ERROR("%s() failed - state for id %d is state = %d expected %d", __func__, id, + sdp_local_param.sdp_slots[id]->state, SDP_RECORD_ALLOCED); + break; + } + slot->sdp_handle = sdp_handle; + slot->record_data = NULL; + if (uuid) { + memcpy(&slot->uuid, uuid, sizeof(esp_bt_uuid_t)); + } else { + memset(&slot->uuid, 0, sizeof(esp_bt_uuid_t)); + } + } while (0); + osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); } - -static bool get_sdp_record_by_handle(int handle, bluetooth_sdp_record* record) +static void get_sdp_slot_info(int id, int *sdp_handle, esp_bt_uuid_t *uuid, sdp_flag_t *flag) { sdp_slot_t *slot = NULL; + if(id >= SDP_MAX_RECORDS) { + BTC_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id); + return; + } + osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - for (int i = 0; i < SDP_MAX_RECORDS; i++) { - slot = sdp_local_param.sdp_slots[i]; - if ((slot != NULL) && (slot->sdp_handle == handle)) { - memcpy(record, slot->record_data, sizeof(bluetooth_sdp_record)); - osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); - return true; + do { + slot = sdp_local_param.sdp_slots[id]; + if (slot == NULL) { + break; } - } + + if (slot->state != SDP_RECORD_ALLOCED) { + BTC_TRACE_ERROR("%s() failed - state for id %d is state = %d expected %d", __func__, id, + sdp_local_param.sdp_slots[id]->state, SDP_RECORD_ALLOCED); + break; + } + + if (sdp_handle) { + *sdp_handle = slot->sdp_handle; + } + + if (uuid) { + memcpy(uuid, &slot->uuid, sizeof(esp_bt_uuid_t)); + } + + if (flag) { + *flag = slot->flag; + } + } while (0); osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); - return false; } static int get_sdp_slot_id_by_handle(int handle) @@ -152,9 +198,10 @@ static int get_sdp_slot_id_by_handle(int handle) return -1; } -static sdp_slot_t *start_create_sdp(int id) +static bluetooth_sdp_record *start_create_sdp(int id) { - sdp_slot_t *sdp_slot = NULL; + sdp_slot_t *slot = NULL; + bluetooth_sdp_record* record_data = NULL; if(id >= SDP_MAX_RECORDS) { BTC_TRACE_ERROR("%s() failed - id %d is invalid", __func__, id); @@ -162,64 +209,88 @@ static sdp_slot_t *start_create_sdp(int id) } osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - sdp_slot = sdp_local_param.sdp_slots[id]; - if (sdp_slot == NULL) { - BTC_TRACE_ERROR("%s() id = %d ", __func__, id); - } else if(sdp_slot->state != SDP_RECORD_ALLOCED) { - BTC_TRACE_ERROR("%s() failed - state for id %d is state = %d expected %d", __func__, - id, sdp_local_param.sdp_slots[id]->state, SDP_RECORD_ALLOCED); - /* The record have been removed before this event occurred - e.g. deinit */ - sdp_slot = NULL; - } + + do { + slot = sdp_local_param.sdp_slots[id]; + if (slot == NULL) { + BTC_TRACE_ERROR("%s() id = %d ", __func__, id); + break; + } + + if (slot->state != SDP_RECORD_ALLOCED) { + BTC_TRACE_ERROR("%s() failed - state for id %d is state = %d expected %d", __func__, id, + sdp_local_param.sdp_slots[id]->state, SDP_RECORD_ALLOCED); + break; + } + record_data = slot->record_data; + } while (0); + osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); - return sdp_slot; + return record_data; } /* Deep copy all content of in_records into out_records. * out_records must point to a chunk of memory large enough to contain all * the data. Use getSdpRecordsSize() to calculate the needed size. */ -static void copy_sdp_records(bluetooth_sdp_record* in_records, bluetooth_sdp_record* out_records, int count) +static void copy_sdp_record_common(bluetooth_sdp_record* in_record, bluetooth_sdp_record* out_record) { - bluetooth_sdp_record *in_record; - bluetooth_sdp_record *out_record; - char *free_ptr = (char*)(&out_records[count]); /* set pointer to after the last entry */ - - for(int i = 0; i < count; i++) { - in_record = &in_records[i]; - out_record = &out_records[i]; - *out_record = *in_record; - - if(in_record->hdr.service_name == NULL || in_record->hdr.service_name_length == 0) { - out_record->hdr.service_name = NULL; - out_record->hdr.service_name_length = 0; - } else { - out_record->hdr.service_name = free_ptr; // Update service_name pointer - // Copy string - memcpy(free_ptr, in_record->hdr.service_name, in_record->hdr.service_name_length); - free_ptr += in_record->hdr.service_name_length; - *(free_ptr) = '\0'; // Set '\0' termination of string - free_ptr++; - } - if(in_record->hdr.user1_ptr != NULL) { - out_record->hdr.user1_ptr = (UINT8*)free_ptr; // Update pointer - memcpy(free_ptr, in_record->hdr.user1_ptr, in_record->hdr.user1_ptr_len); // Copy content - free_ptr += in_record->hdr.user1_ptr_len; - } - if(in_record->hdr.user2_ptr != NULL) { - out_record->hdr.user2_ptr = (UINT8*)free_ptr; // Update pointer - memcpy(free_ptr, in_record->hdr.user2_ptr, in_record->hdr.user2_ptr_len); // Copy content - free_ptr += in_record->hdr.user2_ptr_len; - } + uint8_t *free_ptr = (uint8_t *)(out_record + 1); /* set pointer to after the last entry */ + + memcpy(out_record, in_record, sizeof(bluetooth_sdp_record)); + + if (in_record->hdr.service_name == NULL || in_record->hdr.service_name_length == 0) { + out_record->hdr.service_name = NULL; + out_record->hdr.service_name_length = 0; + } else { + out_record->hdr.service_name = (char *)free_ptr; // Update service_name pointer + // Copy string + memcpy(free_ptr, in_record->hdr.service_name, in_record->hdr.service_name_length); + free_ptr += in_record->hdr.service_name_length; + *(free_ptr) = '\0'; // Set '\0' termination of string + free_ptr++; + } +} + +static void copy_sdp_record(bluetooth_sdp_record* in_record, bluetooth_sdp_record* out_record) +{ + switch (in_record->hdr.type) { + case SDP_TYPE_DIP_SERVER: + memcpy(out_record, in_record, sizeof(bluetooth_sdp_record)); + break; + + default: + copy_sdp_record_common(in_record, out_record); + break; + } +} + +static bool check_if_primary_di_record(bluetooth_sdp_record* record) +{ + bool ret = false; + + if (record->hdr.type == SDP_TYPE_DIP_SERVER) { + bluetooth_sdp_dip_record *di_record = (bluetooth_sdp_dip_record *)record; + ret = di_record->primary_record; } + + return ret; +} + +static bool check_if_di_record(bluetooth_sdp_record* record) +{ + return record->hdr.type == SDP_TYPE_DIP_SERVER ? true : false; } static int alloc_sdp_slot(bluetooth_sdp_record* in_record) { int i; - int record_size = get_sdp_records_size(in_record, 1); + int record_size = get_sdp_record_size(in_record); bluetooth_sdp_record *record = NULL; sdp_slot_t **slot = NULL; + bool is_di_record = check_if_di_record(in_record); + bool is_primary_di_record = check_if_primary_di_record(in_record); + bool primary_di_record_found = false; record = osi_malloc(record_size); if (record == NULL) { @@ -227,22 +298,42 @@ static int alloc_sdp_slot(bluetooth_sdp_record* in_record) return -1; } - copy_sdp_records(in_record, record, 1); + copy_sdp_record(in_record, record); osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - for(i = 0; i < SDP_MAX_RECORDS; i++) - { - slot = &sdp_local_param.sdp_slots[i]; - if ((*slot) == NULL) { - if (((*slot) = (sdp_slot_t *)osi_malloc(sizeof(sdp_slot_t))) == NULL) { - osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); - BTC_TRACE_ERROR("%s() osi_malloc slot failed!", __func__); - osi_free(record); - return -1; + // find the primary di record slot + if (is_di_record && is_primary_di_record) { + for (i = 0; i < SDP_MAX_RECORDS; i++) { + slot = &sdp_local_param.sdp_slots[i]; + if ((*slot) && (*slot)->flag.di && (*slot)->flag.primary_di) { + BTC_TRACE_WARNING("%s() overwrite primary di record!", __func__); + if ((*slot)->record_data) { + osi_free((*slot)->record_data); + } + + (*slot)->record_data = record; + primary_di_record_found = true; + break; + } + } + } + + if (!primary_di_record_found) { + for (i = 0; i < SDP_MAX_RECORDS; i++) { + slot = &sdp_local_param.sdp_slots[i]; + if ((*slot) == NULL) { + if (((*slot) = (sdp_slot_t *)osi_malloc(sizeof(sdp_slot_t))) == NULL) { + osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); + BTC_TRACE_ERROR("%s() osi_malloc slot failed!", __func__); + osi_free(record); + return -1; + } + (*slot)->flag.di = is_di_record; + (*slot)->flag.primary_di = is_primary_di_record; + (*slot)->state = SDP_RECORD_ALLOCED; + (*slot)->record_data = record; + break; } - (*slot)->state = SDP_RECORD_ALLOCED; - (*slot)->record_data = record; - break; } } osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); @@ -292,7 +383,7 @@ static int free_sdp_slot(int id) } /* Create a raw SDP record based on information stored in a bluetooth_sdp_raw_record */ -static int add_raw_sdp(const bluetooth_sdp_record* rec) +static int add_raw_sdp(const bluetooth_sdp_raw_record *rec) { tSDP_PROTOCOL_ELEM protoList [2]; UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP; @@ -301,6 +392,7 @@ static int add_raw_sdp(const bluetooth_sdp_record* rec) UINT8 temp[LEN_UUID_128]; UINT8* p_temp = temp; UINT32 sdp_handle = 0; + const esp_bt_uuid_t *p_uuid = &rec->hdr.uuid; BTC_TRACE_DEBUG("%s(): scn 0x%02x, psm = 0x%04x\n service name %s", __func__, rec->hdr.rfcomm_channel_number, rec->hdr.l2cap_psm, rec->hdr.service_name); @@ -310,15 +402,15 @@ static int add_raw_sdp(const bluetooth_sdp_record* rec) return sdp_handle; } - if (rec->hdr.bt_uuid.len == ESP_UUID_LEN_16) { + if (p_uuid->len == ESP_UUID_LEN_16) { UINT8_TO_BE_STREAM (p_temp, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES); - UINT16_TO_BE_STREAM (p_temp, rec->hdr.bt_uuid.uuid.uuid16); - } else if (rec->hdr.bt_uuid.len == ESP_UUID_LEN_32) { + UINT16_TO_BE_STREAM (p_temp, p_uuid->uuid.uuid16); + } else if (p_uuid->len == ESP_UUID_LEN_32) { UINT8_TO_BE_STREAM (p_temp, (UUID_DESC_TYPE << 3) | SIZE_FOUR_BYTES); - UINT32_TO_BE_STREAM (p_temp, rec->hdr.bt_uuid.uuid.uuid32); - } else if (rec->hdr.bt_uuid.len == ESP_UUID_LEN_128) { + UINT32_TO_BE_STREAM (p_temp, p_uuid->uuid.uuid32); + } else if (p_uuid->len == ESP_UUID_LEN_128) { UINT8_TO_BE_STREAM (p_temp, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES); - ARRAY_TO_BE_STREAM (p_temp, rec->hdr.bt_uuid.uuid.uuid128, LEN_UUID_128); + ARRAY_TO_BE_STREAM (p_temp, p_uuid->uuid.uuid128, LEN_UUID_128); } else { SDP_DeleteRecord(sdp_handle); sdp_handle = 0; @@ -357,7 +449,7 @@ static int add_raw_sdp(const bluetooth_sdp_record* rec) UINT_DESC_TYPE, (UINT32)2, temp); } - /* Make the service browseable */ + /* Make the service browsable */ status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); if (!status) { @@ -365,12 +457,12 @@ static int add_raw_sdp(const bluetooth_sdp_record* rec) sdp_handle = 0; BTC_TRACE_ERROR("%s() FAILED, status = %d", __func__, status); } else { - if (rec->hdr.bt_uuid.len == ESP_UUID_LEN_16) { - bta_sys_add_uuid(rec->hdr.bt_uuid.uuid.uuid16); - } else if (rec->hdr.bt_uuid.len == ESP_UUID_LEN_32) { - bta_sys_add_uuid_32(rec->hdr.bt_uuid.uuid.uuid32); - } else if (rec->hdr.bt_uuid.len == ESP_UUID_LEN_128) { - bta_sys_add_uuid_128((UINT8 *)&rec->hdr.bt_uuid.uuid.uuid128); + if (p_uuid->len == ESP_UUID_LEN_16) { + bta_sys_add_uuid(p_uuid->uuid.uuid16); + } else if (p_uuid->len == ESP_UUID_LEN_32) { + bta_sys_add_uuid_32(p_uuid->uuid.uuid32); + } else if (p_uuid->len == ESP_UUID_LEN_128) { + bta_sys_add_uuid_128((UINT8 *)&p_uuid->uuid.uuid128); } BTC_TRACE_DEBUG("%s(): SDP Registered (handle 0x%08x)", __func__, sdp_handle); } @@ -448,7 +540,7 @@ static int add_maps_sdp(const bluetooth_sdp_mas_record* rec) UINT_DESC_TYPE, (UINT32)2, temp); } - /* Make the service browseable */ + /* Make the service browsable */ status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); if (!status) { @@ -523,7 +615,7 @@ static int add_mapc_sdp(const bluetooth_sdp_mns_record* rec) UINT_DESC_TYPE, (UINT32)2, temp); } - /* Make the service browseable */ + /* Make the service browsable */ status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); if (!status) { @@ -603,7 +695,7 @@ static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec) UINT_DESC_TYPE, (UINT32)2, temp); } - /* Make the service browseable */ + /* Make the service browsable */ status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); if (!status) { @@ -649,7 +741,7 @@ static int add_pbapc_sdp(const bluetooth_sdp_pce_record* rec) UUID_SERVCLASS_PHONE_ACCESS, rec->hdr.profile_version); - /* Make the service browseable */ + /* Make the service browsable */ status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); if (!status) { @@ -736,7 +828,7 @@ static int add_opps_sdp(const bluetooth_sdp_ops_record* rec) UINT_DESC_TYPE, (UINT32)2, temp); } - /* Make the service browseable */ + /* Make the service browsable */ status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); if (!status) { @@ -799,7 +891,7 @@ static int add_saps_sdp(const bluetooth_sdp_sap_record* rec) UUID_SERVCLASS_SAP, rec->hdr.profile_version); - // Make the service browseable + // Make the service browsable status &= SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse); if (!status) { @@ -814,66 +906,209 @@ static int add_saps_sdp(const bluetooth_sdp_sap_record* rec) return sdp_handle; } +static int add_dips_sdp(bluetooth_sdp_dip_record *rec) +{ + UINT32 sdp_handle = 0; + tBTA_DI_RECORD device_info = {0}; + + device_info.vendor = rec->vendor; + device_info.vendor_id_source = rec->vendor_id_source; + device_info.product = rec->product; + device_info.version = rec->version; + device_info.primary_record = rec->primary_record; + + BTA_DmSetLocalDiRecord(&device_info, &sdp_handle); + + return sdp_handle; +} + static int btc_handle_create_record_event(int id) { - int handle = -1; - const sdp_slot_t *sdp_slot = NULL; + int sdp_handle = 0; + bluetooth_sdp_record *record = start_create_sdp(id); + esp_bt_uuid_t service_uuid = {0}; BTC_TRACE_DEBUG("Sdp Server %s", __func__); - sdp_slot = start_create_sdp(id); - if(sdp_slot != NULL) { - bluetooth_sdp_record* record = sdp_slot->record_data; - switch(record->hdr.type) { + if (record != NULL) { + switch (record->hdr.type) { case SDP_TYPE_RAW: - handle = add_raw_sdp(record); + sdp_handle = add_raw_sdp(&record->raw); + memcpy(&service_uuid, &record->hdr.uuid, sizeof(esp_bt_uuid_t)); break; case SDP_TYPE_MAP_MAS: - handle = add_maps_sdp(&record->mas); + sdp_handle = add_maps_sdp(&record->mas); + service_uuid.len = ESP_UUID_LEN_16; + service_uuid.uuid.uuid16 = UUID_SERVCLASS_MESSAGE_ACCESS; break; case SDP_TYPE_MAP_MNS: - handle = add_mapc_sdp(&record->mns); + sdp_handle = add_mapc_sdp(&record->mns); + service_uuid.len = ESP_UUID_LEN_16; + service_uuid.uuid.uuid16 = UUID_SERVCLASS_MESSAGE_NOTIFICATION; break; case SDP_TYPE_PBAP_PSE: - handle = add_pbaps_sdp(&record->pse); + sdp_handle = add_pbaps_sdp(&record->pse); + service_uuid.len = ESP_UUID_LEN_16; + service_uuid.uuid.uuid16 = UUID_SERVCLASS_PBAP_PSE; break; case SDP_TYPE_PBAP_PCE: - handle = add_pbapc_sdp(&record->pce); + sdp_handle = add_pbapc_sdp(&record->pce); + service_uuid.len = ESP_UUID_LEN_16; + service_uuid.uuid.uuid16 = UUID_SERVCLASS_PBAP_PCE; break; case SDP_TYPE_OPP_SERVER: - handle = add_opps_sdp(&record->ops); + sdp_handle = add_opps_sdp(&record->ops); + service_uuid.len = ESP_UUID_LEN_16; + service_uuid.uuid.uuid16 = UUID_SERVCLASS_OBEX_OBJECT_PUSH; break; case SDP_TYPE_SAP_SERVER: - handle = add_saps_sdp(&record->sap); + sdp_handle = add_saps_sdp(&record->sap); + service_uuid.len = ESP_UUID_LEN_16; + service_uuid.uuid.uuid16 = UUID_SERVCLASS_SAP; + break; + case SDP_TYPE_DIP_SERVER: + sdp_handle = add_dips_sdp(&record->dip); break; default: - BTC_TRACE_DEBUG("Record type %d is not supported",record->hdr.type); + BTC_TRACE_DEBUG("Record type %d is not supported", record->hdr.type); break; } - if(handle != -1) { - set_sdp_handle(id, handle); + + if(sdp_handle != 0) { + set_sdp_slot_info(id, sdp_handle, &service_uuid); + // free the record, since not use it anymore + osi_free(record); + } else { + sdp_handle = -1; } + } else { + sdp_handle = -1; } - return handle; + if (sdp_handle == -1) { + free_sdp_slot(id); + } + + return sdp_handle; } -static bool btc_sdp_remove_record_event(int handle) +static bool btc_sdp_remove_record_event(int id, int *p_sdp_handle) { + BTC_TRACE_DEBUG("Sdp Server %s", __func__); + bool result = false; + int sdp_handle = -1; + sdp_flag_t flag = {0}; + esp_bt_uuid_t service_uuid = {0}; - BTC_TRACE_DEBUG("Sdp Server %s", __func__); + get_sdp_slot_info(id, &sdp_handle, &service_uuid, &flag); - if(handle != -1 && handle != 0) { - result = SDP_DeleteRecord(handle); - if(result == false) { - BTC_TRACE_ERROR(" Unable to remove handle 0x%08x", handle); + if (sdp_handle > 0) { + if (flag.di && BTA_DmRemoveLocalDiRecord(sdp_handle) == BTA_SUCCESS) { + result = true; + } else { + do { + result = SDP_DeleteRecord(sdp_handle); + if (!result) { + BTC_TRACE_ERROR("Unable to remove handle 0x%08x", sdp_handle); + break; + } + + if (service_uuid.len == ESP_UUID_LEN_16) { + bta_sys_remove_uuid(service_uuid.uuid.uuid16); + } else if (service_uuid.len == ESP_UUID_LEN_32) { + bta_sys_remove_uuid_32(service_uuid.uuid.uuid32); + } else if (service_uuid.len == ESP_UUID_LEN_128) { + bta_sys_remove_uuid_128((UINT8 *)&service_uuid.uuid.uuid128); + } + } while (0); + } + + if (p_sdp_handle) { + *p_sdp_handle = sdp_handle; } } return result; } +static void btc_sdp_cb_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) +{ + switch (msg->act) { + case BTA_SDP_SEARCH_COMP_EVT: { + tBTA_SDP_SEARCH_COMP *src_search_comp = (tBTA_SDP_SEARCH_COMP *)p_src; + tBTA_SDP_SEARCH_COMP *dest_search_comp = (tBTA_SDP_SEARCH_COMP *)p_dest; + int record_count = src_search_comp->record_count; + + for (int i = 0; i < record_count; i++) { + bluetooth_sdp_record *src_record = &src_search_comp->records[i]; + bluetooth_sdp_record *dest_record = &dest_search_comp->records[i]; + // deep copy service name + uint32_t src_service_name_length = src_record->hdr.service_name_length; + char *src_service_name = src_record->hdr.service_name; + dest_record->hdr.service_name_length = 0; + dest_record->hdr.service_name = NULL; + if (src_service_name && src_service_name_length) { + char *service_name = (char *)osi_malloc(src_service_name_length + 1); + if (service_name) { + memcpy(service_name, src_service_name, src_service_name_length); + service_name[src_service_name_length] = '\0'; + + dest_record->hdr.service_name_length = src_service_name_length; + dest_record->hdr.service_name = service_name; + } else { + BTC_TRACE_ERROR("%s malloc service name failed, orig service name:%s", __func__, src_service_name); + } + } + + // deep copy user1_ptr fow RAW type + int src_user1_ptr_len = src_record->hdr.user1_ptr_len; + uint8_t *src_user1_ptr = src_record->hdr.user1_ptr; + dest_record->hdr.user1_ptr_len = 0; + dest_record->hdr.user1_ptr = NULL; + if (src_record->hdr.type == SDP_TYPE_RAW && src_user1_ptr && src_user1_ptr_len) { + uint8_t *user1_ptr = (uint8_t *)osi_malloc(src_user1_ptr_len); + if (user1_ptr) { + memcpy(user1_ptr, src_user1_ptr, src_user1_ptr_len); + + dest_record->hdr.user1_ptr_len = src_user1_ptr_len; + dest_record->hdr.user1_ptr = user1_ptr; + } else { + BTC_TRACE_ERROR("%s malloc user1_ptr failed", __func__); + } + } + } + + break; + } + default: + break; + } +} + +static void btc_sdp_cb_arg_deep_free(btc_msg_t *msg) +{ + switch (msg->act) { + case BTA_SDP_SEARCH_COMP_EVT: { + tBTA_SDP_SEARCH_COMP *search_comp = (tBTA_SDP_SEARCH_COMP *)msg->arg; + for (size_t i = 0; i < search_comp->record_count; i++) { + bluetooth_sdp_record *record = &search_comp->records[i]; + if (record->hdr.service_name) { + osi_free(record->hdr.service_name); + } + + if (record->hdr.user1_ptr) { + osi_free(record->hdr.user1_ptr); + } + } + + break; + } + default: + break; + } +} + static void btc_sdp_dm_cback(tBTA_SDP_EVT event, tBTA_SDP* p_data, void* user_data) { btc_msg_t msg; @@ -881,18 +1116,18 @@ static void btc_sdp_dm_cback(tBTA_SDP_EVT event, tBTA_SDP* p_data, void* user_da switch (event) { case BTA_SDP_CREATE_RECORD_USER_EVT: { - if (p_data->status == BTA_SDP_SUCCESS) { + if (p_data->sdp_create_record.status == BTA_SDP_SUCCESS) { p_data->sdp_create_record.handle = btc_handle_create_record_event((int)user_data); if (p_data->sdp_create_record.handle < 0) { - p_data->status = BTA_SDP_FAILURE; + p_data->sdp_create_record.status = BTA_SDP_FAILURE; } } } break; case BTA_SDP_REMOVE_RECORD_USER_EVT: { - if (p_data->status == BTA_SDP_SUCCESS) { - if (btc_sdp_remove_record_event((int)user_data) == false) { - p_data->status = BTA_SDP_FAILURE; + if (p_data->sdp_remove_record.status == BTA_SDP_SUCCESS) { + if (btc_sdp_remove_record_event((int)user_data, &p_data->sdp_remove_record.handle) == false) { + p_data->sdp_remove_record.status = BTA_SDP_FAILURE; } } } @@ -905,7 +1140,7 @@ static void btc_sdp_dm_cback(tBTA_SDP_EVT event, tBTA_SDP* p_data, void* user_da msg.pid = BTC_PID_SDP; msg.act = event; - status = btc_transfer_context(&msg, p_data, sizeof(tBTA_SDP), NULL, NULL); + status = btc_transfer_context(&msg, p_data, sizeof(tBTA_SDP), btc_sdp_cb_arg_deep_copy, btc_sdp_cb_arg_deep_free); if (status != BT_STATUS_SUCCESS) { BTC_TRACE_ERROR("%s btc_transfer_context failed", __func__); @@ -930,23 +1165,27 @@ static void btc_sdp_init(void) ret = ESP_SDP_NO_RESOURCE; break; } - memset((void *)sdp_local_param_ptr, 0, sizeof(sdp_local_param_t)); #endif + memset(&sdp_local_param, 0, sizeof(sdp_local_param_t)); if (osi_mutex_new(&sdp_local_param.sdp_slot_mutex) != 0) { -#if SDP_DYNAMIC_MEMORY == TRUE - osi_free(sdp_local_param_ptr); - sdp_local_param_ptr = NULL; -#endif BTC_TRACE_ERROR("%s osi_mutex_new failed\n", __func__); ret = ESP_SDP_NO_RESOURCE; break; } ret = BTA_SdpEnable(btc_sdp_dm_cback); + if (ret != ESP_SDP_SUCCESS) { + BTC_TRACE_ERROR("%s BTA_SdpEnable failed, ret = %d\n", __func__, ret); + ret = ESP_SDP_FAILURE; + break; + } + + sdp_local_param.search_allowed = true; } while(0); if (ret != ESP_SDP_SUCCESS) { + btc_sdp_cleanup(); param.init.status = ret; btc_sdp_cb_to_app(ESP_SDP_INIT_EVT, ¶m); } @@ -956,7 +1195,6 @@ static void btc_sdp_deinit(void) { esp_sdp_cb_param_t param; esp_sdp_status_t ret = ESP_SDP_SUCCESS; - int handle; do { if (!is_sdp_init()) { @@ -966,12 +1204,13 @@ static void btc_sdp_deinit(void) } for(int i = 0; i < SDP_MAX_RECORDS; i++) { - handle = free_sdp_slot(i); - if (handle > 0) { - BTA_SdpRemoveRecordByUser((void*)handle); + int sdp_handle = -1; + get_sdp_slot_info(i, &sdp_handle, NULL, NULL); + if (sdp_handle > 0) { + BTA_SdpRemoveRecordByUser((void*)i); } } - sdp_disable_handler(); + BTA_SdpDisable(); } while(0); if (ret != ESP_SDP_SUCCESS) { @@ -982,7 +1221,7 @@ static void btc_sdp_deinit(void) static void btc_sdp_create_record(btc_sdp_args_t *arg) { - int handle; + int slot_id; esp_sdp_cb_param_t param; esp_sdp_status_t ret = ESP_SDP_SUCCESS; @@ -993,13 +1232,13 @@ static void btc_sdp_create_record(btc_sdp_args_t *arg) break; } - handle = alloc_sdp_slot(arg->creat_record.record); - if (handle < 0) { + slot_id = alloc_sdp_slot(arg->create_record.record); + if (slot_id < 0) { ret = ESP_SDP_FAILURE; break; } - BTA_SdpCreateRecordByUser((void *) handle); + BTA_SdpCreateRecordByUser((void *) slot_id); } while(0); if (ret != ESP_SDP_SUCCESS) { @@ -1011,7 +1250,6 @@ static void btc_sdp_create_record(btc_sdp_args_t *arg) static void btc_sdp_remove_record(btc_sdp_args_t *arg) { - int handle; esp_sdp_cb_param_t param; esp_sdp_status_t ret = ESP_SDP_SUCCESS; @@ -1022,42 +1260,16 @@ static void btc_sdp_remove_record(btc_sdp_args_t *arg) break; } - bluetooth_sdp_record rec; - if (get_sdp_record_by_handle(arg->remove_record.record_handle, &rec)) { - if (rec.hdr.bt_uuid.len == ESP_UUID_LEN_16) { - bta_sys_remove_uuid(rec.hdr.bt_uuid.uuid.uuid16); - } else if (rec.hdr.bt_uuid.len == ESP_UUID_LEN_32) { - bta_sys_remove_uuid_32(rec.hdr.bt_uuid.uuid.uuid32); - } else if (rec.hdr.bt_uuid.len == ESP_UUID_LEN_128) { - bta_sys_remove_uuid_128((UINT8 *)&rec.hdr.bt_uuid.uuid.uuid128); - } - } else { - BTC_TRACE_ERROR("%s SDP record with handle %d not found", - __func__, arg->remove_record.record_handle); - ret = ESP_SDP_NO_CREATE_RECORD; - break; - } - /* Get the Record handle, and free the slot */ /* The application layer record_handle is equivalent to the id of the btc layer */ - int slot = get_sdp_slot_id_by_handle(arg->remove_record.record_handle); - if (slot < 0) { + int slot_id = get_sdp_slot_id_by_handle(arg->remove_record.record_handle); + if (slot_id < 0) { + BTC_TRACE_ERROR("%s SDP record with handle %d not found", __func__, arg->remove_record.record_handle); ret = ESP_SDP_NO_CREATE_RECORD; break; } - handle = free_sdp_slot(slot); - - BTC_TRACE_DEBUG("Sdp Server %s id=%d to handle=0x%08x", - __func__, arg->remove_record.record_handle, handle); - - /* Pass the actual record handle */ - if(handle > 0) { - BTA_SdpRemoveRecordByUser((void*) handle); - } else { - ret = ESP_SDP_NO_CREATE_RECORD; - break; - } + BTA_SdpRemoveRecordByUser((void *)slot_id); } while(0); if (ret != ESP_SDP_SUCCESS) { @@ -1078,7 +1290,18 @@ static void btc_sdp_search(btc_sdp_args_t *arg) break; } + if (!sdp_local_param.search_allowed) { + BTC_TRACE_ERROR("%s SDP search is not allowed!", __func__); + ret = ESP_SDP_NO_RESOURCE; + break; + } + BTA_SdpSearch(arg->search.bd_addr, &arg->search.sdp_uuid); + /** + * ESP_SDP_SEARCH_COMP_EVT will refer service name in BTA sdp database, so it is not allowed to be search until + * the previous search is completed + */ + sdp_local_param.search_allowed = false; } while(0); if (ret != ESP_SDP_SUCCESS) { @@ -1089,26 +1312,21 @@ static void btc_sdp_search(btc_sdp_args_t *arg) void btc_sdp_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) { - btc_sdp_args_t *dst = (btc_sdp_args_t *)p_dest; - btc_sdp_args_t *src = (btc_sdp_args_t *)p_src; - switch (msg->act) { - case BTC_SDP_ACT_CREATE_RECORD: - dst->creat_record.record = (bluetooth_sdp_record *)osi_calloc(sizeof(bluetooth_sdp_record)); - if (dst->creat_record.record) { - memcpy(dst->creat_record.record, src->creat_record.record, sizeof(bluetooth_sdp_record)); + case BTC_SDP_ACT_CREATE_RECORD: { + bluetooth_sdp_record **dst_record = &((btc_sdp_args_t *)p_dest)->create_record.record; + bluetooth_sdp_record *src_record = ((btc_sdp_args_t *)p_src)->create_record.record; + bluetooth_sdp_record *record = (bluetooth_sdp_record *)osi_calloc(get_sdp_record_size(src_record)); + if (record) { + copy_sdp_record(src_record, record); } else { BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act); break; } - dst->creat_record.record->hdr.service_name = (char *)osi_calloc(src->creat_record.record->hdr.service_name_length); - if (dst->creat_record.record->hdr.service_name) { - strcpy(dst->creat_record.record->hdr.service_name, src->creat_record.record->hdr.service_name); - } else { - BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act); - } + *dst_record = record; break; + } default: break; } @@ -1116,17 +1334,15 @@ void btc_sdp_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) void btc_sdp_arg_deep_free(btc_msg_t *msg) { - btc_sdp_args_t *arg = (btc_sdp_args_t *)msg->arg; - switch (msg->act) { - case BTC_SDP_ACT_CREATE_RECORD: - if (arg->creat_record.record) { - osi_free(arg->creat_record.record); - } - if (arg->creat_record.record->hdr.service_name) { - osi_free(arg->creat_record.record->hdr.service_name); + case BTC_SDP_ACT_CREATE_RECORD: { + btc_sdp_args_t *arg = (btc_sdp_args_t *)msg->arg; + bluetooth_sdp_record *record = arg->create_record.record; + if (record) { + osi_free(record); } break; + } default: break; } @@ -1172,35 +1388,22 @@ void btc_sdp_cb_handler(btc_msg_t *msg) param.init.status = p_data->status; btc_sdp_cb_to_app(ESP_SDP_INIT_EVT, ¶m); break; - case BTA_SDP_DISENABLE_EVT: - BTA_SdpDisable(); - osi_mutex_free(&sdp_local_param.sdp_slot_mutex); - #if SDP_DYNAMIC_MEMORY == TRUE - osi_free(sdp_local_param_ptr); - sdp_local_param_ptr = NULL; - #endif + case BTA_SDP_DISABLE_EVT: + BTA_SdpCleanup(); + btc_sdp_cleanup(); param.deinit.status = ESP_SDP_SUCCESS; btc_sdp_cb_to_app(ESP_SDP_DEINIT_EVT, ¶m); break; case BTA_SDP_SEARCH_COMP_EVT: + // SDP search completed, now can be searched again + sdp_local_param.search_allowed = true; + param.search.status = p_data->sdp_search_comp.status; - if (param.search.status == ESP_SDP_SUCCESS) { - memcpy(param.search.remote_addr, p_data->sdp_search_comp.remote_addr, sizeof(BD_ADDR)); - memcpy(¶m.search.sdp_uuid, &p_data->sdp_search_comp.uuid, sizeof(tSDP_UUID)); - param.search.record_count = p_data->sdp_search_comp.record_count; - param.search.records = osi_malloc(sizeof(esp_bluetooth_sdp_record_t)*p_data->sdp_search_comp.record_count); - if (param.search.records != NULL) { - memcpy(param.search.records, p_data->sdp_search_comp.records, - sizeof(esp_bluetooth_sdp_record_t)*p_data->sdp_search_comp.record_count); - } else { - BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, event); - param.search.status = ESP_SDP_NO_RESOURCE; - } - } + memcpy(param.search.remote_addr, p_data->sdp_search_comp.remote_addr, sizeof(BD_ADDR)); + bta_to_btc_uuid(¶m.search.sdp_uuid, &p_data->sdp_search_comp.uuid); + param.search.record_count = p_data->sdp_search_comp.record_count; + param.search.records = (esp_bluetooth_sdp_record_t *)p_data->sdp_search_comp.records; btc_sdp_cb_to_app(ESP_SDP_SEARCH_COMP_EVT, ¶m); - if (param.search.records != NULL) { - osi_free(param.search.records); - } break; case BTA_SDP_CREATE_RECORD_USER_EVT: param.create_record.status = p_data->sdp_create_record.status; @@ -1208,13 +1411,41 @@ void btc_sdp_cb_handler(btc_msg_t *msg) btc_sdp_cb_to_app(ESP_SDP_CREATE_RECORD_COMP_EVT, ¶m); break; case BTA_SDP_REMOVE_RECORD_USER_EVT: - param.remove_record.status = p_data->status; + if (p_data->sdp_remove_record.status == BTA_SDP_SUCCESS) { + int slot_id = get_sdp_slot_id_by_handle(p_data->sdp_remove_record.handle); + if (slot_id < 0) { + p_data->sdp_remove_record.status = ESP_SDP_NO_CREATE_RECORD; + break; + } else { + free_sdp_slot(slot_id); + } + } + + param.remove_record.status = p_data->sdp_remove_record.status; btc_sdp_cb_to_app(ESP_SDP_REMOVE_RECORD_COMP_EVT, ¶m); break; default: BTC_TRACE_DEBUG("%s: Unhandled event (%d)!", __func__, msg->act); break; } + + btc_sdp_cb_arg_deep_free(msg); +} + +void btc_sdp_get_protocol_status(esp_sdp_protocol_status_t *param) +{ + if (is_sdp_init()) { + param->sdp_inited = true; + osi_mutex_lock(&sdp_local_param.sdp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); + for (size_t i = 0; i <= SDP_MAX_RECORDS; i++) { + if (sdp_local_param.sdp_slots[i] != NULL && sdp_local_param.sdp_slots[i]->state == SDP_RECORD_ALLOCED) { + param->records_num++; + } + } + osi_mutex_unlock(&sdp_local_param.sdp_slot_mutex); + } else { + param->sdp_inited = false; + } } -#endif ///defined BTC_SDP_INCLUDED && BTC_SDP_INCLUDED == TRUE +#endif ///defined BTC_SDP_COMMON_INCLUDED && BTC_SDP_COMMON_INCLUDED == TRUE diff --git a/lib/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c b/lib/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c index cf334494..bb142531 100644 --- a/lib/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c +++ b/lib/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -909,6 +909,9 @@ static void btc_spp_write(btc_spp_args_t *arg) } else { if (fixed_queue_enqueue(slot->tx.queue, arg->write.p_data, 0)) { BTA_JvRfcommWrite(arg->write.handle, slot->id, arg->write.len, arg->write.p_data); + // The TX queue of SPP will handle this memory properly. + // Set it to NULL here to prevent deep free handler from releasing it. + arg->write.p_data = NULL; } else { ret = ESP_SPP_NO_RESOURCE; } @@ -966,6 +969,13 @@ void btc_spp_arg_deep_free(btc_msg_t *msg) case BTC_SPP_ACT_START_DISCOVERY: if (arg->start_discovery.p_uuid_list) { osi_free(arg->start_discovery.p_uuid_list); + arg->start_discovery.p_uuid_list = NULL; + } + break; + case BTC_SPP_ACT_WRITE: + if (arg->write.p_data) { + osi_free(arg->write.p_data); + arg->write.p_data = NULL; } break; default: @@ -1099,7 +1109,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) break; case BTA_JV_RFCOMM_WRITE_EVT: osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - slot = spp_find_slot_by_handle(p_data->rfc_write.handle); + slot = spp_find_slot_by_id(p_data->rfc_write.req_id); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!, handle:%d", __func__, p_data->rfc_write.handle); } @@ -1165,7 +1175,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) param.close.async = p_data->rfc_close.async; if (spp_local_param.spp_mode == ESP_SPP_MODE_CB) { osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - slot = spp_find_slot_by_handle(p_data->rfc_close.handle); + slot = spp_find_slot_by_id((uint32_t)p_data->rfc_close.user_data); if (!slot) { param.close.status = ESP_SPP_NO_CONNECTION; osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -1179,7 +1189,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) bool need_call = true; do { osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - slot = spp_find_slot_by_handle(p_data->rfc_close.handle); + slot = spp_find_slot_by_id((uint32_t)p_data->rfc_close.user_data); if (!slot) { param.close.status = ESP_SPP_NO_CONNECTION; osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -1199,7 +1209,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) slot->alarm_arg = (void *)p_arg; if ((slot->close_alarm = osi_alarm_new("slot", close_timeout_handler, (void *)slot, VFS_CLOSE_TIMEOUT)) == NULL) { - free(p_arg); + osi_free(p_arg); slot->alarm_arg = NULL; param.close.status = ESP_SPP_NO_RESOURCE; osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -1207,7 +1217,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) break; } if (osi_alarm_set(slot->close_alarm, VFS_CLOSE_TIMEOUT) != OSI_ALARM_ERR_PASS) { - free(p_arg); + osi_free(p_arg); slot->alarm_arg = NULL; osi_alarm_free(slot->close_alarm); param.close.status = ESP_SPP_BUSY; @@ -1488,7 +1498,7 @@ static ssize_t spp_vfs_write(int fd, const void * data, size_t size) BTC_TRACE_DEBUG("%s items_waiting:%d, fd:%d\n", __func__, items_waiting, fd); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); - // block untill under water level, be closed or time out + // block until under water level, be closed or time out tx_event_group_val = xEventGroupWaitBits(spp_local_param.tx_event_group, SLOT_WRITE_BIT(serial) | SLOT_CLOSE_BIT(serial), pdTRUE, pdFALSE, VFS_WRITE_TIMEOUT / portTICK_PERIOD_MS); @@ -1687,4 +1697,20 @@ static void btc_spp_vfs_unregister(void) btc_spp_cb_to_app(ESP_SPP_VFS_UNREGISTER_EVT, ¶m); } +void btc_spp_get_profile_status(esp_spp_profile_status_t *param) +{ + if (is_spp_init()) { + param->spp_inited = true; + osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); + for (size_t i = 1; i <= MAX_RFC_PORTS; i++) { + if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->connected) { + param->conn_num++; + } + } + osi_mutex_unlock(&spp_local_param.spp_slot_mutex); + } else { + param->spp_inited = false; + } +} + #endif ///defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE diff --git a/lib/bt/host/bluedroid/common/include/common/bluedroid_user_config.h b/lib/bt/host/bluedroid/common/include/common/bluedroid_user_config.h index 81cfbaac..16a6320d 100644 --- a/lib/bt/host/bluedroid/common/include/common/bluedroid_user_config.h +++ b/lib/bt/host/bluedroid/common/include/common/bluedroid_user_config.h @@ -39,6 +39,25 @@ #define UC_BT_A2DP_ENABLED FALSE #endif +#ifdef CONFIG_BT_A2DP_USE_EXTERNAL_CODEC +#define UC_BT_A2DP_USE_EXTERNAL_CODEC CONFIG_BT_A2DP_USE_EXTERNAL_CODEC +#else +#define UC_BT_A2DP_USE_EXTERNAL_CODEC FALSE +#endif + +//AVRCP +#ifdef CONFIG_BT_AVRCP_ENABLED +#define UC_BT_AVRCP_ENABLED TRUE +#ifdef CONFIG_BT_AVRCP_CT_COVER_ART_ENABLED +#define UC_BT_AVRCP_CT_COVER_ART_ENABLED CONFIG_BT_AVRCP_CT_COVER_ART_ENABLED +#else +#define UC_BT_AVRCP_CT_COVER_ART_ENABLED FALSE +#endif +#else +#define UC_BT_AVRCP_ENABLED FALSE +#define UC_BT_AVRCP_CT_COVER_ART_ENABLED FALSE +#endif + //SPP #ifdef CONFIG_BT_SPP_ENABLED #define UC_BT_SPP_ENABLED CONFIG_BT_SPP_ENABLED @@ -48,16 +67,37 @@ //L2CAP #ifdef CONFIG_BT_L2CAP_ENABLED -#define UC_BT_L2CAP_ENABLED CONFIG_BT_L2CAP_ENABLED +#define UC_BT_L2CAP_ENABLED CONFIG_BT_L2CAP_ENABLED #else -#define UC_BT_L2CAP_ENABLED FALSE +#define UC_BT_L2CAP_ENABLED FALSE +#endif + +//SDP common +#ifdef CONFIG_BT_SDP_COMMON_ENABLED +#define UC_BT_SDP_COMMON_ENABLED CONFIG_BT_SDP_COMMON_ENABLED +#else +#define UC_BT_SDP_COMMON_ENABLED FALSE +#endif + +// SDP Pad Length +#ifdef CONFIG_BT_SDP_PAD_LEN +#define UC_SDP_MAX_PAD_LEN CONFIG_BT_SDP_PAD_LEN +#else +#define UC_SDP_MAX_PAD_LEN 300 +#endif + +// SDP Max Attribute Length +#ifdef CONFIG_BT_SDP_ATTR_LEN +#define UC_SDP_MAX_ATTR_LEN CONFIG_BT_SDP_ATTR_LEN +#else +#define UC_SDP_MAX_ATTR_LEN 300 #endif //HFP(AG) #ifdef CONFIG_BT_HFP_AG_ENABLE -#define UC_BT_HFP_AG_ENABLED CONFIG_BT_HFP_AG_ENABLE +#define UC_BT_HFP_AG_ENABLED CONFIG_BT_HFP_AG_ENABLE #else -#define UC_BT_HFP_AG_ENABLED FALSE +#define UC_BT_HFP_AG_ENABLED FALSE #endif //HFP(Client) @@ -67,6 +107,12 @@ #define UC_BT_HFP_CLIENT_ENABLED FALSE #endif +#ifdef CONFIG_BT_HFP_USE_EXTERNAL_CODEC +#define UC_BT_HFP_USE_EXTERNAL_CODEC CONFIG_BT_HFP_USE_EXTERNAL_CODEC +#else +#define UC_BT_HFP_USE_EXTERNAL_CODEC FALSE +#endif + //HID #ifdef CONFIG_BT_HID_ENABLED #define UC_BT_HID_ENABLED CONFIG_BT_HID_ENABLED @@ -88,6 +134,13 @@ #define UC_BT_HID_DEVICE_ENABLED FALSE #endif +//HID remove device bonding option +#ifdef CONFIG_BT_HID_REMOVE_DEVICE_BONDING_ENABLED +#define UC_BT_HID_REMOVE_DEVICE_BONDING_ENABLED CONFIG_BT_HID_REMOVE_DEVICE_BONDING_ENABLED +#else +#define UC_BT_HID_REMOVE_DEVICE_BONDING_ENABLED FALSE +#endif + //BQB(BT) #ifdef CONFIG_BT_CLASSIC_BQB_ENABLED #define UC_BT_CLASSIC_BQB_ENABLED CONFIG_BT_CLASSIC_BQB_ENABLED @@ -104,6 +157,32 @@ #define UC_BT_ENC_KEY_SIZE_CTRL_MODE 0 #endif +//PBAP Client +#ifdef CONFIG_BT_PBAC_ENABLED +#define UC_BT_PBAC_ENABLED CONFIG_BT_PBAC_ENABLED +#else +#define UC_BT_PBAC_ENABLED FALSE +#endif + +#ifdef CONFIG_BT_PBAC_SUPPORTED_FEAT +#define UC_BT_PBAC_SUPPORTED_FEAT CONFIG_BT_PBAC_SUPPORTED_FEAT +#else +#define UC_BT_PBAC_SUPPORTED_FEAT 0x00 +#endif + +#ifdef CONFIG_BT_PBAC_PREFERRED_MTU +#define UC_BT_PBAC_PREFERRED_MTU CONFIG_BT_PBAC_PREFERRED_MTU +#else +#define UC_BT_PBAC_PREFERRED_MTU 0 +#endif + +//GOEPC (BT) +#ifdef CONFIG_BT_GOEPC_ENABLED +#define UC_BT_GOEPC_ENABLED CONFIG_BT_GOEPC_ENABLED +#else +#define UC_BT_GOEPC_ENABLED FALSE +#endif + //BLE #ifdef CONFIG_BT_BLE_ENABLED #define UC_BT_BLE_ENABLED CONFIG_BT_BLE_ENABLED @@ -133,12 +212,60 @@ #define UC_BT_BLE_42_FEATURES_SUPPORTED FALSE #endif +#ifdef CONFIG_BT_BLE_42_DTM_TEST_EN +#define UC_BT_BLE_42_DTM_TEST_EN CONFIG_BT_BLE_42_DTM_TEST_EN +#else +#define UC_BT_BLE_42_DTM_TEST_EN FALSE +#endif + +#ifdef CONFIG_BT_BLE_42_ADV_EN +#define UC_BT_BLE_42_ADV_EN CONFIG_BT_BLE_42_ADV_EN +#else +#define UC_BT_BLE_42_ADV_EN FALSE +#endif + +#ifdef CONFIG_BT_BLE_42_SCAN_EN +#define UC_BT_BLE_42_SCAN_EN CONFIG_BT_BLE_42_SCAN_EN +#else +#define UC_BT_BLE_42_SCAN_EN FALSE +#endif + #ifdef CONFIG_BT_BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER #define UC_BT_BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER CONFIG_BT_BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER #else #define UC_BT_BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER FALSE #endif +#ifdef CONFIG_BT_BLE_50_EXTEND_ADV_EN +#define UC_BT_BLE_50_EXTEND_ADV_EN CONFIG_BT_BLE_50_EXTEND_ADV_EN +#else +#define UC_BT_BLE_50_EXTEND_ADV_EN FALSE +#endif + +#ifdef CONFIG_BT_BLE_50_PERIODIC_ADV_EN +#define UC_BT_BLE_50_PERIODIC_ADV_EN CONFIG_BT_BLE_50_PERIODIC_ADV_EN +#else +#define UC_BT_BLE_50_PERIODIC_ADV_EN FALSE +#endif + +#ifdef CONFIG_BT_BLE_50_EXTEND_SCAN_EN +#define UC_BT_BLE_50_EXTEND_SCAN_EN CONFIG_BT_BLE_50_EXTEND_SCAN_EN +#else +#define UC_BT_BLE_50_EXTEND_SCAN_EN FALSE +#endif + +#ifdef CONFIG_BT_BLE_50_EXTEND_SYNC_EN +#define UC_BT_BLE_50_EXTEND_SYNC_EN CONFIG_BT_BLE_50_EXTEND_SYNC_EN +#else +#define UC_BT_BLE_50_EXTEND_SYNC_EN FALSE +#endif + +#ifdef CONFIG_BT_BLE_50_DTM_TEST_EN +#define UC_BT_BLE_50_DTM_TEST_EN CONFIG_BT_BLE_50_DTM_TEST_EN +#else +#define UC_BT_BLE_50_DTM_TEST_EN FALSE +#endif + #ifdef CONFIG_BT_BLE_FEAT_PERIODIC_ADV_ENH #define UC_BT_BLE_FEAT_PERIODIC_ADV_ENH CONFIG_BT_BLE_FEAT_PERIODIC_ADV_ENH #else @@ -151,6 +278,98 @@ #define UC_BT_BLE_FEAT_CREATE_SYNC_ENH FALSE #endif +#ifdef CONFIG_BT_BLE_FEAT_ISO_EN +#define UC_BT_BLE_FEAT_ISO_EN CONFIG_BT_BLE_FEAT_ISO_EN +#else +#define UC_BT_BLE_FEAT_ISO_EN FALSE +#endif + +#if CONFIG_BT_BLE_FEAT_ISO_60_EN +#define UC_BT_BLE_FEAT_ISO_60_EN CONFIG_BT_BLE_FEAT_ISO_60_EN +#else +#define UC_BT_BLE_FEAT_ISO_60_EN FALSE +#endif + +#ifdef CONFIG_BT_BLE_FEAT_ISO_BIG_SYNCER +#define UC_BT_BLE_FEAT_ISO_BIG_SYNCER CONFIG_BT_BLE_FEAT_ISO_BIG_SYNCER +#else +#define UC_BT_BLE_FEAT_ISO_BIG_SYNCER FALSE +#endif + +#ifdef CONFIG_BT_BLE_FEAT_ISO_BIG_BROCASTER +#define UC_BT_BLE_FEAT_ISO_BIG_BROCASTER CONFIG_BT_BLE_FEAT_ISO_BIG_BROCASTER +#else +#define UC_BT_BLE_FEAT_ISO_BIG_BROCASTER FALSE +#endif + +#ifdef CONFIG_BT_BLE_FEAT_ISO_CIG_CENTRAL +#define UC_BT_BLE_FEAT_ISO_CIG_CENTRAL CONFIG_BT_BLE_FEAT_ISO_CIG_CENTRAL +#else +#define UC_BT_BLE_FEAT_ISO_CIG_CENTRAL FALSE +#endif + +#ifdef CONFIG_BT_BLE_FEAT_ISO_CIG_PERIPHERAL +#define UC_BT_BLE_FEAT_ISO_CIG_PERIPHERAL CONFIG_BT_BLE_FEAT_ISO_CIG_PERIPHERAL +#else +#define UC_BT_BLE_FEAT_ISO_CIG_PERIPHERAL FALSE +#endif + +#ifdef CONFIG_BT_BLE_ISO_CIS_MAX_COUNT +#define UC_BT_BLE_ISO_CIS_MAX_COUNT CONFIG_BT_BLE_ISO_CIS_MAX_COUNT +#else +#define UC_BT_BLE_ISO_CIS_MAX_COUNT (0) +#endif + +#ifdef CONFIG_BT_BLE_ISO_BIS_MAX_COUNT +#define UC_BT_BLE_ISO_BIS_MAX_COUNT CONFIG_BT_BLE_ISO_BIS_MAX_COUNT +#else +#define UC_BT_BLE_ISO_BIS_MAX_COUNT (0) +#endif + +#ifdef CONFIG_BT_BLE_ISO_STD_FLOW_CTRL +#define UC_BT_BLE_ISO_STD_FLOW_CTRL CONFIG_BT_BLE_ISO_STD_FLOW_CTRL +#endif + +#ifdef CONFIG_BT_BLE_ISO_NON_STD_FLOW_CTRL +#define UC_BT_BLE_ISO_NON_STD_FLOW_CTRL CONFIG_BT_BLE_ISO_NON_STD_FLOW_CTRL +#endif + +#ifdef CONFIG_BT_BLE_FEAT_CTE_EN +#define UC_BT_BLE_FEAT_CTE_EN CONFIG_BT_BLE_FEAT_CTE_EN +#else +#define UC_BT_BLE_FEAT_CTE_EN FALSE +#endif + +#ifdef CONFIG_BT_BLE_FEAT_CTE_CONNECTIONLESS_EN +#define UC_BT_BLE_FEAT_CTE_CONNECTIONLESS_EN CONFIG_BT_BLE_FEAT_CTE_CONNECTIONLESS_EN +#else +#define UC_BT_BLE_FEAT_CTE_CONNECTIONLESS_EN FALSE +#endif + +#ifdef CONFIG_BT_BLE_FEAT_CTE_CONNECTION_EN +#define UC_BT_BLE_FEAT_CTE_CONNECTION_EN CONFIG_BT_BLE_FEAT_CTE_CONNECTION_EN +#else +#define UC_BT_BLE_FEAT_CTE_CONNECTION_EN FALSE +#endif + +#ifdef CONFIG_BT_BLE_FEAT_POWER_CONTROL +#define UC_BT_BLE_FEAT_POWER_CONTROL CONFIG_BT_BLE_FEAT_POWER_CONTROL +#else +#define UC_BT_BLE_FEAT_POWER_CONTROL FALSE +#endif + +#ifdef CONFIG_BT_BLE_FEAT_CONN_SUBRATING +#define UC_BT_BLE_FEAT_CONN_SUBRATING CONFIG_BT_BLE_FEAT_CONN_SUBRATING +#else +#define UC_BT_BLE_FEAT_CONN_SUBRATING FALSE +#endif + +#ifdef CONFIG_BT_BLE_VENDOR_HCI_EN +#define UC_BT_BLE_VENDOR_HCI_EN CONFIG_BT_BLE_VENDOR_HCI_EN +#else +#define UC_BT_BLE_VENDOR_HCI_EN FALSE +#endif + #ifdef CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL #define UC_BT_BLE_HIGH_DUTY_ADV_INTERVAL CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL #else @@ -218,7 +437,19 @@ #define UC_BT_SMP_MAX_BONDS 8 #endif -//Device Nane Maximum Length +#ifdef CONFIG_BT_BLE_SMP_ID_RESET_ENABLE +#define UC_BT_BLE_SMP_ID_RESET_ENABLE CONFIG_BT_BLE_SMP_ID_RESET_ENABLE +#else +#define UC_BT_BLE_SMP_ID_RESET_ENABLE FALSE +#endif + +#ifdef CONFIG_BT_BLE_SMP_BOND_NVS_FLASH +#define UC_BT_BLE_SMP_BOND_NVS_FLASH CONFIG_BT_BLE_SMP_BOND_NVS_FLASH +#else +#define UC_BT_BLE_SMP_BOND_NVS_FLASH FALSE +#endif + +//Device Name Maximum Length #ifdef CONFIG_BT_MAX_DEVICE_NAME_LEN #define UC_MAX_LOC_BD_NAME_LEN CONFIG_BT_MAX_DEVICE_NAME_LEN #else @@ -294,14 +525,6 @@ #define UC_BT_BLE_ESTAB_LINK_CONN_TOUT 30 #endif - -//HOST QUEUE CONGEST CHECK -#ifdef CONFIG_BT_BLE_HOST_QUEUE_CONGESTION_CHECK -#define UC_BT_BLE_HOST_QUEUE_CONGESTION_CHECK CONFIG_BT_BLE_HOST_QUEUE_CONGESTION_CHECK -#else -#define UC_BT_BLE_HOST_QUEUE_CONGESTION_CHECK FALSE -#endif - #ifdef CONFIG_BT_GATTS_PPCP_CHAR_GAP #define UC_CONFIG_BT_GATTS_PPCP_CHAR_GAP CONFIG_BT_GATTS_PPCP_CHAR_GAP #else @@ -375,20 +598,6 @@ * Memory reference **********************************************************/ -//MEMORY ALLOCATOR -#ifdef CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST -#define UC_HEAP_ALLOCATION_FROM_SPIRAM_FIRST CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST -#else -#define UC_HEAP_ALLOCATION_FROM_SPIRAM_FIRST FALSE -#endif - -//MEMORY DEBUG -#ifdef CONFIG_BT_BLUEDROID_MEM_DEBUG -#define UC_BT_BLUEDROID_MEM_DEBUG CONFIG_BT_BLUEDROID_MEM_DEBUG -#else -#define UC_BT_BLUEDROID_MEM_DEBUG FALSE -#endif - //ESP COEXIST VSC #ifdef CONFIG_BT_BLUEDROID_ESP_COEX_VSC #define UC_BT_BLUEDROID_ESP_COEX_VSC CONFIG_BT_BLUEDROID_ESP_COEX_VSC diff --git a/lib/bt/host/bluedroid/common/include/common/bt_target.h b/lib/bt/host/bluedroid/common/include/common/bt_target.h index 0adad84f..d1dfd177 100644 --- a/lib/bt/host/bluedroid/common/include/common/bt_target.h +++ b/lib/bt/host/bluedroid/common/include/common/bt_target.h @@ -88,9 +88,19 @@ #define BTC_AV_INCLUDED TRUE #define BTA_AV_SINK_INCLUDED TRUE #define BTC_AV_SINK_INCLUDED TRUE -#define SBC_DEC_INCLUDED TRUE #define BTC_AV_SRC_INCLUDED TRUE +#if (UC_BT_A2DP_USE_EXTERNAL_CODEC == TRUE) +#define BTC_AV_EXT_CODEC TRUE +#define BTA_AV_EXT_CODEC TRUE +#else +#define SBC_DEC_INCLUDED TRUE #define SBC_ENC_INCLUDED TRUE +#endif +#if UC_BT_AVRCP_CT_COVER_ART_ENABLED +#define BTA_AV_CA_INCLUDED TRUE +#define BTC_AV_CA_INCLUDED TRUE +#define AVRC_CA_INCLUDED TRUE +#endif /* UC_BT_AVRCP_CT_COVER_ART_ENABLED */ #endif /* UC_BT_A2DP_ENABLED */ #if (UC_BT_SPP_ENABLED == TRUE) @@ -103,10 +113,13 @@ #if (UC_BT_L2CAP_ENABLED == TRUE) #define BTA_JV_INCLUDED TRUE #define BTC_L2CAP_INCLUDED TRUE -#define BTC_SDP_INCLUDED TRUE #define VND_BT_JV_BTA_L2CAP TRUE #endif /* UC_BT_L2CAP_ENABLED */ +#if (UC_BT_SDP_COMMON_ENABLED == TRUE) +#define BTC_SDP_COMMON_INCLUDED TRUE +#endif /* UC_BT_SDP_COMMON_ENABLED */ + #if (UC_BT_HFP_AG_ENABLED == TRUE) || (UC_BT_HFP_CLIENT_ENABLED == TRUE) #ifndef RFCOMM_INCLUDED #define RFCOMM_INCLUDED TRUE @@ -114,14 +127,22 @@ #ifndef BTM_SCO_INCLUDED #define BTM_SCO_INCLUDED TRUE #endif +#if (UC_BT_HFP_AUDIO_DATA_PATH_HCI == TRUE) +#if (UC_BT_HFP_USE_EXTERNAL_CODEC == TRUE) +#define BTC_HFP_EXT_CODEC TRUE +#define BTA_HFP_EXT_CODEC TRUE +#define PLC_INCLUDED FALSE +#else #ifndef SBC_DEC_INCLUDED #define SBC_DEC_INCLUDED TRUE #endif #ifndef SBC_ENC_INCLUDED #define SBC_ENC_INCLUDED TRUE #endif -#ifndef PLC_INCLUDED #define PLC_INCLUDED TRUE +#endif /* (UC_BT_HFP_USE_EXTERNAL_CODEC == TRUE) */ +#else +#define PLC_INCLUDED FALSE #endif #if (UC_BT_HFP_AG_ENABLED == TRUE) @@ -168,6 +189,27 @@ #define BTC_HD_INCLUDED TRUE #endif /* UC_BT_HID_DEVICE_ENABLED */ +#if UC_BT_HID_REMOVE_DEVICE_BONDING_ENABLED +#define BTC_HID_REMOVE_DEVICE_BONDING TRUE +#endif + +#if UC_BT_GOEPC_ENABLED +#ifndef RFCOMM_INCLUDED +#define RFCOMM_INCLUDED TRUE +#endif +#ifndef OBEX_INCLUDED +#define OBEX_INCLUDED TRUE +#endif +#define GOEPC_INCLUDED TRUE +#endif /* UC_BT_GOEPC_ENABLED */ + +#if UC_BT_PBAC_ENABLED +#define BTC_PBA_CLIENT_INCLUDED TRUE +#define BTC_PBA_SUPPORTED_FEAT UC_BT_PBAC_SUPPORTED_FEAT +#define BTC_PBA_PREFERRED_MTU UC_BT_PBAC_PREFERRED_MTU +#define BTA_PBA_CLIENT_INCLUDED TRUE +#endif + #endif /* UC_BT_CLASSIC_ENABLED */ /* This is set to enable use of GAP L2CAP connections. */ @@ -200,11 +242,64 @@ #define BLE_50_FEATURE_SUPPORT FALSE #endif +#if (UC_BT_BLE_ENABLED ==TRUE) #if (UC_BT_BLE_42_FEATURES_SUPPORTED == TRUE || BLE_50_FEATURE_SUPPORT == FALSE) #define BLE_42_FEATURE_SUPPORT TRUE #else #define BLE_42_FEATURE_SUPPORT FALSE #endif +#else +#define BLE_42_FEATURE_SUPPORT FALSE +#define BLE_50_FEATURE_SUPPORT FALSE +#endif /* UC_BT_BLE_ENABLED */ + +#if (UC_BT_BLE_42_DTM_TEST_EN == TRUE) +#define BLE_42_DTM_TEST_EN TRUE +#else +#define BLE_42_DTM_TEST_EN FALSE +#endif + +#if (UC_BT_BLE_42_ADV_EN == TRUE) +#define BLE_42_ADV_EN TRUE +#else +#define BLE_42_ADV_EN FALSE +#endif + +#if (UC_BT_BLE_42_SCAN_EN == TRUE) +#define BLE_42_SCAN_EN TRUE +#else +#define BLE_42_SCAN_EN FALSE +#endif + +#if (UC_BT_BLE_50_EXTEND_ADV_EN == TRUE) +#define BLE_50_EXTEND_ADV_EN TRUE +#else +#define BLE_50_EXTEND_ADV_EN FALSE +#endif + +#if (UC_BT_BLE_50_PERIODIC_ADV_EN == TRUE) +#define BLE_50_PERIODIC_ADV_EN TRUE +#else +#define BLE_50_PERIODIC_ADV_EN FALSE +#endif + +#if (UC_BT_BLE_50_EXTEND_SCAN_EN == TRUE) +#define BLE_50_EXTEND_SCAN_EN TRUE +#else +#define BLE_50_EXTEND_SCAN_EN FALSE +#endif + +#if (UC_BT_BLE_50_EXTEND_SYNC_EN == TRUE) +#define BLE_50_EXTEND_SYNC_EN TRUE +#else +#define BLE_50_EXTEND_SYNC_EN FALSE +#endif + +#if (UC_BT_BLE_50_DTM_TEST_EN == TRUE) +#define BLE_50_DTM_TEST_EN TRUE +#else +#define BLE_50_DTM_TEST_EN FALSE +#endif #if (UC_BT_BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) #define BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER TRUE @@ -224,6 +319,108 @@ #define BLE_FEAT_CREATE_SYNC_ENH FALSE #endif +#if (UC_BT_BLE_FEAT_ISO_EN == TRUE) +#define BLE_FEAT_ISO_EN TRUE +#else +#define BLE_FEAT_ISO_EN FALSE +#endif + +#if (UC_BT_BLE_FEAT_ISO_60_EN == TRUE) +#define BLE_FEAT_ISO_60_EN TRUE +#else +#define BLE_FEAT_ISO_60_EN FALSE +#endif + +#if (UC_BT_BLE_FEAT_ISO_BIG_BROCASTER == TRUE) +#define BLE_FEAT_ISO_BIG_BROCASTER_EN TRUE +#else +#define BLE_FEAT_ISO_BIG_BROCASTER_EN FALSE +#endif + +#if (UC_BT_BLE_FEAT_ISO_BIG_SYNCER == TRUE) +#define BLE_FEAT_ISO_BIG_SYNCER_EN TRUE +#else +#define BLE_FEAT_ISO_BIG_SYNCER_EN FALSE +#endif + +#if (UC_BT_BLE_FEAT_ISO_CIG_CENTRAL == TRUE) +#define BLE_FEAT_ISO_CIG_CENTRAL_EN TRUE +#else +#define BLE_FEAT_ISO_CIG_CENTRAL_EN FALSE +#endif + +#if (UC_BT_BLE_FEAT_ISO_CIG_PERIPHERAL == TRUE) +#define BLE_FEAT_ISO_CIG_PERIPHERAL_EN TRUE +#else +#define BLE_FEAT_ISO_CIG_PERIPHERAL_EN FALSE +#endif + +#if ((BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) || (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE)) +#define BLE_FEAT_ISO_CIG_EN TRUE +#else +#define BLE_FEAT_ISO_CIG_EN FALSE +#endif + +#ifdef UC_BT_BLE_ISO_CIS_MAX_COUNT +#define BLE_ISO_CIS_MAX_COUNT UC_BT_BLE_ISO_CIS_MAX_COUNT +#else +#define BLE_ISO_CIS_MAX_COUNT (0) +#endif + +#ifdef CONFIG_BT_BLE_ISO_BIS_MAX_COUNT +#define BLE_ISO_BIS_MAX_COUNT CONFIG_BT_BLE_ISO_BIS_MAX_COUNT +#else +#define BLE_ISO_BIS_MAX_COUNT (0) +#endif + +#ifdef UC_BT_BLE_ISO_STD_FLOW_CTRL +#define BLE_ISO_STD_FLOW_CTRL TRUE +#endif + +#ifdef UC_BT_BLE_ISO_NON_STD_FLOW_CTRL +#define BLE_ISO_NON_STD_FLOW_CTRL TRUE +#endif + +#if ((UC_BT_BLE_ISO_STD_FLOW_CTRL == TRUE) && (UC_BT_BLE_ISO_NON_STD_FLOW_CTRL == TRUE)) +#error "Only one of standard or non-standard can be enabled" +#endif + +#if (UC_BT_BLE_FEAT_CTE_EN == TRUE) +#define BLE_FEAT_CTE_EN TRUE +#else +#define BLE_FEAT_CTE_EN FALSE +#endif + +#if (UC_BT_BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#define BLE_FEAT_CTE_CONNECTIONLESS_EN TRUE +#else +#define BLE_FEAT_CTE_CONNECTIONLESS_EN FALSE +#endif + +#if (UC_BT_BLE_FEAT_CTE_CONNECTION_EN == TRUE) +#define BLE_FEAT_CTE_CONNECTION_EN TRUE +#else +#define BLE_FEAT_CTE_CONNECTION_EN FALSE +#endif + +#if (UC_BT_BLE_FEAT_POWER_CONTROL == TRUE) +#define BLE_FEAT_POWER_CONTROL_EN TRUE +#else +#define BLE_FEAT_POWER_CONTROL_EN FALSE +#endif + +#if (UC_BT_BLE_FEAT_CONN_SUBRATING == TRUE) +#define BLE_FEAT_CONN_SUBRATING TRUE +#else +#define BLE_FEAT_CONN_SUBRATING FALSE +#endif + +#if (UC_BT_BLE_VENDOR_HCI_EN == TRUE) +#define BLE_VENDOR_HCI_EN TRUE +#else +#define BLE_VENDOR_HCI_EN FALSE +#endif + #if (UC_BT_BLE_HIGH_DUTY_ADV_INTERVAL == TRUE) #define BLE_HIGH_DUTY_ADV_INTERVAL TRUE #else @@ -290,6 +487,18 @@ #define SMP_SLAVE_CON_PARAMS_UPD_ENABLE FALSE #endif /* UC_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE */ +#if (UC_BT_BLE_SMP_ID_RESET_ENABLE) +#define BLE_SMP_ID_RESET_ENABLE TRUE +#else +#define BLE_SMP_ID_RESET_ENABLE FALSE +#endif + +#if (UC_BT_BLE_SMP_BOND_NVS_FLASH) +#define BLE_SMP_BOND_NVS_FLASH TRUE +#else +#define BLE_SMP_BOND_NVS_FLASH FALSE +#endif + #ifdef UC_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP #define BLE_ADV_REPORT_FLOW_CONTROL (UC_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP && BLE_INCLUDED) #endif /* UC_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP */ @@ -367,6 +576,10 @@ #define BTC_AV_INCLUDED FALSE #endif +#ifndef BTC_AV_CA_INCLUDED +#define BTC_AV_CA_INCLUDED FALSE +#endif + #ifndef BTC_AV_SINK_INCLUDED #define BTC_AV_SINK_INCLUDED FALSE #endif @@ -375,6 +588,10 @@ #define BTC_AV_SRC_INCLUDED FALSE #endif +#ifndef BTC_AV_EXT_CODEC +#define BTC_AV_EXT_CODEC FALSE +#endif + #ifndef BTC_SPP_INCLUDED #define BTC_SPP_INCLUDED FALSE #endif @@ -387,6 +604,10 @@ #define BTC_HD_INCLUDED FALSE #endif +#ifndef BTC_HID_REMOVE_DEVICE_BONDING +#define BTC_HID_REMOVE_DEVICE_BONDING FALSE +#endif + #ifndef SBC_DEC_INCLUDED #define SBC_DEC_INCLUDED FALSE #endif @@ -395,6 +616,10 @@ #define SBC_ENC_INCLUDED FALSE #endif +#ifndef BTC_HFP_EXT_CODEC +#define BTC_HFP_EXT_CODEC FALSE +#endif + /****************************************************************************** ** ** BTA-layer components @@ -440,6 +665,14 @@ #define BTA_AV_INCLUDED FALSE #endif +#ifndef BTA_AV_CA_INCLUDED +#define BTA_AV_CA_INCLUDED FALSE +#endif + +#ifndef BTA_AV_EXT_CODEC +#define BTA_AV_EXT_CODEC FALSE +#endif + #ifndef BTA_AV_SINK_INCLUDED #define BTA_AV_SINK_INCLUDED FALSE #endif @@ -452,6 +685,10 @@ #define BTA_SDP_INCLUDED FALSE #endif +#ifndef BTA_HFP_EXT_CODEC +#define BTA_HFP_EXT_CODEC FALSE +#endif + /* This is set to enable use of GAP L2CAP connections. */ #ifndef VND_BT_JV_BTA_L2CAP #define VND_BT_JV_BTA_L2CAP FALSE @@ -523,12 +760,6 @@ #define BTA_AV_CO_CP_SCMS_T FALSE #endif -#if UC_BT_BLE_HOST_QUEUE_CONGESTION_CHECK -#define SCAN_QUEUE_CONGEST_CHECK TRUE -#else -#define SCAN_QUEUE_CONGEST_CHECK FALSE -#endif - #ifdef UC_CONFIG_BT_GATTS_PPCP_CHAR_GAP #define BTM_PERIPHERAL_ENABLED UC_CONFIG_BT_GATTS_PPCP_CHAR_GAP #endif @@ -569,7 +800,7 @@ #define BT_CLASSIC_BQB_INCLUDED FALSE #endif -/* This feature is used to eanble interleaved scan*/ +/* This feature is used to enable interleaved scan*/ #ifndef BTA_HOST_INTERLEAVE_SEARCH #define BTA_HOST_INTERLEAVE_SEARCH FALSE #endif @@ -904,9 +1135,95 @@ #define BTM_SEC_MAX_DEVICE_RECORDS UC_BT_SMP_MAX_BONDS #endif -/* The number of security records for services. 32 AS Default*/ +#if BTA_SDP_INCLUDED +#define BTM_SDP_SEC_SERVICE_RECORDS 1 +#else +#define BTM_SDP_SEC_SERVICE_RECORDS 0 +#endif + +#if BTA_AG_INCLUDED +#define BTM_AG_SEC_SERVICE_RECORDS 1 +#else +#define BTM_AG_SEC_SERVICE_RECORDS 0 +#endif + +#if BTA_HF_INCLUDED +#define BTM_HF_SEC_SERVICE_RECORDS 1 +#else +#define BTM_HF_SEC_SERVICE_RECORDS 0 +#endif + +#if BTA_JV_INCLUDED +#define BTM_JV_SEC_SERVICE_RECORDS (MAX_RFC_PORTS - BTM_HF_SEC_SERVICE_RECORDS - BTM_AG_SEC_SERVICE_RECORDS) +#else +#define BTM_JV_SEC_SERVICE_RECORDS 0 +#endif + +#if BTA_PBA_CLIENT_INCLUDED +#define BTM_PBA_SEC_SERVICE_RECORDS 2 +#else +#define BTM_PBA_SEC_SERVICE_RECORDS 0 +#endif + +#if BTA_AV_CA_INCLUDED +#define BTM_AC_VA_SEC_SERVICE_RECORDS 1 +#else +#define BTM_AC_VA_SEC_SERVICE_RECORDS 0 +#endif + +#if AVCT_INCLUDED +#if AVCT_BROWSE_INCLUDED +#define BTM_AVCT_SEC_SERVICE_RECORDS 2 +#else +#define BTM_AVCT_SEC_SERVICE_RECORDS 1 +#endif // AVCT_BROWSE_INCLUDED +#else +#define BTM_AVCT_SEC_SERVICE_RECORDS 0 +#endif + +#if AVDT_INCLUDED +#if AVDT_REPORTING +#define BTM_AVDT_SEC_SERVICE_RECORDS 3 +#else +#define BTM_AVDT_SEC_SERVICE_RECORDS 2 +#endif // AVDT_INCLUDED +#else +#define BTM_AVDT_SEC_SERVICE_RECORDS 0 +#endif + +#if GAP_CONN_INCLUDED +#define BTM_GAP_SEC_SERVICE_RECORDS GAP_MAX_CONNECTIONS +#else +#define BTM_GAP_SEC_SERVICE_RECORDS 0 +#endif + +#if HID_DEV_INCLUDED +#define BTM_HIDD_SEC_SERVICE_RECORDS 3 +#else +#define BTM_HIDD_SEC_SERVICE_RECORDS 0 +#endif + +#if HID_HOST_INCLUDED +#define BTM_HIDH_SEC_SERVICE_RECORDS 3 +#else +#define BTM_HIDH_SEC_SERVICE_RECORDS 0 +#endif + +#if BLE_INCLUDED +#define BTM_GATT_SEC_SERVICE_RECORDS 1 +#else +#define BTM_GATT_SEC_SERVICE_RECORDS 0 +#endif + +#define BTM_SEC_DEV_SERVICE_RECORDS 1 + +/* The number of security records for services. */ #ifndef BTM_SEC_MAX_SERVICE_RECORDS -#define BTM_SEC_MAX_SERVICE_RECORDS 8 // 32 +#define BTM_SEC_MAX_SERVICE_RECORDS (BTM_SDP_SEC_SERVICE_RECORDS + BTM_AG_SEC_SERVICE_RECORDS \ + + BTM_AVCT_SEC_SERVICE_RECORDS + BTM_AVDT_SEC_SERVICE_RECORDS + BTM_GAP_SEC_SERVICE_RECORDS \ + + BTM_HIDD_SEC_SERVICE_RECORDS + BTM_GATT_SEC_SERVICE_RECORDS + BTM_PBA_SEC_SERVICE_RECORDS \ + + BTM_HIDH_SEC_SERVICE_RECORDS + BTM_SEC_DEV_SERVICE_RECORDS + BTM_HF_SEC_SERVICE_RECORDS \ + + BTM_JV_SEC_SERVICE_RECORDS + BTM_AC_VA_SEC_SERVICE_RECORDS ) #endif /* If True, force a retrieval of remote device name for each bond in case it's changed */ @@ -1028,10 +1345,12 @@ **************************/ /* 4.1/4.2 secure connections feature */ -#ifndef SC_MODE_INCLUDED -// Disable AES-CCM (BT 4.1) for BT Classic to workaround controller AES issue. E0 encryption (BT 4.0) will be used. +#if defined(CONFIG_IDF_TARGET_ESP32) && (BT_CONTROLLER_INCLUDED == TRUE) +// Disable AES-CCM (BT 4.1) for BT Classic to workaround controller AES issue on ESP32 controller. E0 encryption (BT 4.0) will be used. #define SC_MODE_INCLUDED FALSE -#endif +#else +#define SC_MODE_INCLUDED TRUE +#endif // CONFIG_IDF_TARGET_ESP32 /* Used for conformance testing ONLY */ #ifndef BTM_BLE_CONFORMANCE_TESTING @@ -1247,7 +1566,72 @@ #endif #ifndef BLE_ANDROID_CONTROLLER_SCAN_FILTER -#define BLE_ANDROID_CONTROLLER_SCAN_FILTER TRUE +#define BLE_ANDROID_CONTROLLER_SCAN_FILTER FALSE +#endif + +#ifndef BLE_HOST_BLE_MULTI_ADV_EN +#define BLE_HOST_BLE_MULTI_ADV_EN FALSE +#endif + +#ifndef BLE_HOST_TRACK_ADVERTISER_EN +#define BLE_HOST_TRACK_ADVERTISER_EN FALSE +#endif + +#ifndef BLE_HOST_ENERGY_INFO_EN +#define BLE_HOST_ENERGY_INFO_EN FALSE +#endif + + +#ifndef BLE_HOST_ENABLE_TEST_MODE_EN +#define BLE_HOST_ENABLE_TEST_MODE_EN FALSE +#endif + +#ifndef BLE_HOST_EXECUTE_CBACK_EN +#define BLE_HOST_EXECUTE_CBACK_EN FALSE +#endif + +#ifndef BLE_HOST_REMOVE_ALL_ACL_EN +#define BLE_HOST_REMOVE_ALL_ACL_EN FALSE +#endif + +#ifndef BLE_HOST_REMOVE_AN_ACL_EN +#define BLE_HOST_REMOVE_AN_ACL_EN FALSE +#endif + +#ifndef BLE_HOST_READ_TX_POWER_EN +#define BLE_HOST_READ_TX_POWER_EN FALSE +#endif + +#ifndef BLE_HOST_STOP_ADV_UNUSED +#define BLE_HOST_STOP_ADV_UNUSED FALSE +#endif + +#ifndef BLE_HOST_BLE_OBSERVE_EN +#define BLE_HOST_BLE_OBSERVE_EN FALSE +#endif + +#ifndef BLE_HOST_BLE_SCAN_PARAM_UNUSED +#define BLE_HOST_BLE_SCAN_PARAM_UNUSED FALSE +#endif + +#ifndef BLE_HOST_CONN_SCAN_PARAM_EN +#define BLE_HOST_CONN_SCAN_PARAM_EN FALSE +#endif + +#ifndef BLE_HOST_SETUP_STORAGE_EN +#define BLE_HOST_SETUP_STORAGE_EN FALSE +#endif + +#ifndef BLE_HOST_READ_SCAN_REPORTS_EN +#define BLE_HOST_READ_SCAN_REPORTS_EN FALSE +#endif + +#ifndef BLE_HOST_BATCH_SCAN_EN +#define BLE_HOST_BATCH_SCAN_EN FALSE +#endif + +#ifndef BLE_HOST_BG_CONNECT_EN +#define BLE_HOST_BG_CONNECT_EN FALSE #endif #ifndef LOCAL_BLE_CONTROLLER_ID @@ -1281,7 +1665,7 @@ #ifdef CONFIG_IDF_TARGET_ESP32 #define BTM_BLE_ADV_TX_POWER {-12, -9, -6, -3, 0, 3, 6, 9} #else -#define BTM_BLE_ADV_TX_POWER {-24, -21, -18, -15, -12, -9, -6, -3, 0, 3, 6, 9, 12, 15, 18, 21} +#define BTM_BLE_ADV_TX_POWER {-24, -21, -18, -15, -12, -9, -6, -3, 0, 3, 6, 9, 12, 15, 18, 20} #endif #endif @@ -1289,7 +1673,7 @@ #ifdef CONFIG_IDF_TARGET_ESP32 #define BTM_TX_POWER {-12, -9, -6, -3, 0, 3, 6, 9} #else -#define BTM_TX_POWER {-24, -21, -18, -15, -12, -9, -6, -3, 0, 3, 6, 9, 12, 15, 18, 21} +#define BTM_TX_POWER {-24, -21, -18, -15, -12, -9, -6, -3, 0, 3, 6, 9, 12, 15, 18, 20} #endif #endif @@ -1385,7 +1769,7 @@ #define GATT_CONFORMANCE_TESTING FALSE #endif -/* number of background connection device allowence, ideally to be the same as WL size +/* number of background connection device allowance, ideally to be the same as WL size */ #ifndef GATT_MAX_BG_CONN_DEV #define GATT_MAX_BG_CONN_DEV 8 /*MAX is 32*/ @@ -1494,20 +1878,21 @@ /* The maximum number of attributes in each record. */ #ifndef SDP_MAX_REC_ATTR -#if (defined(HID_DEV_INCLUDED) && (HID_DEV_INCLUDED==TRUE)) || (defined(BTC_SDP_INCLUDED) && (BTC_SDP_INCLUDED==TRUE)) +#if (defined(HID_DEV_INCLUDED) && (HID_DEV_INCLUDED==TRUE)) || (defined(BTC_SDP_COMMON_INCLUDED) && (BTC_SDP_COMMON_INCLUDED==TRUE)) #define SDP_MAX_REC_ATTR 25 #else #define SDP_MAX_REC_ATTR 8 #endif /* defined(HID_DEV_INCLUDED) && (HID_DEV_INCLUDED==TRUE) */ #endif +/* The maximum length, in bytes, of all SDP attributes combined. */ #ifndef SDP_MAX_PAD_LEN -#define SDP_MAX_PAD_LEN 300 +#define SDP_MAX_PAD_LEN UC_SDP_MAX_PAD_LEN #endif /* The maximum length, in bytes, of an attribute. */ #ifndef SDP_MAX_ATTR_LEN -#define SDP_MAX_ATTR_LEN 400 +#define SDP_MAX_ATTR_LEN UC_SDP_MAX_ATTR_LEN #endif /* The maximum number of attribute filters supported by SDP databases. */ @@ -1800,6 +2185,26 @@ #define OBX_FCR_TX_POOL_ID 3 #endif +/* Maximum OBEX connection allowed */ +#ifndef OBEX_MAX_CONNECTION +#define OBEX_MAX_CONNECTION 3 +#endif + +/* Maximum OBEX server allowed */ +#ifndef OBEX_MAX_SERVER +#define OBEX_MAX_SERVER 2 +#endif + +/****************************************************************************** +** +** GOEP +** +******************************************************************************/ + +/* Maximum GOEP client connection allowed */ +#ifndef GOEPC_MAX_CONNECTION +#define GOEPC_MAX_CONNECTION 3 +#endif /****************************************************************************** ** @@ -2132,6 +2537,20 @@ #define HID_HOST_REPAGE_WIN (2) #endif +/************************************************************************* +** Definitions for OBEX +*/ +#ifndef OBEX_INCLUDED +#define OBEX_INCLUDED FALSE +#endif + +/************************************************************************* +** Definitions for OBEX +*/ +#ifndef GOEPC_INCLUDED +#define GOEPC_INCLUDED FALSE +#endif + /************************************************************************* * A2DP Definitions */ @@ -2170,6 +2589,10 @@ #define AVRC_INCLUDED FALSE #endif +#ifndef AVRC_CA_INCLUDED +#define AVRC_CA_INCLUDED FALSE +#endif + #ifndef AVRC_METADATA_INCLUDED #if AVRC_INCLUDED == TRUE #define AVRC_METADATA_INCLUDED TRUE @@ -2372,12 +2795,6 @@ The maximum number of payload octets that the local device can receive in a sing #define BTSNOOP_MEM FALSE #endif -#if UC_HEAP_ALLOCATION_FROM_SPIRAM_FIRST -#define HEAP_ALLOCATION_FROM_SPIRAM_FIRST TRUE -#else -#define HEAP_ALLOCATION_FROM_SPIRAM_FIRST FALSE -#endif - #include "common/bt_trace.h" #endif /* BT_TARGET_H */ diff --git a/lib/bt/host/bluedroid/common/include/common/bt_trace.h b/lib/bt/host/bluedroid/common/include/common/bt_trace.h index a4f1ca74..b5f0a9bb 100644 --- a/lib/bt/host/bluedroid/common/include/common/bt_trace.h +++ b/lib/bt/host/bluedroid/common/include/common/bt_trace.h @@ -25,6 +25,9 @@ #include "stack/bt_types.h" #include "bt_common.h" +#if (BT_BLE_LOG_SPI_OUT_HOST_ENABLED && !CLASSIC_BT_INCLUDED) +#include "ble_log/ble_log_spi_out.h" +#endif // (BT_BLE_LOG_SPI_OUT_HOST_ENABLED && !CLASSIC_BT_INCLUDED) static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t len) { uint16_t i; @@ -217,20 +220,76 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l /* Define tracing for BTM */ +#if (BT_BLE_LOG_SPI_OUT_HOST_ENABLED && !CLASSIC_BT_INCLUDED) + +#define BTM_TRACE_ERROR(fmt, args...) { \ + if (btm_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(BTM, ERROR)) BT_PRINT_E("BT_BTM", fmt, ## args); \ +} + +#define BTM_TRACE_WARNING(fmt, args...) { \ + if (btm_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(BTM, WARNING)) BT_PRINT_W("BT_BTM", fmt, ## args); \ +} + +#define BTM_TRACE_API(fmt, args...) { \ + ble_log_spi_out_printf_enh(BLE_LOG_SPI_OUT_SOURCE_BLUEDROID, BLE_LOG_SPI_OUT_LEVEL_INFO, "BT_BTM", fmt, ## args); \ + if (btm_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(BTM, API)) BT_PRINT_I("BT_BTM", fmt, ## args); \ +} + +#define BTM_TRACE_EVENT(fmt, args...) { \ + ble_log_spi_out_printf_enh(BLE_LOG_SPI_OUT_SOURCE_BLUEDROID, BLE_LOG_SPI_OUT_LEVEL_DEBUG, "BT_BTM", fmt, ## args); \ + if (btm_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(BTM, EVENT)) BT_PRINT_D("BT_BTM", fmt, ## args); \ +} + +#define BTM_TRACE_DEBUG(fmt, args...) { \ + if (btm_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(BTM, DEBUG)) BT_PRINT_D("BT_BTM", fmt, ## args); \ +} + +#else + #define BTM_TRACE_ERROR(fmt, args...) {if (btm_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(BTM, ERROR)) BT_PRINT_E("BT_BTM", fmt, ## args);} #define BTM_TRACE_WARNING(fmt, args...) {if (btm_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(BTM, WARNING)) BT_PRINT_W("BT_BTM", fmt, ## args);} #define BTM_TRACE_API(fmt, args...) {if (btm_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(BTM,API)) BT_PRINT_I("BT_BTM", fmt, ## args);} #define BTM_TRACE_EVENT(fmt, args...) {if (btm_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(BTM,EVENT)) BT_PRINT_D("BT_BTM", fmt, ## args);} #define BTM_TRACE_DEBUG(fmt, args...) {if (btm_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(BTM,DEBUG)) BT_PRINT_D("BT_BTM", fmt, ## args);} +#endif // (BT_BLE_LOG_SPI_OUT_HOST_ENABLED && !CLASSIC_BT_INCLUDED) + /* Define tracing for the L2CAP unit */ +#if (BT_BLE_LOG_SPI_OUT_HOST_ENABLED && !CLASSIC_BT_INCLUDED) + +#define L2CAP_TRACE_ERROR(fmt, args...) { \ + if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(L2CAP, ERROR)) BT_PRINT_E("BT_L2CAP", fmt, ## args); \ +} + +#define L2CAP_TRACE_WARNING(fmt, args...) { \ + if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(L2CAP, WARNING)) BT_PRINT_W("BT_L2CAP", fmt, ## args); \ +} + +#define L2CAP_TRACE_API(fmt, args...) { \ + ble_log_spi_out_printf_enh(BLE_LOG_SPI_OUT_SOURCE_BLUEDROID, BLE_LOG_SPI_OUT_LEVEL_INFO, "BT_L2CAP", fmt, ## args); \ + if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(L2CAP, API)) BT_PRINT_I("BT_L2CAP", fmt, ## args); \ +} + +#define L2CAP_TRACE_EVENT(fmt, args...) { \ + if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(L2CAP, EVENT)) BT_PRINT_D("BT_L2CAP", fmt, ## args); \ +} + +#define L2CAP_TRACE_DEBUG(fmt, args...) { \ + if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(L2CAP, DEBUG)) BT_PRINT_D("BT_L2CAP", fmt, ## args); \ +} + +#else + #define L2CAP_TRACE_ERROR(fmt, args...) {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(L2CAP, ERROR)) BT_PRINT_E("BT_L2CAP", fmt, ## args);} #define L2CAP_TRACE_WARNING(fmt, args...) {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(L2CAP, WARNING)) BT_PRINT_W("BT_L2CAP", fmt, ## args);} #define L2CAP_TRACE_API(fmt, args...) {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(L2CAP,API)) BT_PRINT_I("BT_L2CAP", fmt, ## args);} #define L2CAP_TRACE_EVENT(fmt, args...) {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(L2CAP,EVENT)) BT_PRINT_D("BT_L2CAP", fmt, ## args);} #define L2CAP_TRACE_DEBUG(fmt, args...) {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(L2CAP,DEBUG)) BT_PRINT_D("BT_L2CAP", fmt, ## args);} +#endif // (BT_BLE_LOG_SPI_OUT_HOST_ENABLED && !CLASSIC_BT_INCLUDED) + + /* Define tracing for the SDP unit */ #define SDP_TRACE_ERROR(fmt, args...) {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(SDP, ERROR)) BT_PRINT_E("BT_SDP", fmt, ## args);} @@ -248,11 +307,35 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l #define RFCOMM_TRACE_DEBUG(fmt, args...) {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(RFCOMM,DEBUG)) BT_PRINT_D("BT_RFCOMM", fmt, ## args);} /* Generic Access Profile traces */ +#if (BT_BLE_LOG_SPI_OUT_HOST_ENABLED && !CLASSIC_BT_INCLUDED) + +#define GAP_TRACE_ERROR(fmt, args...) { \ + if (gap_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(GAP, ERROR)) BT_PRINT_E("BT_GAP", fmt, ## args); \ +} + +#define GAP_TRACE_WARNING(fmt, args...) { \ + if (gap_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(GAP, WARNING)) BT_PRINT_W("BT_GAP", fmt, ## args); \ +} + +#define GAP_TRACE_API(fmt, args...) { \ + ble_log_spi_out_printf_enh(BLE_LOG_SPI_OUT_SOURCE_BLUEDROID, BLE_LOG_SPI_OUT_LEVEL_INFO, "BT_GAP", fmt, ## args); \ + if (gap_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(GAP, API)) BT_PRINT_I("BT_GAP", fmt, ## args); \ +} + +#define GAP_TRACE_EVENT(fmt, args...) { \ + if (gap_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(GAP, EVENT)) BT_PRINT_D("BT_GAP", fmt, ## args); \ +} + +#else + #define GAP_TRACE_ERROR(fmt, args...) {if (gap_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(GAP, ERROR)) BT_PRINT_E("BT_GAP", fmt, ## args);} #define GAP_TRACE_API(fmt, args...) {if (gap_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(GAP,API)) BT_PRINT_I("BT_GAP", fmt, ## args);} #define GAP_TRACE_EVENT(fmt, args...) {if (gap_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(GAP,EVENT)) BT_PRINT_D("BT_GAP", fmt, ## args);} #define GAP_TRACE_WARNING(fmt, args...) {if (gap_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(GAP, WARNING)) BT_PRINT_W("BT_GAP", fmt, ## args);} +#endif // (BT_BLE_LOG_SPI_OUT_HOST_ENABLED && !CLASSIC_BT_INCLUDED) + + /* define traces for HID Host */ #define HIDH_TRACE_ERROR(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(HIDH, ERROR)) BT_PRINT_E("BT_HIDH", fmt, ## args);} #define HIDH_TRACE_WARNING(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(HIDH, WARNING)) BT_PRINT_W("BT_HIDH", fmt, ## args);} @@ -316,6 +399,34 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l #define AVRC_TRACE_EVENT(fmt, args...) {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(AVRC,EVENT)) BT_PRINT_D("BT_AVRC", fmt, ## args);} #define AVRC_TRACE_DEBUG(fmt, args...) {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(AVRC,DEBUG)) BT_PRINT_D("BT_AVRC", fmt, ## args);} +/* Define tracing for OBEX */ +#define OBEX_TRACE_ERROR(fmt, args...) {if (obex_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(AVRC, ERROR)) BT_PRINT_E("BT_OBEX", fmt, ## args);} +#define OBEX_TRACE_WARNING(fmt, args...) {if (obex_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(AVRC, WARNING)) BT_PRINT_W("BT_OBEX", fmt, ## args);} +#define OBEX_TRACE_API(fmt, args...) {if (obex_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(AVRC,API)) BT_PRINT_I("BT_OBEX", fmt, ## args);} +#define OBEX_TRACE_EVENT(fmt, args...) {if (obex_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(AVRC,EVENT)) BT_PRINT_D("BT_OBEX", fmt, ## args);} +#define OBEX_TRACE_DEBUG(fmt, args...) {if (obex_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(AVRC,DEBUG)) BT_PRINT_D("BT_OBEX", fmt, ## args);} + +/* Define tracing for OBEX_TL_L2CAP */ +#define OBEX_TL_L2CAP_TRACE_ERROR(fmt, args...) {if (obex_tl_l2cap_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(AVRC, ERROR)) BT_PRINT_E("OBEX_TL_L2CAP", fmt, ## args);} +#define OBEX_TL_L2CAP_TRACE_WARNING(fmt, args...) {if (obex_tl_l2cap_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(AVRC, WARNING)) BT_PRINT_W("OBEX_TL_L2CAP", fmt, ## args);} +#define OBEX_TL_L2CAP_TRACE_API(fmt, args...) {if (obex_tl_l2cap_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(AVRC,API)) BT_PRINT_I("OBEX_TL_L2CAP", fmt, ## args);} +#define OBEX_TL_L2CAP_TRACE_EVENT(fmt, args...) {if (obex_tl_l2cap_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(AVRC,EVENT)) BT_PRINT_D("OBEX_TL_L2CAP", fmt, ## args);} +#define OBEX_TL_L2CAP_TRACE_DEBUG(fmt, args...) {if (obex_tl_l2cap_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(AVRC,DEBUG)) BT_PRINT_D("OBEX_TL_L2CAP", fmt, ## args);} + +/* Define tracing for OBEX_TL_RFCOMM */ +#define OBEX_TL_RFCOMM_TRACE_ERROR(fmt, args...) {if (obex_tl_rfcomm_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(AVRC, ERROR)) BT_PRINT_E("OBEX_TL_RFCOMM", fmt, ## args);} +#define OBEX_TL_RFCOMM_TRACE_WARNING(fmt, args...) {if (obex_tl_rfcomm_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(AVRC, WARNING)) BT_PRINT_W("OBEX_TL_RFCOMM", fmt, ## args);} +#define OBEX_TL_RFCOMM_TRACE_API(fmt, args...) {if (obex_tl_rfcomm_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(AVRC,API)) BT_PRINT_I("OBEX_TL_RFCOMM", fmt, ## args);} +#define OBEX_TL_RFCOMM_TRACE_EVENT(fmt, args...) {if (obex_tl_rfcomm_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(AVRC,EVENT)) BT_PRINT_D("OBEX_TL_RFCOMM", fmt, ## args);} +#define OBEX_TL_RFCOMM_TRACE_DEBUG(fmt, args...) {if (obex_tl_rfcomm_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(AVRC,DEBUG)) BT_PRINT_D("OBEX_TL_RFCOMM", fmt, ## args);} + +/* Define tracing for GOEPC */ +#define GOEPC_TRACE_ERROR(fmt, args...) {if (goepc_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(AVRC, ERROR)) BT_PRINT_E("BT_GOEPC", fmt, ## args);} +#define GOEPC_TRACE_WARNING(fmt, args...) {if (goepc_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(AVRC, WARNING)) BT_PRINT_W("BT_GOEPC", fmt, ## args);} +#define GOEPC_TRACE_API(fmt, args...) {if (goepc_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(AVRC,API)) BT_PRINT_I("BT_GOEPC", fmt, ## args);} +#define GOEPC_TRACE_EVENT(fmt, args...) {if (goepc_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(AVRC,EVENT)) BT_PRINT_D("BT_GOEPC", fmt, ## args);} +#define GOEPC_TRACE_DEBUG(fmt, args...) {if (goepc_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(AVRC,DEBUG)) BT_PRINT_D("BT_GOEPC", fmt, ## args);} + /* MCAP */ #define MCA_TRACE_ERROR(fmt, args...) {if (mca_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(MCA, ERROR)) BT_PRINT_E("BT_MCA", fmt, ## args);} @@ -326,20 +437,73 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l /* Define tracing for the ATT/GATT unit */ +#if (BT_BLE_LOG_SPI_OUT_HOST_ENABLED && !CLASSIC_BT_INCLUDED) + +#define GATT_TRACE_ERROR(fmt, args...) { \ + if (gatt_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(GATT, ERROR)) BT_PRINT_E("BT_GATT", fmt, ## args); \ +} + +#define GATT_TRACE_WARNING(fmt, args...) { \ + if (gatt_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(GATT, WARNING)) BT_PRINT_W("BT_GATT", fmt, ## args); \ +} + +#define GATT_TRACE_API(fmt, args...) { \ + ble_log_spi_out_printf_enh(BLE_LOG_SPI_OUT_SOURCE_BLUEDROID, BLE_LOG_SPI_OUT_LEVEL_INFO, "BT_GATT", fmt, ## args); \ + if (gatt_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(GATT, API)) BT_PRINT_I("BT_GATT", fmt, ## args); \ +} + +#define GATT_TRACE_EVENT(fmt, args...) { \ + if (gatt_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(GATT, EVENT)) BT_PRINT_D("BT_GATT", fmt, ## args); \ +} + +#define GATT_TRACE_DEBUG(fmt, args...) { \ + if (gatt_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(GATT, DEBUG)) BT_PRINT_D("BT_GATT", fmt, ## args); \ +} + +#else + #define GATT_TRACE_ERROR(fmt, args...) {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(GATT, ERROR)) BT_PRINT_E("BT_GATT", fmt, ## args);} #define GATT_TRACE_WARNING(fmt, args...) {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(GATT, WARNING)) BT_PRINT_W("BT_GATT", fmt, ## args);} #define GATT_TRACE_API(fmt, args...) {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(GATT,API)) BT_PRINT_I("BT_GATT", fmt, ## args);} #define GATT_TRACE_EVENT(fmt, args...) {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(GATT,EVENT)) BT_PRINT_D("BT_GATT", fmt, ## args);} #define GATT_TRACE_DEBUG(fmt, args...) {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(GATT,DEBUG)) BT_PRINT_D("BT_GATT", fmt, ## args);} +#endif // (BT_BLE_LOG_SPI_OUT_HOST_ENABLED && !CLASSIC_BT_INCLUDED) + /* Define tracing for the SMP unit */ +#if (BT_BLE_LOG_SPI_OUT_HOST_ENABLED && !CLASSIC_BT_INCLUDED) + +#define SMP_TRACE_ERROR(fmt, args...) { \ + if (smp_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(SMP, ERROR)) BT_PRINT_E("BT_SMP", fmt, ## args); \ +} + +#define SMP_TRACE_WARNING(fmt, args...) { \ + if (smp_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(SMP, WARNING)) BT_PRINT_W("BT_SMP", fmt, ## args); \ +} + +#define SMP_TRACE_API(fmt, args...) { \ + ble_log_spi_out_printf_enh(BLE_LOG_SPI_OUT_SOURCE_BLUEDROID, BLE_LOG_SPI_OUT_LEVEL_INFO, "BT_SMP", fmt, ## args); \ + if (smp_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(SMP, API)) BT_PRINT_I("BT_SMP", fmt, ## args); \ +} + +#define SMP_TRACE_EVENT(fmt, args...) { \ + if (smp_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(SMP, EVENT)) BT_PRINT_D("BT_SMP", fmt, ## args); \ +} + +#define SMP_TRACE_DEBUG(fmt, args...) { \ + if (smp_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(SMP, DEBUG)) BT_PRINT_D("BT_SMP", fmt, ## args); \ +} + +#else + #define SMP_TRACE_ERROR(fmt, args...) {if (smp_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(SMP, ERROR)) BT_PRINT_E("BT_SMP", fmt, ## args);} #define SMP_TRACE_WARNING(fmt, args...) {if (smp_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(SMP, WARNING)) BT_PRINT_W("BT_SMP", fmt, ## args);} #define SMP_TRACE_API(fmt, args...) {if (smp_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(SMP,API)) BT_PRINT_I("BT_SMP", fmt, ## args);} #define SMP_TRACE_EVENT(fmt, args...) {if (smp_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(SMP,EVENT)) BT_PRINT_D("BT_SMP", fmt, ## args);} #define SMP_TRACE_DEBUG(fmt, args...) {if (smp_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(SMP,DEBUG)) BT_PRINT_D("BT_SMP", fmt, ## args);} +#endif // (BT_BLE_LOG_SPI_OUT_HOST_ENABLED && !CLASSIC_BT_INCLUDED) extern UINT8 btif_trace_level; @@ -484,6 +648,34 @@ extern UINT8 btif_trace_level; #define AVRC_TRACE_DEBUG(fmt, args...) #define AVRC_TRACE_API(fmt, args...) +/* Define tracing for OBEX */ +#define OBEX_TRACE_ERROR(fmt, args...) +#define OBEX_TRACE_WARNING(fmt, args...) +#define OBEX_TRACE_API(fmt, args...) +#define OBEX_TRACE_EVENT(fmt, args...) +#define OBEX_TRACE_DEBUG(fmt, args...) + +/* Define tracing for OBEX L2CAP transport layer */ +#define OBEX_TL_L2CAP_TRACE_ERROR(fmt, args...) +#define OBEX_TL_L2CAP_TRACE_WARNING(fmt, args...) +#define OBEX_TL_L2CAP_TRACE_API(fmt, args...) +#define OBEX_TL_L2CAP_TRACE_EVENT(fmt, args...) +#define OBEX_TL_L2CAP_TRACE_DEBUG(fmt, args...) + +/* Define tracing for OBEX RFCOMM transport layer */ +#define OBEX_TL_RFCOMM_TRACE_ERROR(fmt, args...) +#define OBEX_TL_RFCOMM_TRACE_WARNING(fmt, args...) +#define OBEX_TL_RFCOMM_TRACE_API(fmt, args...) +#define OBEX_TL_RFCOMM_TRACE_EVENT(fmt, args...) +#define OBEX_TL_RFCOMM_TRACE_DEBUG(fmt, args...) + +/* Define tracing for GOEPC */ +#define GOEPC_TRACE_ERROR(fmt, args...) +#define GOEPC_TRACE_WARNING(fmt, args...) +#define GOEPC_TRACE_API(fmt, args...) +#define GOEPC_TRACE_EVENT(fmt, args...) +#define GOEPC_TRACE_DEBUG(fmt, args...) + /* MCAP */ #define MCA_TRACE_ERROR(fmt, args...) diff --git a/lib/bt/host/bluedroid/config/include/config/stack_config.h b/lib/bt/host/bluedroid/config/include/config/stack_config.h index 8b777723..ca48316e 100644 --- a/lib/bt/host/bluedroid/config/include/config/stack_config.h +++ b/lib/bt/host/bluedroid/config/include/config/stack_config.h @@ -12,10 +12,11 @@ struct bluedroid_config { bool (*get_ssp_enabled)(void); + bool (*get_sc_enabled) (void); }; -bt_status_t bluedriod_config_init(esp_bluedroid_config_t *cfg); +bt_status_t bluedroid_config_init(esp_bluedroid_config_t *cfg); -void bluedriod_config_deinit(void); +void bluedroid_config_deinit(void); -const struct bluedroid_config *bluedriod_config_get(void); +const struct bluedroid_config *bluedroid_config_get(void); diff --git a/lib/bt/host/bluedroid/config/stack_config.c b/lib/bt/host/bluedroid/config/stack_config.c index 66d04a63..94ec24d7 100644 --- a/lib/bt/host/bluedroid/config/stack_config.c +++ b/lib/bt/host/bluedroid/config/stack_config.c @@ -25,7 +25,14 @@ static bool get_ssp_enabled(void) return cfg->ssp_en; } -bt_status_t bluedriod_config_init(esp_bluedroid_config_t *cfg) +static bool get_sc_enabled(void) +{ + assert(s_stack_config_env); + esp_bluedroid_config_t *cfg = &s_stack_config_env->cfg; + return cfg->sc_en; +} + +bt_status_t bluedroid_config_init(esp_bluedroid_config_t *cfg) { s_stack_config_env = osi_calloc(sizeof(struct stack_config_env_tag)); if (!s_stack_config_env) { @@ -36,11 +43,12 @@ bt_status_t bluedriod_config_init(esp_bluedroid_config_t *cfg) struct bluedroid_config *interface = &s_stack_config_env->interface; interface->get_ssp_enabled = get_ssp_enabled; + interface->get_sc_enabled = get_sc_enabled; return BT_STATUS_SUCCESS; } -void bluedriod_config_deinit(void) +void bluedroid_config_deinit(void) { if (s_stack_config_env) { osi_free(s_stack_config_env); @@ -48,7 +56,7 @@ void bluedriod_config_deinit(void) } } -const struct bluedroid_config *bluedriod_config_get(void) +const struct bluedroid_config *bluedroid_config_get(void) { assert(s_stack_config_env); return &s_stack_config_env->interface; diff --git a/lib/bt/host/bluedroid/device/controller.c b/lib/bt/host/bluedroid/device/controller.c index beb7d676..4b68eb93 100644 --- a/lib/bt/host/bluedroid/device/controller.c +++ b/lib/bt/host/bluedroid/device/controller.c @@ -31,10 +31,10 @@ #include "osi/future.h" #include "config/stack_config.h" #if (BLE_50_FEATURE_SUPPORT == TRUE) -const bt_event_mask_t BLE_EVENT_MASK = { "\x00\x00\x00\x00\x00\xff\xff\xff" }; +const bt_event_mask_t BLE_EVENT_MASK = { "\x00\x00\x00\x07\xff\xff\xff\xff" }; #else const bt_event_mask_t BLE_EVENT_MASK = { "\x00\x00\x00\x00\x00\x00\x06\x7f" }; -#endif +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_INCLUDED) const bt_event_mask_t CLASSIC_EVENT_MASK = { HCI_DUMO_EVENT_MASK_EXT }; @@ -83,7 +83,12 @@ typedef struct { bool simple_pairing_supported; bool secure_connections_supported; #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) uint16_t ble_ext_adv_data_max_len; +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) + uint16_t get_ble_periodic_advertiser_list_size; +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #endif //#if (BLE_50_FEATURE_SUPPORT == TRUE) } controller_local_param_t; @@ -96,11 +101,16 @@ static controller_local_param_t *controller_param_ptr; #define AWAIT_COMMAND(command) future_await(controller_param.hci->transmit_command_futured(command)) +static bool loaded = false; // Module lifecycle functions static void start_up(void) { BT_HDR *response; +#if (BLE_FEAT_ISO_EN == TRUE) + uint16_t iso_pktlen = 0; + uint8_t iso_max_pkts = 0; +#endif // #if (BLE_FEAT_ISO_EN == TRUE) // Send the initial reset command response = AWAIT_COMMAND(controller_param.packet_factory->make_reset()); @@ -119,11 +129,13 @@ static void start_up(void) response = AWAIT_COMMAND(controller_param.packet_factory->make_set_c2h_flow_control(HCI_HOST_FLOW_CTRL_ACL_ON)); controller_param.packet_parser->parse_generic_command_complete(response); #endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE +#if (BLE_42_SCAN_EN == TRUE) #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) // Enable adv flow control response = AWAIT_COMMAND(controller_param.packet_factory->make_set_adv_report_flow_control(HCI_HOST_FLOW_CTRL_ADV_REPORT_ON, (uint16_t)BLE_ADV_REPORT_FLOW_CONTROL_NUM, (uint16_t)BLE_ADV_REPORT_DISCARD_THRSHOLD)); controller_param.packet_parser->parse_generic_command_complete(response); #endif +#endif // #if (BLE_42_SCAN_EN == TRUE) // Tell the controller about our buffer sizes and buffer counts next // TODO(zachoverflow): factor this out. eww l2cap contamination. And why just a hardcoded 10? response = AWAIT_COMMAND( @@ -176,7 +188,7 @@ static void start_up(void) // dependent on what we configure from page 0 and host SSP configuration controller_param.simple_pairing_supported = HCI_SIMPLE_PAIRING_SUPPORTED( controller_param.features_classic[0].as_array) && - (bluedriod_config_get()->get_ssp_enabled()); + (bluedroid_config_get()->get_ssp_enabled()); if (controller_param.simple_pairing_supported) { response = AWAIT_COMMAND(controller_param.packet_factory->make_write_simple_pairing_mode(HCI_SP_MODE_ENABLED)); controller_param.packet_parser->parse_generic_command_complete(response); @@ -211,13 +223,13 @@ static void start_up(void) } #endif -#if (SC_MODE_INCLUDED == TRUE) +if ((bluedroid_config_get()->get_sc_enabled())) { controller_param.secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(controller_param.features_classic[2].as_array); if (controller_param.secure_connections_supported) { response = AWAIT_COMMAND(controller_param.packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED)); controller_param.packet_parser->parse_generic_command_complete(response); } -#endif +} #if (BLE_INCLUDED == TRUE) #if (CLASSIC_BT_INCLUDED) @@ -237,7 +249,19 @@ static void start_up(void) &controller_param.acl_data_size_ble, &controller_param.acl_buffer_count_ble ); - +#if (BLE_FEAT_ISO_EN == TRUE) + // Request the ble buffer size next + response = AWAIT_COMMAND(controller_param.packet_factory->make_ble_read_buffer_size_v2()); + controller_param.packet_parser->parse_ble_read_buffer_size_response_v2( + response, + &controller_param.acl_data_size_ble, + &controller_param.acl_buffer_count_ble, + &iso_pktlen, + &iso_max_pkts + ); + extern int ble_hci_set_iso_buf_sz(uint16_t pktlen, uint8_t max_pkts); + ble_hci_set_iso_buf_sz(iso_pktlen, iso_max_pkts); +#endif // #if (BLE_FEAT_ISO_EN == TRUE) // Response of 0 indicates ble has the same buffer size as classic if (controller_param.acl_data_size_ble == 0) { controller_param.acl_data_size_ble = controller_param.acl_data_size_classic; @@ -265,16 +289,26 @@ static void start_up(void) &controller_param.ble_resolving_list_max_size); } #if BLE_50_FEATURE_SUPPORT == TRUE +#if (BLE_50_EXTEND_ADV_EN == TRUE) controller_param.ble_ext_adv_data_max_len = BLE_EXT_ADV_DATA_LEN_MAX; +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) #endif //#if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_50_FEATURE_SUPPORT == TRUE && BLE_42_FEATURE_SUPPORT == FALSE) - if (HCI_LE_ENHANCED_PRIVACY_SUPPORTED(controller_param.features_ble.as_array)) { +#if (BLE_50_EXTEND_ADV_EN == TRUE) + if (HCI_LE_EXT_ADV_SUPPORTED(controller_param.features_ble.as_array)) { response = AWAIT_COMMAND(controller_param.packet_factory->make_read_max_adv_data_len()); controller_param.packet_parser->parse_ble_read_adv_max_len_response( response, &controller_param.ble_ext_adv_data_max_len); } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) + response = AWAIT_COMMAND(controller_param.packet_factory->read_periodic_adv_list_size()); + controller_param.packet_parser->parse_ble_read_periodic_adv_list_size_response( + response, + &controller_param.get_ble_periodic_advertiser_list_size); +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #endif // (BLE_50_FEATURE_SUPPORT == TRUE && BLE_42_FEATURE_SUPPORT == FALSE) if (HCI_LE_DATA_LEN_EXT_SUPPORTED(controller_param.features_ble.as_array)) { @@ -315,6 +349,17 @@ static void shut_down(void) controller_param.readable = false; } +#if (BT_BLE_DYNAMIC_ENV_MEMORY == TRUE) +void free_controller_param(void) +{ + if (controller_param_ptr) { + osi_free(controller_param_ptr); + controller_param_ptr = NULL; + loaded = false; + } +} +#endif + static bool get_is_ready(void) { return controller_param.readable; @@ -508,6 +553,7 @@ static void set_ble_resolving_list_max_size(int resolving_list_max_size) controller_param.ble_resolving_list_max_size = resolving_list_max_size; } #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) static uint16_t ble_get_ext_adv_data_max_len(void) { assert(controller_param.readable); @@ -515,6 +561,15 @@ static uint16_t ble_get_ext_adv_data_max_len(void) return controller_param.ble_ext_adv_data_max_len; } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) +static uint8_t get_ble_periodic_adv_list_size(void) +{ + assert(controller_param.readable); + assert(controller_param.ble_supported); + return controller_param.get_ble_periodic_advertiser_list_size; +} +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BTM_SCO_HCI_INCLUDED == TRUE) static uint8_t get_sco_data_size(void) @@ -574,7 +629,12 @@ static const controller_t interface = { get_ble_resolving_list_max_size, set_ble_resolving_list_max_size, #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) ble_get_ext_adv_data_max_len, +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) + get_ble_periodic_adv_list_size, +#endif // (BLE_50_EXTEND_SYNC_EN == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BTM_SCO_HCI_INCLUDED == TRUE) get_sco_data_size, @@ -584,7 +644,6 @@ static const controller_t interface = { const controller_t *controller_get_interface(void) { - static bool loaded = false; if (!loaded) { loaded = true; #if (BT_BLE_DYNAMIC_ENV_MEMORY == TRUE) diff --git a/lib/bt/host/bluedroid/device/include/device/controller.h b/lib/bt/host/bluedroid/device/include/device/controller.h index 6fc766f3..6345d7a9 100644 --- a/lib/bt/host/bluedroid/device/include/device/controller.h +++ b/lib/bt/host/bluedroid/device/include/device/controller.h @@ -81,7 +81,12 @@ typedef struct controller_t { void (*set_ble_resolving_list_max_size)(int resolving_list_max_size); #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) uint16_t (*ble_get_ext_adv_data_max_len)(void); +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) + uint8_t (*get_ble_periodic_adv_list_size)(void); +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #endif // BLE_50_FEATURE_SUPPORT #if (BTM_SCO_HCI_INCLUDED == TRUE) diff --git a/lib/bt/host/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h b/lib/bt/host/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h index 495fbf6b..ae87317c 100644 --- a/lib/bt/host/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h +++ b/lib/bt/host/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h @@ -372,7 +372,7 @@ OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, * * @param frameData Pointer to the SBC data. * - * @param frameBytes Number of bytes avaiable in the frameData buffer + * @param frameBytes Number of bytes available in the frameData buffer * */ OI_UINT8 OI_CODEC_SBC_FrameCount(OI_BYTE *frameData, diff --git a/lib/bt/host/bluedroid/external/sbc/encoder/srce/sbc_encoder.c b/lib/bt/host/bluedroid/external/sbc/encoder/srce/sbc_encoder.c index c0ab99b8..fa1d40c9 100644 --- a/lib/bt/host/bluedroid/external/sbc/encoder/srce/sbc_encoder.c +++ b/lib/bt/host/bluedroid/external/sbc/encoder/srce/sbc_encoder.c @@ -18,7 +18,7 @@ /****************************************************************************** * - * contains code for encoder flow and initalization of encoder + * contains code for encoder flow and initialization of encoder * ******************************************************************************/ @@ -62,7 +62,7 @@ void SBC_Encoder(SBC_ENC_PARAMS *pstrEncParams) pstrEncParams->ps16NextPcmBuffer = pstrEncParams->as16PcmBuffer; #endif do { - /* SBC ananlysis filter*/ + /* SBC analysis filter*/ if (s32NumOfSubBands == 4) { SbcAnalysisFilter4(pstrEncParams); } else { @@ -73,7 +73,7 @@ void SBC_Encoder(SBC_ENC_PARAMS *pstrEncParams) ps16ScfL = pstrEncParams->as16ScaleFactor; s32Ch = pstrEncParams->s16NumOfChannels * s32NumOfSubBands; - pstrEncParams->ps16NextPcmBuffer += s32Ch * s32NumOfBlocks; /* in case of multible sbc frame to encode update the pcm pointer */ + pstrEncParams->ps16NextPcmBuffer += s32Ch * s32NumOfBlocks; /* in case of multiple sbc frame to encode update the pcm pointer */ for (s32Sb = 0; s32Sb < s32Ch; s32Sb++) { SbBuffer = pstrEncParams->s32SbBuffer + s32Sb; @@ -101,7 +101,7 @@ void SBC_Encoder(SBC_ENC_PARAMS *pstrEncParams) /* In case of JS processing,check whether to use JS */ #if (SBC_JOINT_STE_INCLUDED == TRUE) if (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) { - /* Calculate sum and differance scale factors for making JS decision */ + /* Calculate sum and difference scale factors for making JS decision */ ps16ScfL = pstrEncParams->as16ScaleFactor ; /* calculate the scale factor of Joint stereo max sum and diff */ for (s32Sb = 0; s32Sb < s32NumOfSubBands - 1; s32Sb++) { @@ -191,7 +191,7 @@ void SBC_Encoder(SBC_ENC_PARAMS *pstrEncParams) } /**************************************************************************** -* InitSbcAnalysisFilt - Initalizes the input data to 0 +* InitSbcAnalysisFilt - Initializes the input data to 0 * * RETURNS : N/A */ @@ -306,7 +306,7 @@ void SBC_Encoder_Init(SBC_ENC_PARAMS *pstrEncParams) /* allocation method: loudness */ pstrEncParams->s16AllocationMethod = SBC_LOUDNESS; - /* set the header paramers, unused for mSBC */ + /* set the header parameters, unused for mSBC */ pstrEncParams->FrameHeader = 0; } diff --git a/lib/bt/host/bluedroid/hci/ble_hci_iso.c b/lib/bt/host/bluedroid/hci/ble_hci_iso.c new file mode 100644 index 00000000..9c73fae2 --- /dev/null +++ b/lib/bt/host/bluedroid/hci/ble_hci_iso.c @@ -0,0 +1,346 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include "hci/ble_hci_iso.h" +#include "common/bt_target.h" +#include "osi/mutex.h" + +#if (BLE_FEAT_ISO_EN == TRUE) + +#define BLE_HCI_ISO_PB_FIRST_FRAG 0 +#define BLE_HCI_ISO_PB_CONT_FRAG 1 +#define BLE_HCI_ISO_PB_COMP_SDU 2 +#define BLE_HCI_ISO_PB_LAST_FRAG 3 + +#define BLE_HCI_ISO_DATA_HDR_SZ 4 +#define BLE_HCI_ISO_DATA_LOAD_TS_SZ 4 +#define BLE_HCI_ISO_DATA_LOAD_HDR_SZ 4 + +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + +static uint16_t ble_hs_iso_buf_sz; +static uint8_t ble_hs_iso_max_pkts; + +#if (BLE_ISO_STD_FLOW_CTRL == TRUE) +/* Number of available ISO transmit buffers on the controller. + * It must only be accessed while the host mutex is locked. + */ +static uint16_t ble_hs_iso_avail_pkts; +#endif // #if (BLE_ISO_STD_FLOW_CTRL == TRUE) + +static struct ble_hci_iso_conn g_iso_conn[BLE_ISO_BIS_MAX_COUNT + BLE_ISO_CIS_MAX_COUNT]; + +int +ble_hci_set_iso_buf_sz(uint16_t pktlen, uint8_t max_pkts) +{ + if (pktlen == 0 || max_pkts == 0) { + return 3; + } + + ble_hs_iso_buf_sz = pktlen; + ble_hs_iso_max_pkts = max_pkts; + +#if (BLE_ISO_STD_FLOW_CTRL == TRUE) + ble_hs_iso_avail_pkts = max_pkts; +#endif /* (BLE_ISO_STD_FLOW_CTRL) */ + + HCI_TRACE_WARNING("ISO Flow Control:\n"); + HCI_TRACE_WARNING(" Length: %u\n", pktlen); + HCI_TRACE_WARNING(" Count: %u\n", max_pkts); + HCI_TRACE_WARNING(" Status: "); +#if (BLE_ISO_STD_FLOW_CTRL == TRUE) + HCI_TRACE_WARNING("%s\n", "Standard"); +#elif (BLE_ISO_NON_STD_FLOW_CTRL == TRUE) + HCI_TRACE_WARNING("%s\n", "Non-standard"); +#else + HCI_TRACE_WARNING("%s\n", "Not support"); +#endif + + return 0; +} + +void +ble_hci_get_iso_buf_size(uint16_t *pktlen, uint8_t *max_pkts) +{ + assert(pktlen && max_pkts); + + *pktlen = ble_hs_iso_buf_sz; + *max_pkts = ble_hs_iso_max_pkts; +} + +#if (BLE_ISO_STD_FLOW_CTRL == TRUE) +void +ble_hci_add_iso_avail_pkts(uint16_t delta) +{ + osi_mutex_global_lock(); + + if (ble_hs_iso_avail_pkts + delta > ble_hs_iso_max_pkts) { + HCI_TRACE_ERROR("ISO_HS_RESET %u %u %u\n", ble_hs_iso_avail_pkts, delta, ble_hs_iso_max_pkts); + // ble_hs_sched_reset(BLE_HS_ECONTROLLER); + assert(0); + } else { + ble_hs_iso_avail_pkts += delta; + } + + osi_mutex_global_unlock(); +} +#endif /* (BLE_ISO_STD_FLOW_CTRL) */ + +#define BLE_ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) + +struct ble_hci_iso_conn * +ble_hci_iso_conn_find(uint16_t conn_handle) +{ + for (size_t i = 0; i < BLE_ARRAY_SIZE(g_iso_conn); i++) { + struct ble_hci_iso_conn *conn = &g_iso_conn[i]; + + if (conn->enabled && + conn->conn_handle == conn_handle) { + return conn; + } + } + + return NULL; +} + +int ble_hci_iso_conn_free(uint16_t conn_handle) +{ + for (size_t i = 0; i < BLE_ARRAY_SIZE(g_iso_conn); i++) { + struct ble_hci_iso_conn *conn = &g_iso_conn[i]; + + if (conn->enabled && + conn->conn_handle == conn_handle) { + conn->enabled = 0; + conn->conn_handle = 0; + return 0; + } + } + + return 1; +} + +static struct ble_hci_iso_conn * +ble_hci_iso_alloc_conn(uint16_t conn_handle) +{ + for (size_t i = 0; i < BLE_ARRAY_SIZE(g_iso_conn); i++) { + struct ble_hci_iso_conn *conn = &g_iso_conn[i]; + + if (!conn->enabled) { + conn->enabled = 1; + conn->conn_handle = conn_handle; + conn->pkt_seq_num = 0; /* Initialize to 0 */ + return conn; + } + } + + return NULL; +} + +#if (BLE_ISO_STD_FLOW_CTRL == TRUE) +static uint8_t +ble_hci_iso_buf_needed(struct ble_hs_iso_conn *conn) +{ + uint16_t sdu_offset; + uint16_t dl_len; + uint8_t dlh_len; + uint8_t count; + + dlh_len = (conn->ts_flag ? BLE_HCI_ISO_DATA_LOAD_TS_SZ : 0) + BLE_HCI_ISO_DATA_LOAD_HDR_SZ; + sdu_offset = 0; + count = 1; /* 1 extra since framed pdu may be used */ + + while (1) { + dl_len = min(dlh_len + conn->sdu_len - sdu_offset, ble_hs_iso_buf_sz); + + count += 1; + + sdu_offset += dl_len - dlh_len; + assert(sdu_offset <= conn->sdu_len); + + if (sdu_offset == conn->sdu_len) { + break; + } + + /* No data load header for continuation/last segment */ + dlh_len = 0; + } + + return count; +} +#endif /* (BLE_ISO_STD_FLOW_CTRL) */ + +static void +ble_hci_iso_hdr_append(struct ble_hci_iso_conn *conn, + uint8_t *frag, + uint8_t pb_flag, uint16_t dl_len) +{ + uint32_t pkt_hdr; + uint32_t dl_hdr; + + pkt_hdr = conn->conn_handle; + pkt_hdr |= (pb_flag << 12); + if (pb_flag == BLE_HCI_ISO_PB_FIRST_FRAG || + pb_flag == BLE_HCI_ISO_PB_COMP_SDU) { + pkt_hdr |= (conn->ts_flag << 14); + } + pkt_hdr |= (dl_len << 16); + + memcpy(frag, &pkt_hdr, BLE_HCI_ISO_DATA_HDR_SZ); + + /* No data load header for continuation/last segment */ + if (pb_flag == BLE_HCI_ISO_PB_CONT_FRAG || + pb_flag == BLE_HCI_ISO_PB_LAST_FRAG) { + return; + } + + if (conn->ts_flag) { + memcpy(frag + BLE_HCI_ISO_DATA_HDR_SZ, &conn->time_stamp, BLE_HCI_ISO_DATA_LOAD_TS_SZ); + } + + dl_hdr = (conn->sdu_len << 16) | conn->pkt_seq_num; + + memcpy(frag + BLE_HCI_ISO_DATA_HDR_SZ + (conn->ts_flag ? BLE_HCI_ISO_DATA_LOAD_TS_SZ : 0), + &dl_hdr, BLE_HCI_ISO_DATA_LOAD_HDR_SZ); +} + +int +ble_hci_tx_iso_data(const uint8_t *data, uint16_t len, void *arg) +{ + int rc = 1; +#if CONFIG_BT_LE_ISO_SUPPORT + // return ble_transport_to_ll_iso(data, len, arg); + extern int ble_hci_trans_hs_iso_tx(const uint8_t *data, uint16_t length, void *arg); + rc = ble_hci_trans_hs_iso_tx(data, len, arg); +#endif // #if CONFIG_BT_LE_ISO_SUPPORT + return rc; +} + +static int +ble_hci_iso_tx_now(struct ble_hci_iso_conn *conn, const uint8_t *sdu, + uint32_t time_stamp, uint16_t pkt_seq_num) +{ + uint8_t dlh_len; + uint8_t *frag; + int rc; + +#if (BLE_ISO_STD_FLOW_CTRL == TRUE) + /* Get the Controller ISO buffer needed for the SDU */ + uint8_t count = ble_hs_hci_iso_buf_needed(conn); + + /* Make sure the Controller ISO buffer can accommodate the SDU completely */ + if (count > ble_hs_iso_avail_pkts) { + HCI_TRACE_ERROR("ISO flow control(%u/%u)!\n", count, ble_hs_iso_avail_pkts); + return 1; + } +#elif (BLE_ISO_NON_STD_FLOW_CTRL == TRUE) + extern uint16_t ble_ll_iso_free_buf_num_get(uint16_t conn_handle); + if (ble_ll_iso_free_buf_num_get(conn->conn_handle) == 0) { + HCI_TRACE_ERROR("ISO flow control!\n"); + return 1; + } +#endif + + dlh_len = (conn->ts_flag ? BLE_HCI_ISO_DATA_LOAD_TS_SZ : 0) + BLE_HCI_ISO_DATA_LOAD_HDR_SZ; + + frag = malloc(BLE_HCI_ISO_DATA_HDR_SZ + dlh_len + conn->sdu_len); + if (frag == NULL) { + HCI_TRACE_ERROR("frag is null\n"); + return 6; + } + + ble_hci_iso_hdr_append(conn, + frag, + BLE_HCI_ISO_PB_COMP_SDU, + dlh_len + conn->sdu_len); + + memcpy(frag + BLE_HCI_ISO_DATA_HDR_SZ + dlh_len, + sdu, + conn->sdu_len); + + rc = ble_hci_tx_iso_data(frag, BLE_HCI_ISO_DATA_HDR_SZ + dlh_len + conn->sdu_len, NULL); + if (rc) { + HCI_TRACE_ERROR("iso tx failed\n"); + return 14; + } + +#if (BLE_ISO_STD_FLOW_CTRL == TRUE) + /* If an ISO SDU is fragmented into fragments, flow control is not supported. + * + * Currently even if an SDU is larger than the ISO buffer size, fragmentation + * will not happen here, the SDU will be posted to Controller completely. + */ + ble_hs_iso_avail_pkts -= 1; +#endif /* (BLE_ISO_STD_FLOW_CTRL) */ + + return 0; +} + +int +esp_ble_hci_iso_tx(uint16_t conn_handle, const uint8_t *sdu, uint16_t sdu_len, + bool ts_flag, uint32_t time_stamp, uint16_t pkt_seq_num) +{ + struct ble_hci_iso_conn *conn; + uint16_t max_sdu; + int rc; + + osi_mutex_global_lock(); + + /* For sending empty SDU, we could use an SDU with zero length. */ + if (sdu == NULL && sdu_len != 0) { + HCI_TRACE_ERROR("Invalid iso sdu\n"); + rc = 3; + goto end; + } + + /* TODO: + * Use Host functions to replace the above LL implementation. + */ + max_sdu = 0x0FFF; + + if (sdu_len > max_sdu) { + HCI_TRACE_ERROR("Too large iso sdu %d, max_sdu %d\n", sdu_len, max_sdu); + rc = 8; + goto end; + } + + conn = ble_hci_iso_conn_find(conn_handle); + if (!conn) { + conn = ble_hci_iso_alloc_conn(conn_handle); + } + if (!conn) { + rc = 7; + goto end; + } + + conn->ts_flag = ts_flag; + conn->time_stamp = time_stamp; + conn->pkt_seq_num = pkt_seq_num; + conn->sdu_len = sdu_len; + + rc = ble_hci_iso_tx_now(conn, sdu, time_stamp, pkt_seq_num); +end: + osi_mutex_global_unlock(); + return rc; +} + +#endif // #if (BLE_FEAT_ISO_EN == TRUE) diff --git a/lib/bt/host/bluedroid/hci/hci_hal_h4.c b/lib/bt/host/bluedroid/hci/hci_hal_h4.c index 9663126a..1dcdf67d 100644 --- a/lib/bt/host/bluedroid/hci/hci_hal_h4.c +++ b/lib/bt/host/bluedroid/hci/hci_hal_h4.c @@ -35,16 +35,16 @@ #include "esp_bluedroid_hci.h" #include "stack/hcimsgs.h" -#if ((BT_CONTROLLER_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER) -#include "ble_hci_trans.h" -#endif - #if (C2H_FLOW_CONTROL_INCLUDED == TRUE) #include "l2c_int.h" #endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE #include "stack/hcimsgs.h" #include "hci_log/bt_hci_log.h" +#if CONFIG_BT_BLE_LOG_SPI_OUT_HCI_ENABLED +#include "ble_log/ble_log_spi_out.h" +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_HCI_ENABLED + #define HCI_BLE_EVENT 0x3e #define PACKET_TYPE_TO_INBOUND_INDEX(type) ((type) - 2) #define PACKET_TYPE_TO_INDEX(type) ((type) - 1) @@ -56,9 +56,6 @@ #define HCI_HAL_BLE_ADV_RPT_QUEUE_LEN_MAX (200) #endif -extern bool BTU_check_queue_is_congest(void); - - static const uint8_t preamble_sizes[] = { HCI_COMMAND_PREAMBLE_SIZE, HCI_ACL_PREAMBLE_SIZE, @@ -75,6 +72,7 @@ static const uint16_t outbound_event_types[] = { typedef struct { fixed_queue_t *rx_q; +#if (BLE_42_SCAN_EN == TRUE) struct pkt_queue *adv_rpt_q; #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) osi_mutex_t adv_flow_lock; @@ -84,6 +82,7 @@ typedef struct { pkt_linked_item_t *adv_fc_cmd_buf; bool cmd_buf_in_use; #endif +#endif // #if (BLE_42_SCAN_EN == TRUE) hci_hal_callbacks_t *callbacks; osi_thread_t *hci_h4_thread; struct osi_event *upstream_data_ready; @@ -97,15 +96,18 @@ static const esp_bluedroid_hci_driver_callbacks_t hci_host_cb; static void host_send_pkt_available_cb(void); static int host_recv_pkt_cb(uint8_t *data, uint16_t len); static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet); +#if (BLE_42_SCAN_EN == TRUE) static void hci_hal_h4_hdl_rx_adv_rpt(pkt_linked_item_t *linked_pkt); +#endif // #if (BLE_42_SCAN_EN == TRUE) static void hci_upstream_data_handler(void *arg); static bool hci_upstream_data_post(uint32_t timeout); +#if (BLE_42_SCAN_EN == TRUE) #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) static void hci_adv_flow_monitor(void *context); static void hci_adv_flow_cmd_free_cb(pkt_linked_item_t *linked_pkt); #endif - +#endif // #if (BLE_42_SCAN_EN == TRUE) static bool hci_hal_env_init(const hci_hal_callbacks_t *upper_callbacks, osi_thread_t *task_thread) { assert(upper_callbacks != NULL); @@ -113,7 +115,7 @@ static bool hci_hal_env_init(const hci_hal_callbacks_t *upper_callbacks, osi_thr hci_hal_env.hci_h4_thread = task_thread; hci_hal_env.callbacks = (hci_hal_callbacks_t *)upper_callbacks; - +#if (BLE_42_SCAN_EN == TRUE) #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) hci_hal_env.adv_fc_cmd_buf = osi_calloc(HCI_CMD_LINKED_BUF_SIZE(HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL)); assert(hci_hal_env.adv_fc_cmd_buf != NULL); @@ -126,12 +128,13 @@ static bool hci_hal_env_init(const hci_hal_callbacks_t *upper_callbacks, osi_thr hci_hal_env.adv_flow_monitor = osi_alarm_new("adv_fc_mon", hci_adv_flow_monitor, NULL, HCI_ADV_FLOW_MONITOR_PERIOD_MS); assert (hci_hal_env.adv_flow_monitor != NULL); #endif - +#endif // #if (BLE_42_SCAN_EN == TRUE) hci_hal_env.rx_q = fixed_queue_new(QUEUE_SIZE_MAX); assert(hci_hal_env.rx_q != NULL); - +#if (BLE_42_SCAN_EN == TRUE) hci_hal_env.adv_rpt_q = pkt_queue_create(); assert(hci_hal_env.adv_rpt_q != NULL); +#endif // #if (BLE_42_SCAN_EN == TRUE) struct osi_event *event = osi_event_create(hci_upstream_data_handler, NULL); assert(event != NULL); @@ -144,19 +147,22 @@ static bool hci_hal_env_init(const hci_hal_callbacks_t *upper_callbacks, osi_thr static void hci_hal_env_deinit(void) { fixed_queue_t *rx_q = hci_hal_env.rx_q; +#if (BLE_42_SCAN_EN == TRUE) struct pkt_queue *adv_rpt_q = hci_hal_env.adv_rpt_q; +#endif // #if (BLE_42_SCAN_EN == TRUE) struct osi_event *upstream_data_ready = hci_hal_env.upstream_data_ready; hci_hal_env.rx_q = NULL; +#if (BLE_42_SCAN_EN == TRUE) hci_hal_env.adv_rpt_q = NULL; +#endif // #if (BLE_42_SCAN_EN == TRUE) hci_hal_env.upstream_data_ready = NULL; - fixed_queue_free(rx_q, osi_free_func); - +#if (BLE_42_SCAN_EN == TRUE) pkt_queue_destroy(adv_rpt_q, NULL); - +#endif // #if (BLE_42_SCAN_EN == TRUE) osi_event_delete(upstream_data_ready); - +#if (BLE_42_SCAN_EN == TRUE) #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) hci_hal_env.cmd_buf_in_use = true; osi_alarm_cancel(hci_hal_env.adv_flow_monitor); @@ -166,7 +172,7 @@ static void hci_hal_env_deinit(void) osi_free(hci_hal_env.adv_fc_cmd_buf); hci_hal_env.adv_fc_cmd_buf = NULL; #endif - +#endif // #if (BLE_42_SCAN_EN == TRUE) hci_hal_env.hci_h4_thread = NULL; memset(&hci_hal_env, 0, sizeof(hci_hal_env_t)); @@ -225,11 +231,37 @@ static uint16_t transmit_data(serial_data_type_t type, return length - 1; } +#if (BLE_FEAT_ISO_EN == TRUE) +typedef void ble_host_rx_iso_data_fn(uint8_t *data, uint16_t len); + +static ble_host_rx_iso_data_fn *ble_host_iso_rx_cb = NULL; + +void ble_host_register_rx_iso_data_cb(void *cb) +{ + /* If the iso rx cb is already registered, we will give + * a warning log here, and the cb will still be updated. + */ + if (ble_host_iso_rx_cb) { + HCI_TRACE_WARNING("iso rx cb %p already registered\n", ble_host_iso_rx_cb); + } + + ble_host_iso_rx_cb = cb; +} + +void ble_hci_register_rx_iso_data_cb(void *cb) +{ + ble_host_register_rx_iso_data_cb(cb); +} + +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + // Internal functions static void hci_upstream_data_handler(void *arg) { fixed_queue_t *rx_q = hci_hal_env.rx_q; +#if (BLE_42_SCAN_EN == TRUE) struct pkt_queue *adv_rpt_q = hci_hal_env.adv_rpt_q; +#endif // #if (BLE_42_SCAN_EN == TRUE) size_t pkts_to_process; do { @@ -241,7 +273,7 @@ static void hci_upstream_data_handler(void *arg) } } } while (0); - +#if (BLE_42_SCAN_EN == TRUE) do { pkts_to_process = pkt_queue_length(adv_rpt_q); for (size_t i = 0; i < pkts_to_process; i++) { @@ -251,8 +283,12 @@ static void hci_upstream_data_handler(void *arg) } } } while (0); - - if (!fixed_queue_is_empty(rx_q) || pkt_queue_length(adv_rpt_q) > 0) { +#endif // #if (BLE_42_SCAN_EN == TRUE) + if (!fixed_queue_is_empty(rx_q) +#if (BLE_42_SCAN_EN == TRUE) + || pkt_queue_length(adv_rpt_q) > 0 +#endif // #if (BLE_42_SCAN_EN == TRUE) + ) { hci_upstream_data_post(OSI_THREAD_MAX_TIMEOUT); } } @@ -293,6 +329,7 @@ bool host_recv_adv_packet(uint8_t *packet) return false; } +#if (BLE_42_SCAN_EN == TRUE) #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) static void hci_adv_flow_monitor(void *context) { @@ -418,6 +455,7 @@ int hci_adv_credits_force_release(uint16_t num) return credits_released; } #endif +#endif // #if (BLE_42_SCAN_EN == TRUE) static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet) { @@ -479,7 +517,7 @@ static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet) packet->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)]; hci_hal_env.callbacks->packet_ready(packet); } - +#if (BLE_42_SCAN_EN == TRUE) static void hci_hal_h4_hdl_rx_adv_rpt(pkt_linked_item_t *linked_pkt) { uint8_t type; @@ -515,13 +553,6 @@ static void hci_hal_h4_hdl_rx_adv_rpt(pkt_linked_item_t *linked_pkt) goto _discard_packet; } -#if SCAN_QUEUE_CONGEST_CHECK - if(BTU_check_queue_is_congest()) { - HCI_TRACE_DEBUG("BtuQueue is congested"); - goto _discard_packet; - } -#endif - packet->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)]; hci_hal_env.callbacks->adv_rpt_ready(linked_pkt); @@ -533,6 +564,7 @@ _discard_packet: hci_adv_credits_prep_to_release(1); #endif } +#endif // #if (BLE_42_SCAN_EN == TRUE) static void host_send_pkt_available_cb(void) { @@ -555,7 +587,12 @@ void bt_record_hci_data(uint8_t *data, uint16_t len) )) { bt_hci_log_record_hci_adv(HCI_LOG_DATA_TYPE_ADV, &data[2], len - 2); } else { - uint8_t data_type = ((data[0] == 2) ? HCI_LOG_DATA_TYPE_C2H_ACL : data[0]); + uint8_t data_type; + if (data[0] == HCI_LOG_DATA_TYPE_ISO_DATA) { + data_type = HCI_LOG_DATA_TYPE_ISO_DATA; + } else { + data_type = ((data[0] == 2) ? HCI_LOG_DATA_TYPE_C2H_ACL : data[0]); + } bt_hci_log_record_hci_data(data_type, &data[1], len - 1); } #endif // (BT_HCI_LOG_INCLUDED == TRUE) @@ -563,17 +600,33 @@ void bt_record_hci_data(uint8_t *data, uint16_t len) static int host_recv_pkt_cb(uint8_t *data, uint16_t len) { +#if (BT_BLE_LOG_SPI_OUT_HCI_ENABLED && !SOC_ESP_NIMBLE_CONTROLLER) + ble_log_spi_out_write_with_ts(BLE_LOG_SPI_OUT_SOURCE_HCI_UPSTREAM, data, len); +#endif // (BT_BLE_LOG_SPI_OUT_HCI_ENABLED && !SOC_ESP_NIMBLE_CONTROLLER) //Target has packet to host, malloc new buffer for packet BT_HDR *pkt = NULL; +#if (BLE_42_SCAN_EN == TRUE) pkt_linked_item_t *linked_pkt = NULL; +#endif // #if (BLE_42_SCAN_EN == TRUE) size_t pkt_size; - if (hci_hal_env.rx_q == NULL) { + if ((hci_hal_env.rx_q == NULL) || (data == NULL)) { return 0; } bt_record_hci_data(data, len); +#if (BLE_FEAT_ISO_EN == TRUE) + if (data[0] == DATA_TYPE_ISO) { + if (ble_host_iso_rx_cb) { + ble_host_iso_rx_cb(&data[1], len -1); + } + + free(data); + return 0; + } +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + bool is_adv_rpt = host_recv_adv_packet(data); if (!is_adv_rpt) { @@ -588,8 +641,11 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len) pkt->len = len; pkt->layer_specific = 0; memcpy(pkt->data, data, len); - fixed_queue_enqueue(hci_hal_env.rx_q, pkt, FIXED_QUEUE_MAX_TIMEOUT); + { + fixed_queue_enqueue(hci_hal_env.rx_q, pkt, FIXED_QUEUE_MAX_TIMEOUT); + } } else { +#if (BLE_42_SCAN_EN == TRUE) #if !BLE_ADV_REPORT_FLOW_CONTROL // drop the packets if pkt_queue length goes beyond upper limit if (pkt_queue_length(hci_hal_env.adv_rpt_q) > HCI_HAL_BLE_ADV_RPT_QUEUE_LEN_MAX) { @@ -597,7 +653,11 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len) } #endif pkt_size = BT_PKT_LINKED_HDR_SIZE + BT_HDR_SIZE + len; + #if HEAP_MEMORY_DEBUG linked_pkt = (pkt_linked_item_t *) osi_calloc(pkt_size); + #else + linked_pkt = (pkt_linked_item_t *) osi_calloc_base(pkt_size); + #endif if (!linked_pkt) { #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) hci_adv_credits_consumed(1); @@ -614,6 +674,9 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len) #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) hci_adv_credits_consumed(1); #endif +#else + assert(0); +#endif // #if (BLE_42_SCAN_EN == TRUE) } hci_upstream_data_post(OSI_THREAD_MAX_TIMEOUT); @@ -622,42 +685,7 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len) return 0; } -#if ((BT_CONTROLLER_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER) -int -ble_hs_hci_rx_evt(uint8_t *hci_ev, void *arg) -{ - if(esp_bluedroid_get_status() == ESP_BLUEDROID_STATUS_UNINITIALIZED) { - ble_hci_trans_buf_free(hci_ev); - return 0; - } - uint16_t len = hci_ev[1] + 3; - uint8_t *data = (uint8_t *)malloc(len); - assert(data != NULL); - data[0] = 0x04; - memcpy(&data[1], hci_ev, len - 1); - ble_hci_trans_buf_free(hci_ev); - host_recv_pkt_cb(data, len); - free(data); - return 0; -} - - -int -ble_hs_rx_data(struct os_mbuf *om, void *arg) -{ - uint16_t len = OS_MBUF_PKTHDR(om)->omp_len + 1; - uint8_t *data = (uint8_t *)malloc(len); - assert(data != NULL); - data[0] = 0x02; - os_mbuf_copydata(om, 0, len - 1, &data[1]); - host_recv_pkt_cb(data, len); - free(data); - os_mbuf_free_chain(om); - return 0; -} - -#endif static const esp_bluedroid_hci_driver_callbacks_t hci_host_cb = { .notify_host_send_available = host_send_pkt_available_cb, .notify_host_recv = host_recv_pkt_cb, diff --git a/lib/bt/host/bluedroid/hci/hci_layer.c b/lib/bt/host/bluedroid/hci/hci_layer.c index c9f1f5e3..e5cd263f 100644 --- a/lib/bt/host/bluedroid/hci/hci_layer.c +++ b/lib/bt/host/bluedroid/hci/hci_layer.c @@ -537,9 +537,11 @@ static void dispatch_adv_report(pkt_linked_item_t *linked_pkt) //Tell Up-layer received packet. if (btu_task_post(SIG_BTU_HCI_ADV_RPT_MSG, linked_pkt, OSI_THREAD_MAX_TIMEOUT) == false) { osi_free(linked_pkt); +#if (BLE_42_SCAN_EN == TRUE) #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) hci_adv_credits_try_release(1); #endif +#endif // #if (BLE_42_SCAN_EN == TRUE) } } // Misc internal functions diff --git a/lib/bt/host/bluedroid/hci/hci_packet_factory.c b/lib/bt/host/bluedroid/hci/hci_packet_factory.c index 5010e99d..6a84f9ca 100644 --- a/lib/bt/host/bluedroid/hci/hci_packet_factory.c +++ b/lib/bt/host/bluedroid/hci/hci_packet_factory.c @@ -52,6 +52,7 @@ static BT_HDR *make_set_c2h_flow_control(uint8_t enable) return packet; } +#if (BLE_42_SCAN_EN == TRUE) static BT_HDR *make_set_adv_report_flow_control(uint8_t enable, uint16_t num, uint16_t lost_threshold) { uint8_t *stream; @@ -63,7 +64,7 @@ static BT_HDR *make_set_adv_report_flow_control(uint8_t enable, uint16_t num, ui UINT16_TO_STREAM(stream, lost_threshold); return packet; } - +#endif // #if (BLE_42_SCAN_EN == TRUE) static BT_HDR *make_host_buffer_size(uint16_t acl_size, uint8_t sco_size, uint16_t acl_count, uint16_t sco_count) { uint8_t *stream; @@ -158,6 +159,13 @@ static BT_HDR *make_ble_read_buffer_size(void) return make_command_no_params(HCI_BLE_READ_BUFFER_SIZE); } +#if (BLE_FEAT_ISO_EN == TRUE) +static BT_HDR *make_ble_read_buffer_size_v2(void) +{ + return make_command_no_params(HCI_BLE_READ_BUFFER_SZIE_V2); +} +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + static BT_HDR *make_ble_read_supported_states(void) { return make_command_no_params(HCI_BLE_READ_SUPPORTED_STATES); @@ -219,10 +227,18 @@ static BT_HDR *make_write_default_erroneous_data_report(uint8_t enable) return packet; } #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) static BT_HDR *make_read_max_adv_data_len(void) { return make_command_no_params(HCI_BLE_RD_MAX_ADV_DATA_LEN); } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) +static BT_HDR *read_periodic_adv_list_size(void) +{ + return make_command_no_params(HCI_BLE_RD_PERIOD_ADV_LIST_SIZE); +} +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) // Internal functions @@ -252,7 +268,9 @@ static const hci_packet_factory_t interface = { make_reset, make_read_buffer_size, make_set_c2h_flow_control, +#if (BLE_42_SCAN_EN == TRUE) make_set_adv_report_flow_control, +#endif // #if (BLE_42_SCAN_EN == TRUE) make_host_buffer_size, make_read_local_version_info, make_read_bd_addr, @@ -265,11 +283,19 @@ static const hci_packet_factory_t interface = { make_ble_write_host_support, make_ble_read_white_list_size, make_ble_read_buffer_size, +#if (BLE_FEAT_ISO_EN == TRUE) + make_ble_read_buffer_size_v2, +#endif // #if (BLE_FEAT_ISO_EN == TRUE) make_ble_read_supported_states, make_ble_read_local_supported_features, make_ble_read_resolving_list_size, #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) make_read_max_adv_data_len, +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) + read_periodic_adv_list_size, +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) make_ble_read_suggested_default_data_length, make_ble_write_suggested_default_data_length, diff --git a/lib/bt/host/bluedroid/hci/hci_packet_parser.c b/lib/bt/host/bluedroid/hci/hci_packet_parser.c index 88515376..b254c9be 100644 --- a/lib/bt/host/bluedroid/hci/hci_packet_parser.c +++ b/lib/bt/host/bluedroid/hci/hci_packet_parser.c @@ -155,6 +155,26 @@ static void parse_ble_read_buffer_size_response( osi_free(response); } +#if (BLE_FEAT_ISO_EN == TRUE) +static void parse_ble_read_buffer_size_response_v2 ( + BT_HDR *response, + uint16_t *data_size_ptr, + uint8_t *acl_buffer_count_ptr, + uint16_t *iso_pkt_len_ptr, + uint8_t *iso_pkt_num_ptr) +{ + + uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_BUFFER_SZIE_V2, 3 /* bytes after */); + assert(stream != NULL); + STREAM_TO_UINT16(*data_size_ptr, stream); + STREAM_TO_UINT8(*acl_buffer_count_ptr, stream); + STREAM_TO_UINT16(*iso_pkt_len_ptr, stream); + STREAM_TO_UINT8(*iso_pkt_num_ptr, stream); + + osi_free(response); +} +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + static void parse_ble_read_supported_states_response( BT_HDR *response, uint8_t *supported_states, @@ -186,7 +206,9 @@ static void parse_ble_read_resolving_list_size_response( { uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_RESOLVING_LIST_SIZE, 1 /* bytes after */); - STREAM_TO_UINT8(*resolving_list_size_ptr, stream); + if (stream) { + STREAM_TO_UINT8(*resolving_list_size_ptr, stream); + } osi_free(response); } @@ -198,22 +220,43 @@ static void parse_ble_read_suggested_default_data_length_response( { uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_DEFAULT_DATA_LENGTH, 2 /* bytes after */); - STREAM_TO_UINT16(*ble_default_packet_length_ptr, stream); - STREAM_TO_UINT16(*ble_default_packet_txtime_ptr, stream); + if (stream) { + STREAM_TO_UINT16(*ble_default_packet_length_ptr, stream); + STREAM_TO_UINT16(*ble_default_packet_txtime_ptr, stream); + } + osi_free(response); } + #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) static void parse_ble_read_adv_max_len_response( BT_HDR *response, uint16_t *adv_max_len_ptr) { uint8_t *stream = read_command_complete_header(response, HCI_BLE_RD_MAX_ADV_DATA_LEN, 1 /* bytes after */); - // Size: 2 Octets ; Value: 0x001F – 0x0672 ; Maximum supported advertising data length - STREAM_TO_UINT16(*adv_max_len_ptr, stream); + if (stream) { + // Size: 2 Octets ; Value: 0x001F – 0x0672 ; Maximum supported advertising data length + STREAM_TO_UINT16(*adv_max_len_ptr, stream); + } + osi_free(response); +} +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE +#if (BLE_50_EXTEND_SYNC_EN == TRUE) +static void parse_ble_read_periodic_adv_list_size_response( + BT_HDR *response, + uint16_t *periodic_adv_list_size_ptr) +{ + uint8_t *stream = read_command_complete_header(response, HCI_BLE_RD_PERIOD_ADV_LIST_SIZE, 1 /* bytes after */); + if (stream) { + // Size: 1 Octets ; Value: 0x01 to 0xFF ; Total number of Periodic Advertiser list entries that can be stored in the Controller + STREAM_TO_UINT8(*periodic_adv_list_size_ptr, stream); + } osi_free(response); } +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) @@ -254,6 +297,7 @@ static uint8_t *read_command_complete_header( STREAM_TO_UINT8(status, stream); if (status != HCI_SUCCESS) { + HCI_TRACE_ERROR("%s failed: opcode 0x%04x, status 0x%02x", __func__, opcode, status); return NULL; } @@ -270,11 +314,19 @@ static const hci_packet_parser_t interface = { parse_read_local_extended_features_response, parse_ble_read_white_list_size_response, parse_ble_read_buffer_size_response, +#if (BLE_FEAT_ISO_EN == TRUE) + parse_ble_read_buffer_size_response_v2, +#endif // #if (BLE_FEAT_ISO_EN == TRUE) parse_ble_read_supported_states_response, parse_ble_read_local_supported_features_response, parse_ble_read_resolving_list_size_response, #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) parse_ble_read_adv_max_len_response, +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) + parse_ble_read_periodic_adv_list_size_response, +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) parse_ble_read_suggested_default_data_length_response }; diff --git a/lib/bt/host/bluedroid/hci/include/hci/ble_hci_iso.h b/lib/bt/host/bluedroid/hci/include/hci/ble_hci_iso.h new file mode 100644 index 00000000..9b289677 --- /dev/null +++ b/lib/bt/host/bluedroid/hci/include/hci/ble_hci_iso.h @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_HCI_ISO_ +#define H_BLE_HCI_ISO_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_hci_iso_pkt_hdr { + uint16_t conn_handle : 12, + pb_flag : 2, + ts_flag : 1; + uint16_t data_load_len; +} __attribute__((packed)); + +struct ble_hci_iso_pkt { + /* ISO header */ + uint16_t conn_handle; /* CIS or BIS handle. */ + uint8_t pb_flag : 2, /* Packet boundary flag. */ + ts_flag : 1; /* Timestamp flag. */ + uint16_t iso_data_load_len; /* ISO Data Load length. */ + + /* ISO Data Load */ + uint32_t time_stamp; /* Timestamp. */ + uint16_t packet_seq; /* Packet sequence number. */ + uint16_t iso_sdu_len; /* SDU length. */ + uint8_t ps_flag; /* Packet status. */ + const uint8_t *sdu; /* First byte of ISO SDU. */ +}; + +struct ble_hci_iso_tx { + struct ble_hci_iso_pkt pkt; +}; + +struct ble_hci_iso_rx { + struct ble_hci_iso_pkt pkt; +}; + +struct ble_hci_iso_conn { + uint16_t conn_handle; + uint8_t enabled : 1, + pb_flag : 2, + ts_flag : 1; + uint32_t time_stamp; + uint16_t pkt_seq_num; + uint16_t sdu_len; +}; + +int ble_hci_set_iso_buf_sz(uint16_t pktlen, uint8_t max_pkts); + +void ble_hci_get_iso_buf_size(uint16_t *pktlen, uint8_t *max_pkts); + +void ble_hci_add_iso_avail_pkts(uint16_t delta); + +struct ble_hci_iso_conn *ble_hci_iso_conn_find(uint16_t conn_handle); + +int esp_ble_hci_iso_tx(uint16_t conn_handle, const uint8_t *sdu, uint16_t sdu_len, + bool ts_flag, uint32_t time_stamp, uint16_t pkt_seq_num); + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_HCI_ISO_ */ diff --git a/lib/bt/host/bluedroid/hci/include/hci/hci_hal.h b/lib/bt/host/bluedroid/hci/include/hci/hci_hal.h index fe5796db..aec926b6 100644 --- a/lib/bt/host/bluedroid/hci/include/hci/hci_hal.h +++ b/lib/bt/host/bluedroid/hci/include/hci/hci_hal.h @@ -31,7 +31,8 @@ typedef enum { DATA_TYPE_COMMAND = 1, DATA_TYPE_ACL = 2, DATA_TYPE_SCO = 3, - DATA_TYPE_EVENT = 4 + DATA_TYPE_EVENT = 4, + DATA_TYPE_ISO = 5, } serial_data_type_t; typedef void (*packet_ready_cb)(BT_HDR *packet); diff --git a/lib/bt/host/bluedroid/hci/include/hci/hci_layer.h b/lib/bt/host/bluedroid/hci/include/hci/hci_layer.h index 8e822f0f..c48d0565 100644 --- a/lib/bt/host/bluedroid/hci/include/hci/hci_layer.h +++ b/lib/bt/host/bluedroid/hci/include/hci/hci_layer.h @@ -104,10 +104,11 @@ void hci_shut_down(void); bool hci_downstream_data_post(uint32_t timeout); +#if (BLE_42_SCAN_EN == TRUE) #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) int hci_adv_credits_prep_to_release(uint16_t num); int hci_adv_credits_try_release(uint16_t num); int hci_adv_credits_force_release(uint16_t num); #endif - +#endif // #if (BLE_42_SCAN_EN == TRUE) #endif /* _HCI_LAYER_H_ */ diff --git a/lib/bt/host/bluedroid/hci/include/hci/hci_packet_factory.h b/lib/bt/host/bluedroid/hci/include/hci/hci_packet_factory.h index c1580fd8..2d36051a 100644 --- a/lib/bt/host/bluedroid/hci/include/hci/hci_packet_factory.h +++ b/lib/bt/host/bluedroid/hci/include/hci/hci_packet_factory.h @@ -26,7 +26,9 @@ typedef struct { BT_HDR *(*make_reset)(void); BT_HDR *(*make_read_buffer_size)(void); BT_HDR *(*make_set_c2h_flow_control)(uint8_t enable); +#if (BLE_42_SCAN_EN == TRUE) BT_HDR *(*make_set_adv_report_flow_control)(uint8_t enable, uint16_t num, uint16_t lost_threshold); +#endif // #if (BLE_42_SCAN_EN == TRUE) BT_HDR *(*make_host_buffer_size)(uint16_t acl_size, uint8_t sco_size, uint16_t acl_count, uint16_t sco_count); BT_HDR *(*make_read_local_version_info)(void); BT_HDR *(*make_read_bd_addr)(void); @@ -39,11 +41,19 @@ typedef struct { BT_HDR *(*make_ble_write_host_support)(uint8_t supported_host, uint8_t simultaneous_host); BT_HDR *(*make_ble_read_white_list_size)(void); BT_HDR *(*make_ble_read_buffer_size)(void); +#if (BLE_FEAT_ISO_EN == TRUE) + BT_HDR *(*make_ble_read_buffer_size_v2)(void); +#endif // #if (BLE_FEAT_ISO_EN == TRUE) BT_HDR *(*make_ble_read_supported_states)(void); BT_HDR *(*make_ble_read_local_supported_features)(void); BT_HDR *(*make_ble_read_resolving_list_size)(void); #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) BT_HDR *(*make_read_max_adv_data_len)(void); +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) + BT_HDR *(*read_periodic_adv_list_size)(void); +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) BT_HDR *(*make_ble_read_suggested_default_data_length)(void); BT_HDR *(*make_ble_write_suggested_default_data_length)(uint16_t SuggestedMaxTxOctets, uint16_t SuggestedMaxTxTime); diff --git a/lib/bt/host/bluedroid/hci/include/hci/hci_packet_parser.h b/lib/bt/host/bluedroid/hci/include/hci/hci_packet_parser.h index e46acc17..c40ffef9 100644 --- a/lib/bt/host/bluedroid/hci/include/hci/hci_packet_parser.h +++ b/lib/bt/host/bluedroid/hci/include/hci/hci_packet_parser.h @@ -79,6 +79,16 @@ typedef struct { uint8_t *acl_buffer_count_ptr ); +#if (BLE_FEAT_ISO_EN == TRUE) + void (*parse_ble_read_buffer_size_response_v2) ( + BT_HDR *response, + uint16_t *data_size_ptr, + uint8_t *acl_buffer_count_ptr, + uint16_t *iso_pkt_len_ptr, + uint8_t *iso_pkt_num_ptr + ); +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + void (*parse_ble_read_supported_states_response)( BT_HDR *response, uint8_t *supported_states, @@ -95,10 +105,18 @@ typedef struct { uint8_t *resolving_list_size_ptr ); #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) void (*parse_ble_read_adv_max_len_response) ( - BT_HDR *respone, + BT_HDR *response, uint16_t *ble_ext_adv_data_max_len_ptr ); +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) + void (*parse_ble_read_periodic_adv_list_size_response) ( + BT_HDR *response, + uint16_t *periodic_advertiser_list_size + ); +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) void (*parse_ble_read_suggested_default_data_length_response)( BT_HDR *response, diff --git a/lib/bt/host/bluedroid/hci/packet_fragmenter.c b/lib/bt/host/bluedroid/hci/packet_fragmenter.c index 78b6151e..d8f2ff91 100644 --- a/lib/bt/host/bluedroid/hci/packet_fragmenter.c +++ b/lib/bt/host/bluedroid/hci/packet_fragmenter.c @@ -171,6 +171,12 @@ static void reassemble_and_dispatch(BT_HDR *packet) return; } partial_packet = (BT_HDR *)osi_calloc(full_length + sizeof(BT_HDR)); + + if (partial_packet == NULL) { + HCI_TRACE_WARNING("%s full_length %d no memory.\n", __func__, full_length); + assert(0); + } + partial_packet->event = packet->event; partial_packet->len = full_length; partial_packet->offset = packet->len; diff --git a/lib/bt/host/bluedroid/main/bte_init.c b/lib/bt/host/bluedroid/main/bte_init.c index 80c4357b..c60f6f7b 100644 --- a/lib/bt/host/bluedroid/main/bte_init.c +++ b/lib/bt/host/bluedroid/main/bte_init.c @@ -27,8 +27,8 @@ #include -/* Stack Configuation Related Init Definaton - * TODO: Now Just Unmask these defination until stack layer is OK +/* Stack Configuration Related Init Definaton + * TODO: Now Just Unmask these definition until stack layer is OK */ #ifndef BTA_INCLUDED @@ -91,6 +91,15 @@ #endif #endif +#if (defined(OBEX_INCLUDED) && OBEX_INCLUDED == TRUE) +#include "stack/obex_api.h" +#endif + +#if (defined(GOEPC_INCLUDED) && GOEPC_INCLUDED == TRUE) +#include "stack/goep_common.h" +#include "stack/goepc_api.h" +#endif + //BTA Modules #if BTA_INCLUDED == TRUE && BTA_DYNAMIC_MEMORY == TRUE #include "bta/bta_api.h" @@ -147,6 +156,10 @@ #include "bta_pan_int.h" #endif +#if BTA_PBA_CLIENT_INCLUDED == TRUE +#include "bta_pba_client_int.h" +#endif + #include "bta_sys_int.h" // control block for patch ram downloading @@ -175,6 +188,12 @@ void BTE_DeinitStack(void) { //BTA Modules #if (BTA_INCLUDED == TRUE && BTA_DYNAMIC_MEMORY == TRUE) +#if BTA_PBA_CLIENT_INCLUDED == TRUE + if (bta_pba_client_cb_ptr) { + osi_free(bta_pba_client_cb_ptr); + bta_pba_client_cb_ptr = NULL; + } +#endif #if GATTS_INCLUDED == TRUE if (bta_gatts_cb_ptr){ osi_free(bta_gatts_cb_ptr); @@ -267,6 +286,14 @@ void BTE_DeinitStack(void) } #endif // BTA_INCLUDED == TRUE +#if (defined(GOEPC_INCLUDED) && GOEPC_INCLUDED == TRUE) + GOEPC_Deinit(); +#endif + +#if (defined(OBEX_INCLUDED) && OBEX_INCLUDED == TRUE) + OBEX_Deinit(); +#endif + #if (defined(HID_DEV_INCLUDED) && HID_DEV_INCLUDED == TRUE) HID_DevDeinit(); #endif @@ -388,6 +415,18 @@ bt_status_t BTE_InitStack(void) MCA_Init(); #endif +#if (defined(OBEX_INCLUDED) && OBEX_INCLUDED == TRUE) + if (OBEX_Init() != OBEX_SUCCESS) { + goto error_exit; + } +#endif + +#if (defined(GOEPC_INCLUDED) && GOEPC_INCLUDED == TRUE) + if (GOEPC_Init() != GOEP_SUCCESS) { + goto error_exit; + } +#endif + //BTA Modules #if (BTA_INCLUDED == TRUE && BTA_DYNAMIC_MEMORY == TRUE) if ((bta_sys_cb_ptr = (tBTA_SYS_CB *)osi_malloc(sizeof(tBTA_SYS_CB))) == NULL) { @@ -492,6 +531,12 @@ bt_status_t BTE_InitStack(void) #if BTA_PAN_INCLUDED==TRUE memset((void *)bta_pan_cb_ptr, 0, sizeof(tBTA_PAN_CB)); #endif +#if BTA_PBA_CLIENT_INCLUDED == TRUE + if ((bta_pba_client_cb_ptr = (tBTA_PBA_CLIENT_CB *)osi_malloc(sizeof(tBTA_PBA_CLIENT_CB))) == NULL) { + goto error_exit; + } + memset((void *)bta_pba_client_cb_ptr, 0, sizeof(tBTA_PBA_CLIENT_CB)); +#endif #endif // BTA_INCLUDED == TRUE return BT_STATUS_SUCCESS; diff --git a/lib/bt/host/bluedroid/main/bte_main.c b/lib/bt/host/bluedroid/main/bte_main.c index c47bdc15..c974037e 100644 --- a/lib/bt/host/bluedroid/main/bte_main.c +++ b/lib/bt/host/bluedroid/main/bte_main.c @@ -64,6 +64,9 @@ static void bte_main_enable(void); bluedroid_init_done_cb_t bluedroid_init_done_cb; extern void osi_mem_dbg_init(void); +#if (BT_BLE_DYNAMIC_ENV_MEMORY == TRUE) +extern void free_controller_param(void); +#endif /****************************************************************************** ** ** Function bte_main_boot_entry @@ -85,7 +88,7 @@ int bte_main_boot_entry(bluedroid_init_done_cb_t cb) osi_init(); - //Enbale HCI + //Enable HCI bte_main_enable(); return 0; @@ -105,6 +108,11 @@ void bte_main_shutdown(void) #if (BLE_INCLUDED == TRUE) BTA_VendorCleanup(); #endif + +#if (BT_BLE_DYNAMIC_ENV_MEMORY == TRUE) + free_controller_param(); +#endif + bte_main_disable(); osi_deinit(); diff --git a/lib/bt/host/bluedroid/stack/avct/avct_lcb.c b/lib/bt/host/bluedroid/stack/avct/avct_lcb.c index 61f6c9a5..84a0f021 100644 --- a/lib/bt/host/bluedroid/stack/avct/avct_lcb.c +++ b/lib/bt/host/bluedroid/stack/avct/avct_lcb.c @@ -430,10 +430,10 @@ BOOLEAN avct_lcb_last_ccb(tAVCT_LCB *p_lcb, tAVCT_CCB *p_ccb_last) tAVCT_CCB *p_ccb = &avct_cb.ccb[0]; int i; - AVCT_TRACE_WARNING("avct_lcb_last_ccb"); + AVCT_TRACE_DEBUG("avct_lcb_last_ccb"); for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) { - AVCT_TRACE_WARNING("%x: aloc:%d, lcb:%p/%p, ccb:%p/%p", - i, p_ccb->allocated, p_ccb->p_lcb, p_lcb, p_ccb, p_ccb_last); + AVCT_TRACE_DEBUG("%x: aloc:%d, lcb:%p/%p, ccb:%p/%p", + i, p_ccb->allocated, p_ccb->p_lcb, p_lcb, p_ccb, p_ccb_last); if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb) && (p_ccb != p_ccb_last)) { return FALSE; } diff --git a/lib/bt/host/bluedroid/stack/avdt/avdt_api.c b/lib/bt/host/bluedroid/stack/avdt/avdt_api.c index f37db816..9fb84fb9 100644 --- a/lib/bt/host/bluedroid/stack/avdt/avdt_api.c +++ b/lib/bt/host/bluedroid/stack/avdt/avdt_api.c @@ -264,6 +264,37 @@ UINT16 AVDT_CreateStream(UINT8 *p_handle, tAVDT_CS *p_cs) return result; } +/******************************************************************************* +** +** Function AVDT_UpdateCodecInfo +** +** Description Update codec capability for a stream endpoint. +** +** +** Returns AVDT_SUCCESS if successful, otherwise error. +** +*******************************************************************************/ +UINT16 AVDT_UpdateCodecInfo(UINT8 handle, UINT8 num_codec, UINT8 *codec_info, UINT16 codec_info_len) +{ + UINT16 result = AVDT_SUCCESS; + tAVDT_SCB *p_scb; + + /* look up scb */ + if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) { + result = AVDT_BAD_HANDLE; + } + else if (num_codec != 1 || codec_info == NULL || codec_info_len != AVDT_CODEC_SIZE) { + /* currently, only allow one codec info */ + result = AVDT_BAD_PARAMS; + } + else { + /* update codec info */ + p_scb->cs.cfg.num_codec = num_codec; + memcpy(p_scb->cs.cfg.codec_info, codec_info, codec_info_len); + } + return result; +} + /******************************************************************************* ** ** Function AVDT_RemoveStream diff --git a/lib/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c b/lib/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c index 18106870..279313d4 100644 --- a/lib/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c +++ b/lib/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c @@ -50,7 +50,7 @@ static tAVRC_STS avrc_bld_next_cmd (tAVRC_NEXT_CMD *p_cmd, BT_HDR *p_pkt) p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start + 2; /* pdu + rsvd */ - /* add fixed lenth 1 - pdu_id (1) */ + /* add fixed length 1 - pdu_id (1) */ UINT16_TO_BE_STREAM(p_data, 1); UINT8_TO_BE_STREAM(p_data, p_cmd->target_pdu); p_pkt->len = (p_data - p_start); @@ -81,7 +81,7 @@ static tAVRC_STS avrc_bld_set_abs_volume_cmd (tAVRC_SET_VOLUME_CMD *p_cmd, BT_HD /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start + 2; /* pdu + rsvd */ - /* add fixed lenth 1 - volume (1) */ + /* add fixed length 1 - volume (1) */ UINT16_TO_BE_STREAM(p_data, 1); UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_cmd->volume)); p_pkt->len = (p_data - p_start); @@ -163,7 +163,7 @@ static BT_HDR *avrc_bld_init_cmd_buffer(tAVRC_COMMAND *p_cmd) /* reserved 0, packet_type 0 */ UINT8_TO_BE_STREAM(p_data, 0); /* continue to the next "case to add length */ - /* add fixed lenth - 0 */ + /* add fixed length - 0 */ UINT16_TO_BE_STREAM(p_data, 0); break; } @@ -237,6 +237,20 @@ static tAVRC_STS avrc_bld_get_element_attr_cmd (tAVRC_GET_ELEM_ATTRS_CMD *p_cmd, return AVRC_STS_NO_ERROR; } +static tAVRC_STS avrc_bld_get_play_status_cmd(tAVRC_CMD *p_cmd, BT_HDR *p_pkt) +{ + UINT8 *p_data, *p_start; + + AVRC_TRACE_API("avrc_bld_get_play_status"); + /* get the existing length */ + p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; + p_data = p_start + 2; /* pdu + rsvd */ + /* add parameter length 0 */ + UINT16_TO_BE_STREAM(p_data, 0); + p_pkt->len = (p_data - p_start); + return AVRC_STS_NO_ERROR; +} + static tAVRC_STS avrc_bld_get_caps_cmd(tAVRC_GET_CAPS_CMD *p_cmd, BT_HDR *p_pkt) { UINT8 *p_data, *p_start; @@ -309,6 +323,10 @@ tAVRC_STS AVRC_BldCommand( tAVRC_COMMAND *p_cmd, BT_HDR **pp_pkt) status = avrc_bld_get_element_attr_cmd(&p_cmd->get_elem_attrs, p_pkt); break; + case AVRC_PDU_GET_PLAY_STATUS: /* 0x30 */ + status = avrc_bld_get_play_status_cmd(&p_cmd->get_play_status, p_pkt); + break; + case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */ status = avrc_bld_register_change_notfn(p_cmd->reg_notif.event_id, p_cmd->reg_notif.param, p_pkt); break; diff --git a/lib/bt/host/bluedroid/stack/avrc/avrc_pars_ct.c b/lib/bt/host/bluedroid/stack/avrc/avrc_pars_ct.c index f185e7b5..72f26513 100644 --- a/lib/bt/host/bluedroid/stack/avrc/avrc_pars_ct.c +++ b/lib/bt/host/bluedroid/stack/avrc/avrc_pars_ct.c @@ -113,6 +113,19 @@ static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR *p_msg, tAVRC_RESPONSE *p } } break; + case AVRC_PDU_GET_PLAY_STATUS: + if (p_msg->hdr.ctype == AVRC_RSP_IMPL_STBL) { + BE_STREAM_TO_UINT32(p_result->get_play_status.song_len, p); + BE_STREAM_TO_UINT32(p_result->get_play_status.song_pos, p); + BE_STREAM_TO_UINT8(p_result->get_play_status.play_status, p); + } + else { + /* got error response */ + p_result->get_play_status.song_len = 0; + p_result->get_play_status.song_pos = 0; + p_result->get_play_status.play_status = AVRC_PLAYSTATE_ERROR; + } + break; default: status = AVRC_STS_BAD_CMD; break; diff --git a/lib/bt/host/bluedroid/stack/avrc/avrc_pars_tg.c b/lib/bt/host/bluedroid/stack/avrc/avrc_pars_tg.c index c30bf94a..fe04ca8f 100644 --- a/lib/bt/host/bluedroid/stack/avrc/avrc_pars_tg.c +++ b/lib/bt/host/bluedroid/stack/avrc/avrc_pars_tg.c @@ -71,7 +71,7 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_ p++; /* skip the reserved byte */ BE_STREAM_TO_UINT16 (len, p); if ((len + 4) != (p_msg->vendor_len)) { - status = AVRC_STS_INTERNAL_ERR; + status = AVRC_STS_NOT_FOUND; } if (status != AVRC_STS_NO_ERROR) { diff --git a/lib/bt/host/bluedroid/stack/avrc/avrc_sdp.c b/lib/bt/host/bluedroid/stack/avrc/avrc_sdp.c index fa98082e..0b624b3f 100644 --- a/lib/bt/host/bluedroid/stack/avrc/avrc_sdp.c +++ b/lib/bt/host/bluedroid/stack/avrc/avrc_sdp.c @@ -29,8 +29,8 @@ #if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE) -#ifndef SDP_AVRCP_1_5 -#define SDP_AVRCP_1_5 TRUE +#ifndef SDP_AVRCP_1_6 +#define SDP_AVRCP_1_6 TRUE #endif #ifndef SDP_AVCTP_1_4 @@ -52,7 +52,7 @@ const tSDP_PROTOCOL_ELEM avrc_proto_list [] = { #if SDP_AVCTP_1_4 == TRUE {UUID_PROTOCOL_AVCTP, 1, {AVCT_REV_1_4, 0} } #else -#if (SDP_AVRCP_1_4 == TRUE || SDP_AVRCP_1_5 == TRUE) +#if SDP_AVRCP_1_6 == TRUE {UUID_PROTOCOL_AVCTP, 1, {AVCT_REV_1_3, 0} } #else #if AVRC_METADATA_INCLUDED == TRUE @@ -64,7 +64,7 @@ const tSDP_PROTOCOL_ELEM avrc_proto_list [] = { #endif }; -#if SDP_AVRCP_1_5 == TRUE +#if SDP_AVRCP_1_6 == TRUE const tSDP_PROTO_LIST_ELEM avrc_add_proto_list [] = { { AVRC_NUM_PROTO_ELEMS, @@ -251,7 +251,7 @@ UINT16 AVRC_AddRecord(UINT16 service_uuid, char *p_service_name, char *p_provide /* add service class id list */ class_list[0] = service_uuid; -#if (SDP_AVCTP_1_4 == TRUE || SDP_AVRCP_1_5 == TRUE) +#if (SDP_AVCTP_1_4 == TRUE || SDP_AVRCP_1_6 == TRUE) if ( service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL ) { class_list[1] = UUID_SERVCLASS_AV_REM_CTRL_CONTROL; count = 2; @@ -263,7 +263,7 @@ UINT16 AVRC_AddRecord(UINT16 service_uuid, char *p_service_name, char *p_provide result &= SDP_AddProtocolList(sdp_handle, AVRC_NUM_PROTO_ELEMS, (tSDP_PROTOCOL_ELEM *)avrc_proto_list); /* add profile descriptor list */ -#if SDP_AVRCP_1_5 == TRUE +#if SDP_AVRCP_1_6 == TRUE if (browsing_en) { add_additional_protocol_list = TRUE; } else if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET && @@ -277,7 +277,7 @@ UINT16 AVRC_AddRecord(UINT16 service_uuid, char *p_service_name, char *p_provide result &= SDP_AddAdditionProtoLists( sdp_handle, 1, (tSDP_PROTO_LIST_ELEM *)avrc_add_proto_list); } - result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_5); + result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_6); #else #if AVRC_METADATA_INCLUDED == TRUE result &= SDP_AddProfileDescriptorList(sdp_handle, UUID_SERVCLASS_AV_REMOTE_CONTROL, AVRC_REV_1_3); @@ -292,6 +292,13 @@ UINT16 AVRC_AddRecord(UINT16 service_uuid, char *p_service_name, char *p_provide } else if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET && media_player_virtual_filesystem_supported) { supported_feature |= AVRC_SUPF_TG_BROWSE; } +#if AVRC_CA_INCLUDED + if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_CONTROL || service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL) { + supported_feature |= AVRC_SUPF_CT_COVER_ART_GIP; + supported_feature |= AVRC_SUPF_CT_COVER_ART_GI; + supported_feature |= AVRC_SUPF_CT_COVER_ART_GLT; + } +#endif /* add supported feature */ p = temp; UINT16_TO_BE_STREAM(p, supported_feature); @@ -383,7 +390,7 @@ bt_status_t AVRC_Init(void) ** ** Function AVRC_Deinit ** -** Description This function is called at stack shotdown to free the +** Description This function is called at stack shutdown to free the ** control block (if using dynamic memory), and deinitializes the ** control block and tracing level. ** diff --git a/lib/bt/host/bluedroid/stack/btm/btm_acl.c b/lib/bt/host/bluedroid/stack/btm/btm_acl.c index 4b7e7eed..90506785 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_acl.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_acl.c @@ -335,7 +335,7 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, UINT8 bdn[BTM_MAX_REM_BD_NAME_L #if (CLASSIC_BT_INCLUDED == TRUE) const UINT8 req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND); #endif ///CLASSIC_BT_INCLUDED == TRUE - /* Store the Peer Security Capabilites (in SM4 and rmt_sec_caps) */ + /* Store the Peer Security Capabilities (in SM4 and rmt_sec_caps) */ #if (SMP_INCLUDED == TRUE) btm_sec_set_peer_sec_caps(p, p_dev_rec); #endif ///SMP_INCLUDED == TRUE @@ -350,7 +350,7 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, UINT8 bdn[BTM_MAX_REM_BD_NAME_L return; } } else { - /* If remote features indicated secure connection (SC) mode, check the remote feautres again*/ + /* If remote features indicated secure connection (SC) mode, check the remote features again*/ /* this is to prevent from BIAS attack where attacker can downgrade SC mode*/ btm_read_remote_features (p->hci_handle); } @@ -474,7 +474,7 @@ void btm_acl_removed (BD_ADDR bda, tBT_TRANSPORT transport) BTM_TRACE_DEBUG("Bonded\n"); } } else { - BTM_TRACE_DEBUG("Bletooth link down\n"); + BTM_TRACE_DEBUG("Bluetooth link down\n"); p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED); } @@ -531,10 +531,11 @@ void btm_acl_device_down (void) *******************************************************************************/ void btm_acl_update_busy_level (tBTM_BLI_EVENT event) { - tBTM_BL_UPDATE_DATA evt; - UINT8 busy_level; - BTM_TRACE_DEBUG ("btm_acl_update_busy_level\n"); + UINT8 busy_level_flags = 0; BOOLEAN old_inquiry_state = btm_cb.is_inquiry; + + BTM_TRACE_DEBUG ("btm_acl_update_busy_level\n"); + switch (event) { case BTM_BLI_ACL_UP_EVT: BTM_TRACE_DEBUG ("BTM_BLI_ACL_UP_EVT\n"); @@ -545,30 +546,31 @@ void btm_acl_update_busy_level (tBTM_BLI_EVENT event) case BTM_BLI_PAGE_EVT: BTM_TRACE_DEBUG ("BTM_BLI_PAGE_EVT\n"); btm_cb.is_paging = TRUE; - evt.busy_level_flags = BTM_BL_PAGING_STARTED; + busy_level_flags = BTM_BL_PAGING_STARTED; break; case BTM_BLI_PAGE_DONE_EVT: BTM_TRACE_DEBUG ("BTM_BLI_PAGE_DONE_EVT\n"); btm_cb.is_paging = FALSE; - evt.busy_level_flags = BTM_BL_PAGING_COMPLETE; + busy_level_flags = BTM_BL_PAGING_COMPLETE; break; case BTM_BLI_INQ_EVT: BTM_TRACE_DEBUG ("BTM_BLI_INQ_EVT\n"); btm_cb.is_inquiry = TRUE; - evt.busy_level_flags = BTM_BL_INQUIRY_STARTED; + busy_level_flags = BTM_BL_INQUIRY_STARTED; break; case BTM_BLI_INQ_CANCEL_EVT: BTM_TRACE_DEBUG ("BTM_BLI_INQ_CANCEL_EVT\n"); btm_cb.is_inquiry = FALSE; - evt.busy_level_flags = BTM_BL_INQUIRY_CANCELLED; + busy_level_flags = BTM_BL_INQUIRY_CANCELLED; break; case BTM_BLI_INQ_DONE_EVT: BTM_TRACE_DEBUG ("BTM_BLI_INQ_DONE_EVT\n"); btm_cb.is_inquiry = FALSE; - evt.busy_level_flags = BTM_BL_INQUIRY_COMPLETE; + busy_level_flags = BTM_BL_INQUIRY_COMPLETE; break; } + UINT8 busy_level; if (btm_cb.is_paging || btm_cb.is_inquiry) { busy_level = 10; } else { @@ -576,8 +578,11 @@ void btm_acl_update_busy_level (tBTM_BLI_EVENT event) } if ((busy_level != btm_cb.busy_level) || (old_inquiry_state != btm_cb.is_inquiry)) { - evt.event = BTM_BL_UPDATE_EVT; - evt.busy_level = busy_level; + tBTM_BL_UPDATE_DATA evt = { + .event = BTM_BL_UPDATE_EVT, + .busy_level = busy_level, + .busy_level_flags = busy_level_flags, + }; btm_cb.busy_level = busy_level; if (btm_cb.p_bl_changed_cb && (btm_cb.bl_evt_mask & BTM_BL_UPDATE_MASK)) { (*btm_cb.p_bl_changed_cb)((tBTM_BL_EVENT_DATA *)&evt); @@ -1016,7 +1021,7 @@ void btm_process_remote_ext_features (tACL_CONN *p_acl_cb, UINT8 num_read_pages) const UINT8 req_pend = (p_dev_rec->sm4 & BTM_SM4_REQ_PEND); #if (SMP_INCLUDED == TRUE) - /* Store the Peer Security Capabilites (in SM4 and rmt_sec_caps) */ + /* Store the Peer Security Capabilities (in SM4 and rmt_sec_caps) */ btm_sec_set_peer_sec_caps(p_acl_cb, p_dev_rec); #endif ///SMP_INCLUDED == TRUE BTM_TRACE_API("%s: pend:%d\n", __FUNCTION__, req_pend); @@ -1455,7 +1460,7 @@ void btm_process_clk_off_comp_evt (UINT16 hci_handle, UINT16 clock_offset) ** ** Function btm_acl_role_changed ** -** Description This function is called whan a link's master/slave role change +** Description This function is called when a link's master/slave role change ** event or command status event (with error) is received. ** It updates the link control block, and calls ** the registered callback with status and role (if registered). @@ -2060,6 +2065,7 @@ tBTM_STATUS BTM_ReadLinkQuality (BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb) return (BTM_UNKNOWN_ADDR); } +#if (BLE_HOST_READ_TX_POWER_EN == TRUE) /******************************************************************************* ** ** Function BTM_ReadTxPower @@ -2116,6 +2122,7 @@ tBTM_STATUS BTM_ReadTxPower (BD_ADDR remote_bda, tBT_TRANSPORT transport, tBTM_C /* If here, no BD Addr found */ return (BTM_UNKNOWN_ADDR); } +#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) tBTM_STATUS BTM_SetAclPktTypes(BD_ADDR remote_bda, UINT16 pkt_types, tBTM_CMPL_CB *p_cb) { @@ -2182,6 +2189,55 @@ void btm_acl_pkt_types_changed(UINT8 status, UINT16 handle, UINT16 pkt_types) } #if (BLE_INCLUDED == TRUE) + +/******************************************************************************* +** +** Function BTM_ReadChannelMap +** +** Description This function is called to read the current channel map +** for the given connection. The results are returned via +** the callback (tBTM_BLE_CH_MAP_RESULTS). +** +** Returns BTM_CMD_STARTED if successfully initiated or error code +** +*******************************************************************************/ +tBTM_STATUS BTM_ReadChannelMap(BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb) +{ + tACL_CONN *p; + tBTM_BLE_CH_MAP_RESULTS result; + + BTM_TRACE_DEBUG("BTM_ReadChannelMap: RemBdAddr: %02x%02x%02x%02x%02x%02x\n", + remote_bda[0], remote_bda[1], remote_bda[2], + remote_bda[3], remote_bda[4], remote_bda[5]); + + memset(result.channel_map, 0, sizeof(result.channel_map)); // Clear channel map data + /* If someone already waiting for the channel map, do not allow another */ + if (btm_cb.devcb.p_ble_ch_map_cmpl_cb) { + result.status = BTM_BUSY; + (*p_cb)(&result); + return BTM_BUSY; + } + p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_LE); + if (p != NULL) { + btm_cb.devcb.p_ble_ch_map_cmpl_cb = p_cb; + + if (!btsnd_hcic_ble_read_chnl_map(p->hci_handle)) { + btm_cb.devcb.p_ble_ch_map_cmpl_cb = NULL; + result.status = BTM_NO_RESOURCES; + (*p_cb)(&result); + return BTM_NO_RESOURCES; + } else { + return BTM_CMD_STARTED; + } + } + + /* If here, no BD Addr found */ + result.status = BTM_UNKNOWN_ADDR; + (*p_cb)(&result); + return BTM_UNKNOWN_ADDR; +} + +#if (BLE_HOST_READ_TX_POWER_EN == TRUE) tBTM_STATUS BTM_BleReadAdvTxPower(tBTM_CMPL_CB *p_cb) { BOOLEAN ret; @@ -2208,6 +2264,7 @@ tBTM_STATUS BTM_BleReadAdvTxPower(tBTM_CMPL_CB *p_cb) return BTM_CMD_STARTED; } } +#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) void BTM_BleGetWhiteListSize(uint16_t *length) { @@ -2218,8 +2275,21 @@ void BTM_BleGetWhiteListSize(uint16_t *length) *length = p_cb->white_list_avail_size; return; } + +#if (BLE_50_EXTEND_SYNC_EN == TRUE) +void BTM_BleGetPeriodicAdvListSize(uint8_t *size) +{ + tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; + if (p_cb->periodic_adv_list_size == 0) { + BTM_TRACE_WARNING("%s Periodic Adv list is full.", __func__); + } + *size = p_cb->periodic_adv_list_size; +} +#endif //#if (BLE_50_EXTEND_SYNC_EN == TRUE) + #endif ///BLE_INCLUDED == TRUE +#if (BLE_HOST_READ_TX_POWER_EN == TRUE) /******************************************************************************* ** ** Function btm_read_tx_power_complete @@ -2273,6 +2343,63 @@ void btm_read_tx_power_complete (UINT8 *p, BOOLEAN is_ble) (*p_cb)(&results); } } +#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) + +/******************************************************************************* +** +** Function btm_read_channel_map_complete +** +** Description This function is called when the command complete message +** is received from the HCI for the read channel map request. +** It processes the received channel map data and invokes the +** registered callback function with the results. +** +** Returns void +** +*******************************************************************************/ +void btm_read_channel_map_complete(UINT8 *p) +{ + tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_ble_ch_map_cmpl_cb; + tBTM_BLE_CH_MAP_RESULTS results; + UINT16 handle; + tACL_CONN *p_acl_cb = NULL; + + BTM_TRACE_DEBUG("btm_read_channel_map_complete\n"); + + /* Reset the callback pointer to prevent duplicate calls */ + btm_cb.devcb.p_ble_ch_map_cmpl_cb = NULL; + + if (p_cb) { + /* Extract HCI status from the response */ + STREAM_TO_UINT8(results.hci_status, p); + + if (results.hci_status == HCI_SUCCESS) { + results.status = BTM_SUCCESS; + + /* Extract the connection handle and channel map */ + STREAM_TO_UINT16(handle, p); + STREAM_TO_ARRAY(results.channel_map, p, 5); + + BTM_TRACE_DEBUG("BTM Channel Map Complete: handle 0x%04x, hci status 0x%02x", handle, results.hci_status); + BTM_TRACE_DEBUG("Channel Map: %02x %02x %02x %02x %02x", + results.channel_map[0], results.channel_map[1], results.channel_map[2], + results.channel_map[3], results.channel_map[4]); + + /* Retrieve the remote BD address using the connection handle */ + p_acl_cb = btm_handle_to_acl(handle); + if (p_acl_cb) { + memcpy(results.rem_bda, p_acl_cb->remote_addr, BD_ADDR_LEN); + } + } else { + results.status = BTM_ERR_PROCESSING; + BTM_TRACE_ERROR("BTM Channel Map Read Failed: hci status 0x%02x", results.hci_status); + } + + /* Invoke the registered callback with the results */ + (*p_cb)(&results); + } +} + /******************************************************************************* ** @@ -2705,7 +2832,7 @@ void btm_acl_connected(BD_ADDR bda, UINT16 handle, UINT8 link_type, UINT8 enc_mo l2c_link_hci_conn_comp(status, handle, bda); } #if BTM_SCO_INCLUDED == TRUE - else { + else if (link_type == HCI_LINK_TYPE_SCO) { memset(&esco_data, 0, sizeof(tBTM_ESCO_DATA)); esco_data.link_type = HCI_LINK_TYPE_SCO; memcpy (esco_data.bd_addr, bda, BD_ADDR_LEN); @@ -2721,9 +2848,10 @@ void btm_acl_connected(BD_ADDR bda, UINT16 handle, UINT8 link_type, UINT8 enc_mo ** Description Handle ACL disconnection complete event ** *******************************************************************************/ -void btm_acl_disconnected(UINT16 handle, UINT8 reason) +BOOLEAN btm_acl_disconnected(UINT16 handle, UINT8 reason) { - + BOOLEAN status = FALSE; + BOOLEAN dis_status; /* Report BR/EDR ACL disconnection result to upper layer */ tACL_CONN *conn = btm_handle_to_acl(handle); if (conn) { @@ -2731,6 +2859,7 @@ void btm_acl_disconnected(UINT16 handle, UINT8 reason) if (conn->transport == BT_TRANSPORT_BR_EDR) #endif { + status = TRUE; tBTM_ACL_LINK_STAT_EVENT_DATA evt_data = { .event = BTM_ACL_DISCONN_CMPL_EVT, .link_act.disconn_cmpl.reason = reason, @@ -2742,16 +2871,29 @@ void btm_acl_disconnected(UINT16 handle, UINT8 reason) } #if BTM_SCO_INCLUDED == TRUE + dis_status = l2c_link_hci_disc_comp (handle, reason); /* If L2CAP doesn't know about it, send it to SCO */ - if (!l2c_link_hci_disc_comp (handle, reason)) { - btm_sco_removed (handle, reason); + if (!dis_status) { + dis_status = btm_sco_removed (handle, reason); + } else { + status = TRUE; } #else - l2c_link_hci_disc_comp(handle, reason); + dis_status = l2c_link_hci_disc_comp(handle, reason); #endif /* BTM_SCO_INCLUDED */ + if (dis_status) { + // find tL2C_LCB + status = TRUE; + } #if (SMP_INCLUDED == TRUE) /* Notify security manager */ - btm_sec_disconnected(handle, reason); + if (btm_sec_disconnected(handle, reason)) { + // find tBTM_SEC_DEV_REC + status = TRUE; + } + #endif /* SMP_INCLUDED == TRUE */ + + return status; } diff --git a/lib/bt/host/bluedroid/stack/btm/btm_ble.c b/lib/bt/host/bluedroid/stack/btm/btm_ble.c index 334001fe..8f676a65 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_ble.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_ble.c @@ -217,7 +217,7 @@ void BTM_BleLoadLocalKeys(UINT8 key_type, tBTM_BLE_LOCAL_KEYS *p_key) break; default: - BTM_TRACE_ERROR("unknow local key type: %d", key_type); + BTM_TRACE_ERROR("unknown local key type: %d", key_type); break; } } @@ -553,6 +553,7 @@ void BTM_BleSecureConnectionCreateOobData(void) #endif } +#if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) /****************************************************************************** ** ** Function BTM_BleSetConnScanParams @@ -582,15 +583,17 @@ void BTM_BleSetConnScanParams (UINT32 scan_interval, UINT32 scan_window) p_ble_cb->scan_win = scan_window; new_param = TRUE; } - +#if (tGATT_BG_CONN_DEV == TRUE) if (new_param && p_ble_cb->conn_state == BLE_BG_CONN) { btm_ble_suspend_bg_conn(); } +#endif // #if (tGATT_BG_CONN_DEV == TRUE) } else { BTM_TRACE_ERROR("Illegal Connection Scan Parameters"); } #endif } +#endif // #if (BLE_HOST_CONN_SCAN_PARAM_EN == TRUE) /******************************************************** ** @@ -694,7 +697,7 @@ void BTM_ReadDevInfo (BD_ADDR remote_bda, tBT_DEVICE_TYPE *p_dev_type, tBLE_ADDR BTM_TRACE_DEBUG ("btm_find_dev_type - unknown device, BR/EDR assumed"); } } - } else { /* there is a security device record exisitng */ + } else { /* there is a security device record existing */ /* new inquiry result, overwrite device type in security device record */ if (p_inq_info) { p_dev_rec->device_type = p_inq_info->results.device_type; @@ -707,7 +710,7 @@ void BTM_ReadDevInfo (BD_ADDR remote_bda, tBT_DEVICE_TYPE *p_dev_type, tBLE_ADDR } else if (memcmp(p_dev_rec->ble.pseudo_addr, remote_bda, BD_ADDR_LEN) == 0) { *p_dev_type = BT_DEVICE_TYPE_BLE; *p_addr_type = p_dev_rec->ble.ble_addr_type; - } else { /* matching static adddress only */ + } else { /* matching static address only */ *p_dev_type = BT_DEVICE_TYPE_BREDR; *p_addr_type = BLE_ADDR_PUBLIC; } @@ -766,6 +769,7 @@ BOOLEAN BTM_ReadConnectedTransportAddress(BD_ADDR remote_bda, tBT_TRANSPORT tran } #if (BLE_INCLUDED == TRUE) +#if (BLE_42_DTM_TEST_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleReceiverTest @@ -805,7 +809,8 @@ void BTM_BleTransmitterTest(UINT8 tx_freq, UINT8 test_data_len, BTM_TRACE_ERROR("%s: Unable to Trigger LE transmitter test", __FUNCTION__); } } - +#endif // #if (BLE_42_DTM_TEST_EN == TRUE) +#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) /******************************************************************************* ** ** Function BTM_BleTestEnd @@ -837,9 +842,9 @@ void btm_ble_test_command_complete(UINT8 *p) (*p_cb)(p); } } +#endif // #if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) - -#if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_DTM_TEST_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleEnhancedReceiverTest @@ -882,7 +887,7 @@ void BTM_BleEnhancedTransmitterTest(UINT8 tx_freq, UINT8 test_data_len, BTM_TRACE_ERROR("%s: Unable to Trigger LE enhanced transmitter test", __FUNCTION__); } } -#endif // BLE_50_FEATURE_SUPPORT +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) /******************************************************************************* ** @@ -1061,7 +1066,7 @@ tBTM_SEC_ACTION btm_ble_determine_security_act(BOOLEAN is_originator, BD_ADDR bd ** LE link for LE COC. ** ** Parameter bdaddr: remote device address. -** psm : PSM of the LE COC sevice. +** psm : PSM of the LE COC service. ** is_originator: TRUE if outgoing connection. ** p_callback : Pointer to the callback function. ** p_ref_data : Pointer to be returned along with the callback. @@ -1078,7 +1083,7 @@ BOOLEAN btm_ble_start_sec_check(BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_originat /* If there is no application registered with this PSM do not allow connection */ if (!p_serv_rec) { - BTM_TRACE_WARNING ("%s PSM: %d no application registerd", __func__, psm); + BTM_TRACE_WARNING ("%s PSM: %d no application registered", __func__, psm); (*p_callback) (bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_MODE_UNSUPPORTED); return FALSE; } @@ -1151,7 +1156,7 @@ void btm_ble_rand_enc_complete (UINT8 *p, UINT16 op_code, tBTM_RAND_ENC_CB *p_en /* If there was a callback address for vcs complete, call it */ if (p_enc_cplt_cback && p) { - /* Pass paramters to the callback function */ + /* Pass parameters to the callback function */ STREAM_TO_UINT8(params.status, p); /* command status */ if (params.status == HCI_SUCCESS) { @@ -1208,7 +1213,7 @@ void btm_ble_increment_sign_ctr(BD_ADDR bd_addr, BOOLEAN is_local ) ** Function btm_ble_get_enc_key_type ** ** Description This function is to get the BLE key type that has been exchanged -** in betweem local device and peer device. +** in between local device and peer device. ** ** Returns p_key_type: output parameter to carry the key type value. ** @@ -1235,7 +1240,7 @@ BOOLEAN btm_ble_get_enc_key_type(BD_ADDR bd_addr, UINT8 *p_key_types) ** ** Description This function is called to read the local DIV ** -** Returns TRUE - if a valid DIV is availavle +** Returns TRUE - if a valid DIV is available *******************************************************************************/ BOOLEAN btm_get_local_div (BD_ADDR bd_addr, UINT16 *p_div) { @@ -1487,7 +1492,7 @@ void btm_ble_link_sec_check(BD_ADDR bd_addr, tBTM_LE_AUTH_REQ auth_req, tBTM_BLE BTM_TRACE_DEBUG ("dev_rec sec_flags=0x%x", p_dev_rec->sec_flags); - /* currently encrpted */ + /* currently encrypted */ if (p_dev_rec->sec_flags & BTM_SEC_LE_ENCRYPTED) { if (p_dev_rec->sec_flags & BTM_SEC_LE_AUTHENTICATED) { cur_sec_level = BTM_LE_SEC_AUTHENTICATED; @@ -1691,7 +1696,7 @@ tBTM_STATUS btm_ble_start_encrypt(BD_ADDR bda, BOOLEAN use_stk, BT_OCTET16 stk) ** ** Function btm_ble_link_encrypted ** -** Description This function is called when LE link encrption status is changed. +** Description This function is called when LE link encryption status is changed. ** ** Returns void ** @@ -1949,7 +1954,7 @@ static void btm_ble_resolve_random_addr_on_conn_cmpl(void *p_rec, void *p_data) ** Function btm_ble_connected ** ** Description This function is when a LE connection to the peer device is -** establsihed +** established ** ** Returns void ** @@ -2060,7 +2065,7 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced) peer_addr_type = bda_type; match = btm_identity_addr_to_random_pseudo (bda, &bda_type, FALSE); - /* possiblly receive connection complete with resolvable random on + /* possibly receive connection complete with resolvable random on slave role while the device has been paired */ /* It will cause that scanner doesn't send scan request to advertiser @@ -2143,6 +2148,16 @@ void btm_ble_create_ll_conn_complete (UINT8 status) if (status != HCI_SUCCESS) { btm_ble_set_conn_st(BLE_CONN_IDLE); btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, NULL, status); + if(l2cb.is_ble_connecting) { + /* see L2CA_CancelBleConnectReq() */ + tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(l2cb.ble_connecting_bda, BT_TRANSPORT_LE); + /* Do not remove lcb if an LE link is already up as a peripheral */ + if (p_lcb != NULL && + !(p_lcb->link_role == HCI_ROLE_SLAVE && BTM_LE_ACL_IS_CONNECTED(l2cb.ble_connecting_bda))) { + p_lcb->disc_reason = L2CAP_CONN_CANCEL; + l2cu_release_lcb (p_lcb); + } + } } } @@ -2279,17 +2294,16 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data) } - } else { - if (event == SMP_SC_LOC_OOB_DATA_UP_EVT) { - tBTM_LE_EVT_DATA evt_data; - memcpy(&evt_data.local_oob_data, &p_data->loc_oob_data, sizeof(tSMP_LOC_OOB_DATA)); - if (btm_cb.api.p_le_callback) { - (*btm_cb.api.p_le_callback)(event, bd_addr, &evt_data); - } - } else { - BTM_TRACE_ERROR("btm_proc_smp_cback received for unknown device"); + } + + if (event == SMP_SC_LOC_OOB_DATA_UP_EVT) { + tBTM_LE_EVT_DATA evt_data; + memcpy(&evt_data.local_oob_data, &p_data->loc_oob_data, sizeof(tSMP_LOC_OOB_DATA)); + if (btm_cb.api.p_le_callback) { + (*btm_cb.api.p_le_callback)(event, bd_addr, &evt_data); } } + return 0; } #endif ///SMP_INCLUDED == TRUE @@ -2300,7 +2314,7 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data) ** Function BTM_BleDataSignature ** ** Description This function is called to sign the data using AES128 CMAC -** algorith. +** algorithm. ** ** Parameter bd_addr: target device the data to be signed for. ** p_text: singing data @@ -2308,7 +2322,7 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data) ** signature: output parameter where data signature is going to ** be stored. ** -** Returns TRUE if signing sucessul, otherwise FALSE. +** Returns TRUE if signing successful, otherwise FALSE. ** *******************************************************************************/ #if (SMP_INCLUDED == TRUE) @@ -2491,7 +2505,7 @@ BOOLEAN BTM_BleSecurityProcedureIsRunning(BD_ADDR bd_addr) ** Function BTM_BleGetSupportedKeySize ** ** Description This function gets the maximum encryption key size in bytes -** the local device can suport. +** the local device can support. ** record. ** ** Returns the key size or 0 if the size can't be retrieved. @@ -2932,7 +2946,7 @@ uint8_t btm_ble_scan_active_count(void) } #if (SMP_INCLUDED == TRUE) -uint8_t btm_ble_sec_dev_active_count(void) +uint8_t btm_ble_sec_dev_record_count(void) { tBTM_SEC_DEV_REC *p_dev_rec = NULL; list_node_t *p_node = NULL; @@ -2948,6 +2962,12 @@ uint8_t btm_ble_sec_dev_active_count(void) return count; } + +void btm_ble_clear_sec_dev_record(void) +{ + /* only used when connection is closed */ + if(btm_cb.p_sec_dev_rec_list) list_clear(btm_cb.p_sec_dev_rec_list); +} #endif #if (BLE_PRIVACY_SPT == TRUE) diff --git a/lib/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c b/lib/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c index 04ad4804..76fe63c0 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_ble_5_gap.c @@ -21,6 +21,7 @@ extern BOOLEAN BTM_GetLocalResolvablePrivateAddr(BD_ADDR bda); extern void BTM_UpdateAddrInfor(uint8_t addr_type, BD_ADDR bda); extern void BTM_BleSetStaticAddr(BD_ADDR rand_addr); extern uint32_t BTM_BleUpdateOwnType(uint8_t *own_bda_type, tBTM_START_ADV_CMPL_CBACK *cb); +#if (BLE_50_EXTEND_ADV_EN == TRUE) static tBTM_STATUS btm_ble_ext_adv_params_validate(tBTM_BLE_GAP_EXT_ADV_PARAMS *params); static tBTM_STATUS btm_ble_ext_adv_set_data_validate(UINT8 instance, UINT16 len, UINT8 *data); @@ -35,6 +36,8 @@ typedef struct { } tBTM_EXT_ADV_RECORD; tBTM_EXT_ADV_RECORD adv_record[MAX_BLE_ADV_INSTANCE] = {0}; +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) + extern void btm_ble_inter_set(bool extble_inter); #if !UC_BT_STACK_NO_LOG @@ -193,11 +196,12 @@ void btm_ble_extendadvcb_init(void) { memset(&extend_adv_cb, 0, sizeof(tBTM_BLE_EXTENDED_CB)); } - +#if (BLE_50_EXTEND_ADV_EN == TRUE) void btm_ble_advrecod_init(void) { memset(&adv_record[0], 0, sizeof(tBTM_EXT_ADV_RECORD)*MAX_BLE_ADV_INSTANCE); } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) void BTM_BleGapRegisterCallback(tBTM_BLE_5_HCI_CBACK cb) { @@ -249,10 +253,10 @@ tBTM_STATUS BTM_BleSetPreferDefaultPhy(UINT8 tx_phy_mask, UINT8 rx_phy_mask) if ((err = btsnd_hcic_ble_set_prefered_default_phy(all_phys, tx_phy_mask, rx_phy_mask)) != HCI_SUCCESS) { BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)", __func__, btm_ble_hci_status_to_str(err), err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } - cb_params.set_perf_def_phy.status = err; + cb_params.set_perf_def_phy.status = status; BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_SET_PREFERED_DEFAULT_PHY_COMPLETE_EVT, &cb_params); @@ -286,6 +290,7 @@ tBTM_STATUS BTM_BleSetPreferPhy(BD_ADDR bd_addr, UINT8 all_phys, UINT8 tx_phy_ma return BTM_SUCCESS; } +#if (BLE_50_EXTEND_ADV_EN == TRUE) tBTM_STATUS BTM_BleSetExtendedAdvRandaddr(UINT8 instance, BD_ADDR rand_addr) { tBTM_STATUS status = BTM_SUCCESS; @@ -330,7 +335,7 @@ tBTM_STATUS BTM_BleSetExtendedAdvRandaddr(UINT8 instance, BD_ADDR rand_addr) if((err = btsnd_hcic_ble_set_extend_rand_address(instance, rand_addr)) != HCI_SUCCESS) { BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)", __func__, btm_ble_hci_status_to_str(err), err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } else { // set random address success, update address info if(extend_adv_cb.inst[instance].configured && extend_adv_cb.inst[instance].connetable) { @@ -340,8 +345,8 @@ tBTM_STATUS BTM_BleSetExtendedAdvRandaddr(UINT8 instance, BD_ADDR rand_addr) } end: - cb_params.status = status; - + cb_params.set_ext_rand_addr.status = status; + cb_params.set_ext_rand_addr.instance = instance; BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT, &cb_params); return status; @@ -403,7 +408,7 @@ tBTM_STATUS BTM_BleSetExtendedAdvParams(UINT8 instance, tBTM_BLE_GAP_EXT_ADV_PAR params->primary_phy, params->max_skip, params->secondary_phy, params->sid, params->scan_req_notif)) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE EA SetParams: cmd err=0x%x", err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; goto end; } @@ -414,13 +419,14 @@ end: // update RPA address if((err = btsnd_hcic_ble_set_extend_rand_address(instance, rand_addr)) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE EA SetParams: cmd err=0x%x", err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } else { // set addr success, update address info BTM_UpdateAddrInfor(BLE_ADDR_RANDOM, rand_addr); } } - cb_params.status = status; + cb_params.set_params.status = status; + cb_params.set_params.instance = instance; BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_EXT_ADV_SET_PARAMS_COMPLETE_EVT, &cb_params); return status; @@ -451,27 +457,36 @@ tBTM_STATUS BTM_BleConfigExtendedAdvDataRaw(BOOLEAN is_scan_rsp, UINT8 instance, } else if (rem_len <= BTM_BLE_EXT_ADV_DATA_LEN_MAX) { operation = BTM_BLE_ADV_DATA_OP_LAST_FRAG; } else { - operation = BTM_BLE_ADV_DATA_OP_INTERMEDIATE_FRAG; - } + operation = BTM_BLE_ADV_DATA_OP_INTERMEDIATE_FRAG; + } } if (!is_scan_rsp) { if ((err = btsnd_hcic_ble_set_ext_adv_data(instance, operation, 0, send_data_len, &data[data_offset])) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE EA SetAdvData: cmd err=0x%x", err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; + break; } } else { if ((err = btsnd_hcic_ble_set_ext_adv_scan_rsp_data(instance, operation, 0, send_data_len, &data[data_offset])) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE EA SetScanRspData: cmd err=0x%x", err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; + break; } } rem_len -= send_data_len; - data_offset += send_data_len; + data_offset += send_data_len; } while (rem_len); end: - cb_params.status = status; + if (is_scan_rsp) { + cb_params.scan_rsp_data_set.status = status; + cb_params.scan_rsp_data_set.instance = instance; + } else { + cb_params.adv_data_set.status = status; + cb_params.adv_data_set.instance = instance; + } + BTM_ExtBleCallbackTrigger(is_scan_rsp ? BTM_BLE_5_GAP_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT : BTM_BLE_5_GAP_EXT_ADV_DATA_SET_COMPLETE_EVT, &cb_params); return status; @@ -514,7 +529,7 @@ tBTM_STATUS BTM_BleStartExtAdv(BOOLEAN enable, UINT8 num, tBTM_BLE_EXT_ADV *ext_ if ((err = btsnd_hcic_ble_ext_adv_enable(enable, num, instance, duration, max_events)) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE EA En=%d: cmd err=0x%x", enable, err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } osi_free(instance); @@ -525,7 +540,7 @@ tBTM_STATUS BTM_BleStartExtAdv(BOOLEAN enable, UINT8 num, tBTM_BLE_EXT_ADV *ext_ if ((err = btsnd_hcic_ble_ext_adv_enable(enable, num, NULL, NULL, NULL)) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE EA En=%d: cmd err=0x%x", enable, err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } goto end; } @@ -574,7 +589,12 @@ end: } } - cb_params.status = status; + cb_params.adv_start.status = status; + cb_params.adv_start.instance_num = num; + for (uint8_t i = 0; i < num; i++) { + cb_params.adv_start.instance[i] = ext_adv[i].instance; + } + BTM_ExtBleCallbackTrigger(enable ? BTM_BLE_5_GAP_EXT_ADV_START_COMPLETE_EVT : BTM_BLE_5_GAP_EXT_ADV_STOP_COMPLETE_EVT, &cb_params); return status; @@ -593,6 +613,7 @@ tBTM_STATUS BTM_BleStartExtAdvRestart(uint8_t con_handle) } if((index >= MAX_BLE_ADV_INSTANCE) || (!adv_record[index].invalid)) { + BTM_TRACE_WARNING("%s failed to find extend adv, adv_handle %u con_handle %u", __func__, index, con_handle); return BTM_WRONG_MODE; } @@ -618,7 +639,7 @@ tBTM_STATUS BTM_BleExtAdvSetRemove(UINT8 instance) if ((err = btsnd_hcic_ble_remove_adv_set(instance)) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE EAS Rm: cmd err=0x%x", err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } else { extend_adv_cb.inst[instance].configured = false; extend_adv_cb.inst[instance].legacy_pdu = false; @@ -629,7 +650,9 @@ tBTM_STATUS BTM_BleExtAdvSetRemove(UINT8 instance) end: - cb_params.status = status; + cb_params.adv_start.status = status; + cb_params.adv_start.instance_num = 1; + cb_params.adv_start.instance[0] = instance; BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_EXT_ADV_SET_REMOVE_COMPLETE_EVT, &cb_params); @@ -644,7 +667,7 @@ tBTM_STATUS BTM_BleExtAdvSetClear(void) if ((err = btsnd_hcic_ble_clear_adv_set()) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE EAS Clr: cmd err=0x%x", err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } else { for (uint8_t i = 0; i < MAX_BLE_ADV_INSTANCE; i++) { extend_adv_cb.inst[i].configured = false; @@ -655,13 +678,15 @@ tBTM_STATUS BTM_BleExtAdvSetClear(void) } } - cb_params.status = status; + cb_params.adv_start.status = status; BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_EXT_ADV_SET_CLEAR_COMPLETE_EVT, &cb_params); return status; } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) tBTM_STATUS BTM_BlePeriodicAdvSetParams(UINT8 instance, tBTM_BLE_Periodic_Adv_Params *params) { tBTM_STATUS status = BTM_SUCCESS; @@ -688,12 +713,13 @@ tBTM_STATUS BTM_BlePeriodicAdvSetParams(UINT8 instance, tBTM_BLE_Periodic_Adv_Pa if ((err= btsnd_hcic_ble_set_periodic_adv_params(instance, params->interval_min, params->interval_max, params->properties)) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE PA SetParams: cmd err=0x%x", err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } end: - cb_params.status = status; + cb_params.per_adv_set_params.status = status; + cb_params.per_adv_set_params.instance = instance; BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PERIODIC_ADV_SET_PARAMS_COMPLETE_EVT, &cb_params); @@ -740,14 +766,18 @@ tBTM_STATUS BTM_BlePeriodicAdvCfgDataRaw(UINT8 instance, UINT16 len, UINT8 *data if ((err = btsnd_hcic_ble_set_periodic_adv_data(instance, operation, send_data_len, &data[data_offset])) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE PA SetData: cmd err=0x%x", err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; + break; } + rem_len -= send_data_len; - data_offset += send_data_len; + data_offset += send_data_len; } while(rem_len); end: - cb_params.status = status; + cb_params.per_adv_data_set.status = status; + cb_params.per_adv_data_set.instance = instance; + BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PERIODIC_ADV_DATA_SET_COMPLETE_EVT, &cb_params); return status; @@ -767,19 +797,26 @@ tBTM_STATUS BTM_BlePeriodicAdvEnable(UINT8 instance, UINT8 enable) if ((err = btsnd_hcic_ble_periodic_adv_enable(enable, instance)) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE PA En=%d: cmd err=0x%x", enable, err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } end: - - cb_params.status = status; + if (enable) { + cb_params.per_adv_start.status = status; + cb_params.per_adv_start.instance = instance; + } else { + cb_params.per_adv_stop.status = status; + cb_params.per_adv_stop.instance = instance; + } BTM_ExtBleCallbackTrigger(enable ? BTM_BLE_5_GAP_PERIODIC_ADV_START_COMPLETE_EVT : BTM_BLE_5_GAP_PERIODIC_ADV_STOP_COMPLETE_EVT, &cb_params); return status; } +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) tBTM_STATUS BTM_BlePeriodicAdvCreateSync(tBTM_BLE_Periodic_Sync_Params *params) { //tHCI_STATUS err = HCI_SUCCESS; @@ -794,10 +831,10 @@ tBTM_STATUS BTM_BlePeriodicAdvCreateSync(tBTM_BLE_Periodic_Sync_Params *params) if ((params->sync_timeout < 0x0a || params->sync_timeout > 0x4000) || (params->filter_policy > 0x01) - #if (CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH) +#if (BLE_FEAT_CREATE_SYNC_ENH == TRUE) || (params->reports_disabled > 0x01) || (params->filter_duplicates > 0x01) - #endif +#endif // (BLE_FEAT_CREATE_SYNC_ENH == TRUE) /*If the Periodic Advertiser List is not used, the Advertising_SID, Advertiser Address_Type, and Advertiser Address parameters specify the periodic advertising device to listen to; otherwise they @@ -814,17 +851,17 @@ tBTM_STATUS BTM_BlePeriodicAdvCreateSync(tBTM_BLE_Periodic_Sync_Params *params) SET_BIT(option, 0); } - #if (CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH) +#if (BLE_FEAT_CREATE_SYNC_ENH == TRUE) if (params->reports_disabled) { SET_BIT(option, 1); } if (params->filter_duplicates) { SET_BIT(option, 2); } - #endif +#endif // (BLE_FEAT_CREATE_SYNC_ENH == TRUE) if (!btsnd_hcic_ble_periodic_adv_create_sync(option, params->sid, params->addr_type, - params->addr, params->sync_timeout, 0)) { + params->addr, params->sync_timeout, params->sync_cte_type)) { BTM_TRACE_ERROR("LE PA CreateSync cmd failed"); status = BTM_ILLEGAL_VALUE; } @@ -837,6 +874,8 @@ end: return status; } +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) + void btm_set_phy_callback(UINT8 status) { tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; @@ -845,6 +884,8 @@ void btm_set_phy_callback(UINT8 status) BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_SET_PREFERED_PHY_COMPLETE_EVT, &cb_params); } + +#if (BLE_50_EXTEND_SYNC_EN == TRUE) void btm_create_sync_callback(UINT8 status) { tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; @@ -852,6 +893,7 @@ void btm_create_sync_callback(UINT8 status) BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PERIODIC_ADV_CREATE_SYNC_COMPLETE_EVT, &cb_params); } +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) void btm_read_phy_callback(uint8_t hci_status, uint16_t conn_handle, uint8_t tx_phy, uint8_t rx_phy) { @@ -872,6 +914,7 @@ void btm_read_phy_callback(uint8_t hci_status, uint16_t conn_handle, uint8_t tx_ BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_READ_PHY_COMPLETE_EVT, &cb_params); } +#if (BLE_50_EXTEND_SYNC_EN == TRUE) tBTM_STATUS BTM_BlePeriodicAdvSyncCancel(void) { tHCI_STATUS err = HCI_SUCCESS; @@ -880,7 +923,7 @@ tBTM_STATUS BTM_BlePeriodicAdvSyncCancel(void) if ((err = btsnd_hcic_ble_periodic_adv_create_sync_cancel()) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE PA SyncCancel, cmd err=0x%x", err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } cb_params.status = status; @@ -898,7 +941,7 @@ tBTM_STATUS BTM_BlePeriodicAdvSyncTerm(UINT16 sync_handle) if (( err = btsnd_hcic_ble_periodic_adv_term_sync(sync_handle)) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE PA SyncTerm: cmd err=0x%x", err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } cb_params.status = status; @@ -922,7 +965,7 @@ tBTM_STATUS BTM_BlePeriodicAdvAddDevToList(tBLE_ADDR_TYPE addr_type, BD_ADDR add if ((err = btsnd_hcic_ble_add_dev_to_periodic_adv_list(addr_type, addr, sid)) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE PA AddDevToList: cmd err=0x%x", err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } end: @@ -946,7 +989,7 @@ tBTM_STATUS BTM_BlePeriodicAdvRemoveDevFromList(tBLE_ADDR_TYPE addr_type, BD_ADD if ((err = btsnd_hcic_ble_rm_dev_from_periodic_adv_list(addr_type, addr, sid)) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE PA RmDevFromList: cmd err=0x%x", err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } end: @@ -964,7 +1007,7 @@ tBTM_STATUS BTM_BlePeriodicAdvClearDev(void) if ((err = btsnd_hcic_ble_clear_periodic_adv_list()) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE PA ClrDev: cmd err=0x%x", err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } cb_params.status = status; @@ -972,7 +1015,9 @@ tBTM_STATUS BTM_BlePeriodicAdvClearDev(void) return status; } +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if (BLE_50_EXTEND_SCAN_EN == TRUE) tBTM_STATUS BTM_BleSetExtendedScanParams(tBTM_BLE_EXT_SCAN_PARAMS *params) { UINT8 phy_mask = 0; @@ -1016,7 +1061,7 @@ tBTM_STATUS BTM_BleSetExtendedScanParams(tBTM_BLE_EXT_SCAN_PARAMS *params) if ((err = btsnd_hcic_ble_set_ext_scan_params(params->own_addr_type, params->filter_policy, phy_mask, phy_count, hci_params)) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE ES SetParams: cmd err=0x%x", err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } end: @@ -1042,7 +1087,7 @@ tBTM_STATUS BTM_BleExtendedScan(BOOLEAN enable, UINT16 duration, UINT16 period) if ((err = btsnd_hcic_ble_ext_scan_enable(enable, extend_adv_cb.scan_duplicate, duration, period)) != HCI_SUCCESS) { BTM_TRACE_ERROR("LE ES En=%d: cmd err=0x%x", enable, err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } end: @@ -1053,22 +1098,28 @@ end: return status; } +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) void BTM_BleSetPreferExtenedConnParams (BD_ADDR bd_addr, tBTM_EXT_CONN_PARAMS *params) { tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (bd_addr); + tBTM_STATUS status = BTM_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; if (p_dev_rec) { if (params) { memcpy(&p_dev_rec->ext_conn_params, params, sizeof(tBTM_EXT_CONN_PARAMS)); } else { - BTM_TRACE_ERROR("Invalid Extand connection parameters"); + BTM_TRACE_ERROR("Invalid Extended connection parameters"); + status = BTM_ILLEGAL_VALUE; } } else { - BTM_TRACE_ERROR("Unknown Device, setting rejected"); + BTM_TRACE_ERROR("Unknown Device, setting rejected"); + status = BTM_UNKNOWN_ADDR; } - return; + cb_params.status = status; + BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PREFER_EXT_CONN_PARAMS_SET_COMPLETE_EVT, &cb_params); } void btm_ble_extended_init(void) @@ -1081,6 +1132,7 @@ void btm_ble_extended_cleanup(void) } +#if (BLE_50_EXTEND_ADV_EN == TRUE) static tBTM_STATUS btm_ble_ext_adv_params_validate(tBTM_BLE_GAP_EXT_ADV_PARAMS *params) { if (!params) { @@ -1157,6 +1209,7 @@ static tBTM_STATUS btm_ble_ext_adv_set_data_validate(UINT8 instance, UINT16 len, return BTM_SUCCESS; } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) void btm_ble_update_phy_evt(tBTM_BLE_UPDATE_PHY *params) { @@ -1184,11 +1237,14 @@ void btm_ble_update_phy_evt(tBTM_BLE_UPDATE_PHY *params) return; } +#if (BLE_50_EXTEND_SCAN_EN == TRUE) void btm_ble_scan_timeout_evt(void) { BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_SCAN_TIMEOUT_EVT, NULL); } +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) void btm_ble_adv_set_terminated_evt(tBTM_BLE_ADV_TERMINAT *params) { tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; @@ -1199,7 +1255,7 @@ void btm_ble_adv_set_terminated_evt(tBTM_BLE_ADV_TERMINAT *params) } // adv terminated due to connection, save the adv handle and connection handle - if(params->completed_event == 0x00) { + if(params->status == 0x00) { adv_record[params->adv_handle].ter_con_handle = params->conn_handle; } else { adv_record[params->adv_handle].ter_con_handle = INVALID_VALUE; @@ -1214,7 +1270,9 @@ void btm_ble_adv_set_terminated_evt(tBTM_BLE_ADV_TERMINAT *params) return; } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SCAN_EN == TRUE) void btm_ble_ext_adv_report_evt(tBTM_BLE_EXT_ADV_REPORT *params) { tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; @@ -1232,7 +1290,9 @@ void btm_ble_ext_adv_report_evt(tBTM_BLE_EXT_ADV_REPORT *params) return; } +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) void btm_ble_scan_req_received_evt(tBTM_BLE_SCAN_REQ_RECEIVED *params) { tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; @@ -1249,7 +1309,7 @@ void btm_ble_scan_req_received_evt(tBTM_BLE_SCAN_REQ_RECEIVED *params) return; } - +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) void btm_ble_channel_select_algorithm_evt(tBTM_BLE_CHANNEL_SEL_ALG *params) { tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; @@ -1267,6 +1327,7 @@ void btm_ble_channel_select_algorithm_evt(tBTM_BLE_CHANNEL_SEL_ALG *params) return; } +#if (BLE_50_EXTEND_SYNC_EN == TRUE) void btm_ble_periodic_adv_report_evt(tBTM_PERIOD_ADV_REPORT *params) { tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; @@ -1320,7 +1381,9 @@ void btm_ble_periodic_adv_sync_establish_evt(tBTM_BLE_PERIOD_ADV_SYNC_ESTAB *par return; } +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) uint8_t btm_ble_ext_adv_active_count(void) { uint8_t count = 0; @@ -1333,6 +1396,7 @@ uint8_t btm_ble_ext_adv_active_count(void) return count; } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) @@ -1378,7 +1442,7 @@ void BTM_BlePeriodicAdvRecvEnable(UINT16 sync_handle, UINT8 enable) if ((err = btsnd_hcic_ble_set_periodic_adv_recv_enable(sync_handle, enable)) != HCI_SUCCESS) { BTM_TRACE_ERROR("%s cmd err=0x%x", __func__, err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } cb_params.status = status; @@ -1437,7 +1501,7 @@ void BTM_BleSetPeriodicAdvSyncTransParams(BD_ADDR bd_addr, UINT8 mode, UINT16 sk tHCI_STATUS err = HCI_SUCCESS; if ((err = btsnd_hcic_ble_set_default_periodic_adv_sync_trans_params(mode, skip, sync_timeout, cte_type)) != HCI_SUCCESS) { BTM_TRACE_ERROR("%s cmd err=0x%x", __func__, err); - status = BTM_ILLEGAL_VALUE; + status = BTM_HCI_ERROR | err; } cb_params.set_past_params.status = status; @@ -1476,3 +1540,192 @@ void btm_ble_periodic_adv_sync_trans_recv_evt(tBTM_BLE_PERIOD_ADV_SYNC_TRANS_REC BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_PERIODIC_ADV_SYNC_TRANS_RECV_EVT, &cb_params); } #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +void BTM_BleEnhReadTransPowerLevel(uint16_t conn_handle, uint8_t phy) +{ + btsnd_hcic_ble_enh_read_trans_power_level(conn_handle, phy); +} + +void BTM_BleReadRemoteTransPwrLevel(uint16_t conn_handle, uint8_t phy) +{ + btsnd_hcic_ble_read_remote_trans_power_level(conn_handle, phy); +} + +void BTM_BleSetPathLossRptParams(uint16_t conn_handle, uint8_t high_threshold, uint8_t high_hysteresis, + uint8_t low_threshold, uint8_t low_hysteresis, uint16_t min_time_spent) +{ + tBTM_STATUS status = BTM_SUCCESS; + tHCI_STATUS err = HCI_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_set_path_loss_rpt_params(conn_handle, high_threshold, high_hysteresis, low_threshold, low_hysteresis, min_time_spent)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("%s cmd err=0x%x", __func__, err); + status = BTM_HCI_ERROR | err; + } + + cb_params.path_loss_rpting_params.status = status; + cb_params.path_loss_rpting_params.conn_handle = conn_handle; + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_SET_PATH_LOSS_REPORTING_PARAMS_EVT, &cb_params); +} + +void BTM_BleSetPathLossRptEnable(uint16_t conn_handle, uint8_t enable) +{ + tBTM_STATUS status = BTM_SUCCESS; + tHCI_STATUS err = HCI_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_set_path_loss_rpt_enable(conn_handle, enable)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("%s cmd err=0x%x", __func__, err); + status = BTM_HCI_ERROR | err; + } + + cb_params.path_loss_rpting_enable.status = status; + cb_params.path_loss_rpting_enable.conn_handle = conn_handle; + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_SET_PATH_LOSS_REPORTING_ENABLE_EVT, &cb_params); +} + +void BTM_BleSetTransPwrRptEnable(uint16_t conn_handle, uint8_t local_enable, uint8_t remote_enable) +{ + tBTM_STATUS status = BTM_SUCCESS; + tHCI_STATUS err = HCI_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_set_trans_pwr_rpt_enable(conn_handle, local_enable, remote_enable)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("%s cmd err=0x%x", __func__, err); + status = BTM_HCI_ERROR | err; + } + + cb_params.trans_pwr_rpting_enable.status = status; + cb_params.trans_pwr_rpting_enable.conn_handle = conn_handle; + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_SET_TRANS_POWER_REPORTING_ENABLE_EVT, &cb_params); +} + +void btm_enh_read_trans_pwr_level_cmpl_evt(uint8_t *p) +{ + uint8_t hci_status; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + STREAM_TO_UINT8(hci_status, p); + STREAM_TO_UINT16(cb_params.enh_trans_pwr_level_cmpl.conn_handle, p); + STREAM_TO_UINT8(cb_params.enh_trans_pwr_level_cmpl.phy, p); + STREAM_TO_UINT8(cb_params.enh_trans_pwr_level_cmpl.cur_tx_pwr_level, p); + STREAM_TO_UINT8(cb_params.enh_trans_pwr_level_cmpl.max_tx_pwr_level, p); + + if(hci_status != HCI_SUCCESS) { + hci_status = BTM_HCI_ERROR | hci_status; + BTM_TRACE_ERROR("%s error status %d", __func__, hci_status); + } + cb_params.enh_trans_pwr_level_cmpl.status = hci_status; + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_ENH_READ_TRANS_POWER_LEVEL_EVT, &cb_params); +} + +void btm_read_remote_trans_pwr_level_cmpl(UINT8 status) +{ + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if (status != HCI_SUCCESS) { + status = (status | BTM_HCI_ERROR); + } + + cb_params.remote_pwr_level_cmpl.status = status; + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_READ_REMOTE_TRANS_POWER_LEVEL_EVT, &cb_params); +} + +void btm_ble_path_loss_threshold_evt(tBTM_BLE_PATH_LOSS_THRESHOLD_EVT *params) +{ + if (!params) { + BTM_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + // If the user has register the callback function, should callback it to the application. + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_PATH_LOSS_THRESHOLD_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)params); +} + +void btm_ble_transmit_power_report_evt(tBTM_BLE_TRANS_POWER_REPORT_EVT *params) +{ + if (!params) { + BTM_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + if (params->status != HCI_SUCCESS) { + params->status = (params->status | BTM_HCI_ERROR); + } + + // If the user has register the callback function, should callback it to the application. + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_TRANMIT_POWER_REPORTING_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)params); +} + +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +void BTM_BleSetDefaultSubrate(UINT16 subrate_min, UINT16 subrate_max, UINT16 max_latency, UINT16 continuation_number, UINT16 supervision_timeout) +{ + tBTM_STATUS status = BTM_SUCCESS; + tHCI_STATUS err = HCI_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_set_default_subrate(subrate_min, subrate_max, max_latency, continuation_number, supervision_timeout)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("%s cmd err=0x%x", __func__, err); + status = BTM_HCI_ERROR | err; + } + + cb_params.status = status; + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_SET_DEFAULT_SUBRATE_EVT, &cb_params); +} + +void BTM_BleSubrateRequest(UINT16 conn_handle, UINT16 subrate_min, UINT16 subrate_max, UINT16 max_latency, UINT16 continuation_number, UINT16 supervision_timeout) +{ + btsnd_hcic_ble_subrate_request(conn_handle, subrate_min, subrate_max, max_latency, continuation_number, supervision_timeout); +} + +void btm_subrate_req_cmd_status(UINT8 status) +{ + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + if (status != HCI_SUCCESS) { + status = (status | BTM_HCI_ERROR); + } + cb_params.status = status; + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_SUBRATE_REQUEST_EVT, &cb_params); +} + +void btm_ble_subrate_change_evt(tBTM_BLE_SUBRATE_CHANGE_EVT *params) +{ + if (params->status != HCI_SUCCESS) { + params->status = (params->status | BTM_HCI_ERROR); + } + + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_SUBRATE_CHANGE_EVT, (tBTM_BLE_5_GAP_CB_PARAMS *)params); +} +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + +#if (BLE_50_FEATURE_SUPPORT == TRUE) +tBTM_STATUS BTM_BleSetHostFeature(uint16_t bit_num, uint8_t bit_val) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0}; + + BTM_TRACE_DEBUG("BTM_BleSetHostFeature bit_num %d bit_value %d\n", bit_num, bit_val); + + if ((err = btsnd_hcic_ble_set_host_feature(bit_num, bit_val)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("set host feature, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.status = status; + BTM_ExtBleCallbackTrigger(BTM_BLE_GAP_SET_HOST_FEATURE_EVT, &cb_params); + + return status; +} +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) diff --git a/lib/bt/host/bluedroid/stack/btm/btm_ble_addr.c b/lib/bt/host/bluedroid/stack/btm/btm_ble_addr.c index d7ed2095..60548a76 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_ble_addr.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_ble_addr.c @@ -384,6 +384,10 @@ static BOOLEAN btm_ble_match_random_bda(tBTM_SEC_DEV_REC *p_dev_rec) void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK *p_cback, void *p) { #if (SMP_INCLUDED == TRUE) + if (btm_cb.addr_res_en == FALSE) { + return; + } + tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb; list_node_t *p_node = NULL; tBTM_SEC_DEV_REC *p_dev_rec = NULL; @@ -458,6 +462,10 @@ tBTM_SEC_DEV_REC *btm_find_dev_by_identity_addr(BD_ADDR bd_addr, UINT8 addr_type BOOLEAN btm_identity_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type, BOOLEAN refresh) { #if BLE_PRIVACY_SPT == TRUE + if (btm_cb.addr_res_en == FALSE) { + return TRUE; + } + tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_identity_addr(bd_addr, *p_addr_type); BTM_TRACE_EVENT ("%s", __func__); @@ -491,6 +499,10 @@ BOOLEAN btm_identity_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type, BOOLEAN btm_random_pseudo_to_identity_addr(BD_ADDR random_pseudo, UINT8 *p_static_addr_type) { #if BLE_PRIVACY_SPT == TRUE + if (btm_cb.addr_res_en == FALSE) { + return TRUE; + } + tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (random_pseudo); if (p_dev_rec != NULL) { diff --git a/lib/bt/host/bluedroid/stack/btm/btm_ble_adv_filter.c b/lib/bt/host/bluedroid/stack/btm/btm_ble_adv_filter.c index c0ae0aaa..9da09143 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_ble_adv_filter.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_ble_adv_filter.c @@ -22,6 +22,7 @@ #include "common/bt_target.h" #if (BLE_INCLUDED == TRUE) +#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE #include "stack/bt_types.h" #include "stack/hcimsgs.h" #include "stack/btu.h" @@ -445,11 +446,11 @@ BOOLEAN btm_ble_dealloc_addr_filter_counter(tBLE_BD_ADDR *p_bd_addr, UINT8 filte ** ** Function btm_ble_update_pf_local_name ** -** Description this function update(add,delete or clear) the adv lcoal name filtering condition. +** Description this function update(add,delete or clear) the adv local name filtering condition. ** ** -** Returns BTM_SUCCESS if sucessful, -** BTM_ILLEGAL_VALUE if paramter is not valid. +** Returns BTM_SUCCESS if successful, +** BTM_ILLEGAL_VALUE if parameter is not valid. ** *******************************************************************************/ tBTM_STATUS btm_ble_update_pf_local_name(tBTM_BLE_SCAN_COND_OP action, @@ -506,8 +507,8 @@ tBTM_STATUS btm_ble_update_pf_local_name(tBTM_BLE_SCAN_COND_OP action, ** Description this function update(add/remove) service data change filter. ** ** -** Returns BTM_SUCCESS if sucessful, -** BTM_ILLEGAL_VALUE if paramter is not valid. +** Returns BTM_SUCCESS if successful, +** BTM_ILLEGAL_VALUE if parameter is not valid. ** *******************************************************************************/ tBTM_STATUS btm_ble_update_srvc_data_change(tBTM_BLE_SCAN_COND_OP action, @@ -534,8 +535,8 @@ tBTM_STATUS btm_ble_update_srvc_data_change(tBTM_BLE_SCAN_COND_OP action, ** data filtering condition. ** ** -** Returns BTM_SUCCESS if sucessful, -** BTM_ILLEGAL_VALUE if paramter is not valid. +** Returns BTM_SUCCESS if successful, +** BTM_ILLEGAL_VALUE if parameter is not valid. ** *******************************************************************************/ tBTM_STATUS btm_ble_update_pf_manu_data(tBTM_BLE_SCAN_COND_OP action, @@ -708,8 +709,8 @@ UINT8 btm_ble_cs_update_pf_counter(tBTM_BLE_SCAN_COND_OP action, ** Description this function update(add,delete or clear) the address filter of adv. ** ** -** Returns BTM_SUCCESS if sucessful, -** BTM_ILLEGAL_VALUE if paramter is not valid. +** Returns BTM_SUCCESS if successful, +** BTM_ILLEGAL_VALUE if parameter is not valid. ** *******************************************************************************/ tBTM_STATUS btm_ble_update_addr_filter(tBTM_BLE_SCAN_COND_OP action, @@ -757,8 +758,8 @@ tBTM_STATUS btm_ble_update_addr_filter(tBTM_BLE_SCAN_COND_OP action, ** Description this function update(add,delete or clear) service UUID filter. ** ** -** Returns BTM_SUCCESS if sucessful, -** BTM_ILLEGAL_VALUE if paramter is not valid. +** Returns BTM_SUCCESS if successful, +** BTM_ILLEGAL_VALUE if parameter is not valid. ** *******************************************************************************/ tBTM_STATUS btm_ble_update_uuid_filter(tBTM_BLE_SCAN_COND_OP action, @@ -872,7 +873,7 @@ tBTM_STATUS btm_ble_update_uuid_filter(tBTM_BLE_SCAN_COND_OP action, memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR)); } } else { - BTM_TRACE_ERROR("UUID filter udpating failed"); + BTM_TRACE_ERROR("UUID filter updating failed"); } return st; @@ -886,8 +887,8 @@ tBTM_STATUS btm_ble_update_uuid_filter(tBTM_BLE_SCAN_COND_OP action, ** Description clear all adv payload filter by de-select all the adv pf feature bits ** ** -** Returns BTM_SUCCESS if sucessful, -** BTM_ILLEGAL_VALUE if paramter is not valid. +** Returns BTM_SUCCESS if successful, +** BTM_ILLEGAL_VALUE if parameter is not valid. ** *******************************************************************************/ tBTM_STATUS btm_ble_clear_scan_pf_filter(tBTM_BLE_SCAN_COND_OP action, @@ -1303,4 +1304,5 @@ void btm_ble_adv_filter_cleanup(void) #endif } +#endif // #if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE #endif diff --git a/lib/bt/host/bluedroid/stack/btm/btm_ble_batchscan.c b/lib/bt/host/bluedroid/stack/btm/btm_ble_batchscan.c index 5b0fcd8f..b4b58643 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_ble_batchscan.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_ble_batchscan.c @@ -29,15 +29,22 @@ #include "stack/hcimsgs.h" #if (BLE_INCLUDED == TRUE) +#if (BLE_HOST_BATCH_SCAN_EN == TRUE) #if BTM_DYNAMIC_MEMORY == FALSE tBTM_BLE_BATCH_SCAN_CB ble_batchscan_cb; +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) tBTM_BLE_ADV_TRACK_CB ble_advtrack_cb; +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) #else tBTM_BLE_BATCH_SCAN_CB *ble_batchscan_cb_ptr; +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) tBTM_BLE_ADV_TRACK_CB *ble_advtrack_cb_ptr; +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) #define ble_batchscan_cb (*ble_batchscan_cb_ptr) +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) #define ble_advtrack_cb (*ble_advtrack_cb_ptr) +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) #endif /* length of each batch scan command */ @@ -66,10 +73,11 @@ void btm_ble_batchscan_cleanup(void); *******************************************************************************/ void btm_ble_batchscan_filter_track_adv_vse_cback(UINT8 len, UINT8 *p) { +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) tBTM_BLE_TRACK_ADV_DATA adv_data; - - UINT8 sub_event = 0; tBTM_BLE_VSC_CB cmn_ble_vsc_cb; +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) + UINT8 sub_event = 0; STREAM_TO_UINT8(sub_event, p); BTM_TRACE_EVENT("btm_ble_batchscan_filter_track_adv_vse_cback called with event:%x", sub_event); @@ -78,7 +86,7 @@ void btm_ble_batchscan_filter_track_adv_vse_cback(UINT8 len, UINT8 *p) ble_batchscan_cb.p_thres_cback(ble_batchscan_cb.ref_value); return; } - +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) if (HCI_VSE_SUBCODE_BLE_TRACKING_SUB_EVT == sub_event && NULL != ble_advtrack_cb.p_track_cback) { if (len < 10) { return; @@ -125,6 +133,7 @@ void btm_ble_batchscan_filter_track_adv_vse_cback(UINT8 len, UINT8 *p) ble_advtrack_cb.p_track_cback(&adv_data); return; } +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) } /******************************************************************************* @@ -598,6 +607,7 @@ tBTM_STATUS btm_ble_enable_disable_batchscan(BOOLEAN should_enable) return status; } +#if (BLE_HOST_SETUP_STORAGE_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleSetStorageConfig @@ -676,7 +686,7 @@ tBTM_STATUS BTM_BleSetStorageConfig(UINT8 batch_scan_full_max, UINT8 batch_scan_ return status; } - +#endif // #if (BLE_HOST_SETUP_STORAGE_EN == TRUE) /******************************************************************************* ** @@ -796,6 +806,7 @@ tBTM_STATUS BTM_BleDisableBatchScan(tBTM_BLE_REF_VALUE ref_value) return status; } +#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleReadScanReports @@ -854,8 +865,9 @@ tBTM_STATUS BTM_BleReadScanReports(tBTM_BLE_BATCH_SCAN_MODE scan_mode, } return status; } +#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) - +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleTrackAdvertiser @@ -888,6 +900,7 @@ tBTM_STATUS BTM_BleTrackAdvertiser(tBTM_BLE_TRACK_ADV_CBACK *p_track_cback, ble_advtrack_cb.ref_value = ref_value; return BTM_CMD_STARTED; } +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) /******************************************************************************* ** @@ -904,7 +917,9 @@ void btm_ble_batchscan_init(void) { #if BTM_DYNAMIC_MEMORY == TRUE ble_batchscan_cb_ptr = (tBTM_BLE_BATCH_SCAN_CB *)osi_malloc(sizeof(tBTM_BLE_BATCH_SCAN_CB)); +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) ble_advtrack_cb_ptr = (tBTM_BLE_ADV_TRACK_CB *)osi_malloc(sizeof(tBTM_BLE_ADV_TRACK_CB)); +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) if (ble_batchscan_cb_ptr == NULL || ble_advtrack_cb_ptr == NULL) { BTM_TRACE_ERROR("%s malloc failed", __func__); return; @@ -912,7 +927,9 @@ void btm_ble_batchscan_init(void) #endif BTM_TRACE_EVENT (" btm_ble_batchscan_init"); memset(&ble_batchscan_cb, 0, sizeof(tBTM_BLE_BATCH_SCAN_CB)); +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) memset(&ble_advtrack_cb, 0, sizeof(tBTM_BLE_ADV_TRACK_CB)); +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) BTM_RegisterForVSEvents(btm_ble_batchscan_filter_track_adv_vse_cback, TRUE); } @@ -940,14 +957,21 @@ void btm_ble_batchscan_cleanup(void) } memset(&ble_batchscan_cb, 0, sizeof(tBTM_BLE_BATCH_SCAN_CB)); +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) memset(&ble_advtrack_cb, 0, sizeof(tBTM_BLE_ADV_TRACK_CB)); +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) #if BTM_DYNAMIC_MEMORY == TRUE osi_free(ble_batchscan_cb_ptr); - osi_free(ble_advtrack_cb_ptr); ble_batchscan_cb_ptr = NULL; +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) + osi_free(ble_advtrack_cb_ptr); ble_advtrack_cb_ptr = NULL; +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) + #endif } +#endif // #if (BLE_HOST_BATCH_SCAN_EN == TRUE) + #endif diff --git a/lib/bt/host/bluedroid/stack/btm/btm_ble_bgconn.c b/lib/bt/host/bluedroid/stack/btm/btm_ble_bgconn.c index 4cb282b7..bf9b1adb 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_ble_bgconn.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_ble_bgconn.c @@ -201,7 +201,12 @@ BOOLEAN btm_add_dev_to_controller (BOOLEAN to_add, BD_ADDR bd_addr, tBLE_ADDR_TY /* Controller do not support resolvable address now, only support public address and static random address */ BOOLEAN started = FALSE; - if(wl_addr_type > BLE_ADDR_RANDOM) { +#if (BLE_50_FEATURE_SUPPORT == TRUE) + if (wl_addr_type > BLE_ADDR_RANDOM && wl_addr_type != BLE_ADDR_ANONYMOUS) +#else + if (wl_addr_type > BLE_ADDR_RANDOM) +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + { BTM_TRACE_ERROR("wl_addr_type is error\n"); return started; } @@ -278,7 +283,12 @@ void btm_enq_wl_dev_operation(BOOLEAN to_add, BD_ADDR bd_addr, tBLE_ADDR_TYPE ad *******************************************************************************/ BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, tBLE_ADDR_TYPE addr_type, tBTM_UPDATE_WHITELIST_CBACK *update_wl_cb) { - if(addr_type > BLE_ADDR_RANDOM) { +#if (BLE_50_FEATURE_SUPPORT == TRUE) + if (addr_type > BLE_ADDR_RANDOM && addr_type != BLE_ADDR_ANONYMOUS) +#else + if (addr_type > BLE_ADDR_RANDOM) +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + { BTM_TRACE_ERROR("%s address type is error, unable to add device", __func__); if (update_wl_cb){ update_wl_cb(HCI_ERR_ILLEGAL_PARAMETER_FMT,to_add); @@ -423,6 +433,23 @@ void btm_ble_white_list_init(UINT8 white_list_size) btm_cb.ble_ctr_cb.white_list_avail_size = white_list_size; } +#if (BLE_50_EXTEND_SYNC_EN == TRUE) +/******************************************************************************* +** +** Function btm_ble_periodic_adv_list_init +** +** Description Initialize the periodic advertiser list size. +** +** Parameters periodic_adv_size: The size of the periodic advertiser list to be initialized. +** +*******************************************************************************/ +void btm_ble_periodic_adv_list_init(UINT8 periodic_adv_size) +{ + BTM_TRACE_DEBUG("%s white_list_size = %d", __func__, periodic_adv_size); + btm_cb.ble_ctr_cb.periodic_adv_list_size = periodic_adv_size; +} +#endif //#if (BLE_50_EXTEND_SYNC_EN == TRUE) + /******************************************************************************* ** ** Function btm_ble_add_2_white_list_complete @@ -648,6 +675,7 @@ void btm_ble_initiate_select_conn(BD_ADDR bda) BTM_TRACE_ERROR("btm_ble_initiate_select_conn failed"); } } +#if (tGATT_BG_CONN_DEV == TRUE) /******************************************************************************* ** ** Function btm_ble_suspend_bg_conn @@ -672,6 +700,8 @@ BOOLEAN btm_ble_suspend_bg_conn(void) return FALSE; } +#endif // #if (tGATT_BG_CONN_DEV == TRUE) + /******************************************************************************* ** ** Function btm_suspend_wl_activity @@ -689,10 +719,11 @@ static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state) if (wl_state & BTM_BLE_WL_SCAN) { btm_ble_start_select_conn(FALSE, NULL); } +#if (BLE_42_ADV_EN == TRUE) if (wl_state & BTM_BLE_WL_ADV) { btm_ble_stop_adv(); } - +#endif // #if (BLE_42_ADV_EN == TRUE) } /******************************************************************************* ** @@ -705,9 +736,13 @@ static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state) *******************************************************************************/ void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state) { +#if (tGATT_BG_CONN_DEV == TRUE) btm_ble_resume_bg_conn(); +#endif // #if (tGATT_BG_CONN_DEV == TRUE) if (wl_state & BTM_BLE_WL_ADV) { +#if (BLE_42_ADV_EN == TRUE) btm_ble_start_adv(); +#endif // #if (BLE_42_ADV_EN == TRUE) } } @@ -724,12 +759,13 @@ void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state) static void btm_wl_update_to_controller(void) { /* whitelist will be added in the btm_ble_resume_bg_conn(), we do not - support background connection now, so we nedd to use btm_execute_wl_dev_operation + support background connection now, so we need to use btm_execute_wl_dev_operation to add whitelist directly ,if we support background connection in the future, please delete btm_execute_wl_dev_operation(). */ btm_execute_wl_dev_operation(); } +#if (tGATT_BG_CONN_DEV == TRUE) /******************************************************************************* ** ** Function btm_ble_resume_bg_conn @@ -759,6 +795,8 @@ BOOLEAN btm_ble_resume_bg_conn(void) return ret; } +#endif // #if (tGATT_BG_CONN_DEV == TRUE) + /******************************************************************************* ** ** Function btm_ble_get_conn_st diff --git a/lib/bt/host/bluedroid/stack/btm/btm_ble_cont_energy.c b/lib/bt/host/bluedroid/stack/btm/btm_ble_cont_energy.c index dd23d3e9..4b68fe80 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_ble_cont_energy.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_ble_cont_energy.c @@ -20,6 +20,7 @@ #include "common/bt_target.h" #if (BLE_INCLUDED == TRUE) +#if (BLE_HOST_ENERGY_INFO_EN == TRUE) #include "stack/bt_types.h" #include "stack/hcimsgs.h" #include "stack/btu.h" @@ -104,5 +105,6 @@ tBTM_STATUS BTM_BleGetEnergyInfo(tBTM_BLE_ENERGY_INFO_CBACK *p_ener_cback) return status; } +#endif // #if (BLE_HOST_ENERGY_INFO_EN == TRUE) #endif diff --git a/lib/bt/host/bluedroid/stack/btm/btm_ble_cte.c b/lib/bt/host/bluedroid/stack/btm/btm_ble_cte.c new file mode 100644 index 00000000..a79932de --- /dev/null +++ b/lib/bt/host/bluedroid/stack/btm/btm_ble_cte.c @@ -0,0 +1,237 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "btm_int.h" +#include "stack/hcimsgs.h" +#include "osi/allocator.h" +#include "device/controller.h" +#include +#include "l2c_int.h" + +tBTM_BLE_CTE_CBACK ble_cte_cb; + +extern void btm_ble_inter_set(bool extble_inter); + +void BTM_BleCteRegisterCallback(tBTM_BLE_CTE_CBACK cb) +{ + if (cb) { + ble_cte_cb = cb; + } else { + BTM_TRACE_ERROR("%s, register fail, the cb function is NULL.", __func__); + } +} + +void BTM_CteBleCallbackTrigger(tBTM_BLE_5_GAP_EVENT event, tBTM_BLE_CTE_CB_PARAMS *params) +{ + BTM_TRACE_DEBUG("%s event %x", __func__, event); + + if(params && params->status == BTM_SUCCESS) { + btm_ble_inter_set(true); + } + if (ble_cte_cb) { + ble_cte_cb(event, params); + } +} +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +tBTM_STATUS BTM_BleSetCteTransParams(uint8_t adv_handle, uint8_t cte_len, uint8_t cte_type, uint8_t cte_count, uint8_t switching_pattern_len, uint8_t *antenna_ids) +{ + + + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + tBTM_BLE_CTE_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_set_connless_cte_trans_params(adv_handle, cte_len, cte_type, cte_count, switching_pattern_len, antenna_ids)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("cte set trans params, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.cte_trans_params_cmpl.status = status; + BTM_CteBleCallbackTrigger(BTM_BLE_CTE_SET_TRANS_PARAMS_EVT, &cb_params); + + return status; +} + +tBTM_STATUS BTM_BleCteSetConnectionlessTransEnable(uint8_t adv_handle, uint8_t cte_en) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + tBTM_BLE_CTE_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_set_connless_cte_enable(adv_handle, cte_en)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("cte set trans enable, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.cte_trans_en_cmpl.status = status; + BTM_CteBleCallbackTrigger(BTM_BLE_CTE_SET_TRANS_ENABLE_EVT, &cb_params); + + return status; +} + +tBTM_STATUS BTM_BleCteSetConnectionlessIqSamplingEnable(uint16_t sync_handle, uint8_t sampling_en, uint8_t slot_dur, + uint8_t max_sampled_ctes, uint8_t switching_pattern_len, uint8_t *ant_ids) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + tBTM_BLE_CTE_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_set_connless_iq_sampling_enable(sync_handle, sampling_en, slot_dur, max_sampled_ctes, switching_pattern_len, ant_ids)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("cte set trans enable, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.cte_iq_samp_en_cmpl.status = status; + cb_params.cte_iq_samp_en_cmpl.sync_handle = sync_handle; + BTM_CteBleCallbackTrigger(BTM_BLE_CTE_SET_IQ_SAMP_ENABLE_EVT, &cb_params); + + return status; +} +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +tBTM_STATUS BTM_BleCteSetConnectionReceiveParams(uint16_t conn_handle, uint8_t sampling_en, uint8_t slot_dur, + uint8_t switching_pattern_len, uint8_t *ant_ids) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + tBTM_BLE_CTE_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_set_conn_cte_receive_params(conn_handle, sampling_en, slot_dur, switching_pattern_len, ant_ids)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("cte set conn recv params, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.cte_recv_params_cmpl.status = status; + cb_params.cte_recv_params_cmpl.conn_handle = conn_handle; + BTM_CteBleCallbackTrigger(BTM_BLE_CTE_SET_CONN_RECV_PARAMS_EVT, &cb_params); + + return status; +} + +tBTM_STATUS BTM_BleCteSetConnectionTransParams(uint16_t conn_handle, uint8_t cte_types, uint8_t switching_pattern_len, uint8_t *ant_ids) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + tBTM_BLE_CTE_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_set_conn_cte_trans_params(conn_handle, cte_types, switching_pattern_len, ant_ids)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("cte set conn trans params, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.cte_conn_trans_params_cmpl.status = status; + cb_params.cte_conn_trans_params_cmpl.conn_handle = conn_handle; + BTM_CteBleCallbackTrigger(BTM_BLE_CTE_SET_CONN_TRANS_PARAMS_EVT, &cb_params); + + return status; +} + +tBTM_STATUS BTM_BleCteSetConnectionRequestEnable(uint16_t conn_handle, uint8_t enable, uint16_t cte_req_int, + uint8_t req_cte_len, uint8_t req_cte_type) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + tBTM_BLE_CTE_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_conn_cte_req_enable(conn_handle, enable, cte_req_int, req_cte_len, req_cte_type)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("cte set conn req en, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.cte_conn_req_en_cmpl.status = status; + cb_params.cte_conn_req_en_cmpl.conn_handle = conn_handle; + BTM_CteBleCallbackTrigger(BTM_BLE_CTE_SET_CONN_REQ_ENABLE_EVT, &cb_params); + + return status; +} + +tBTM_STATUS BTM_BleCteSetConnectionRspEnable(uint16_t conn_handle, uint8_t enable) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + tBTM_BLE_CTE_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_conn_cte_rsp_enable(conn_handle, enable)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("cte set conn rsp en, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.cte_conn_rsp_en_cmpl.status = status; + cb_params.cte_conn_rsp_en_cmpl.conn_handle = conn_handle; + BTM_CteBleCallbackTrigger(BTM_BLE_CTE_SET_CONN_RSP_ENABLE_EVT, &cb_params); + + return status; +} +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + +tBTM_STATUS BTM_BleCteReadAntInfor(void) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + + if ((err = btsnd_hcic_ble_read_antenna_info()) != HCI_SUCCESS) { + BTM_TRACE_ERROR("cte read ant information, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + return status; +} + +void btm_ble_cte_read_ant_infor_complete(UINT8 *p) +{ + tBTM_BLE_CTE_CB_PARAMS cb_params = {0}; + + STREAM_TO_UINT8(cb_params.cte_read_ant_infor_cmpl.status, p); + STREAM_TO_UINT8(cb_params.cte_read_ant_infor_cmpl.supported_switching_sampling_rates, p); + STREAM_TO_UINT8(cb_params.cte_read_ant_infor_cmpl.num_ant, p); + STREAM_TO_UINT8(cb_params.cte_read_ant_infor_cmpl.max_switching_pattern_len, p); + STREAM_TO_UINT8(cb_params.cte_read_ant_infor_cmpl.max_cte_len, p); + + if (cb_params.cte_read_ant_infor_cmpl.status != HCI_SUCCESS) { + cb_params.cte_read_ant_infor_cmpl.status = (BTM_HCI_ERROR | cb_params.cte_read_ant_infor_cmpl.status); + } + + BTM_CteBleCallbackTrigger(BTM_BLE_CTE_READ_ANT_INFOR_EVT, &cb_params); +} + +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +void btm_ble_connless_iq_report_evt(tBTM_BLE_CTE_CONNLESS_IQ_REPORT_EVT *params) +{ + if (!params) { + BTM_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + BTM_CteBleCallbackTrigger(BTM_BLE_CTE_CONNLESS_IQ_REPORT_EVT, (tBTM_BLE_CTE_CB_PARAMS *)params); +} +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +void btm_ble_conn_iq_report_evt(tBTM_BLE_CTE_CONN_IQ_REPORT_EVT *params) +{ + if (!params) { + BTM_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + BTM_CteBleCallbackTrigger(BTM_BLE_CTE_CONN_IQ_REPORT_EVT, (tBTM_BLE_CTE_CB_PARAMS *)params); +} + +void btm_ble_cte_req_failed_evt(tBTM_BLE_CTE_REQ_FAILED_EVT *params) +{ + if (!params) { + BTM_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + if (params->status != HCI_SUCCESS) { + params->status = (params->status | BTM_HCI_ERROR); + } + + BTM_CteBleCallbackTrigger(BTM_BLE_CTE_REQUEST_FAILED_EVT, (tBTM_BLE_CTE_CB_PARAMS *)params); +} +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) diff --git a/lib/bt/host/bluedroid/stack/btm/btm_ble_gap.c b/lib/bt/host/bluedroid/stack/btm/btm_ble_gap.c index df24fa08..f3886643 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_ble_gap.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_ble_gap.c @@ -71,20 +71,28 @@ static tBTM_BLE_CTRL_FEATURES_CBACK *p_ctrl_le_feature_rd_cmpl_cback = NULL; #endif tBTM_CallbackFunc conn_callback_func; +// BLE vendor HCI event callback +#if (BLE_VENDOR_HCI_EN == TRUE) +static tBTM_BLE_VENDOR_HCI_EVT_CBACK *ble_vs_evt_callback = NULL; +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) /******************************************************************************* ** Local functions *******************************************************************************/ static void btm_ble_update_adv_flag(UINT8 flag); static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt_type, UINT8 *p); + UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst, tBTM_BLE_ADV_DATA *p_data); + static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb, BD_ADDR_PTR p_peer_addr_ptr, tBLE_ADDR_TYPE *p_peer_addr_type, tBLE_ADDR_TYPE *p_own_addr_type); static void btm_ble_stop_observe(void); static void btm_ble_stop_discover(void); +#if (BLE_42_SCAN_EN == TRUE) static void btm_adv_pkt_handler(void *arg); +#endif // #if (BLE_42_SCAN_EN == TRUE) uint32_t BTM_BleUpdateOwnType(uint8_t *own_bda_type, tBTM_START_ADV_CMPL_CBACK *cb); #define BTM_BLE_INQ_RESULT 0x01 @@ -246,56 +254,77 @@ const UINT8 btm_le_state_combo_tbl[BTM_BLE_STATE_MAX][BTM_BLE_STATE_MAX][2] = { /* check LE combo state supported */ #define BTM_LE_STATES_SUPPORTED(x, y, z) ((x)[(z)] & (y)) +#if (BLE_42_ADV_EN == TRUE) static osi_mutex_t adv_enable_lock; static osi_mutex_t adv_data_lock; static osi_mutex_t adv_param_lock; -static osi_mutex_t scan_enable_lock; -static osi_mutex_t scan_param_lock; osi_sem_t adv_enable_sem; osi_sem_t adv_data_sem; osi_sem_t adv_param_sem; -osi_sem_t scan_enable_sem; -osi_sem_t scan_param_sem; uint8_t adv_enable_status = 0; uint8_t adv_data_status = 0; uint8_t adv_param_status = 0; +#endif // #if (BLE_42_ADV_EN == TRUE) + +#if (BLE_42_SCAN_EN == TRUE) +static osi_mutex_t scan_enable_lock; +static osi_mutex_t scan_param_lock; +osi_sem_t scan_enable_sem; +osi_sem_t scan_param_sem; uint8_t scan_enable_status = 0; uint8_t scan_param_status = 0; +#endif // #if (BLE_42_SCAN_EN == TRUE) void btm_ble_lock_init(void) { +#if (BLE_42_ADV_EN == TRUE) osi_mutex_new(&adv_enable_lock); osi_mutex_new(&adv_data_lock); osi_mutex_new(&adv_param_lock); +#endif // #if (BLE_42_ADV_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) osi_mutex_new(&scan_enable_lock); osi_mutex_new(&scan_param_lock); +#endif // #if (BLE_42_SCAN_EN == TRUE) } void btm_ble_lock_free(void) { +#if (BLE_42_ADV_EN == TRUE) osi_mutex_free(&adv_enable_lock); osi_mutex_free(&adv_data_lock); osi_mutex_free(&adv_param_lock); +#endif // #if (BLE_42_ADV_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) osi_mutex_free(&scan_enable_lock); osi_mutex_free(&scan_param_lock); +#endif // #if (BLE_42_SCAN_EN == TRUE) } void btm_ble_sem_init(void) { +#if (BLE_42_ADV_EN == TRUE) osi_sem_new(&adv_enable_sem, 1, 0); osi_sem_new(&adv_data_sem, 1, 0); osi_sem_new(&adv_param_sem, 1, 0); +#endif // #if (BLE_42_ADV_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) osi_sem_new(&scan_enable_sem, 1, 0); osi_sem_new(&scan_param_sem, 1, 0); +#endif // #if (BLE_42_SCAN_EN == TRUE) } void btm_ble_sem_free(void) { +#if (BLE_42_ADV_EN == TRUE) osi_sem_free(&adv_enable_sem); osi_sem_free(&adv_data_sem); osi_sem_free(&adv_param_sem); +#endif // #if (BLE_42_ADV_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) osi_sem_free(&scan_enable_sem); osi_sem_free(&scan_param_sem); +#endif // #if (BLE_42_SCAN_EN == TRUE) } /******************************************************************************* @@ -326,6 +355,13 @@ void BTM_BleRegiseterPktLengthChangeCallback(tBTM_SET_PKT_DATA_LENGTH_CBACK *ptk conn_callback_func.set_pkt_data_length_cb = ptk_len_chane_cb; } +#if (BLE_VENDOR_HCI_EN == TRUE) +void BTM_BleRegisterVendorHciEventCallback(tBTM_BLE_VENDOR_HCI_EVT_CBACK *vendor_hci_evt_cb) +{ + ble_vs_evt_callback = vendor_hci_evt_cb; +} +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) + /******************************************************************************* ** ** Function BTM_BleUpdateAdvWhitelist @@ -380,14 +416,22 @@ void BTM_BleUpdateAdvFilterPolicy(tBTM_BLE_AFP adv_policy) if (p_cb->afp != adv_policy) { p_cb->afp = adv_policy; +#if (BLE_42_ADV_EN == TRUE) /* if adv active, stop and restart */ btm_ble_stop_adv (); +#endif // #if (BLE_42_ADV_EN == TRUE) if (p_cb->connectable_mode & BTM_BLE_CONNECTABLE) { p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &p_cb->adv_addr_type); } + uint8_t null_addr[BD_ADDR_LEN] = {0}; + if ((p_cb->evt_type == 0x01 || p_cb->evt_type == 0x04) && memcmp(p_addr_ptr, null_addr, BD_ADDR_LEN) == 0) { + /* directed advertising */ + return; + } + btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : BTM_BLE_GAP_ADV_SLOW_INT), (UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : @@ -400,7 +444,9 @@ void BTM_BleUpdateAdvFilterPolicy(tBTM_BLE_AFP adv_policy) p_cb->afp); if (adv_mode == BTM_BLE_ADV_ENABLE) { +#if (BLE_42_ADV_EN == TRUE) btm_ble_start_adv (); +#endif // #if (BLE_42_ADV_EN == TRUE) } } @@ -506,8 +552,9 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT32 duration, btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, BTM_BLE_DEFAULT_SFP); } - +#if (BLE_42_SCAN_EN == TRUE) status = btm_ble_start_scan(); +#endif // #if (BLE_42_SCAN_EN == TRUE) } if (status == BTM_CMD_STARTED) { @@ -529,6 +576,7 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT32 duration, } +#if (BLE_42_SCAN_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleScan @@ -606,7 +654,9 @@ tBTM_STATUS BTM_BleScan(BOOLEAN start, UINT32 duration, return status; } +#endif // #if (BLE_42_SCAN_EN == TRUE) +#if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleBroadcast @@ -665,7 +715,7 @@ tBTM_STATUS BTM_BleBroadcast(BOOLEAN start, tBTM_START_STOP_ADV_CMPL_CBACK *p_s } return status; } - +#endif // #if (BLE_42_ADV_EN == TRUE) #if BLE_VND_INCLUDED == TRUE /******************************************************************************* ** @@ -717,11 +767,11 @@ static void btm_ble_vendor_capability_vsc_cmpl_cback (tBTM_VSC_CMPL *p_vcs_cplt_ __func__, status, btm_cb.cmn_ble_vsc_cb.max_irk_list_sz, btm_cb.cmn_ble_vsc_cb.adv_inst_max, btm_cb.cmn_ble_vsc_cb.rpa_offloading, btm_cb.cmn_ble_vsc_cb.energy_support, btm_cb.cmn_ble_vsc_cb.extended_scan_support); - +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) if (BTM_BleMaxMultiAdvInstanceCount() > 0) { btm_ble_multi_adv_init(); } - +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) if (btm_cb.cmn_ble_vsc_cb.max_filter > 0) { btm_ble_adv_filter_init(); } @@ -899,9 +949,11 @@ BOOLEAN BTM_BleConfigPrivacy(BOOLEAN privacy_mode, tBTM_SET_LOCAL_PRIVACY_CBACK btm_gen_resolvable_private_addr((void *)btm_gen_resolve_paddr_low); #endif +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) if (BTM_BleMaxMultiAdvInstanceCount() > 0) { btm_ble_multi_adv_enb_privacy(privacy_mode); } +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) /* 4.2 controller only allow privacy 1.2 or mixed mode, resolvable private address in controller */ if (controller_get_interface()->supports_ble_privacy()) { @@ -1139,6 +1191,7 @@ void BTM_BleConfigConnParams(uint16_t int_min, uint16_t int_max, uint16_t latenc #endif } +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleMaxMultiAdvInstanceCount @@ -1153,6 +1206,7 @@ extern UINT8 BTM_BleMaxMultiAdvInstanceCount(void) return btm_cb.cmn_ble_vsc_cb.adv_inst_max < BTM_BLE_MULTI_ADV_MAX ? btm_cb.cmn_ble_vsc_cb.adv_inst_max : BTM_BLE_MULTI_ADV_MAX; } +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) #if BLE_PRIVACY_SPT == TRUE /******************************************************************************* @@ -1291,7 +1345,9 @@ void BTM_BleClearBgConnDev(void) { btm_ble_start_auto_conn(FALSE); btm_ble_clear_white_list(NULL); +#if (tGATT_BG_CONN_DEV == TRUE) gatt_reset_bgdev_list(); +#endif // #if (tGATT_BG_CONN_DEV == TRUE) } /******************************************************************************* @@ -1314,7 +1370,7 @@ BOOLEAN BTM_BleUpdateBgConnDev(BOOLEAN add_remove, BD_ADDR remote_bda) BTM_TRACE_EVENT("%s() add=%d", __func__, add_remove); return btm_update_dev_to_white_list(add_remove, remote_bda, 0, NULL); } - +#if 0 /******************************************************************************* ** ** Function BTM_BleSetConnectableMode @@ -1342,7 +1398,7 @@ tBTM_STATUS BTM_BleSetConnectableMode(tBTM_BLE_CONN_MODE connectable_mode) p_cb->directed_conn = connectable_mode; return btm_ble_set_connectability( p_cb->connectable_mode); } - +#endif /******************************************************************************* ** ** Function btm_set_conn_mode_adv_init_addr @@ -1435,76 +1491,7 @@ static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb, return evt_type; } -/******************************************************************************* -** -** Function BTM_BleSetAdvParams -** -** Description This function is called to set advertising parameters. -** -** Parameters adv_int_min: minimum advertising interval -** adv_int_max: maximum advertising interval -** p_dir_bda: connectable direct initiator's LE device address -** chnl_map: advertising channel map. -** -** Returns void -** -*******************************************************************************/ -tBTM_STATUS BTM_BleSetAdvParams(UINT16 adv_int_min, UINT16 adv_int_max, - tBLE_BD_ADDR *p_dir_bda, - tBTM_BLE_ADV_CHNL_MAP chnl_map) -{ - tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb; - tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; - tBTM_STATUS status = BTM_SUCCESS; - BD_ADDR p_addr_ptr = {0}; - tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC; - tBLE_ADDR_TYPE own_addr_type = p_addr_cb->own_addr_type; - UINT8 adv_mode = p_cb->adv_mode; - - BTM_TRACE_EVENT ("BTM_BleSetAdvParams"); - - if (!controller_get_interface()->supports_ble()) { - return BTM_ILLEGAL_VALUE; - } - - if (!BTM_BLE_ISVALID_PARAM(adv_int_min, BTM_BLE_ADV_INT_MIN, BTM_BLE_ADV_INT_MAX) || - !BTM_BLE_ISVALID_PARAM(adv_int_max, BTM_BLE_ADV_INT_MIN, BTM_BLE_ADV_INT_MAX)) { - return BTM_ILLEGAL_VALUE; - } - - p_cb->adv_interval_min = adv_int_min; - p_cb->adv_interval_max = adv_int_max; - p_cb->adv_chnl_map = chnl_map; - - if (p_dir_bda) { - memcpy(&p_cb->direct_bda, p_dir_bda, sizeof(tBLE_BD_ADDR)); - } - - BTM_TRACE_EVENT ("update params for an active adv\n"); - - btm_ble_stop_adv(); - - p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, - &own_addr_type); - - /* update adv params */ - btsnd_hcic_ble_write_adv_params (p_cb->adv_interval_min, - p_cb->adv_interval_max, - p_cb->evt_type, - own_addr_type, - init_addr_type, - p_addr_ptr, - p_cb->adv_chnl_map, - p_cb->afp); - - if (adv_mode == BTM_BLE_ADV_ENABLE) { - btm_ble_start_adv(); - } - - return status; -} - - +#if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleSetAdvParamsAll @@ -1599,6 +1586,7 @@ tBTM_STATUS BTM_BleStartAdv(void) return status; } +#endif // #if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleReadAdvParams @@ -1632,6 +1620,7 @@ void BTM_BleReadAdvParams (UINT16 *adv_int_min, UINT16 *adv_int_max, } } +#if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) /******************************************************************************* ** ** Function BTM_BleSetScanParams @@ -1690,7 +1679,9 @@ void BTM_BleSetScanParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_ } } +#endif // #if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) +#if (BLE_42_SCAN_EN == TRUE) tBTM_STATUS BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_window, tBLE_SCAN_MODE scan_mode, UINT8 addr_type_own, UINT8 scan_duplicate_filter, tBTM_BLE_SFP scan_filter_policy, tBLE_SCAN_PARAM_SETUP_CBACK scan_setup_status_cback) @@ -1746,8 +1737,9 @@ tBTM_STATUS BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, osi_mutex_unlock(&scan_param_lock); return ret; } +#endif // #if (BLE_42_SCAN_EN == TRUE) - +#if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleWriteScanRsp @@ -1822,6 +1814,7 @@ tBTM_STATUS BTM_BleWriteScanRspRaw(UINT8 *p_raw_scan_rsp, UINT32 raw_scan_rsp_le return ret; } +#endif // #if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** @@ -1888,6 +1881,7 @@ tBTM_STATUS BTM_UpdateBleDuplicateExceptionalList(uint8_t subcode, uint32_t type return status; } +#if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleWriteAdvData @@ -1938,38 +1932,6 @@ tBTM_STATUS BTM_BleWriteAdvData(tBTM_BLE_AD_MASK data_mask, tBTM_BLE_ADV_DATA *p return ret; } -/******************************************************************************* -** -** Function BTM_BleWriteLongAdvData -** -** Description This function is called to write long advertising data. -** -** Parameters: adv_data: long advertising data -** adv_data_len: the length of long advertising data -** -** Returns void -** -*******************************************************************************/ -tBTM_STATUS BTM_BleWriteLongAdvData(uint8_t *adv_data, uint8_t adv_data_len) -{ - tBTM_STATUS status = BTM_NO_RESOURCES; - if (!controller_get_interface()->supports_ble()) { - return BTM_ILLEGAL_VALUE; - } - if(!adv_data || adv_data_len <= 0 || adv_data_len > BTM_BLE_LONG_ADV_MAX_LEN) { - return BTM_ILLEGAL_VALUE; - } - uint8_t long_adv[BTM_BLE_LONG_ADV_MAX_LEN + 1] = {0}; - long_adv[0] = adv_data_len; - memcpy(&long_adv[1], adv_data, adv_data_len); - status = BTM_VendorSpecificCommand(HCI_VENDOR_BLE_LONG_ADV_DATA, BTM_BLE_LONG_ADV_MAX_LEN + 1, long_adv, NULL); - if(status == BTM_CMD_STARTED) { - status = BTM_SUCCESS; - } - - return status; -} - /******************************************************************************* ** ** Function BTM_BleWriteAdvDataRaw @@ -1995,7 +1957,7 @@ tBTM_STATUS BTM_BleWriteAdvDataRaw(UINT8 *p_raw_adv, UINT32 raw_adv_len) return ret; } - +#endif // #if (BLE_42_ADV_EN == TRUE) /******************************************************************************* ** @@ -2082,6 +2044,7 @@ BOOLEAN BTM_BleGetCurrentAddress(BD_ADDR addr, uint8_t *addr_type) return TRUE; } +#if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) /******************************************************************************* ** ** Function BTM_CheckAdvData @@ -2095,7 +2058,7 @@ BOOLEAN BTM_BleGetCurrentAddress(BD_ADDR addr, uint8_t *addr_type) ** Returns pointer of ADV data ** *******************************************************************************/ -UINT8 *BTM_CheckAdvData( UINT8 *p_adv, UINT8 type, UINT8 *p_length) +UINT8 *BTM_CheckAdvData( UINT8 *p_adv, UINT16 adv_data_len, UINT8 type, UINT8 *p_length) { UINT8 *p = p_adv; UINT8 length; @@ -2104,7 +2067,7 @@ UINT8 *BTM_CheckAdvData( UINT8 *p_adv, UINT8 type, UINT8 *p_length) STREAM_TO_UINT8(length, p); - while ( length && (p - p_adv < BTM_BLE_CACHE_ADV_DATA_MAX)) { + while ( length && (p - p_adv < adv_data_len)) { STREAM_TO_UINT8(adv_type, p); if ( adv_type == type ) { @@ -2117,7 +2080,7 @@ UINT8 *BTM_CheckAdvData( UINT8 *p_adv, UINT8 type, UINT8 *p_length) /* Break loop if advertising data is in an incorrect format, as it may lead to memory overflow */ - if (p >= p_adv + BTM_BLE_CACHE_ADV_DATA_MAX) { + if (p >= p_adv + adv_data_len) { break; } @@ -2127,7 +2090,7 @@ UINT8 *BTM_CheckAdvData( UINT8 *p_adv, UINT8 type, UINT8 *p_length) *p_length = 0; return NULL; } - +#endif // #if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) /******************************************************************************* ** ** Function BTM__BLEReadDiscoverability @@ -2165,16 +2128,20 @@ UINT16 BTM_BleReadConnectability(void) void BTM_Recovery_Pre_State(void) { +#if ((BLE_42_ADV_EN == TRUE) || (BLE_42_SCAN_EN == TRUE)) tBTM_BLE_INQ_CB *ble_inq_cb = &btm_cb.ble_ctr_cb.inq_var; - +#endif // #if ((BLE_42_ADV_EN == TRUE) || (BLE_42_SCAN_EN == TRUE)) +#if (BLE_42_ADV_EN == TRUE) if (ble_inq_cb->state & BTM_BLE_ADVERTISING) { btm_ble_stop_adv(); btm_ble_start_adv(); } +#endif // #if (BLE_42_ADV_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) if (ble_inq_cb->state & BTM_BLE_SCANNING) { btm_ble_start_scan(); } - +#endif // #if (BLE_42_SCAN_EN == TRUE) return; } @@ -2203,6 +2170,26 @@ BOOLEAN BTM_GetCurrentConnParams(BD_ADDR bda, uint16_t *interval, uint16_t *late return FALSE; } +/******************************************************************************* +** +** Function btm_ble_map_adv_tx_power +** +** Description return the actual power in dBm based on the mapping in config file +** +** Parameters advertise parameters used for this instance. +** +** Returns tx power in dBm +** +*******************************************************************************/ +static const int btm_ble_tx_power[BTM_BLE_ADV_TX_POWER_MAX + 1] = BTM_BLE_ADV_TX_POWER; +char btm_ble_map_adv_tx_power(int tx_power_index) +{ + if (0 <= tx_power_index && tx_power_index <= BTM_BLE_ADV_TX_POWER_MAX) { + return (char)btm_ble_tx_power[tx_power_index]; + } + return 0; +} + /******************************************************************************* ** ** Function btm_ble_build_adv_data @@ -2564,6 +2551,7 @@ void btm_ble_set_adv_flag(UINT16 connect_mode, UINT16 disc_mode) btm_ble_update_adv_flag(flag); } } +#if 0 /******************************************************************************* ** ** Function btm_ble_set_discoverability @@ -2615,7 +2603,9 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode) if (evt_type != p_cb->evt_type || p_cb->adv_addr_type != own_addr_type || !p_cb->fast_adv_on) { +#if (BLE_42_ADV_EN == TRUE) btm_ble_stop_adv(); +#endif // #if (BLE_42_ADV_EN == TRUE) /* update adv params */ if (!btsnd_hcic_ble_write_adv_params (adv_int_min, @@ -2635,11 +2625,13 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode) } if (status == BTM_SUCCESS && p_cb->adv_mode != new_mode) { +#if (BLE_42_ADV_EN == TRUE) if (new_mode == BTM_BLE_ADV_ENABLE) { status = btm_ble_start_adv(); } else { status = btm_ble_stop_adv(); } +#endif // #if (BLE_42_ADV_EN == TRUE) } if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE) { @@ -2662,7 +2654,7 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode) } return status; } - +#endif /******************************************************************************* ** ** Function btm_ble_set_connectability @@ -2710,7 +2702,9 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode) btm_ble_set_adv_flag (combined_mode, btm_cb.btm_inq_vars.discoverable_mode); if (p_cb->evt_type != evt_type || p_cb->adv_addr_type != p_addr_cb->own_addr_type || !p_cb->fast_adv_on) { +#if (BLE_42_ADV_EN == TRUE) btm_ble_stop_adv(); +#endif // #if (BLE_42_ADV_EN == TRUE) if (!btsnd_hcic_ble_write_adv_params (adv_int_min, adv_int_max, @@ -2730,11 +2724,13 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode) /* update advertising mode */ if (status == BTM_SUCCESS && new_mode != p_cb->adv_mode) { +#if (BLE_42_ADV_EN == TRUE) if (new_mode == BTM_BLE_ADV_ENABLE) { status = btm_ble_start_adv(); } else { status = btm_ble_stop_adv(); } +#endif // #if (BLE_42_ADV_EN == TRUE) } if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE) { @@ -2795,7 +2791,9 @@ tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration) /* enable IRK list */ //btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN); #endif +#if (BLE_42_SCAN_EN == TRUE) status = btm_ble_start_scan(); +#endif // #if (BLE_42_SCAN_EN == TRUE) } else if ((p_ble_cb->inq_var.scan_interval != BTM_BLE_LOW_LATENCY_SCAN_INT) || (p_ble_cb->inq_var.scan_window != BTM_BLE_LOW_LATENCY_SCAN_WIN)) { BTM_TRACE_DEBUG("%s, restart LE scan with low latency scan params", __FUNCTION__); @@ -3170,7 +3168,7 @@ UINT8 btm_ble_is_discoverable(BD_ADDR bda, UINT8 evt_type, UINT8 *p) } if (p_le_inq_cb->adv_len != 0) { - if ((p_flag = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, + if ((p_flag = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, p_le_inq_cb->adv_len, BTM_BLE_AD_TYPE_FLAG, &data_len)) != NULL) { flag = * p_flag; @@ -3386,7 +3384,7 @@ BOOLEAN btm_ble_update_inq_result(BD_ADDR bda, tINQ_DB_ENT *p_i, UINT8 addr_type p_i->inq_count = p_inq->inq_counter; /* Mark entry for current inquiry */ if (p_le_inq_cb->adv_len != 0) { - if ((p_flag = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, BTM_BLE_AD_TYPE_FLAG, &len)) != NULL) { + if ((p_flag = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, p_le_inq_cb->adv_len, BTM_BLE_AD_TYPE_FLAG, &len)) != NULL) { p_cur->flag = * p_flag; } } @@ -3396,11 +3394,11 @@ BOOLEAN btm_ble_update_inq_result(BD_ADDR bda, tINQ_DB_ENT *p_i, UINT8 addr_type * then try to convert the appearance value to a class of device value Bluedroid can use. * Otherwise fall back to trying to infer if it is a HID device based on the service class. */ - p_uuid16 = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, BTM_BLE_AD_TYPE_APPEARANCE, &len); + p_uuid16 = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, p_le_inq_cb->adv_len, BTM_BLE_AD_TYPE_APPEARANCE, &len); if (p_uuid16 && len == 2) { btm_ble_appearance_to_cod((UINT16)p_uuid16[0] | (p_uuid16[1] << 8), p_cur->dev_class); } else { - if ((p_uuid16 = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, + if ((p_uuid16 = BTM_CheckAdvData(p_le_inq_cb->adv_data_cache, p_le_inq_cb->adv_len, BTM_BLE_AD_TYPE_16SRV_CMPL, &len)) != NULL) { UINT8 i; for (i = 0; i + 2 <= len; i = i + 2) { @@ -3487,10 +3485,10 @@ void btm_send_sel_conn_callback(BD_ADDR remote_bda, UINT8 evt_type, UINT8 *p_dat /* get the device name if exist in ADV data */ if (data_len != 0) { - p_dev_name = BTM_CheckAdvData(p_data, BTM_BLE_AD_TYPE_NAME_CMPL, &len); + p_dev_name = BTM_CheckAdvData(p_data, data_len, BTM_BLE_AD_TYPE_NAME_CMPL, &len); if (p_dev_name == NULL) { - p_dev_name = BTM_CheckAdvData(p_data, BTM_BLE_AD_TYPE_NAME_SHORT, &len); + p_dev_name = BTM_CheckAdvData(p_data, data_len, BTM_BLE_AD_TYPE_NAME_SHORT, &len); } if (p_dev_name) { @@ -3504,6 +3502,7 @@ void btm_send_sel_conn_callback(BD_ADDR remote_bda, UINT8 evt_type, UINT8 *p_dat } } +#if (BLE_42_SCAN_EN == TRUE) static void btm_adv_pkt_handler(void *arg) { UINT8 hci_evt_code, hci_evt_len; @@ -3546,6 +3545,7 @@ static void btm_adv_pkt_handler(void *arg) UNUSED(hci_evt_code); UNUSED(hci_evt_len); } +#endif // #if (BLE_42_SCAN_EN == TRUE) /******************************************************************************* ** @@ -3832,6 +3832,7 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt void btm_ble_process_adv_discard_evt(UINT8 *p) { +#if (BLE_42_SCAN_EN == TRUE) #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) uint32_t num_dis = 0; STREAM_TO_UINT32 (num_dis, p); @@ -3840,6 +3841,7 @@ void btm_ble_process_adv_discard_evt(UINT8 *p) (p_obs_discard_cb)(num_dis); } #endif +#endif // #if (BLE_42_SCAN_EN == TRUE) } void btm_ble_process_direct_adv_pkt(UINT8 *p) @@ -3847,6 +3849,7 @@ void btm_ble_process_direct_adv_pkt(UINT8 *p) // TODO } +#if (BLE_42_SCAN_EN == TRUE) /******************************************************************************* ** ** Function btm_ble_start_scan @@ -3884,6 +3887,7 @@ tBTM_STATUS btm_ble_start_scan(void) osi_mutex_unlock(&scan_enable_lock); return status; } +#endif // #if (BLE_42_SCAN_EN == TRUE) /******************************************************************************* ** @@ -3933,8 +3937,10 @@ void btm_ble_stop_inquiry(void) } else if ((p_ble_cb->inq_var.scan_interval != BTM_BLE_LOW_LATENCY_SCAN_INT) || (p_ble_cb->inq_var.scan_window != BTM_BLE_LOW_LATENCY_SCAN_WIN)) { BTM_TRACE_DEBUG("%s: setting default params for ongoing observe", __FUNCTION__); +#if (BLE_42_SCAN_EN == TRUE) btm_ble_stop_scan(); btm_ble_start_scan(); +#endif // #if (BLE_42_SCAN_EN == TRUE) } /* If we have a callback registered for inquiry complete, call it */ @@ -3985,6 +3991,7 @@ static void btm_ble_stop_observe(void) *******************************************************************************/ static void btm_ble_stop_discover(void) { +#if (BLE_42_SCAN_EN == TRUE) tBTM_BLE_CB *p_ble_cb = & btm_cb.ble_ctr_cb; tBTM_CMPL_CB *p_scan_cb = p_ble_cb->p_scan_cmpl_cb; btu_stop_timer (&p_ble_cb->scan_timer_ent); @@ -3997,18 +4004,21 @@ static void btm_ble_stop_discover(void) if (!BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity)) { /* Clear the inquiry callback if set */ - btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE; btm_cb.ble_ctr_cb.inq_var.state &= ~BTM_BLE_SCANNING; /* stop discovery now */ if(btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE)) { osi_sem_take(&scan_enable_sem, OSI_SEM_MAX_TIMEOUT); } + /* reset status */ + btm_ble_clear_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT); + btm_ble_clear_topology_mask(BTM_BLE_STATE_PASSIVE_SCAN_BIT); } if (p_scan_cb) { (p_scan_cb)((tBTM_INQUIRY_CMPL *) &btm_cb.btm_inq_vars.inq_cmpl_info); } osi_mutex_unlock(&scan_enable_lock); +#endif // #if (BLE_42_SCAN_EN == TRUE) } /******************************************************************************* @@ -4021,6 +4031,7 @@ static void btm_ble_stop_discover(void) ** *******************************************************************************/ typedef BOOLEAN (BTM_TOPOLOGY_FUNC_PTR)(tBTM_BLE_STATE_MASK); +#if (BLE_42_ADV_EN == TRUE) static BOOLEAN btm_ble_adv_states_operation(BTM_TOPOLOGY_FUNC_PTR *p_handler, UINT8 adv_evt) { BOOLEAN rt = FALSE; @@ -4053,7 +4064,6 @@ static BOOLEAN btm_ble_adv_states_operation(BTM_TOPOLOGY_FUNC_PTR *p_handler, UI return rt; } - /******************************************************************************* ** ** Function btm_ble_start_adv @@ -4165,14 +4175,19 @@ tBTM_STATUS btm_ble_stop_adv(void) } return rt; } +#endif // #if (BLE_42_ADV_EN == TRUE) tBTM_STATUS btm_ble_set_random_addr(BD_ADDR random_bda) { tBTM_STATUS rt = BTM_SUCCESS; - +#if (BLE_42_ADV_EN == TRUE) osi_mutex_lock(&adv_enable_lock, OSI_MUTEX_MAX_TIMEOUT); +#endif // #if (BLE_42_ADV_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) osi_mutex_lock(&scan_enable_lock, OSI_MUTEX_MAX_TIMEOUT); +#endif // #if (BLE_42_SCAN_EN == TRUE) +#if (BLE_42_ADV_EN == TRUE) if (btm_cb.ble_ctr_cb.inq_var.adv_mode == BTM_BLE_ADV_ENABLE) { if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE)) { osi_sem_take(&adv_enable_sem, OSI_SEM_MAX_TIMEOUT); @@ -4181,7 +4196,9 @@ tBTM_STATUS btm_ble_set_random_addr(BD_ADDR random_bda) rt = BTM_BAD_VALUE_RET; } } +#endif // #if (BLE_42_ADV_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) if (BTM_BLE_IS_DISCO_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) { if (btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_SCAN_DUPLICATE_DISABLE)) { osi_sem_take(&scan_enable_sem, OSI_SEM_MAX_TIMEOUT); @@ -4190,11 +4207,13 @@ tBTM_STATUS btm_ble_set_random_addr(BD_ADDR random_bda) rt = BTM_BAD_VALUE_RET; } } +#endif // #if (BLE_42_SCAN_EN == TRUE) if (rt == BTM_SUCCESS) { btsnd_hcic_ble_set_random_addr(random_bda); } +#if (BLE_42_ADV_EN == TRUE) if (btm_cb.ble_ctr_cb.inq_var.adv_mode == BTM_BLE_ADV_ENABLE) { if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE)) { osi_sem_take(&adv_enable_sem, OSI_SEM_MAX_TIMEOUT); @@ -4203,7 +4222,9 @@ tBTM_STATUS btm_ble_set_random_addr(BD_ADDR random_bda) rt = BTM_BAD_VALUE_RET; } } +#endif // #if (BLE_42_ADV_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) if (BTM_BLE_IS_DISCO_ACTIVE(btm_cb.ble_ctr_cb.scan_activity)) { if (btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, btm_cb.ble_ctr_cb.inq_var.scan_duplicate_filter)) { osi_sem_take(&scan_enable_sem, OSI_SEM_MAX_TIMEOUT); @@ -4212,9 +4233,14 @@ tBTM_STATUS btm_ble_set_random_addr(BD_ADDR random_bda) rt = BTM_BAD_VALUE_RET; } } +#endif // #if (BLE_42_SCAN_EN == TRUE) +#if (BLE_42_ADV_EN == TRUE) osi_mutex_unlock(&adv_enable_lock); +#endif // #if (BLE_42_ADV_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) osi_mutex_unlock(&scan_enable_lock); +#endif // #if (BLE_42_SCAN_EN == TRUE) return rt; } @@ -4231,6 +4257,7 @@ tBTM_STATUS btm_ble_set_random_addr(BD_ADDR random_bda) *******************************************************************************/ static void btm_ble_start_slow_adv (void) { +#if (BLE_42_ADV_EN == TRUE) tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE) { @@ -4249,9 +4276,9 @@ static void btm_ble_start_slow_adv (void) p_cb->evt_type, own_addr_type, init_addr_type, p_addr_ptr, p_cb->adv_chnl_map, p_cb->afp); - btm_ble_start_adv(); } +#endif // #if (BLE_42_ADV_EN == TRUE) } /******************************************************************************* ** @@ -4291,9 +4318,11 @@ void btm_ble_timeout(TIMER_LIST_ENT *p_tle) btm_gen_resolvable_private_addr((void *)btm_gen_resolve_paddr_low); #endif } else { +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) if (BTM_BleMaxMultiAdvInstanceCount() > 0) { btm_ble_multi_adv_configure_rpa((tBTM_BLE_MULTI_ADV_INST *)p_tle->param); } +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) } } break; @@ -4515,12 +4544,36 @@ BOOLEAN btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, UINT8 st now in order */ if (btm_ble_get_conn_st() == BLE_CONN_IDLE && status != HCI_ERR_HOST_REJECT_RESOURCES && !btm_send_pending_direct_conn()) { +#if (tGATT_BG_CONN_DEV == TRUE) bg_con = btm_ble_resume_bg_conn(); +#endif // #if (tGATT_BG_CONN_DEV == TRUE) } return bg_con; } +#if (BLE_VENDOR_HCI_EN == TRUE) +static void btm_ble_vs_evt_callback(UINT8 len, UINT8 *p) +{ + UINT8 sub_event; + + if (!len || !p) { + return; + } + + STREAM_TO_UINT8(sub_event, p); + len--; + + if (sub_event < HCI_VSE_LE_SUBEVT_BASE) { + return; + } + + if (ble_vs_evt_callback) { + ble_vs_evt_callback(sub_event, len, p); + } +} +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) + /******************************************************************************* ** ** Function btm_ble_init @@ -4566,17 +4619,22 @@ void btm_ble_init (void) p_cb->scan_int = p_cb->scan_win = BTM_BLE_SCAN_PARAM_UNDEF; p_cb->inq_var.evt_type = BTM_BLE_NON_CONNECT_EVT; - +#if (BLE_42_SCAN_EN == TRUE) p_cb->adv_rpt_queue = pkt_queue_create(); assert(p_cb->adv_rpt_queue != NULL); p_cb->adv_rpt_ready = osi_event_create(btm_adv_pkt_handler, NULL); assert(p_cb->adv_rpt_ready != NULL); osi_event_bind(p_cb->adv_rpt_ready, btu_get_current_thread(), 0); - +#endif // #if (BLE_42_SCAN_EN == TRUE) #if BLE_VND_INCLUDED == FALSE +#if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE btm_ble_adv_filter_init(); +#endif // #if BLE_ANDROID_CONTROLLER_SCAN_FILTER == TRUE #endif +#if (BLE_VENDOR_HCI_EN == TRUE) + BTM_RegisterForVSEvents(btm_ble_vs_evt_callback, TRUE); +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) } /******************************************************************************* @@ -4595,19 +4653,25 @@ void btm_ble_free (void) BTM_TRACE_DEBUG("%s", __func__); fixed_queue_free(p_cb->conn_pending_q, osi_free_func); - +#if (BLE_42_SCAN_EN == TRUE) pkt_queue_destroy(p_cb->adv_rpt_queue, NULL); p_cb->adv_rpt_queue = NULL; osi_event_delete(p_cb->adv_rpt_ready); p_cb->adv_rpt_ready = NULL; - +#endif // #if (BLE_42_SCAN_EN == TRUE) #if BTM_DYNAMIC_MEMORY == TRUE osi_free(cmn_ble_gap_vsc_cb_ptr); cmn_ble_gap_vsc_cb_ptr = NULL; #endif } +static bool enable_topology_check_flag = true; +void esp_qa_enable_topology_check(bool enable) +{ + // This is a workaround: If the topology check is disabled, the 'Supported States' will not be checked. + enable_topology_check_flag = enable; +} /******************************************************************************* ** ** Function btm_ble_topology_check @@ -4620,6 +4684,7 @@ void btm_ble_free (void) *******************************************************************************/ BOOLEAN btm_ble_topology_check(tBTM_BLE_STATE_MASK request_state_mask) { + if(!enable_topology_check_flag) return TRUE; BOOLEAN rt = FALSE; UINT8 state_offset = 0; @@ -4696,6 +4761,7 @@ BOOLEAN BTM_Ble_Authorization(BD_ADDR bd_addr, BOOLEAN authorize) return FALSE; } +#if (BLE_VENDOR_HCI_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleClearAdv @@ -4717,6 +4783,30 @@ BOOLEAN BTM_BleClearAdv(tBTM_CLEAR_ADV_CMPL_CBACK *p_clear_adv_cback) p_cb->inq_var.p_clear_adv_cb = p_clear_adv_cback; return TRUE; } + +BOOLEAN BTM_BleSetCsaSupport(UINT8 csa_select, tBTM_SET_CSA_SUPPORT_CMPL_CBACK *p_callback) +{ + if (btsnd_hcic_ble_set_csa_support(csa_select) != TRUE) { + BTM_TRACE_ERROR("LE SetCsaSupport csa_select=%d: error", csa_select); + return FALSE; + } + + btm_cb.ble_ctr_cb.set_csa_support_cmpl_cb = p_callback; + return TRUE; +} + +BOOLEAN BTM_BleSetVendorEventMask(UINT32 evt_mask, tBTM_SET_VENDOR_EVT_MASK_CBACK *p_callback) +{ + if (btsnd_hcic_ble_set_vendor_evt_mask(evt_mask) != TRUE) { + BTM_TRACE_ERROR("LE SetVendorEventMask evt_mask=%x: error", evt_mask); + return FALSE; + } + + btm_cb.ble_ctr_cb.set_vendor_evt_mask_cmpl_cb = p_callback; + return TRUE; +} +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) + BOOLEAN BTM_BleSetRpaTimeout(uint16_t rpa_timeout,tBTM_SET_RPA_TIMEOUT_CMPL_CBACK *p_set_rpa_timeout_cback) { if ((btsnd_hcic_ble_set_rand_priv_addr_timeout(rpa_timeout)) != TRUE) { @@ -4752,6 +4842,7 @@ BOOLEAN BTM_BleSetPrivacyMode(UINT8 addr_type, BD_ADDR bd_addr, UINT8 privacy_mo return TRUE; } +#if (BLE_42_SCAN_EN == TRUE) bool btm_ble_adv_pkt_ready(void) { tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb; @@ -4770,4 +4861,6 @@ bool btm_ble_adv_pkt_post(pkt_linked_item_t *pkt) pkt_queue_enqueue(p_cb->adv_rpt_queue, pkt); return true; } +#endif // #if (BLE_42_SCAN_EN == TRUE) + #endif /* BLE_INCLUDED */ diff --git a/lib/bt/host/bluedroid/stack/btm/btm_ble_iso.c b/lib/bt/host/bluedroid/stack/btm/btm_ble_iso.c new file mode 100644 index 00000000..c66f10b9 --- /dev/null +++ b/lib/bt/host/bluedroid/stack/btm/btm_ble_iso.c @@ -0,0 +1,525 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "btm_int.h" +#include "stack/hcimsgs.h" +#include "osi/allocator.h" +#include "device/controller.h" +#include +#include "l2c_int.h" + +tBTM_BLE_ISO_CBACK ble_iso_cb; + +extern void btm_ble_inter_set(bool extble_inter); + +void BTM_BleIsoRegisterCallback(tBTM_BLE_ISO_CBACK cb) +{ + if (cb) { + ble_iso_cb = cb; + } else { + BTM_TRACE_ERROR("%s, register fail, the cb function is NULL.", __func__); + } +} + +void BTM_IsoBleCallbackTrigger(tBTM_BLE_5_GAP_EVENT event, tBTM_BLE_ISO_CB_PARAMS *params) +{ + if(params && params->status == BTM_SUCCESS) { + btm_ble_inter_set(true); + } + if (ble_iso_cb) { + ble_iso_cb(event, params); + } +} + +void btm_ble_iso_read_iso_tx_sync_complete(UINT8 *p) +{ + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + STREAM_TO_UINT8(cb_params.btm_read_tx_sync.status, p); + STREAM_TO_UINT16(cb_params.btm_read_tx_sync.conn_hdl, p); + STREAM_TO_UINT16(cb_params.btm_read_tx_sync.pkt_seq_num, p); + STREAM_TO_UINT32(cb_params.btm_read_tx_sync.tx_time_stamp, p); + STREAM_TO_UINT24(cb_params.btm_read_tx_sync.time_offset, p); + + if (cb_params.btm_read_tx_sync.status != HCI_SUCCESS) { + cb_params.btm_read_tx_sync.status = (BTM_HCI_ERROR | cb_params.btm_read_tx_sync.status); + } + cb_params.btm_read_tx_sync.conn_hdl = (cb_params.btm_read_tx_sync.conn_hdl & 0xEFF); + cb_params.btm_read_tx_sync.time_offset = (cb_params.btm_read_tx_sync.time_offset & 0xFFFFFF); + BTM_TRACE_DEBUG("read tx sync cmpl, status 0x%x conn_hdl 0x%x pkt_seq_num %d tx_time_stamp %ld time_offset %ld\n", + cb_params.btm_read_tx_sync.status, cb_params.btm_read_tx_sync.conn_hdl, cb_params.btm_read_tx_sync.pkt_seq_num, + cb_params.btm_read_tx_sync.tx_time_stamp, cb_params.btm_read_tx_sync.time_offset); + + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_READ_TX_SYNC_EVT, &cb_params); +} + +void btm_ble_iso_read_iso_link_quality_complete(UINT8 *p) +{ + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + STREAM_TO_UINT8(cb_params.btm_read_link_quality.status, p); + STREAM_TO_UINT16(cb_params.btm_read_link_quality.conn_hdl, p); + STREAM_TO_UINT32(cb_params.btm_read_link_quality.tx_unacked_pkts, p); + STREAM_TO_UINT32(cb_params.btm_read_link_quality.tx_flushed_pkts, p); + STREAM_TO_UINT32(cb_params.btm_read_link_quality.tx_last_subevt_pkts, p); + STREAM_TO_UINT32(cb_params.btm_read_link_quality.retransmitted_pkts, p); + STREAM_TO_UINT32(cb_params.btm_read_link_quality.crc_error_pkts, p); + STREAM_TO_UINT32(cb_params.btm_read_link_quality.rx_unreceived_pkts, p); + STREAM_TO_UINT32(cb_params.btm_read_link_quality.duplicate_pkts, p); + + if (cb_params.btm_read_link_quality.status != HCI_SUCCESS) { + cb_params.btm_read_link_quality.status = (BTM_HCI_ERROR | cb_params.btm_read_link_quality.status); + } + + BTM_TRACE_DEBUG("read link quality cmpl, status 0x%x conn_hdl 0x%x tx_unacked_pkts %d tx_flushed_pkts %ld tx_last_subevt_pkts %ld retransmitted_pkts %d\ + crc_error_pkts %d rx_unreceived_pkts %d duplicate_pkts %d\n", + cb_params.btm_read_link_quality.status, cb_params.btm_read_link_quality.conn_hdl, cb_params.btm_read_link_quality.tx_unacked_pkts, + cb_params.btm_read_link_quality.tx_flushed_pkts, cb_params.btm_read_link_quality.tx_last_subevt_pkts, cb_params.btm_read_link_quality.retransmitted_pkts, + cb_params.btm_read_link_quality.crc_error_pkts, cb_params.btm_read_link_quality.rx_unreceived_pkts, cb_params.btm_read_link_quality.duplicate_pkts); + + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_READ_LINK_QUALITY_EVT, &cb_params); +} + +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +void btm_ble_iso_set_cig_params_complete(UINT8 *p) +{ + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + + STREAM_TO_UINT8(cb_params.btm_set_cig_params.status, p); + STREAM_TO_UINT8(cb_params.btm_set_cig_params.cig_id, p); + STREAM_TO_UINT8(cb_params.btm_set_cig_params.cis_count, p); + for (uint8_t i = 0; i < cb_params.btm_set_cig_params.cis_count; i++) + { + STREAM_TO_UINT16(cb_params.btm_set_cig_params.conn_hdl[i], p); + BTM_TRACE_DEBUG("i = %d, conn_hdl = %d", i, cb_params.btm_set_cig_params.conn_hdl[i]); + } + + if (cb_params.btm_set_cig_params.status != HCI_SUCCESS) { + cb_params.btm_set_cig_params.status = (BTM_HCI_ERROR | cb_params.btm_set_cig_params.status); + } + + BTM_TRACE_DEBUG("set cig params, status 0x%x cig_id %d cis_count %d\n", + cb_params.btm_set_cig_params.status, cb_params.btm_set_cig_params.cig_id, cb_params.btm_set_cig_params.cis_count); + + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_SET_CIG_PARAMS_EVT, &cb_params); +} +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_EN == TRUE) +void btm_ble_cis_disconnected_evt(tBTM_BLE_CIS_DISCON_CMPL *params) +{ + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + if (!params) { + BTM_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + cb_params.btm_cis_disconnectd_evt.cis_handle = params->cis_handle; + cb_params.btm_cis_disconnectd_evt.reason = params->reason; + + BTM_TRACE_DEBUG("btm cis disconnect, cis_handle %d reason 0x%x\n", params->cis_handle, params->reason); + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_CIS_DISCONNECTED_EVT, &cb_params); +} + +void btm_ble_cis_established_evt(tBTM_BLE_CIS_ESTABLISHED_CMPL *params) +{ + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + if (!params) { + BTM_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + if (params->status != HCI_SUCCESS) { + params->status = (params->status | BTM_HCI_ERROR); + } + + memcpy(&cb_params.btm_cis_established_evt, params, sizeof(tBTM_BLE_CIS_ESTABLISHED_CMPL)); + + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_CIS_ESTABLISHED_EVT, &cb_params); +} +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +void btm_ble_cis_request_evt(tBTM_BLE_CIS_REQUEST_CMPL *params) +{ + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + if (!params) { + BTM_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + memcpy(&cb_params.btm_cis_request_evt, params, sizeof(tBTM_BLE_CIS_REQUEST_CMPL)); + + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_CIS_REQUEST_EVT, &cb_params); +} +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +void btm_ble_big_create_cmpl_evt(tBTM_BLE_BIG_CREATE_CMPL *params) +{ + BTM_TRACE_DEBUG("%s", __func__); + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + if (!params) { + BTM_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + if (params->status != HCI_SUCCESS) { + params->status = (params->status | BTM_HCI_ERROR); + } + + cb_params.btm_big_cmpl.status = params->status; + cb_params.btm_big_cmpl.big_handle = params->big_handle; + cb_params.btm_big_cmpl.big_sync_delay = params->big_sync_delay; + cb_params.btm_big_cmpl.transport_latency = params->transport_latency; + cb_params.btm_big_cmpl.phy = params->phy; + cb_params.btm_big_cmpl.nse = params->nse; + cb_params.btm_big_cmpl.bn = params->bn; + cb_params.btm_big_cmpl.pto = params->pto; + cb_params.btm_big_cmpl.irc = params->irc; + cb_params.btm_big_cmpl.max_pdu = params->max_pdu; + cb_params.btm_big_cmpl.iso_interval = params->iso_interval; + cb_params.btm_big_cmpl.num_bis = params->num_bis; + // for (uint8_t i = 0; i < params->num_bis; i++) + // { + // cb_params.btm_big_cmpl.bis_handle[i] = params->bis_handle[i]; + // } + memcpy(&cb_params.btm_big_cmpl.bis_handle[0], ¶ms->bis_handle[0], params->num_bis * 2); + + //memcpy(&cb_params.btm_big_cmpl, params, sizeof(tBTM_BLE_BIG_CREATE_CMPL)); + + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_BIG_CREATE_COMPLETE_EVT, &cb_params); +} + +void btm_ble_big_terminate_cmpl_evt(tBTM_BLE_BIG_TERMINATE_CMPL *params) +{ + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + if (!params) { + BTM_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + memcpy(&cb_params.btm_big_term, params, sizeof(tBTM_BLE_BIG_TERMINATE_CMPL)); + + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_BIG_TERMINATE_COMPLETE_EVT, &cb_params); +} +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +void btm_ble_big_sync_estab_evt(tBTM_BLE_BIG_SYNC_ESTAB_CMPL *params) +{ + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + if (!params) { + BTM_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + if (params->status != HCI_SUCCESS) { + params->status = (params->status | BTM_HCI_ERROR); + } + + memcpy(&cb_params.btm_big_sync_estab, params, sizeof(tBTM_BLE_BIG_SYNC_ESTAB_CMPL)); + + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_BIG_SYNC_ESTABLISHED_EVT, &cb_params); +} + +void btm_ble_big_sync_terminate_complete(UINT8 hci_status, UINT8 big_handle) +{ + BTM_TRACE_DEBUG("%s hci_status 0x%x big_handle %d\n", __func__, hci_status, big_handle); + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + + if (hci_status != HCI_SUCCESS) { + hci_status = (hci_status | BTM_HCI_ERROR); + } + + cb_params.status = hci_status; + cb_params.btm_big_sync_ter.big_hdl = big_handle; + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_BIG_SYNC_TERMINATE_COMPLETE_EVT, &cb_params); +} + +void btm_ble_big_sync_lost_evt(tBTM_BLE_BIG_SYNC_LOST_EVT *params) +{ + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + if (!params) { + BTM_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + memcpy(&cb_params.btm_big_sync_lost, params, sizeof(tBTM_BLE_BIG_SYNC_LOST_EVT)); + + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_BIG_SYNC_LOST_EVT, &cb_params); +} + +void btm_ble_biginfo_adv_report_evt(tBTM_BLE_BIGINFO_ADV_REPORT_EVT *params) +{ + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + if (!params) { + BTM_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + memcpy(&cb_params.btm_biginfo_report, params, sizeof(tBTM_BLE_BIGINFO_ADV_REPORT_EVT)); + + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_BIGINFO_ADV_REPORT_EVT, &cb_params); +} +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + +void btm_ble_iso_data_path_update_complete(UINT16 opcode, UINT8 hci_status, UINT16 conn_handle) +{ + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + BTM_TRACE_DEBUG("data path update cmpl, opcode 0x%x status 0x%x conn_hdl %d\n", opcode, hci_status, conn_handle); + if (hci_status != HCI_SUCCESS) { + hci_status = (BTM_HCI_ERROR | hci_status); + } + cb_params.status = hci_status; + cb_params.btm_data_path_update.op_type = ((opcode == HCI_BLE_ISO_SET_DATA_PATH) ? BTM_BLE_ISO_DATA_PATH_SETUP : BTM_BLE_ISO_DATA_PATH_REMOVE); + cb_params.btm_data_path_update.conn_hdl = conn_handle; + + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_DATA_PATH_UPFATE_EVT, &cb_params); +} + +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +tBTM_STATUS BTM_BleBigCreate(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, + uint32_t sdu_interval, uint16_t max_sdu, uint16_t max_transport_latency, + uint8_t rtn, uint8_t phy, uint8_t packing, uint8_t framing, + uint8_t encryption, uint8_t *broadcast_code) +{ + BTM_TRACE_API("big_handle %d adv_handle %d num_bis %d sdu_interval %d max_sdu %d max_transport_latency %d \ + rtn %d phy %d packing %d framing %d encryption %d broadcast_code %d", big_handle, adv_handle, num_bis, sdu_interval, max_sdu, max_transport_latency,\ + rtn, phy, packing, framing, encryption, broadcast_code); + + btsnd_hcic_ble_big_create(big_handle, adv_handle, num_bis, sdu_interval, max_sdu, max_transport_latency, + rtn, phy, packing, framing, encryption, broadcast_code); + + + return BTM_SUCCESS; +} + +tBTM_STATUS BTM_BleBigCreateTest(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, + uint32_t sdu_interval, uint16_t iso_interval, uint8_t nse, + uint16_t max_sdu, uint16_t max_pdu, uint8_t phy, + uint8_t packing, uint8_t framing, uint8_t bn, uint8_t irc, + uint8_t pto, uint8_t encryption, uint8_t *broadcast_code) +{ + btsnd_hcic_ble_big_create_test(big_handle, adv_handle, num_bis, sdu_interval, iso_interval, nse, + max_sdu, max_pdu, phy, packing, framing, bn, irc, pto, encryption, + broadcast_code); + return BTM_SUCCESS; +} + +tBTM_STATUS BTM_BleBigTerminate(UINT8 big_handle, UINT8 reason) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_big_terminate(big_handle, reason)) != TRUE) { + BTM_TRACE_ERROR("LE PA SyncCancel, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + if (status != BTM_SUCCESS) { + cb_params.status = status; + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_BIG_TERMINATE_COMPLETE_EVT, &cb_params); + } + + return status; +} +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +tBTM_STATUS BTM_BleBigSyncCreate(uint8_t big_handle, uint16_t sync_handle, + uint8_t encryption, uint8_t *bc_code, + uint8_t mse, uint16_t big_sync_timeout, + uint8_t num_bis, uint8_t *bis) +{ + btsnd_hcic_ble_big_sync_create(big_handle, sync_handle, encryption, bc_code, + mse, big_sync_timeout, num_bis, bis); + return BTM_SUCCESS; +} + +tBTM_STATUS BTM_BleBigSyncTerminate(uint8_t big_handle) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + + if ((err = btsnd_hcic_ble_big_sync_terminate(big_handle)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("LE big sync terminate, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + return status; +} +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + +tBTM_STATUS BTM_BleIsoSetDataPath(uint16_t conn_handle, uint8_t data_path_dir, uint8_t data_path_id, uint8_t coding_fmt, + uint16_t company_id, uint16_t vs_codec_id, uint32_t controller_delay, uint8_t codec_len, + uint8_t *codec_cfg) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + + if (codec_len && (codec_cfg == NULL)) { + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + status = BTM_ILLEGAL_VALUE; + cb_params.btm_data_path_update.op_type = BTM_BLE_ISO_DATA_PATH_SETUP; + cb_params.status = status; + cb_params.btm_data_path_update.conn_hdl = conn_handle; + BTM_TRACE_ERROR("codec_cfg is NULL, set data path error"); + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_DATA_PATH_UPFATE_EVT, &cb_params); + return status; + } + + BTM_TRACE_DEBUG("BTM_BleIsoSetDataPath conn_handle %d data_path_dir %d\n", conn_handle, data_path_dir); + + if ((err = btsnd_hcic_ble_iso_set_data_path(conn_handle, data_path_dir, data_path_id, coding_fmt, company_id, vs_codec_id, + controller_delay, codec_len, codec_cfg)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("iso data path update, cmd err=0x%x", err); + return BTM_HCI_ERROR | err; + } + + return status; +} + +tBTM_STATUS BTM_BleIsoRemoveDataPath(uint16_t conn_handle, uint8_t data_path_dir) +{ + tHCI_STATUS err = HCI_SUCCESS; + + BTM_TRACE_DEBUG("BTM_BleIsoRemoveDataPath conn_handle %d data_path_dir %d\n", conn_handle, data_path_dir); + + if ((err = btsnd_hcic_ble_iso_remove_data_path(conn_handle, data_path_dir)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("iso data path remove, cmd err=0x%x", err); + return BTM_HCI_ERROR | err; + } + + return BTM_SUCCESS; +} + +tBTM_STATUS BTM_BleIsoReadTxSync(uint16_t iso_hdl) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + + BTM_TRACE_DEBUG("BTM_BleIsoReadTxSync iso_hdl %d\n", iso_hdl); + + if ((err = btsnd_hcic_ble_iso_read_tx_sync(iso_hdl)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("iso read tx sync, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + return status; +} + +tBTM_STATUS BTM_BleIsoReadLinkQuality(uint16_t iso_hdl) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + + BTM_TRACE_DEBUG("BTM_BleIsoReadLinkQuality iso_hdl %d\n", iso_hdl); + + if ((err = btsnd_hcic_ble_iso_read_iso_link_quality(iso_hdl)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("iso read link quality, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + return status; +} + +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +tBTM_STATUS BTM_BleSetCigParams(uint8_t cig_id, uint32_t sdu_int_c_to_p, uint32_t sdu_int_p_to_c, uint8_t worse_case_SCA, uint8_t packing, + uint8_t framing, uint16_t mtl_c_to_p, uint16_t mtl_p_to_c, uint8_t cis_cnt, uint8_t *cis_params) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + + if ((err = btsnd_hcic_ble_iso_set_cig_params(cig_id, sdu_int_c_to_p, sdu_int_p_to_c, worse_case_SCA, packing, + framing, mtl_c_to_p, mtl_p_to_c, cis_cnt, (struct ble_hci_le_cis_params *)cis_params)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("iso set cig params, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + return status; +} + +tBTM_STATUS BTM_BleSetCigParamsTest(uint8_t cig_id, uint32_t sdu_int_c_to_p, uint32_t sdu_int_p_to_c, uint8_t ft_c_to_p, uint8_t ft_p_to_c, uint16_t iso_interval, + uint8_t worse_case_SCA, uint8_t packing, uint8_t framing, uint8_t cis_cnt, uint8_t *cis_params) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + + if ((err = btsnd_hcic_ble_iso_set_cig_params_test(cig_id, sdu_int_c_to_p, sdu_int_p_to_c,ft_c_to_p, ft_p_to_c, iso_interval, + worse_case_SCA, packing, framing, cis_cnt, (struct ble_hci_le_cis_params_test *)cis_params)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("iso set cig params test, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + return status; +} + +void btm_ble_create_cis_cmd_status(tBTM_BLE_ISO_CB_PARAMS *cb_params) +{ + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_CREATE_CIS_EVT, cb_params); +} + +tBTM_STATUS BTM_BleCreateCis(uint8_t cis_count, uint8_t *cis_hdls) +{ + btsnd_hcic_ble_iso_create_cis(cis_count, (struct ble_hci_cis_hdls *)cis_hdls); + + return BTM_SUCCESS; +} + +tBTM_STATUS BTM_BleRemoveCig(uint8_t cig_id) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_iso_remove_cig(cig_id)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("iso remove cig, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.btm_remove_cig.status = status; + cb_params.btm_remove_cig.cig_id = cig_id; + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_REMOVE_CIG_EVT, &cb_params); + + return status; +} +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +void btm_ble_accept_cis_req_cmd_status(tBTM_BLE_ISO_CB_PARAMS *cb_params) +{ + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_ACCEPT_CIS_REQ_EVT, cb_params); +} + +tBTM_STATUS BTM_BleAcceptCisReq(uint16_t cis_handle) +{ + btsnd_hcic_ble_iso_accept_cis_req(cis_handle); + return BTM_SUCCESS; +} + +tBTM_STATUS BTM_BleRejectCisReq(uint16_t cis_handle, uint8_t reason) +{ + tHCI_STATUS err = HCI_SUCCESS; + tBTM_STATUS status = BTM_SUCCESS; + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + + if ((err = btsnd_hcic_ble_iso_reject_cis_req(cis_handle, reason)) != HCI_SUCCESS) { + BTM_TRACE_ERROR("iso reject cis req, cmd err=0x%x", err); + status = BTM_HCI_ERROR | err; + } + + cb_params.btm_reject_cis_req.status = status; + cb_params.btm_reject_cis_req.cis_handle = cis_handle; + BTM_IsoBleCallbackTrigger(BTM_BLE_ISO_REJECT_CIS_REQ_EVT, &cb_params); + return status; +} +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_EN == TRUE) +tBTM_STATUS BTM_BleDisconCis(uint16_t cis_handle, uint8_t reason) +{ + btsnd_hcic_disconnect(cis_handle, reason); + + return BTM_SUCCESS; +} +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) diff --git a/lib/bt/host/bluedroid/stack/btm/btm_ble_multi_adv.c b/lib/bt/host/bluedroid/stack/btm/btm_ble_multi_adv.c index bc300b02..31d60546 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_ble_multi_adv.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_ble_multi_adv.c @@ -22,6 +22,8 @@ #include "device/controller.h" #if (BLE_INCLUDED == TRUE) + +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) #include "stack/bt_types.h" #include "stack/hcimsgs.h" #include "stack/btu.h" @@ -218,25 +220,7 @@ tBTM_STATUS btm_ble_enable_multi_adv (BOOLEAN enable, UINT8 inst_id, UINT8 cb_ev } return rt; } -/******************************************************************************* -** -** Function btm_ble_map_adv_tx_power -** -** Description return the actual power in dBm based on the mapping in config file -** -** Parameters advertise parameters used for this instance. -** -** Returns tx power in dBm -** -*******************************************************************************/ -static const int btm_ble_tx_power[BTM_BLE_ADV_TX_POWER_MAX + 1] = BTM_BLE_ADV_TX_POWER; -char btm_ble_map_adv_tx_power(int tx_power_index) -{ - if (0 <= tx_power_index && tx_power_index <= BTM_BLE_ADV_TX_POWER_MAX) { - return (char)btm_ble_tx_power[tx_power_index]; - } - return 0; -} + /******************************************************************************* ** ** Function btm_ble_multi_adv_set_params @@ -882,4 +866,5 @@ void *btm_ble_multi_adv_get_ref(UINT8 inst_id) return NULL; } +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) #endif diff --git a/lib/bt/host/bluedroid/stack/btm/btm_ble_privacy.c b/lib/bt/host/bluedroid/stack/btm/btm_ble_privacy.c index be4b9d15..28e06658 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_ble_privacy.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_ble_privacy.c @@ -330,7 +330,7 @@ void btm_ble_remove_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len) BTM_TRACE_DEBUG("%s status = %d", __func__, status); if (!btm_ble_deq_resolving_pending(pseudo_bda)) { - BTM_TRACE_ERROR("%s no pending resolving list operation", __func__); + BTM_TRACE_DEBUG("%s no pending resolving list operation", __func__); return; } @@ -683,20 +683,22 @@ BOOLEAN btm_ble_suspend_resolving_list_activity(void) p_ble_cb->suspended_rl_state = BTM_BLE_RL_IDLE; +#if (BLE_42_ADV_EN == TRUE) if (p_ble_cb->inq_var.adv_mode == BTM_BLE_ADV_ENABLE) { btm_ble_stop_adv(); p_ble_cb->suspended_rl_state |= BTM_BLE_RL_ADV; } +#endif // #if (BLE_42_ADV_EN == TRUE) if (BTM_BLE_IS_SCAN_ACTIVE(p_ble_cb->scan_activity)) { btm_ble_stop_scan(); p_ble_cb->suspended_rl_state |= BTM_BLE_RL_SCAN; } - +#if (tGATT_BG_CONN_DEV == TRUE) if (btm_ble_suspend_bg_conn()) { p_ble_cb->suspended_rl_state |= BTM_BLE_RL_INIT; } - +#endif // #if (tGATT_BG_CONN_DEV == TRUE) return TRUE; } @@ -714,19 +716,21 @@ BOOLEAN btm_ble_suspend_resolving_list_activity(void) void btm_ble_resume_resolving_list_activity(void) { tBTM_BLE_CB *p_ble_cb = &btm_cb.ble_ctr_cb; - +#if (BLE_42_ADV_EN == TRUE) if (p_ble_cb->suspended_rl_state & BTM_BLE_RL_ADV) { btm_ble_start_adv(); } - +#endif // #if (BLE_42_ADV_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) if (p_ble_cb->suspended_rl_state & BTM_BLE_RL_SCAN) { btm_ble_start_scan(); } - +#endif // #if (BLE_42_SCAN_EN == TRUE) +#if (tGATT_BG_CONN_DEV == TRUE) if (p_ble_cb->suspended_rl_state & BTM_BLE_RL_INIT) { btm_ble_resume_bg_conn(); } - +#endif // #if (tGATT_BG_CONN_DEV == TRUE) p_ble_cb->suspended_rl_state = BTM_BLE_RL_IDLE; } @@ -1147,6 +1151,9 @@ void btm_ble_add_default_entry_to_resolving_list(void) BD_ADDR peer_addr = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; BT_OCTET16 peer_irk = {0x0}; + // Remove the existing entry in resolving list When resetting the device identity + btsnd_hcic_ble_rm_device_resolving_list(BLE_ADDR_PUBLIC, peer_addr); + btsnd_hcic_ble_add_device_resolving_list (BLE_ADDR_PUBLIC, peer_addr, peer_irk, btm_cb.devcb.id_keys.irk); } #endif diff --git a/lib/bt/host/bluedroid/stack/btm/btm_dev.c b/lib/bt/host/bluedroid/stack/btm/btm_dev.c index f9e3ed2b..f705a8dc 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_dev.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_dev.c @@ -179,20 +179,33 @@ BOOLEAN BTM_SecAddDevice (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, *******************************************************************************/ BOOLEAN BTM_SecDeleteDevice (BD_ADDR bd_addr, tBT_TRANSPORT transport) { - tBTM_SEC_DEV_REC *p_dev_rec; if (BTM_IsAclConnectionUp(bd_addr, transport)) { BTM_TRACE_WARNING("%s FAILED: Cannot Delete when connection is active\n", __func__); return FALSE; } + if ((p_dev_rec = btm_find_dev(bd_addr)) != NULL) { +#if (CLASSIC_BT_INCLUDED == TRUE) /* Tell controller to get rid of the link key, if it has one stored */ BTM_DeleteStoredLinkKey (p_dev_rec->bd_addr, NULL); +#endif // (CLASSIC_BT_INCLUDED == TRUE) - btm_sec_free_dev(p_dev_rec, transport); + btm_sec_free_dev(p_dev_rec, transport); } +#if (BLE_SMP_ID_RESET_ENABLE == TRUE) + /* + * There are tracking risks associated with using a fixed or static IRK. + * A best-practices approach, when all pairing and bonding records are deleted, + * assign a new randomly-generated IRK. + */ + if (list_is_empty(btm_cb.p_sec_dev_rec_list)) { + btm_ble_reset_id(); + } +#endif + return TRUE; } @@ -640,7 +653,7 @@ tBTM_SEC_DEV_REC *btm_find_oldest_dev (void) tBTM_SEC_DEV_REC *p_dev_rec = NULL; tBTM_SEC_DEV_REC *p_oldest = NULL; list_node_t *p_node = NULL; - UINT32 ot = 0xFFFFFFFF; + UINT32 old_ts = 0xFFFFFFFF; /* First look for the non-paired devices for the oldest entry */ for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) { @@ -650,13 +663,13 @@ tBTM_SEC_DEV_REC *btm_find_oldest_dev (void) continue; /* Device is paired so skip it */ } - if (p_dev_rec->timestamp < ot) { + if (p_dev_rec->timestamp < old_ts) { p_oldest = p_dev_rec; - ot = p_dev_rec->timestamp; + old_ts = p_dev_rec->timestamp; } } - if (ot != 0xFFFFFFFF) { + if (old_ts != 0xFFFFFFFF) { return (p_oldest); } @@ -666,9 +679,9 @@ tBTM_SEC_DEV_REC *btm_find_oldest_dev (void) continue; } - if (p_dev_rec->timestamp < ot) { + if (p_dev_rec->timestamp < old_ts) { p_oldest = p_dev_rec; - ot = p_dev_rec->timestamp; + old_ts = p_dev_rec->timestamp; } } return (p_oldest); diff --git a/lib/bt/host/bluedroid/stack/btm/btm_devctl.c b/lib/bt/host/bluedroid/stack/btm/btm_devctl.c index bab88739..2250c78b 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_devctl.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_devctl.c @@ -82,7 +82,9 @@ void btm_dev_init (void) /* Initialize nonzero defaults */ #if (BTM_MAX_LOC_BD_NAME_LEN > 0) memset(btm_cb.cfg.ble_bd_name, 0, sizeof(tBTM_LOC_BD_NAME)); +#if (CLASSIC_BT_INCLUDED == TRUE) memset(btm_cb.cfg.bredr_bd_name, 0, sizeof(tBTM_LOC_BD_NAME)); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #endif btm_cb.devcb.reset_timer.param = (TIMER_PARAM_TYPE)TT_DEV_RESET; @@ -169,8 +171,12 @@ static void reset_complete(void) btm_cb.ble_ctr_cb.conn_state = BLE_CONN_IDLE; btm_cb.ble_ctr_cb.bg_conn_type = BTM_BLE_CONN_NONE; btm_cb.ble_ctr_cb.p_select_cback = NULL; +#if (tGATT_BG_CONN_DEV == TRUE) gatt_reset_bgdev_list(); +#endif // #if (tGATT_BG_CONN_DEV == TRUE) +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) btm_ble_multi_adv_init(); +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) #endif btm_pm_reset(); @@ -193,6 +199,9 @@ static void reset_complete(void) if (controller->supports_ble()) { btm_ble_white_list_init(controller->get_ble_white_list_size()); + #if (BLE_50_EXTEND_SYNC_EN == TRUE) + btm_ble_periodic_adv_list_init(controller->get_ble_periodic_adv_list_size()); + #endif //#if (BLE_50_EXTEND_SYNC_EN == TRUE) l2c_link_processs_ble_num_bufs(controller->get_acl_buffer_count_ble()); } #endif @@ -471,7 +480,7 @@ tBTM_STATUS BTM_SetLocalDeviceName (char *p_name, tBT_DEVICE_TYPE name_type) btm_cb.cfg.ble_bd_name[BTM_MAX_LOC_BD_NAME_LEN] = '\0'; } } - +#if (CLASSIC_BT_INCLUDED == TRUE) if (name_type & BT_DEVICE_TYPE_BREDR) { p = (UINT8 *)btm_cb.cfg.bredr_bd_name; if (p != (UINT8 *)p_name) { @@ -479,6 +488,7 @@ tBTM_STATUS BTM_SetLocalDeviceName (char *p_name, tBT_DEVICE_TYPE name_type) btm_cb.cfg.bredr_bd_name[BTM_MAX_LOC_BD_NAME_LEN] = '\0'; } } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #else p = (UINT8 *)p_name; #endif @@ -519,21 +529,22 @@ tBTM_STATUS BTM_ReadLocalDeviceName (char **p_name, tBT_DEVICE_TYPE name_type) */ #if BTM_MAX_LOC_BD_NAME_LEN > 0 +#if (CLASSIC_BT_INCLUDED == TRUE) if ((name_type == BT_DEVICE_TYPE_DUMO) && (BCM_STRNCMP_S(btm_cb.cfg.bredr_bd_name, btm_cb.cfg.ble_bd_name, BTM_MAX_LOC_BD_NAME_LEN) != 0)) { *p_name = NULL; BTM_TRACE_ERROR("Error, BLE and BREDR have different names, return NULL\n"); return (BTM_NO_RESOURCES); } - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) if (name_type & BT_DEVICE_TYPE_BLE) { *p_name = btm_cb.cfg.ble_bd_name; } - +#if (CLASSIC_BT_INCLUDED == TRUE) if (name_type & BT_DEVICE_TYPE_BREDR) { *p_name = btm_cb.cfg.bredr_bd_name; } - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) return (BTM_SUCCESS); #else *p_name = NULL; @@ -752,9 +763,6 @@ void btm_vsc_complete (UINT8 *p, UINT16 opcode, UINT16 evt_len, #if (BLE_INCLUDED == TRUE) tBTM_BLE_CB *ble_cb = &btm_cb.ble_ctr_cb; switch(opcode) { - case HCI_VENDOR_BLE_LONG_ADV_DATA: - BTM_TRACE_EVENT("Set long adv data complete\n"); - break; case HCI_VENDOR_BLE_UPDATE_DUPLICATE_EXCEPTIONAL_LIST: { uint8_t subcode, status; uint32_t length; STREAM_TO_UINT8(status, p); @@ -773,6 +781,22 @@ void btm_vsc_complete (UINT8 *p, UINT16 opcode, UINT16 evt_len, } break; } + case HCI_VENDOR_BLE_SET_CSA_SUPPORT: { + uint8_t status; + STREAM_TO_UINT8(status, p); + if (ble_cb && ble_cb->set_csa_support_cmpl_cb) { + ble_cb->set_csa_support_cmpl_cb(status); + } + break; + } + case HCI_VENDOR_BLE_SET_EVT_MASK: { + uint8_t status; + STREAM_TO_UINT8(status, p); + if (ble_cb && ble_cb->set_vendor_evt_mask_cmpl_cb) { + ble_cb->set_vendor_evt_mask_cmpl_cb(status); + } + break; + } default: break; } @@ -863,7 +887,7 @@ void btm_vendor_specific_evt (UINT8 *p, UINT8 evt_len) STREAM_TO_UINT8(sub_event, p_evt); /* Check in subevent if authentication is through Legacy Authentication. */ - if (sub_event == ESP_VS_REM_LEGACY_AUTH_CMP) { + if (sub_event == HCI_VENDOR_LEGACY_REM_AUTH_EVT_SUBCODE) { UINT16 hci_handle; STREAM_TO_UINT16(hci_handle, p_evt); btm_sec_handle_remote_legacy_auth_cmp(hci_handle); @@ -1066,6 +1090,7 @@ tBTM_STATUS BTM_WriteVoiceSettings(UINT16 settings) return (BTM_NO_RESOURCES); } +#if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) /******************************************************************************* ** ** Function BTM_EnableTestMode @@ -1122,7 +1147,9 @@ tBTM_STATUS BTM_EnableTestMode(void) return (BTM_NO_RESOURCES); } } +#endif // #if (BLE_HOST_ENABLE_TEST_MODE_EN == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function BTM_DeleteStoredLinkKey @@ -1197,6 +1224,7 @@ void btm_delete_stored_link_key_complete (UINT8 *p) } } +#endif // (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btm_report_device_status diff --git a/lib/bt/host/bluedroid/stack/btm/btm_inq.c b/lib/bt/host/bluedroid/stack/btm/btm_inq.c index b8da2327..528c7a06 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_inq.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_inq.c @@ -163,7 +163,7 @@ tBTM_STATUS BTM_SetDiscoverability (UINT16 inq_mode, UINT16 window, UINT16 inter UINT8 scan_mode = 0; UINT16 service_class; UINT8 *p_cod; - UINT8 major, minor; + UINT8 major, minor, reserved_2; DEV_CLASS cod; LAP temp_lap[2]; BOOLEAN is_limited; @@ -255,13 +255,14 @@ tBTM_STATUS BTM_SetDiscoverability (UINT16 inq_mode, UINT16 window, UINT16 inter if (is_limited ^ cod_limited) { BTM_COD_MINOR_CLASS(minor, p_cod ); BTM_COD_MAJOR_CLASS(major, p_cod ); + BTM_COD_RESERVED_2(reserved_2, p_cod); if (is_limited) { service_class |= BTM_COD_SERVICE_LMTD_DISCOVER; } else { service_class &= ~BTM_COD_SERVICE_LMTD_DISCOVER; } - FIELDS_TO_COD(cod, minor, major, service_class); + FIELDS_TO_COD(cod, reserved_2, minor, major, service_class); (void) BTM_SetDeviceClass (cod); } @@ -515,7 +516,7 @@ tBTM_STATUS BTM_SetPeriodicInquiryMode (tBTM_INQ_PARMS *p_inqparms, UINT16 max_d /* Before beginning the inquiry the current filter must be cleared, so initiate the command */ if ((status = btm_set_inq_event_filter (p_inqparms->filter_cond_type, &p_inqparms->filter_cond)) != BTM_CMD_STARTED) { - /* If set filter command is not succesful reset the state */ + /* If set filter command is not successful reset the state */ p_inq->p_inq_results_cb = NULL; p_inq->state = BTM_INQ_INACTIVE_STATE; @@ -688,7 +689,7 @@ UINT16 BTM_ReadConnectability (UINT16 *p_window, UINT16 *p_interval) ** Description This function returns a bit mask of the current inquiry state ** ** Returns BTM_INQUIRY_INACTIVE if inactive (0) -** BTM_LIMITED_INQUIRY_ACTIVE if a limted inquiry is active +** BTM_LIMITED_INQUIRY_ACTIVE if a limited inquiry is active ** BTM_GENERAL_INQUIRY_ACTIVE if a general inquiry is active ** BTM_PERIODIC_INQUIRY_ACTIVE if a periodic inquiry is active ** @@ -783,7 +784,7 @@ tBTM_STATUS BTM_CancelInquiry(void) ** Description This function is called to start an inquiry. ** ** Parameters: p_inqparms - pointer to the inquiry information -** mode - GENERAL or LIMITED inquiry, BR/LE bit mask seperately +** mode - GENERAL or LIMITED inquiry, BR/LE bit mask separately ** duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED) ** max_resps - maximum amount of devices to search for before ending the inquiry ** filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or @@ -1858,7 +1859,7 @@ void btm_process_inq_results (UINT8 *p, UINT8 inq_res_mode) #if BLE_INCLUDED == TRUE /* new device response */ && ( p_i == NULL || - /* exisiting device with BR/EDR info */ + /* existing device with BR/EDR info */ (p_i && (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BREDR) != 0) ) #endif diff --git a/lib/bt/host/bluedroid/stack/btm/btm_main.c b/lib/bt/host/bluedroid/stack/btm/btm_main.c index 8e49aa3e..67882af0 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_main.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_main.c @@ -39,7 +39,9 @@ tBTM_CB *btm_cb_ptr; #if (BLE_50_FEATURE_SUPPORT == TRUE) extern void btm_ble_extendadvcb_init(void); +#if (BLE_50_EXTEND_ADV_EN == TRUE) extern void btm_ble_advrecod_init(void); +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) #endif @@ -84,11 +86,14 @@ void btm_init (void) #if BLE_INCLUDED == TRUE btm_ble_lock_init(); btm_ble_sem_init(); + btm_cb.addr_res_en = TRUE; #endif btm_sec_dev_init(); #if (BLE_50_FEATURE_SUPPORT == TRUE) btm_ble_extendadvcb_init(); +#if (BLE_50_EXTEND_ADV_EN == TRUE) btm_ble_advrecod_init(); +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) #endif } @@ -109,6 +114,9 @@ void btm_free(void) fixed_queue_free(btm_cb.sec_pending_q, osi_free_func); btm_acl_free(); btm_sec_dev_free(); +#if BTM_SCO_INCLUDED == TRUE + btm_sco_free(); +#endif #if BTM_DYNAMIC_MEMORY FREE_AND_RESET(btm_cb_ptr); #endif @@ -118,7 +126,8 @@ void btm_free(void) #endif } -uint8_t btm_acl_active_count(void) +#if (BLE_INCLUDED == TRUE) +uint8_t btm_ble_acl_active_count(void) { list_node_t *p_node = NULL; tACL_CONN *p_acl_conn = NULL; @@ -126,10 +135,23 @@ uint8_t btm_acl_active_count(void) for (p_node = list_begin(btm_cb.p_acl_db_list); p_node; p_node = list_next(p_node)) { p_acl_conn = list_node(p_node); - if (p_acl_conn && p_acl_conn->in_use) { + if (p_acl_conn && p_acl_conn->in_use && p_acl_conn->transport == BT_TRANSPORT_LE) { count++; } } return count; } + +// Address resolution status +uint8_t btm_get_ble_addr_resolve_disable_status(void) +{ + // Returns false if address resolution is enabled, true if disabled + return (btm_cb.addr_res_en) ? 0 : 1; +} + +void btm_ble_addr_resolve_enable(bool enable) +{ + btm_cb.addr_res_en = enable; +} +#endif /*BLE_INCLUDED*/ diff --git a/lib/bt/host/bluedroid/stack/btm/btm_pm.c b/lib/bt/host/bluedroid/stack/btm/btm_pm.c index 4c52348e..1c46a744 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_pm.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_pm.c @@ -543,7 +543,7 @@ static tBTM_PM_MODE btm_pm_get_set_mode(UINT8 pm_id, tBTM_PM_MCB *p_cb, tBTM_PM_ ** Function btm_pm_snd_md_req ** Description get the resulting mode and send the resuest to host controller ** Returns tBTM_STATUS -**, BOOLEAN *p_chg_ind +** *******************************************************************************/ static tBTM_STATUS btm_pm_snd_md_req(UINT8 pm_id, UINT16 link_hdl, tBTM_PM_PWR_MD *p_mode) { @@ -565,6 +565,8 @@ static tBTM_STATUS btm_pm_snd_md_req(UINT8 pm_id, UINT16 link_hdl, tBTM_PM_PWR_M /* already in the resulting mode */ if ( (mode == BTM_PM_MD_ACTIVE) || ((md_res.max >= p_cb->interval) && (md_res.min <= p_cb->interval)) ) { + // Clear request change indication because already in result mode + p_cb->chg_ind = FALSE; return BTM_CMD_STORED; } /* Otherwise, needs to wake, then sleep */ @@ -689,7 +691,7 @@ static void btm_pm_check_stored(void) ** Description This function is called when an HCI command status event occurs ** for power manager related commands. ** -** Input Parms status - status of the event (HCI_SUCCESS if no errors) +** Input Params status - status of the event (HCI_SUCCESS if no errors) ** ** Returns none. ** @@ -717,7 +719,7 @@ void btm_pm_proc_cmd_status(UINT8 status) #if BTM_PM_DEBUG == TRUE BTM_TRACE_DEBUG( "btm_pm_proc_cmd_status new state:0x%x", p_cb->state); #endif // BTM_PM_DEBUG - } else { /* the command was not successfull. Stay in the same state */ + } else { /* the command was not successful. Stay in the same state */ pm_status = BTM_PM_STS_ERROR; } @@ -743,7 +745,7 @@ void btm_pm_proc_cmd_status(UINT8 status) ** ** Description This function is called when an HCI mode change event occurs. ** -** Input Parms hci_status - status of the event (HCI_SUCCESS if no errors) +** Input Params hci_status - status of the event (HCI_SUCCESS if no errors) ** hci_handle - connection handle associated with the change ** mode - HCI_MODE_ACTIVE, HCI_MODE_HOLD, HCI_MODE_SNIFF, or HCI_MODE_PARK ** interval - number of baseband slots (meaning depends on mode) diff --git a/lib/bt/host/bluedroid/stack/btm/btm_sco.c b/lib/bt/host/bluedroid/stack/btm/btm_sco.c index 53a9768a..69640280 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_sco.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_sco.c @@ -117,12 +117,26 @@ void btm_sco_init (void) } #endif /* Initialize nonzero defaults */ - btm_cb.sco_cb.sco_disc_reason = BTM_INVALID_SCO_DISC_REASON; - btm_cb.sco_cb.def_esco_parms = btm_esco_defaults; /* Initialize with defaults */ btm_cb.sco_cb.desired_sco_mode = BTM_DEFAULT_SCO_MODE; } +/******************************************************************************* +** +** Function btm_sco_free +** +** Description Free sco specific fixed_queue from btm control block +** +*******************************************************************************/ +void btm_sco_free(void) +{ +#if (BTM_SCO_HCI_INCLUDED == TRUE) + for (int i = 0; i < BTM_MAX_SCO_LINKS; i++) { + fixed_queue_free(btm_cb.sco_cb.sco_db[i].xmit_data_q, osi_free_func); + } +#endif +} + /******************************************************************************* ** ** Function btm_esco_conn_rsp @@ -233,7 +247,7 @@ void btm_sco_process_num_bufs (UINT16 num_lm_sco_bufs) ** pointer is used, PCM parameter maintained in ** the control block will be used; otherwise update ** control block value. -** err_data_rpt: Lisbon feature to enable the erronous data report +** err_data_rpt: Lisbon feature to enable the erroneous data report ** or not. ** ** Returns BTM_SUCCESS if the successful. @@ -598,12 +612,12 @@ static tBTM_STATUS btm_send_connect_request(UINT16 acl_handle, ** If so, we cannot use SCO-only packet types (HFP 1.7) */ if (BTM_BothEndsSupportSecureConnections(p_acl->remote_addr)) { - temp_pkt_types &= ~(BTM_SCO_PKT_TYPE_MASK); + temp_pkt_types &= ~(BTM_SCO_LINK_ONLY_MASK); BTM_TRACE_DEBUG("%s: SCO Conn: pkt_types after removing SCO (0x%04x)", __FUNCTION__, temp_pkt_types); /* Return error if no packet types left */ - if (temp_pkt_types == 0) { + if (temp_pkt_types == BTM_SCO_EXCEPTION_PKTS_MASK) { BTM_TRACE_ERROR("%s: SCO Conn (BR/EDR SC): No packet types available",__FUNCTION__); return (BTM_WRONG_MODE); } @@ -947,7 +961,7 @@ void btm_sco_conn_req (BD_ADDR bda, DEV_CLASS dev_class, UINT8 link_type) for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { /* * If the sco state is in the SCO_ST_CONNECTING state, we still need - * to return accept sco to avoid race conditon for sco creation + * to return accept sco to avoid race condition for sco creation */ int rem_bd_matches = p->rem_bd_known && !memcmp (p->esco.data.bd_addr, bda, BD_ADDR_LEN); @@ -1032,7 +1046,6 @@ void btm_sco_connected (UINT8 hci_status, BD_ADDR bda, UINT16 hci_handle, tBTM_CHG_ESCO_PARAMS parms; #endif - btm_cb.sco_cb.sco_disc_reason = hci_status; BTM_TRACE_API("%s, handle %x", __FUNCTION__, hci_handle); #if (BTM_MAX_SCO_LINKS>0) for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { @@ -1203,21 +1216,16 @@ void btm_remove_sco_links (BD_ADDR bda) ** Returns void ** *******************************************************************************/ -void btm_sco_removed (UINT16 hci_handle, UINT8 reason) +BOOLEAN btm_sco_removed (UINT16 hci_handle, UINT8 reason) { #if (BTM_MAX_SCO_LINKS>0) tSCO_CONN *p = &btm_cb.sco_cb.sco_db[0]; UINT16 xx; -#endif - - btm_cb.sco_cb.sco_disc_reason = reason; -#if (BTM_MAX_SCO_LINKS>0) p = &btm_cb.sco_cb.sco_db[0]; for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { if ((p->state != SCO_ST_UNUSED) && (p->state != SCO_ST_LISTENING) && (p->hci_handle == hci_handle)) { btm_sco_flush_sco_data(xx); - p->state = SCO_ST_UNUSED; #if BTM_SCO_HCI_INCLUDED == TRUE btm_cb.sco_cb.xmit_window_size += p->sent_not_acked; @@ -1232,10 +1240,11 @@ void btm_sco_removed (UINT16 hci_handle, UINT8 reason) p->esco.p_esco_cback = NULL; /* Deregister eSCO callback */ (*p->p_disc_cb)(xx); - return; + return TRUE; } } #endif + return FALSE; } @@ -1359,24 +1368,6 @@ UINT16 BTM_ReadScoPacketTypes (UINT16 sco_inx) #endif } -/******************************************************************************* -** -** Function BTM_ReadScoDiscReason -** -** Description This function is returns the reason why an (e)SCO connection -** has been removed. It contains the value until read, or until -** another (e)SCO connection has disconnected. -** -** Returns HCI reason or BTM_INVALID_SCO_DISC_REASON if not set. -** -*******************************************************************************/ -UINT16 BTM_ReadScoDiscReason (void) -{ - UINT16 res = btm_cb.sco_cb.sco_disc_reason; - btm_cb.sco_cb.sco_disc_reason = BTM_INVALID_SCO_DISC_REASON; - return (res); -} - /******************************************************************************* ** ** Function BTM_ReadDeviceScoPacketTypes @@ -1878,10 +1869,6 @@ UINT8 *BTM_ReadScoBdAddr(UINT16 sco_inx) { return ((UINT8 *) NULL); } -UINT16 BTM_ReadScoDiscReason (void) -{ - return (BTM_INVALID_SCO_DISC_REASON); -} tBTM_STATUS BTM_SetEScoMode (tBTM_SCO_TYPE sco_mode, tBTM_ESCO_PARAMS *p_parms) { return (BTM_MODE_UNSUPPORTED); diff --git a/lib/bt/host/bluedroid/stack/btm/btm_sec.c b/lib/bt/host/bluedroid/stack/btm/btm_sec.c index ca5f99e1..3ed5d4b1 100644 --- a/lib/bt/host/bluedroid/stack/btm/btm_sec.c +++ b/lib/bt/host/bluedroid/stack/btm/btm_sec.c @@ -1001,12 +1001,12 @@ tBTM_STATUS btm_sec_bond_by_transport (BD_ADDR bd_addr, tBT_TRANSPORT transport, return (BTM_SUCCESS); } +#if (CLASSIC_BT_INCLUDED == TRUE) /* Tell controller to get rid of the link key if it has one stored */ if ((BTM_DeleteStoredLinkKey (bd_addr, NULL)) != BTM_SUCCESS) { return (BTM_NO_RESOURCES); } -#if (CLASSIC_BT_INCLUDED == TRUE) /* Save the PIN code if we got a valid one */ if (p_pin && (pin_len <= PIN_CODE_LEN) && (pin_len != 0)) { btm_cb.pin_code_len = pin_len; @@ -1720,7 +1720,7 @@ void BTM_RemoteOobDataReply(tBTM_STATUS res, BD_ADDR bd_addr, BT_OCTET16 c, BT_O btsnd_hcic_rem_oob_reply (bd_addr, c, r); } } - +#if 0 /******************************************************************************* ** ** Function BTM_BuildOobData @@ -1745,8 +1745,10 @@ UINT16 BTM_BuildOobData(UINT8 *p_data, UINT16 max_len, BT_OCTET16 c, UINT8 *p = p_data; UINT16 len = 0; #if BTM_MAX_LOC_BD_NAME_LEN > 0 +#if (CLASSIC_BT_INCLUDED == TRUE) UINT16 name_size; UINT8 name_type = BTM_EIR_SHORTENED_LOCAL_NAME_TYPE; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #endif if (p_data && max_len >= BTM_OOB_MANDATORY_SIZE) { @@ -1789,6 +1791,7 @@ UINT16 BTM_BuildOobData(UINT8 *p_data, UINT16 max_len, BT_OCTET16 c, max_len -= delta; } #if BTM_MAX_LOC_BD_NAME_LEN > 0 +#if (CLASSIC_BT_INCLUDED == TRUE) name_size = name_len; if (name_size > strlen(btm_cb.cfg.bredr_bd_name)) { name_type = BTM_EIR_COMPLETE_LOCAL_NAME_TYPE; @@ -1802,6 +1805,7 @@ UINT16 BTM_BuildOobData(UINT8 *p_data, UINT16 max_len, BT_OCTET16 c, len += delta; max_len -= delta; } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #endif /* update len */ p = p_data; @@ -1871,6 +1875,7 @@ UINT8 *BTM_ReadOobData(UINT8 *p_data, UINT8 eir_tag, UINT8 *p_len) return p_ret; } +#endif #endif ///BTM_OOB_INCLUDED == TRUE && SMP_INCLUDED == TRUE #if (CLASSIC_BT_INCLUDED == TRUE) @@ -4589,10 +4594,10 @@ tBTM_STATUS btm_sec_disconnect (UINT16 handle, UINT8 reason) ** Description This function is when a connection to the peer device is ** dropped ** -** Returns void +** Returns tBTM_SEC_DEV_REC is not NULL ** *******************************************************************************/ -void btm_sec_disconnected (UINT16 handle, UINT8 reason) +BOOLEAN btm_sec_disconnected (UINT16 handle, UINT8 reason) { tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle (handle); UINT8 old_pairing_flags = btm_cb.pairing_flags; @@ -4608,7 +4613,7 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason) #endif if (!p_dev_rec) { - return; + return FALSE; } p_dev_rec->enc_init_by_we = FALSE; transport = (handle == p_dev_rec->hci_handle) ? BT_TRANSPORT_BR_EDR : BT_TRANSPORT_LE; @@ -4649,7 +4654,7 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason) if (p_dev_rec->sec_state == BTM_SEC_STATE_DISCONNECTING_BOTH) { p_dev_rec->sec_state = (transport == BT_TRANSPORT_LE) ? BTM_SEC_STATE_DISCONNECTING : BTM_SEC_STATE_DISCONNECTING_BLE; - return; + return TRUE; } #endif p_dev_rec->sec_state = BTM_SEC_STATE_IDLE; @@ -4685,6 +4690,7 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason) p_dev_rec->sec_bd_name, result); } } + return TRUE; } /******************************************************************************* diff --git a/lib/bt/host/bluedroid/stack/btm/include/btm_ble_int.h b/lib/bt/host/bluedroid/stack/btm/include/btm_ble_int.h index 0f8888fb..de25c6fa 100644 --- a/lib/bt/host/bluedroid/stack/btm/include/btm_ble_int.h +++ b/lib/bt/host/bluedroid/stack/btm/include/btm_ble_int.h @@ -212,11 +212,14 @@ typedef struct { #define BTM_BLE_MAX_BG_CONN_DEV_NUM 10 typedef struct { + UINT16 scan_interval; + UINT16 scan_window; UINT16 min_conn_int; UINT16 max_conn_int; UINT16 slave_latency; UINT16 supervision_tout; - + UINT16 min_ce_len; + UINT16 max_ce_len; } tBTM_LE_CONN_PRAMS; @@ -339,10 +342,10 @@ typedef struct { tBTM_INQ_RESULTS_CB *p_scan_results_cb; tBTM_CMPL_CB *p_scan_cmpl_cb; TIMER_LIST_ENT scan_timer_ent; - +#if (BLE_42_SCAN_EN == TRUE) struct pkt_queue *adv_rpt_queue; struct osi_event *adv_rpt_ready; - +#endif // #if (BLE_42_SCAN_EN == TRUE) /* background connection procedure cb value */ tBTM_BLE_CONN_TYPE bg_conn_type; UINT32 scan_int; @@ -350,6 +353,10 @@ typedef struct { tBTM_BLE_SEL_CBACK *p_select_cback; /* white list information */ UINT8 white_list_avail_size; +#if (BLE_50_EXTEND_SYNC_EN == TRUE) + /* periodic list information */ + UINT8 periodic_adv_list_size; +#endif //#if (BLE_50_EXTEND_SYNC_EN == TRUE) tBTM_UPDATE_WHITELIST_CBACK *update_wl_cb; tBTM_BLE_WL_STATE wl_state; @@ -377,6 +384,8 @@ typedef struct { tBTM_BLE_STATE_MASK cur_states; /* bit mask of tBTM_BLE_STATE */ UINT8 link_count[2]; /* total link count master and slave*/ tBTM_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_CMPL_CBACK *update_exceptional_list_cmp_cb; + tBTM_SET_CSA_SUPPORT_CMPL_CBACK *set_csa_support_cmpl_cb; + tBTM_SET_VENDOR_EVT_MASK_CBACK *set_vendor_evt_mask_cmpl_cb; } tBTM_BLE_CB; #ifdef __cplusplus @@ -384,12 +393,14 @@ extern "C" { #endif void btm_ble_timeout(TIMER_LIST_ENT *p_tle); +#if (BLE_42_SCAN_EN == TRUE) void btm_ble_process_adv_pkt (UINT8 *p); void btm_ble_process_adv_discard_evt(UINT8 *p); void btm_ble_process_direct_adv_pkt (UINT8 *p); bool btm_ble_adv_pkt_ready(void); bool btm_ble_adv_pkt_post(pkt_linked_item_t *pkt); void btm_ble_proc_scan_rsp_rpt (UINT8 *p); +#endif // #if (BLE_42_SCAN_EN == TRUE) tBTM_STATUS btm_ble_read_remote_name(BD_ADDR remote_bda, tBTM_INQ_INFO *p_cur, tBTM_CMPL_CB *p_cb); BOOLEAN btm_ble_cancel_remote_name(BD_ADDR remote_bda); @@ -405,7 +416,11 @@ void btm_ble_init (void); void btm_ble_free (void); void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role, tBLE_ADDR_TYPE addr_type, BOOLEAN addr_matched); void btm_ble_read_remote_features_complete(UINT8 *p); + +#if (BLE_42_ADV_EN == TRUE) void btm_ble_write_adv_enable_complete(UINT8 *p); +#endif // #if (BLE_42_ADV_EN == TRUE) + void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced); void btm_read_ble_local_supported_states_complete(UINT8 *p, UINT16 evt_len); tBTM_BLE_CONN_ST btm_ble_get_conn_st(void); @@ -455,9 +470,12 @@ void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len); void btm_ble_clear_white_list_complete(UINT8 *p, UINT16 evt_len); void btm_ble_white_list_init(UINT8 white_list_size); +#if (tGATT_BG_CONN_DEV == TRUE) /* background connection function */ BOOLEAN btm_ble_suspend_bg_conn(void); BOOLEAN btm_ble_resume_bg_conn(void); +#endif // #if (tGATT_BG_CONN_DEV == TRUE) + void btm_ble_initiate_select_conn(BD_ADDR bda); BOOLEAN btm_ble_start_auto_conn(BOOLEAN start); BOOLEAN btm_ble_start_select_conn(BOOLEAN start, tBTM_BLE_SEL_CBACK *p_select_cback); @@ -500,12 +518,14 @@ void btm_ble_add_default_entry_to_resolving_list(void); void btm_ble_set_privacy_mode_complete(UINT8 *p, UINT16 evt_len); #endif +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) void btm_ble_multi_adv_configure_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst); void btm_ble_multi_adv_init(void); void *btm_ble_multi_adv_get_ref(UINT8 inst_id); void btm_ble_multi_adv_cleanup(void); void btm_ble_multi_adv_reenable(UINT8 inst_id); void btm_ble_multi_adv_enb_privacy(BOOLEAN enable); +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) char btm_ble_map_adv_tx_power(int tx_power_index); void btm_ble_batchscan_init(void); void btm_ble_batchscan_cleanup(void); @@ -536,12 +556,57 @@ void btm_ble_channel_select_algorithm_evt(tBTM_BLE_CHANNEL_SEL_ALG *params); void btm_ble_periodic_adv_report_evt(tBTM_PERIOD_ADV_REPORT *params); void btm_ble_periodic_adv_sync_lost_evt(tBTM_BLE_PERIOD_ADV_SYNC_LOST *params); void btm_ble_periodic_adv_sync_establish_evt(tBTM_BLE_PERIOD_ADV_SYNC_ESTAB *params); +#if (BLE_50_EXTEND_SYNC_EN == TRUE) +void btm_ble_periodic_adv_list_init(UINT8 periodic_adv_size); +#endif //#if (BLE_50_EXTEND_SYNC_EN == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) void btm_ble_periodic_adv_sync_trans_recv_evt(tBTM_BLE_PERIOD_ADV_SYNC_TRANS_RECV *params); #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_EN == TRUE) +void btm_ble_cis_established_evt(tBTM_BLE_CIS_ESTABLISHED_CMPL *params); +void btm_ble_cis_disconnected_evt(tBTM_BLE_CIS_DISCON_CMPL *params); +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) +void btm_ble_iso_read_iso_tx_sync_complete(UINT8 *p); +void btm_ble_iso_read_iso_link_quality_complete(UINT8 *p); +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +void btm_ble_cis_request_evt(tBTM_BLE_CIS_REQUEST_CMPL *params); +void btm_ble_accept_cis_req_cmd_status(tBTM_BLE_ISO_CB_PARAMS *cb_params); +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +void btm_ble_create_cis_cmd_status(tBTM_BLE_ISO_CB_PARAMS *cb_params); +void btm_ble_iso_set_cig_params_complete(UINT8 *p); +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +void btm_ble_big_create_cmpl_evt(tBTM_BLE_BIG_CREATE_CMPL *param); +void btm_ble_big_terminate_cmpl_evt(tBTM_BLE_BIG_TERMINATE_CMPL *params); +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +void btm_ble_big_sync_estab_evt(tBTM_BLE_BIG_SYNC_ESTAB_CMPL *params); +void btm_ble_big_sync_lost_evt(tBTM_BLE_BIG_SYNC_LOST_EVT *params); +void btm_ble_biginfo_adv_report_evt(tBTM_BLE_BIGINFO_ADV_REPORT_EVT *params); +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +void btm_ble_iso_data_path_update_complete(UINT16 opcode, UINT8 hci_status, UINT16 conn_handle); +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_CTE_EN == TRUE) +void btm_ble_cte_read_ant_infor_complete(UINT8 *p); +void btm_ble_connless_iq_report_evt(tBTM_BLE_CTE_CONNLESS_IQ_REPORT_EVT *params); +void btm_ble_conn_iq_report_evt(tBTM_BLE_CTE_CONN_IQ_REPORT_EVT *params); +void btm_ble_cte_req_failed_evt(tBTM_BLE_CTE_REQ_FAILED_EVT *params); +#endif // #if (BLE_FEAT_CTE_EN == TRUE) + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +void btm_ble_path_loss_threshold_evt(tBTM_BLE_PATH_LOSS_THRESHOLD_EVT *params); +void btm_ble_transmit_power_report_evt(tBTM_BLE_TRANS_POWER_REPORT_EVT *params); +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +void btm_ble_subrate_change_evt(tBTM_BLE_SUBRATE_CHANGE_EVT *params); +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + /* #ifdef __cplusplus } diff --git a/lib/bt/host/bluedroid/stack/btm/include/btm_int.h b/lib/bt/host/bluedroid/stack/btm/include/btm_int.h index 3d01a5c2..d5b69c68 100644 --- a/lib/bt/host/bluedroid/stack/btm/include/btm_int.h +++ b/lib/bt/host/bluedroid/stack/btm/include/btm_int.h @@ -43,13 +43,12 @@ typedef struct tBTM_SEC_DEV_REC tBTM_SEC_DEV_REC; #include "stack/smp_api.h" #endif -#define ESP_VS_REM_LEGACY_AUTH_CMP 0x03 - #if BTM_MAX_LOC_BD_NAME_LEN > 0 typedef char tBTM_LOC_BD_NAME[BTM_MAX_LOC_BD_NAME_LEN + 1]; #endif #define BTM_ACL_IS_CONNECTED(bda) (btm_bda_to_acl (bda, BT_TRANSPORT_BR_EDR) != NULL) +#define BTM_LE_ACL_IS_CONNECTED(bda) (btm_bda_to_acl (bda, BT_TRANSPORT_LE) != NULL) /* Definitions for Server Channel Number (SCN) management */ @@ -192,6 +191,10 @@ tBTM_CMPL_CB *p_rln_cmpl_cb; /* Callback function to be called when TIMER_LIST_ENT rssi_timer; tBTM_CMPL_CB *p_rssi_cmpl_cb; /* Callback function to be called when */ /* read rssi function completes */ + +tBTM_CMPL_CB *p_ble_ch_map_cmpl_cb; /* Callback function to be called when */ +/* read channel map function completes */ + TIMER_LIST_ENT lnk_quality_timer; tBTM_CMPL_CB *p_lnk_qual_cmpl_cb;/* Callback function to be called when */ /* read link quality function completes */ @@ -207,8 +210,10 @@ tBTM_ROLE_SWITCH_CMPL switch_role_ref_data; tBTM_CMPL_CB *p_switch_role_cb; /* Callback function to be called when */ /* requested switch role is completed */ +#if (BLE_HOST_READ_TX_POWER_EN == TRUE) TIMER_LIST_ENT tx_power_timer; tBTM_CMPL_CB *p_tx_power_cmpl_cb;/* Callback function to be called */ +#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) #if CLASSIC_BT_INCLUDED == TRUE TIMER_LIST_ENT afh_channels_timer; @@ -469,7 +474,6 @@ typedef struct { tSCO_CONN sco_db[BTM_MAX_SCO_LINKS]; tBTM_ESCO_PARAMS def_esco_parms; BD_ADDR xfer_addr; - UINT16 sco_disc_reason; BOOLEAN esco_supported; /* TRUE if 1.2 cntlr AND supports eSCO links */ tBTM_SCO_TYPE desired_sco_mode; tBTM_SCO_TYPE xfer_sco_type; @@ -724,14 +728,18 @@ struct tBTM_SEC_DEV_REC{ */ typedef struct { #if BTM_MAX_LOC_BD_NAME_LEN > 0 +#if (CLASSIC_BT_INCLUDED == TRUE) tBTM_LOC_BD_NAME bredr_bd_name; /* local BREDR device name */ +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) tBTM_LOC_BD_NAME ble_bd_name; /* local BLE device name */ #endif +#if (CLASSIC_BT_INCLUDED == TRUE) BOOLEAN pin_type; /* TRUE if PIN type is fixed */ UINT8 pin_code_len; /* Bonding information */ PIN_CODE pin_code; /* PIN CODE if pin type is fixed */ - BOOLEAN connectable; /* If TRUE page scan should be enabled */ - UINT8 def_inq_scan_mode; /* ??? limited/general/none */ + // BOOLEAN connectable; /* If TRUE page scan should be enabled */ + // UINT8 def_inq_scan_mode; /* ??? limited/general/none */ +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) } tBTM_CFG; enum { @@ -885,6 +893,7 @@ typedef struct { UINT16 ediv; /* received ediv value from LTK request */ UINT8 key_size; tBTM_BLE_VSC_CB cmn_ble_vsc_cb; + BOOLEAN addr_res_en; /* internal use for test: address resolution enable/disable */ #endif /* Packet types supported by the local device */ @@ -951,7 +960,7 @@ typedef struct { #endif // SMP_INCLUDED == TRUE || BT_CLASSIC_ENABLED == TRUE list_t *p_sec_dev_rec_list; tBTM_SEC_SERV_REC *p_out_serv; - tBTM_MKEY_CALLBACK *mkey_cback; + // tBTM_MKEY_CALLBACK *mkey_cback; BD_ADDR connecting_bda; DEV_CLASS connecting_dc; @@ -1063,6 +1072,7 @@ void btm_cont_rswitch (tACL_CONN *p, tACL_CONN *btm_handle_to_acl (UINT16 hci_handle); void btm_read_link_policy_complete (UINT8 *p); void btm_read_rssi_complete (UINT8 *p); +void btm_read_channel_map_complete (UINT8 *p); void btm_read_tx_power_complete (UINT8 *p, BOOLEAN is_ble); void btm_acl_pkt_types_changed(UINT8 status, UINT16 handle, UINT16 pkt_types); void btm_read_link_quality_complete (UINT8 *p); @@ -1113,17 +1123,29 @@ void btm_read_phy_callback(uint8_t hci_status, uint16_t conn_handle, uint8_t tx_ #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) void btm_ble_periodic_adv_sync_trans_complete(UINT16 op_code, UINT8 hci_status, UINT16 conn_handle); #endif +void btm_ble_big_sync_terminate_complete(UINT8 hci_status, UINT8 big_handle); + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +void btm_enh_read_trans_pwr_level_cmpl_evt(uint8_t *p); +void btm_read_remote_trans_pwr_level_cmpl(UINT8 status); +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +void btm_subrate_req_cmd_status(UINT8 status); +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + /* Internal functions provided by btm_sco.c ******************************************** */ void btm_sco_init (void); +void btm_sco_free(void); void btm_sco_connected (UINT8 hci_status, BD_ADDR bda, UINT16 hci_handle, tBTM_ESCO_DATA *p_esco_data); void btm_esco_proc_conn_chg (UINT8 status, UINT16 handle, UINT8 tx_interval, UINT8 retrans_window, UINT16 rx_pkt_len, UINT16 tx_pkt_len); void btm_sco_conn_req (BD_ADDR bda, DEV_CLASS dev_class, UINT8 link_type); -void btm_sco_removed (UINT16 hci_handle, UINT8 reason); +BOOLEAN btm_sco_removed (UINT16 hci_handle, UINT8 reason); void btm_sco_acl_removed (BD_ADDR bda); void btm_route_sco_data (BT_HDR *p_msg); BOOLEAN btm_is_sco_active (UINT16 handle); @@ -1203,7 +1225,7 @@ void btm_sec_auth_complete (UINT16 handle, UINT8 status); void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable); void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode); tBTM_STATUS btm_sec_disconnect (UINT16 handle, UINT8 reason); -void btm_sec_disconnected (UINT16 handle, UINT8 reason); +BOOLEAN btm_sec_disconnected (UINT16 handle, UINT8 reason); void btm_sec_rmt_name_request_complete (UINT8 *bd_addr, UINT8 *bd_name, UINT8 status); void btm_sec_rmt_host_support_feat_evt (UINT8 *p); void btm_io_capabilities_req (UINT8 *p); diff --git a/lib/bt/host/bluedroid/stack/btu/btu_hcif.c b/lib/bt/host/bluedroid/stack/btu/btu_hcif.c index 30e76125..eb2995b9 100644 --- a/lib/bt/host/bluedroid/stack/btu/btu_hcif.c +++ b/lib/bt/host/bluedroid/stack/btu/btu_hcif.c @@ -55,6 +55,7 @@ extern void btm_ble_test_command_complete(UINT8 *p); /********************************************************************************/ /* L O C A L F U N C T I O N P R O T O T Y P E S */ /********************************************************************************/ +#if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_inquiry_comp_evt (UINT8 *p); static void btu_hcif_inquiry_result_evt (UINT8 *p); static void btu_hcif_inquiry_rssi_result_evt (UINT8 *p); @@ -62,30 +63,46 @@ static void btu_hcif_extended_inquiry_result_evt (UINT8 *p); static void btu_hcif_connection_comp_evt (UINT8 *p); static void btu_hcif_connection_request_evt (UINT8 *p); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_disconnection_comp_evt (UINT8 *p); #if (SMP_INCLUDED == TRUE) static void btu_hcif_authentication_comp_evt (UINT8 *p); #endif ///SMP_INCLUDED == TRUE +#if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_rmt_name_request_comp_evt (UINT8 *p, UINT16 evt_len); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #if (SMP_INCLUDED == TRUE) static void btu_hcif_encryption_change_evt (UINT8 *p); #endif ///SMP_INCLUDED == TRUE +#if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_read_rmt_features_comp_evt (UINT8 *p); static void btu_hcif_read_rmt_ext_features_comp_evt (UINT8 *p); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_read_rmt_version_comp_evt (UINT8 *p); +#if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_qos_setup_comp_evt (UINT8 *p); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_command_complete_evt (BT_HDR *response, void *context); static void btu_hcif_command_status_evt (uint8_t status, BT_HDR *command, void *context); static void btu_hcif_hardware_error_evt (UINT8 *p); +#if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_flush_occured_evt (void); static void btu_hcif_role_change_evt (UINT8 *p); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_num_compl_data_pkts_evt (UINT8 *p); + +#if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_mode_change_evt (UINT8 *p); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) + #if (SMP_INCLUDED == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_pin_code_request_evt (UINT8 *p); static void btu_hcif_link_key_request_evt (UINT8 *p); static void btu_hcif_link_key_notification_evt (UINT8 *p); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #endif ///SMP_INCLUDED == TRUE +#if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_loopback_command_evt (void); static void btu_hcif_data_buf_overflow_evt (void); static void btu_hcif_max_slots_changed_evt (void); @@ -98,6 +115,8 @@ static void btu_hcif_esco_connection_comp_evt(UINT8 *p); static void btu_hcif_esco_connection_chg_evt(UINT8 *p); static void btu_hcif_host_support_evt (UINT8 *p); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) + /* Simple Pairing Events */ #if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_io_cap_request_evt (UINT8 *p); @@ -111,12 +130,14 @@ static void btu_hcif_keypress_notif_evt (UINT8 *p); #if BTM_OOB_INCLUDED == TRUE && SMP_INCLUDED == TRUE static void btu_hcif_rem_oob_request_evt (UINT8 *p); #endif +#if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_link_supv_to_changed_evt (UINT8 *p); #if L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE static void btu_hcif_enhanced_flush_complete_evt (void); #endif static void btu_hcif_ssr_evt (UINT8 *p, UINT16 evt_len); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #if BLE_INCLUDED == TRUE static void btu_ble_ll_conn_complete_evt (UINT8 *p, UINT16 evt_len); @@ -136,29 +157,91 @@ static void btu_ble_proc_enhanced_conn_cmpl (UINT8 *p, UINT16 evt_len); //#endif #if (BLE_50_FEATURE_SUPPORT == TRUE) static void btu_ble_phy_update_complete_evt(UINT8 *p); +#if (BLE_50_EXTEND_SCAN_EN == TRUE) static void btu_ble_ext_adv_report_evt(UINT8 *p, UINT16 evt_len); +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) static void btu_ble_periodic_adv_sync_establish_evt(UINT8 *p); static void btu_ble_periodic_adv_report_evt(UINT8 *p, UINT8 evt_len); static void btu_ble_periodic_adv_sync_lost_evt(UINT8 *p); +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if (BLE_50_EXTEND_SCAN_EN == TRUE) static void btu_ble_scan_timeout_evt(UINT8 *p); +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) static void btu_ble_adv_set_terminate_evt(UINT8 *p); static void btu_ble_scan_req_received_evt(UINT8 *p); +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +static void btu_ble_channel_select_alg_evt(UINT8 *p); #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) static void btu_ble_periodic_adv_sync_trans_recv(UINT8 *p); #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +void btu_ble_create_big_cmd_status(UINT8 status); +static void btu_ble_big_create_complete_evt(UINT8 *p); +void btu_ble_big_terminate_cmd_status(UINT8 status); +static void btu_ble_big_terminate_complete_evt(UINT8 *p); +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +static void btu_ble_create_big_sync_cmd_status(UINT8 status); +static void btu_ble_big_sync_establish_evt(UINT8 *p); +static void btu_ble_big_sync_lost_evt(UINT8 *p); +static void btu_ble_biginfo_adv_report_evt(UINT8 *p); +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +static void btu_ble_create_cis_cmd_status(UINT8 status); +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +static void btu_ble_accept_cis_req_cmd_status(UINT8 status); +static void btu_ble_cis_request_evt(UINT8 *p); +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_EN == TRUE) +static void btu_ble_cis_established_evt(UINT8 *p); +static void btu_ble_cis_disconnected(UINT16 handle, UINT8 reason); +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) + +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + + +#if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +static void btu_ble_cte_connless_iq_report_evt(UINT8 *p); +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +static void btu_ble_cte_conn_iq_report_evt(UINT8 *p); +static void btu_ble_cte_req_failed_evt(UINT8 *p); +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +#endif // #if (BLE_FEAT_CTE_EN == TRUE) + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +static void btu_ble_path_loss_threshold_evt(UINT8 *p); +static void btu_ble_transmit_power_report_evt(UINT8 *p); +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +static void btu_ble_subrate_change_evt(UINT8 *p); +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + +#if (BLE_42_ADV_EN == TRUE) extern osi_sem_t adv_enable_sem; extern osi_sem_t adv_data_sem; extern osi_sem_t adv_param_sem; -extern osi_sem_t scan_enable_sem; -extern osi_sem_t scan_param_sem; extern uint8_t adv_enable_status; extern uint8_t adv_data_status; extern uint8_t adv_param_status; +#endif // #if (BLE_42_ADV_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) +extern osi_sem_t scan_enable_sem; +extern osi_sem_t scan_param_sem; extern uint8_t scan_enable_status; extern uint8_t scan_param_status; - +#endif // #if (BLE_42_SCAN_EN == TRUE) #endif /******************************************************************************* @@ -182,6 +265,7 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) STREAM_TO_UINT8 (hci_evt_len, p); switch (hci_evt_code) { +#if (CLASSIC_BT_INCLUDED == TRUE) case HCI_INQUIRY_COMP_EVT: btu_hcif_inquiry_comp_evt (p); break; @@ -200,6 +284,7 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) case HCI_CONNECTION_REQUEST_EVT: btu_hcif_connection_request_evt (p); break; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) case HCI_DISCONNECTION_COMP_EVT: btu_hcif_disconnection_comp_evt (p); break; @@ -208,9 +293,11 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) btu_hcif_authentication_comp_evt (p); #endif ///SMP_INCLUDED == TRUE break; +#if (CLASSIC_BT_INCLUDED == TRUE) case HCI_RMT_NAME_REQUEST_COMP_EVT: btu_hcif_rmt_name_request_comp_evt (p, hci_evt_len); break; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) case HCI_ENCRYPTION_CHANGE_EVT: #if (SMP_INCLUDED == TRUE) btu_hcif_encryption_change_evt (p); @@ -223,18 +310,22 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) #endif ///SMP_INCLUDED == TRUE break; #endif +#if (CLASSIC_BT_INCLUDED == TRUE) case HCI_READ_RMT_FEATURES_COMP_EVT: btu_hcif_read_rmt_features_comp_evt (p); break; case HCI_READ_RMT_EXT_FEATURES_COMP_EVT: btu_hcif_read_rmt_ext_features_comp_evt (p); break; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) case HCI_READ_RMT_VERSION_COMP_EVT: btu_hcif_read_rmt_version_comp_evt (p); break; +#if (CLASSIC_BT_INCLUDED == TRUE) case HCI_QOS_SETUP_COMP_EVT: btu_hcif_qos_setup_comp_evt (p); break; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) case HCI_COMMAND_COMPLETE_EVT: //HCI_TRACE_ERROR("%s should not have received a command complete event. " // "Someone didn't go through the hci transmit_command function.", __func__); @@ -246,19 +337,24 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) case HCI_HARDWARE_ERROR_EVT: btu_hcif_hardware_error_evt (p); break; +#if (CLASSIC_BT_INCLUDED == TRUE) case HCI_FLUSH_OCCURED_EVT: btu_hcif_flush_occured_evt (); break; case HCI_ROLE_CHANGE_EVT: btu_hcif_role_change_evt (p); break; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) case HCI_NUM_COMPL_DATA_PKTS_EVT: btu_hcif_num_compl_data_pkts_evt (p); break; + #if (CLASSIC_BT_INCLUDED == TRUE) case HCI_MODE_CHANGE_EVT: btu_hcif_mode_change_evt (p); break; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #if (SMP_INCLUDED == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) case HCI_PIN_CODE_REQUEST_EVT: btu_hcif_pin_code_request_evt (p); break; @@ -268,7 +364,9 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) case HCI_LINK_KEY_NOTIFICATION_EVT: btu_hcif_link_key_notification_evt (p); break; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #endif ///SMP_INCLUDED == TRUE +#if (CLASSIC_BT_INCLUDED == TRUE) case HCI_LOOPBACK_COMMAND_EVT: btu_hcif_loopback_command_evt (); break; @@ -305,7 +403,6 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) case HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT: btu_hcif_host_support_evt (p); break; -#if (CLASSIC_BT_INCLUDED == TRUE) case HCI_IO_CAPABILITY_REQUEST_EVT: btu_hcif_io_cap_request_evt (p); break; @@ -334,7 +431,6 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) case HCI_KEYPRESS_NOTIFY_EVT: btu_hcif_keypress_notif_evt (p); break; -#endif /* (CLASSIC_BT_INCLUDED == TRUE) */ case HCI_LINK_SUPER_TOUT_CHANGED_EVT: btu_hcif_link_supv_to_changed_evt (p); break; @@ -343,6 +439,7 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) btu_hcif_enhanced_flush_complete_evt (); break; #endif +#endif /* (CLASSIC_BT_INCLUDED == TRUE) */ #if (BLE_INCLUDED == TRUE) case HCI_BLE_EVENT: @@ -388,10 +485,13 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) case HCI_BLE_PHY_UPDATE_COMPLETE_EVT: btu_ble_phy_update_complete_evt(p); break; +#if (BLE_50_EXTEND_SCAN_EN == TRUE) case HCI_BLE_EXT_ADV_REPORT_EVT: //HCI_TRACE_ERROR("%s, HCI_BLE_EXT_ADV_REPORT_EVT.", __func__); btu_ble_ext_adv_report_evt(p, hci_evt_len); break; +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) case HCI_BLE_PERIOD_ADV_SYNC_ESTAB_EVT: btu_ble_periodic_adv_sync_establish_evt(p); break; @@ -401,16 +501,22 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) case HCI_BLE_PERIOD_ADV_SYNC_LOST_EVT: btu_ble_periodic_adv_sync_lost_evt(p); break; +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if (BLE_50_EXTEND_SCAN_EN == TRUE) case HCI_BLE_SCAN_TIMEOUT_EVT: btu_ble_scan_timeout_evt(p); break; +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) case HCI_BLE_ADV_SET_TERMINATED_EVT: btu_ble_adv_set_terminate_evt(p); break; case HCI_BLE_SCAN_REQ_RECEIVED_EVT: btu_ble_scan_req_received_evt(p); break; +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) case HCI_BLE_CHANNEL_SELECT_ALG: + btu_ble_channel_select_alg_evt(p); break; #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) @@ -418,6 +524,68 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg) btu_ble_periodic_adv_sync_trans_recv(p); break; #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_EN == TRUE) + case HCI_BLE_CIS_ESTABLISHED_V1_EVT: + case HCI_BLE_CIS_ESTABLISHED_V2_EVT: + btu_ble_cis_established_evt(p); + break; +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + case HCI_BLE_CIS_REQUEST_EVT: + btu_ble_cis_request_evt(p); + break; +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + case HCI_BLE_BIG_CREATE_COMPLETE_EVT: + btu_ble_big_create_complete_evt(p); + break; + case HCI_BLE_BIG_TERMINATE_COMPLETE_EVT: + btu_ble_big_terminate_complete_evt(p); + break; +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + case HCI_BLE_BIG_SYNC_ESTABLISHED_EVT: + btu_ble_big_sync_establish_evt(p); + break; + case HCI_BLE_BIG_SYNC_LOST_EVT: + btu_ble_big_sync_lost_evt(p); + break; + case HCI_BLE_BIGINFO_ADV_REPORT_EVT: + btu_ble_biginfo_adv_report_evt(p); + break; +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +#endif // #if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + case HCI_BLE_CONNLESS_IQ_REPORT_EVT: + btu_ble_cte_connless_iq_report_evt(p); + break; +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + case HCI_BLE_CONN_IQ_REPORT_EVT: + btu_ble_cte_conn_iq_report_evt(p); + break; + case HCI_BLE_CTE_REQUEST_FAILED_EVT: + btu_ble_cte_req_failed_evt(p); + break; +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + +#endif // #if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + case HCI_BLE_PATH_LOSS_THRESHOLD_EVT: + btu_ble_path_loss_threshold_evt(p); + break; + case HCI_BLE_TRANS_POWER_REPORTING_EVT: + btu_ble_transmit_power_report_evt(p); + break; +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) + case HCI_BLE_SUBRATE_CHANGE_EVT: + btu_ble_subrate_change_evt(p); + break; +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) } break; #endif /* BLE_INCLUDED */ @@ -559,7 +727,7 @@ void btu_hcif_send_host_rdy_for_data(void) btsnd_hcic_host_num_xmitted_pkts (num_ents, handles, num_pkts); } } - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btu_hcif_inquiry_comp_evt @@ -687,7 +855,7 @@ static void btu_hcif_connection_request_evt (UINT8 *p) } #endif /* BTM_SCO_INCLUDED */ } - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -702,6 +870,7 @@ static void btu_hcif_disconnection_comp_evt (UINT8 *p) { UINT16 handle; UINT8 reason; + BOOLEAN dev_find = FALSE; ++p; STREAM_TO_UINT16 (handle, p); @@ -709,9 +878,18 @@ static void btu_hcif_disconnection_comp_evt (UINT8 *p) handle = HCID_GET_HANDLE (handle); - btm_acl_disconnected(handle, reason); + dev_find = btm_acl_disconnected(handle, reason); + +#if (BLE_FEAT_ISO_CIG_EN == TRUE) + // Not find device. it is iso handle + if (!dev_find) { + btu_ble_cis_disconnected(handle, reason); + } +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) - HCI_TRACE_WARNING("hcif disc complete: hdl 0x%x, rsn 0x%x", handle, reason); + HCI_TRACE_WARNING("hcif disc complete: hdl 0x%x, rsn 0x%x dev_find %d", handle, reason, dev_find); + + UNUSED(dev_find); } /******************************************************************************* @@ -736,6 +914,7 @@ static void btu_hcif_authentication_comp_evt (UINT8 *p) } #endif ///SMP_INCLUDED == TRUE +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btu_hcif_rmt_name_request_comp_evt @@ -760,7 +939,7 @@ static void btu_hcif_rmt_name_request_comp_evt (UINT8 *p, UINT16 evt_len) btm_sec_rmt_name_request_complete (bd_addr, p, status); #endif ///SMP_INCLUDED == TRUE } - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -786,7 +965,7 @@ static void btu_hcif_encryption_change_evt (UINT8 *p) btm_sec_encrypt_change (handle, status, encr_enable); } #endif ///SMP_INCLUDED == TRUE - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btu_hcif_read_rmt_features_comp_evt @@ -825,6 +1004,7 @@ static void btu_hcif_read_rmt_ext_features_comp_evt (UINT8 *p) btm_read_remote_ext_features_failed(status, handle); } } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -840,7 +1020,7 @@ static void btu_hcif_read_rmt_version_comp_evt (UINT8 *p) btm_read_remote_version_complete (p); } - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btu_hcif_qos_setup_comp_evt @@ -934,6 +1114,7 @@ static void btu_hcif_esco_connection_chg_evt (UINT8 *p) rx_pkt_len, tx_pkt_len); #endif } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -949,6 +1130,7 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l { uint8_t status; switch (opcode) { +#if (CLASSIC_BT_INCLUDED == TRUE) case HCI_INQUIRY_CANCEL: /* Tell inquiry processing that we are done */ btm_process_cancel_complete(HCI_SUCCESS, BTM_BR_INQUIRY_MASK); @@ -961,37 +1143,39 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l btm_delete_stored_link_key_complete (p); break; - case HCI_READ_LOCAL_NAME: - btm_read_local_name_complete (p, evt_len); - break; - case HCI_GET_LINK_QUALITY: btm_read_link_quality_complete (p); break; - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) + case HCI_READ_LOCAL_NAME: + btm_read_local_name_complete (p, evt_len); + break; case HCI_READ_RSSI: btm_read_rssi_complete (p); break; - + case HCI_BLE_READ_CHNL_MAP: + btm_read_channel_map_complete (p); + break; case HCI_READ_TRANSMIT_POWER_LEVEL: +#if (BLE_HOST_READ_TX_POWER_EN == TRUE) btm_read_tx_power_complete(p, FALSE); +#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) break; - +#if (CLASSIC_BT_INCLUDED == TRUE) case HCI_CREATE_CONNECTION_CANCEL: btm_create_conn_cancel_complete(p); break; - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) case HCI_READ_LOCAL_OOB_DATA: #if BTM_OOB_INCLUDED == TRUE && SMP_INCLUDED == TRUE btm_read_local_oob_complete(p); #endif break; - +#if (CLASSIC_BT_INCLUDED == TRUE) case HCI_READ_INQ_TX_POWER_LEVEL: btm_read_linq_tx_power_complete (p); break; -#if (CLASSIC_BT_INCLUDED == TRUE) case HCI_SET_AFH_CHANNELS: btm_set_afh_channels_complete(p); break; @@ -1055,22 +1239,26 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l break; case HCI_BLE_READ_ADV_CHNL_TX_POWER: +#if (BLE_HOST_READ_TX_POWER_EN == TRUE) btm_read_tx_power_complete(p, TRUE); +#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) break; - +#if (BLE_42_ADV_EN == TRUE) case HCI_BLE_WRITE_ADV_ENABLE: btm_ble_write_adv_enable_complete(p); break; - +#endif // #if (BLE_42_ADV_EN == TRUE) case HCI_BLE_CREATE_LL_CONN: btm_ble_create_ll_conn_complete(*p); break; case HCI_BLE_TRANSMITTER_TEST: case HCI_BLE_RECEIVER_TEST: +#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) case HCI_BLE_TEST_END: btm_ble_test_command_complete(p); break; +#endif // #if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) case HCI_BLE_CREATE_CONN_CANCEL: btm_ble_create_conn_cancel_complete(p); break; @@ -1105,6 +1293,7 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l break; #endif // #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) case HCI_BLE_SET_EXT_ADV_PARAM: case HCI_BLE_SET_EXT_ADV_DATA: case HCI_BLE_SET_EXT_SCAN_RSP_DATA: @@ -1113,6 +1302,7 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l HCI_TRACE_EVENT("%s opcode 0x%x status 0x%x", __func__, opcode, status); break; } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) case HCI_BLE_READ_PHY: { uint16_t conn_handle; uint8_t tx_phy; @@ -1124,11 +1314,14 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l btm_read_phy_callback(status, conn_handle, tx_phy, rx_phy); break; } +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_DTM_TEST_EN == TRUE) case HCI_BLE_ENH_RX_TEST: case HCI_BLE_ENH_TX_TEST: btm_ble_test_command_complete(p); break; -#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) + #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) case HCI_BLE_SET_PERIOD_ADV_RECV_ENABLE: case HCI_BLE_SET_DEFAULT_PAST_PARAMS: @@ -1143,6 +1336,59 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l break; } #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + case HCI_BLE_BIG_TERMINATE_SYNC: + UINT16 big_handle; + STREAM_TO_UINT8(status, p); + STREAM_TO_UINT8(big_handle, p); + btm_ble_big_sync_terminate_complete(status, big_handle); + break; +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + case HCI_BLE_ISO_SET_DATA_PATH: + case HCI_BLE_ISO_REMOVE_DATA_PATH: + UINT16 conn_handle; + STREAM_TO_UINT8(status, p); + STREAM_TO_UINT16(conn_handle, p); + btm_ble_iso_data_path_update_complete(opcode, status, conn_handle); + break; + case HCI_BLE_ISO_READ_TX_SYNC: + btm_ble_iso_read_iso_tx_sync_complete(p); + break; + case HCI_BLE_ISO_READ_ISO_LINK_QUALITY: + btm_ble_iso_read_iso_link_quality_complete(p); + break; + +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + case HCI_BLE_ISO_SET_CIG_PARAMS: + case HCI_BLE_ISO_SET_CIG_PARAMS_TEST: + btm_ble_iso_set_cig_params_complete(p); + break; + case HCI_BLE_ISO_REMOVE_CIG: + // do nothing + break; +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + case HCI_BLE_ISO_ACCEPT_CIS_REQ: + case HCI_BLE_ISO_REJECT_CIS_REQ: + // do nothing + break; +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + +#endif // #if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_CTE_EN == TRUE) + case HCI_BLE_READ_ANT_INFOR: + btm_ble_cte_read_ant_infor_complete(p); + break; +#endif // #if (BLE_FEAT_CTE_EN == TRUE) + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + case HCI_BLE_ENH_READ_TRANS_POWER_LEVEL: + btm_enh_read_trans_pwr_level_cmpl_evt(p); + break; +#endif //#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + #endif /* (BLE_INCLUDED == TRUE) */ default: { @@ -1192,6 +1438,7 @@ static void btu_hcif_command_complete_evt(BT_HDR *response, void *context) uint8_t *stream = response->data + response->offset + 3; STREAM_TO_UINT16(opcode, stream); switch (opcode) { +#if (BLE_42_ADV_EN == TRUE) case HCI_BLE_WRITE_ADV_DATA: adv_data_status = *stream; osi_sem_give(&adv_data_sem); @@ -1209,6 +1456,8 @@ static void btu_hcif_command_complete_evt(BT_HDR *response, void *context) adv_param_status = *stream; osi_sem_give(&adv_param_sem); break; +#endif // #if (BLE_42_ADV_EN == TRUE) +#if (BLE_42_SCAN_EN == TRUE) case HCI_BLE_WRITE_SCAN_PARAMS: scan_param_status = *stream; osi_sem_give(&scan_param_sem); @@ -1217,6 +1466,7 @@ static void btu_hcif_command_complete_evt(BT_HDR *response, void *context) scan_enable_status = *stream; osi_sem_give(&scan_enable_sem); break; +#endif // #if (BLE_42_SCAN_EN == TRUE) default: break; } @@ -1265,6 +1515,7 @@ static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_c #endif switch (opcode) { +#if (CLASSIC_BT_INCLUDED == TRUE) case HCI_EXIT_SNIFF_MODE: case HCI_EXIT_PARK_MODE: #if BTM_SCO_WAKE_PARKED_LINK == TRUE @@ -1284,7 +1535,9 @@ static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_c case HCI_PARK_MODE: btm_pm_proc_cmd_status(status); break; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) case HCI_BLE_PERIOD_ADV_CREATE_SYNC: { uint8_t btm_status = BTM_SUCCESS; @@ -1295,6 +1548,7 @@ static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_c btm_create_sync_callback(btm_status); break; } +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) case HCI_BLE_SET_PHY: { uint8_t btm_status = BTM_SUCCESS; @@ -1306,6 +1560,42 @@ static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_c break; } #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + case HCI_BLE_CREATE_BIG: + case HCI_BLE_CREATE_BIG_TEST: + btu_ble_create_big_cmd_status(status); + break; + case HCI_BLE_TERMINATE_BIG: + btu_ble_big_terminate_cmd_status(status); + break; +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + case HCI_BLE_BIG_CREATE_SYNC: + btu_ble_create_big_sync_cmd_status(status); + break; +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + case HCI_BLE_ISO_CREATE_CIS: + btu_ble_create_cis_cmd_status(status); + break; +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + case HCI_BLE_ISO_ACCEPT_CIS_REQ: + btu_ble_accept_cis_req_cmd_status(status); + break; +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#endif // #if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + case HCI_BLE_READ_REMOTE_TRANS_POWER_LEVEL: + btm_read_remote_trans_pwr_level_cmpl(status); + break; +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) + case HCI_BLE_SUBRATE_REQUEST: + btm_subrate_req_cmd_status(status); + break; +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) default: /* If command failed to start, we may need to tell BTM */ if (status != HCI_SUCCESS) { @@ -1379,6 +1669,9 @@ static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_c break; #if BLE_INCLUDED == TRUE +#if (BLE_50_FEATURE_SUPPORT == TRUE) + case HCI_BLE_EXT_CREATE_CONN: +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) case HCI_BLE_CREATE_LL_CONN: btm_ble_create_ll_conn_complete(status); break; @@ -1498,7 +1791,7 @@ static void btu_hcif_hardware_error_evt (UINT8 *p) } } - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btu_hcif_flush_occured_evt @@ -1535,7 +1828,7 @@ static void btu_hcif_role_change_evt (UINT8 *p) l2c_link_role_changed (bda, role, status); btm_acl_role_changed(status, bda, role); } - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** @@ -1556,7 +1849,7 @@ static void btu_hcif_num_compl_data_pkts_evt (UINT8 *p) btm_sco_process_num_completed_pkts (p); #endif } - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btu_hcif_mode_change_evt @@ -1624,7 +1917,7 @@ static void btu_hcif_ssr_evt (UINT8 *p, UINT16 evt_len) HCI_TRACE_WARNING("hcif ssr evt: st 0x%x, hdl 0x%x, tx_lat %d rx_lat %d", status, handle, max_tx_lat, max_rx_lat); } - +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btu_hcif_pin_code_request_evt @@ -1635,6 +1928,7 @@ static void btu_hcif_ssr_evt (UINT8 *p, UINT16 evt_len) ** *******************************************************************************/ #if (SMP_INCLUDED == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) static void btu_hcif_pin_code_request_evt (UINT8 *p) { #if (CLASSIC_BT_INCLUDED == TRUE) @@ -1689,9 +1983,10 @@ static void btu_hcif_link_key_notification_evt (UINT8 *p) btm_sec_link_key_notification (bda, key, key_type); } +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #endif ///SMP_INCLUDED == TRUE - +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btu_hcif_loopback_command_evt @@ -1867,7 +2162,7 @@ static void btu_hcif_host_support_evt (UINT8 *p) ** Returns void ** *******************************************************************************/ -#if (CLASSIC_BT_INCLUDED == TRUE) + static void btu_hcif_io_cap_request_evt (UINT8 *p) { btm_io_capabilities_req(p); @@ -1976,6 +2271,7 @@ static void btu_hcif_rem_oob_request_evt (UINT8 *p) } #endif +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function btu_hcif_link_supv_to_changed_evt @@ -2014,6 +2310,7 @@ static void btu_hcif_enhanced_flush_complete_evt (void) /* This is empty until an upper layer cares about returning event */ } #endif +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) /********************************************** ** End of Simple Pairing Events ***********************************************/ @@ -2133,6 +2430,7 @@ static void btu_ble_phy_update_complete_evt(UINT8 *p) } #if BLE_PRIVACY_SPT == TRUE +#if (BLE_50_EXTEND_SCAN_EN == TRUE) /******************************************************************************* ** ** Function btm_ble_resolve_random_addr_adv_ext @@ -2153,13 +2451,17 @@ static void btm_ble_resolve_random_addr_adv_ext(void *p_rec, void *p) BDADDR_TO_STREAM(pp,bda); } } +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) #endif +#if (BLE_50_EXTEND_SCAN_EN == TRUE) static void btu_ble_ext_adv_report_evt(UINT8 *p, UINT16 evt_len) { tBTM_BLE_EXT_ADV_REPORT ext_adv_report = {0}; UINT8 num_reports = {0}; +#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) UINT8 *pp = p; +#endif //UINT8 legacy_event_type = 0; UINT16 evt_type = 0; uint8_t addr_type; @@ -2233,7 +2535,9 @@ static void btu_ble_ext_adv_report_evt(UINT8 *p, UINT16 evt_len) } } +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) static void btu_ble_periodic_adv_sync_establish_evt(UINT8 *p) { tBTM_BLE_PERIOD_ADV_SYNC_ESTAB sync_estab = {0}; @@ -2274,7 +2578,7 @@ static void btu_ble_periodic_adv_report_evt(UINT8 *p, UINT8 evt_len) STREAM_TO_UINT16(adv_report.sync_handle, p); STREAM_TO_UINT8(adv_report.tx_power, p); STREAM_TO_UINT8(adv_report.rssi, p); - STREAM_TO_UINT8(unused, p); + STREAM_TO_UINT8(adv_report.cte_type, p); STREAM_TO_UINT8(adv_report.data_status, p); STREAM_TO_UINT8(adv_report.data_length, p); @@ -2306,14 +2610,18 @@ static void btu_ble_periodic_adv_sync_lost_evt(UINT8 *p) btm_ble_periodic_adv_sync_lost_evt(&sync_lost); } +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if (BLE_50_EXTEND_SCAN_EN == TRUE) static void btu_ble_scan_timeout_evt(UINT8 *p) { UNUSED(p); btm_ble_scan_timeout_evt(); } +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) static void btu_ble_adv_set_terminate_evt(UINT8 *p) { tBTM_BLE_ADV_TERMINAT adv_term = {0}; @@ -2346,6 +2654,22 @@ static void btu_ble_scan_req_received_evt(UINT8 *p) btm_ble_scan_req_received_evt(&req_received); } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) + +static void btu_ble_channel_select_alg_evt(UINT8 *p) +{ + tBTM_BLE_CHANNEL_SEL_ALG chan_sel_alg = {0}; + + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT16(chan_sel_alg.conn_handle, p); + STREAM_TO_UINT8(chan_sel_alg.channel_sel_alg, p); + + btm_ble_channel_select_algorithm_evt(&chan_sel_alg); +} #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) @@ -2380,6 +2704,384 @@ static void btu_ble_periodic_adv_sync_trans_recv(UINT8 *p) } #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +static void btu_ble_create_cis_cmd_status(UINT8 status) +{ + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + if (status != HCI_SUCCESS) { + status = (BTM_HCI_ERROR | status); + } + cb_params.status = status; + btm_ble_create_cis_cmd_status(&cb_params); +} +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +static void btu_ble_accept_cis_req_cmd_status(UINT8 status) +{ + tBTM_BLE_ISO_CB_PARAMS cb_params = {0}; + if (status != HCI_SUCCESS) { + status = (BTM_HCI_ERROR | status); + } + cb_params.status = status; + + btm_ble_accept_cis_req_cmd_status(&cb_params); +} +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_EN == TRUE) +static void btu_ble_cis_disconnected(UINT16 handle, UINT8 reason) +{ + tBTM_BLE_CIS_DISCON_CMPL cis_disconnected_evt = {0}; + cis_disconnected_evt.cis_handle = handle; + cis_disconnected_evt.reason = reason; + btm_ble_cis_disconnected_evt(&cis_disconnected_evt); +} + +static void btu_ble_cis_established_evt(UINT8 *p) +{ + HCI_TRACE_DEBUG("%s", __func__); + tBTM_BLE_CIS_ESTABLISHED_CMPL cis_estab_evt = {0}; + + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT8(cis_estab_evt.status, p); + STREAM_TO_UINT16(cis_estab_evt.conn_handle, p); + STREAM_TO_UINT24(cis_estab_evt.cig_sync_delay, p); + STREAM_TO_UINT24(cis_estab_evt.cis_sync_delay, p); + STREAM_TO_UINT24(cis_estab_evt.trans_lat_c_to_p, p); + STREAM_TO_UINT24(cis_estab_evt.trans_lat_p_to_c, p); + STREAM_TO_UINT8(cis_estab_evt.phy_c_to_p, p); + STREAM_TO_UINT8(cis_estab_evt.phy_p_to_c, p); + STREAM_TO_UINT8(cis_estab_evt.nse, p); + STREAM_TO_UINT8(cis_estab_evt.bn_c_to_p, p); + STREAM_TO_UINT8(cis_estab_evt.bn_p_to_c, p); + STREAM_TO_UINT8(cis_estab_evt.ft_c_to_p, p); + STREAM_TO_UINT8(cis_estab_evt.ft_p_to_c, p); + STREAM_TO_UINT16(cis_estab_evt.max_pdu_c_to_p, p); + STREAM_TO_UINT16(cis_estab_evt.max_pdu_p_to_c, p); + STREAM_TO_UINT16(cis_estab_evt.iso_interval, p); +#if (BLE_FEAT_ISO_60_EN == TRUE) + STREAM_TO_UINT24(cis_estab_evt.sub_interval, p); + STREAM_TO_UINT16(cis_estab_evt.max_sdu_c_to_p, p); + STREAM_TO_UINT16(cis_estab_evt.max_sdu_p_to_c, p); + STREAM_TO_UINT24(cis_estab_evt.sdu_int_c_to_p, p); + STREAM_TO_UINT24(cis_estab_evt.sdu_int_p_to_c, p); + STREAM_TO_UINT8(cis_estab_evt.framing, p); +#endif // #if (BLE_FEAT_ISO_60_EN == TRUE) + + btm_ble_cis_established_evt(&cis_estab_evt); +} +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +static void btu_ble_cis_request_evt(UINT8 *p) +{ + HCI_TRACE_DEBUG("%s", __func__); + tBTM_BLE_CIS_REQUEST_CMPL cis_req_evt = {0}; + + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT16(cis_req_evt.acl_handle, p); + STREAM_TO_UINT16(cis_req_evt.cis_handle, p); + STREAM_TO_UINT8(cis_req_evt.cig_id, p); + STREAM_TO_UINT8(cis_req_evt.cis_id, p); + + + btm_ble_cis_request_evt(&cis_req_evt); +} +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +void btu_ble_create_big_cmd_status(UINT8 status) +{ + if (status != HCI_SUCCESS) { + tBTM_BLE_BIG_CREATE_CMPL big_cmpl = {0}; + btm_ble_big_create_cmpl_evt(&big_cmpl); + } +} + +static void btu_ble_big_create_complete_evt(UINT8 *p) +{ + HCI_TRACE_DEBUG("%s", __func__); + tBTM_BLE_BIG_CREATE_CMPL big_cmpl = {0}; + + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT8(big_cmpl.status, p); + STREAM_TO_UINT8(big_cmpl.big_handle, p); + STREAM_TO_UINT24(big_cmpl.big_sync_delay, p); + STREAM_TO_UINT24(big_cmpl.transport_latency, p); + STREAM_TO_UINT8(big_cmpl.phy, p); + STREAM_TO_UINT8(big_cmpl.nse, p); + STREAM_TO_UINT8(big_cmpl.bn, p); + STREAM_TO_UINT8(big_cmpl.pto, p); + STREAM_TO_UINT8(big_cmpl.irc, p); + STREAM_TO_UINT16(big_cmpl.max_pdu, p); + STREAM_TO_UINT16(big_cmpl.iso_interval, p); + STREAM_TO_UINT8(big_cmpl.num_bis, p); + for (uint8_t i = 0; i < big_cmpl.num_bis; i++) + { + STREAM_TO_UINT16(big_cmpl.bis_handle[i], p); + // only 12 bits meaningful + big_cmpl.bis_handle[i] = (big_cmpl.bis_handle[i] & 0x0FFF); + } + + btm_ble_big_create_cmpl_evt(&big_cmpl); +} + +void btu_ble_big_terminate_cmd_status(UINT8 status) +{ + if (status != HCI_SUCCESS) { + tBTM_BLE_BIG_TERMINATE_CMPL big_term = {0}; + big_term.status = (status | BTM_HCI_ERROR); + btm_ble_big_terminate_cmpl_evt(&big_term); + } +} + +static void btu_ble_big_terminate_complete_evt(UINT8 *p) +{ + tBTM_BLE_BIG_TERMINATE_CMPL big_term = {0}; + + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT8(big_term.big_handle, p); + STREAM_TO_UINT8(big_term.reason, p); + big_term.status = HCI_SUCCESS; + + btm_ble_big_terminate_cmpl_evt(&big_term); +} +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +void btu_ble_create_big_sync_cmd_status(UINT8 status) +{ + if (status != HCI_SUCCESS) { + tBTM_BLE_BIG_SYNC_ESTAB_CMPL big_estb = {0}; + big_estb.status = status; + btm_ble_big_sync_estab_evt(&big_estb); + } +} + +static void btu_ble_big_sync_establish_evt(UINT8 *p) +{ + tBTM_BLE_BIG_SYNC_ESTAB_CMPL big_estb = {0}; + + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT8(big_estb.status, p); + STREAM_TO_UINT8(big_estb.big_handle, p); + STREAM_TO_UINT24(big_estb.transport_latency_big, p); + STREAM_TO_UINT8(big_estb.nse, p); + STREAM_TO_UINT8(big_estb.bn, p); + STREAM_TO_UINT8(big_estb.pto, p); + STREAM_TO_UINT8(big_estb.irc, p); + STREAM_TO_UINT16(big_estb.max_pdu, p); + STREAM_TO_UINT16(big_estb.iso_interval, p); + STREAM_TO_UINT8(big_estb.num_bis, p); + for (uint8_t i = 0; i < big_estb.num_bis; i++) + { + STREAM_TO_UINT16(big_estb.bis_handle[i], p); + } + + btm_ble_big_sync_estab_evt(&big_estb); +} + +static void btu_ble_big_sync_lost_evt(UINT8 *p) +{ + tBTM_BLE_BIG_SYNC_LOST_EVT big_sync_lost = {0}; + + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT8(big_sync_lost.big_handle, p); + STREAM_TO_UINT8(big_sync_lost.reason, p); + + btm_ble_big_sync_lost_evt(&big_sync_lost); +} + +static void btu_ble_biginfo_adv_report_evt(UINT8 *p) +{ + tBTM_BLE_BIGINFO_ADV_REPORT_EVT biginfo_report = {0}; + + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT16(biginfo_report.sync_handle, p); + STREAM_TO_UINT8(biginfo_report.num_bis, p); + STREAM_TO_UINT8(biginfo_report.nse, p); + STREAM_TO_UINT16(biginfo_report.iso_interval, p); + STREAM_TO_UINT8(biginfo_report.bn, p); + STREAM_TO_UINT8(biginfo_report.pto, p); + STREAM_TO_UINT8(biginfo_report.irc, p); + STREAM_TO_UINT16(biginfo_report.max_pdu, p); + STREAM_TO_UINT24(biginfo_report.sdu_interval, p); + STREAM_TO_UINT16(biginfo_report.max_sdu, p); + STREAM_TO_UINT8(biginfo_report.phy, p); + STREAM_TO_UINT8(biginfo_report.framing, p); + STREAM_TO_UINT8(biginfo_report.encryption, p); + + btm_ble_biginfo_adv_report_evt(&biginfo_report); +} +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +static void btu_ble_cte_connless_iq_report_evt(UINT8 *p) +{ + tBTM_BLE_CTE_CONNLESS_IQ_REPORT_EVT connless_iq_rpt = {0}; + + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT16(connless_iq_rpt.sync_handle, p); + STREAM_TO_UINT8(connless_iq_rpt.channel_idx, p); + STREAM_TO_UINT16(connless_iq_rpt.rssi, p); + STREAM_TO_UINT8(connless_iq_rpt.rssi_ant_id, p); + STREAM_TO_UINT8(connless_iq_rpt.cte_type, p); + STREAM_TO_UINT8(connless_iq_rpt.slot_dur, p); + STREAM_TO_UINT8(connless_iq_rpt.pkt_status, p); + STREAM_TO_UINT16(connless_iq_rpt.periodic_evt_counter, p); + STREAM_TO_UINT8(connless_iq_rpt.sample_count, p); + + for (uint8_t i = 0; i < connless_iq_rpt.sample_count; i++) + { + STREAM_TO_UINT8(connless_iq_rpt.i_sample[i], p); + STREAM_TO_UINT8(connless_iq_rpt.q_sample[i], p); + } + + btm_ble_connless_iq_report_evt(&connless_iq_rpt); +} +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +static void btu_ble_cte_conn_iq_report_evt(UINT8 *p) +{ + tBTM_BLE_CTE_CONN_IQ_REPORT_EVT conn_iq_rpt = {0}; + + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT16(conn_iq_rpt.conn_handle, p); + STREAM_TO_UINT8(conn_iq_rpt.rx_phy, p); + STREAM_TO_UINT8(conn_iq_rpt.data_channel_idx, p); + STREAM_TO_UINT16(conn_iq_rpt.rssi, p); + STREAM_TO_UINT8(conn_iq_rpt.rssi_ant_id, p); + STREAM_TO_UINT8(conn_iq_rpt.cte_type, p); + STREAM_TO_UINT8(conn_iq_rpt.slot_dur, p); + STREAM_TO_UINT8(conn_iq_rpt.pkt_status, p); + STREAM_TO_UINT16(conn_iq_rpt.conn_evt_counter, p); + STREAM_TO_UINT8(conn_iq_rpt.sample_count, p); + + for (uint8_t i = 0; i < conn_iq_rpt.sample_count; i++) + { + STREAM_TO_UINT8(conn_iq_rpt.i_sample[i], p); + STREAM_TO_UINT8(conn_iq_rpt.q_sample[i], p); + } + + btm_ble_conn_iq_report_evt(&conn_iq_rpt); +} + +static void btu_ble_cte_req_failed_evt(UINT8 *p) +{ + tBTM_BLE_CTE_REQ_FAILED_EVT cte_req_failed = {0}; + + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT8(cte_req_failed.status, p); + STREAM_TO_UINT16(cte_req_failed.conn_handle, p); + + btm_ble_cte_req_failed_evt(&cte_req_failed); +} +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + +#endif // #if (BLE_FEAT_CTE_EN == TRUE) + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +static void btu_ble_path_loss_threshold_evt(UINT8 *p) +{ + tBTM_BLE_PATH_LOSS_THRESHOLD_EVT path_loss_thres_evt = {0}; + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT16(path_loss_thres_evt.conn_handle, p); + STREAM_TO_UINT8(path_loss_thres_evt.cur_path_loss, p); + STREAM_TO_UINT8(path_loss_thres_evt.zone_entered, p); + + btm_ble_path_loss_threshold_evt(&path_loss_thres_evt); +} + +static void btu_ble_transmit_power_report_evt(UINT8 *p) +{ + tBTM_BLE_TRANS_POWER_REPORT_EVT trans_pwr_report_evt = {0}; + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT8(trans_pwr_report_evt.status, p); + STREAM_TO_UINT16(trans_pwr_report_evt.conn_handle, p); + STREAM_TO_UINT8(trans_pwr_report_evt.reason, p); + STREAM_TO_UINT8(trans_pwr_report_evt.phy, p); + STREAM_TO_UINT8(trans_pwr_report_evt.tx_power_level, p); + STREAM_TO_UINT8(trans_pwr_report_evt.tx_power_level_flag, p); + STREAM_TO_UINT8(trans_pwr_report_evt.delta, p); + + btm_ble_transmit_power_report_evt(&trans_pwr_report_evt); +} +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +static void btu_ble_subrate_change_evt(UINT8 *p) +{ + tBTM_BLE_SUBRATE_CHANGE_EVT subrate_change_evt = {0}; + if (!p) { + HCI_TRACE_ERROR("%s, Invalid params.", __func__); + return; + } + + STREAM_TO_UINT8(subrate_change_evt.status, p); + STREAM_TO_UINT16(subrate_change_evt.conn_handle, p); + STREAM_TO_UINT16(subrate_change_evt.subrate_factor, p); + STREAM_TO_UINT16(subrate_change_evt.peripheral_latency, p); + STREAM_TO_UINT16(subrate_change_evt.continuation_number, p); + STREAM_TO_UINT16(subrate_change_evt.supervision_timeout, p); + + btm_ble_subrate_change_evt(&subrate_change_evt); +} +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + /********************************************** ** End of BLE Events Handler ***********************************************/ diff --git a/lib/bt/host/bluedroid/stack/btu/btu_init.c b/lib/bt/host/bluedroid/stack/btu/btu_init.c index 9ede9c2d..a00b3243 100644 --- a/lib/bt/host/bluedroid/stack/btu/btu_init.c +++ b/lib/bt/host/bluedroid/stack/btu/btu_init.c @@ -254,17 +254,6 @@ UINT16 BTU_BleAclPktSize(void) #endif } -#if SCAN_QUEUE_CONGEST_CHECK -bool BTU_check_queue_is_congest(void) -{ - if (osi_thread_queue_wait_size(btu_thread, 0) >= BT_QUEUE_CONGEST_SIZE) { - return true; - } - - return false; -} -#endif - int get_btu_work_queue_size(void) { return osi_thread_queue_wait_size(btu_thread, 0); diff --git a/lib/bt/host/bluedroid/stack/btu/btu_task.c b/lib/bt/host/bluedroid/stack/btu/btu_task.c index 9311a36d..bffa6837 100644 --- a/lib/bt/host/bluedroid/stack/btu/btu_task.c +++ b/lib/bt/host/bluedroid/stack/btu/btu_task.c @@ -229,11 +229,13 @@ bool btu_task_post(uint32_t sig, void *param, uint32_t timeout) break; case SIG_BTU_HCI_ADV_RPT_MSG: #if BLE_INCLUDED == TRUE +#if (BLE_42_SCAN_EN == TRUE) if (param != NULL) { btm_ble_adv_pkt_post(param); } btm_ble_adv_pkt_ready(); status = true; +#endif // #if (BLE_42_SCAN_EN == TRUE) #else osi_free(param); status = false; @@ -451,7 +453,7 @@ void btu_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec) // NOTE: This value is in seconds but stored in a ticks field. p_tle->ticks = timeout_sec; p_tle->in_use = TRUE; - osi_alarm_set(alarm, (period_ms_t)(timeout_sec * 1000)); + osi_alarm_set(alarm, (period_ms_t)((period_ms_t)timeout_sec * 1000)); } diff --git a/lib/bt/host/bluedroid/stack/gatt/gatt_api.c b/lib/bt/host/bluedroid/stack/gatt/gatt_api.c index 8d8056f6..51e46e22 100644 --- a/lib/bt/host/bluedroid/stack/gatt/gatt_api.c +++ b/lib/bt/host/bluedroid/stack/gatt/gatt_api.c @@ -75,7 +75,7 @@ UINT8 GATT_SetTraceLevel (UINT8 new_level) ** ** Function GATTS_AddHandleRange ** -** Description This function add the allocated handles range for the specifed +** Description This function add the allocated handles range for the specified ** application UUID, service UUID and service instance ** ** Parameter p_hndl_range: pointer to allocated handles information @@ -105,7 +105,7 @@ BOOLEAN GATTS_AddHandleRange(tGATTS_HNDL_RANGE *p_hndl_range) ** NV save callback function. There can be one and only one ** NV save callback function. ** -** Parameter p_cb_info : callback informaiton +** Parameter p_cb_info : callback information ** ** Returns TRUE if registered OK, else FALSE ** @@ -151,7 +151,7 @@ static void gatt_update_for_database_change(void) ** num_handles : number of handles needed by the service. ** is_pri : is a primary service or not. ** -** Returns service handle if sucessful, otherwise 0. +** Returns service handle if successful, otherwise 0. ** *******************************************************************************/ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid, @@ -170,7 +170,7 @@ UINT16 GATTS_CreateService (tGATT_IF gatt_if, tBT_UUID *p_svc_uuid, GATT_TRACE_API ("GATTS_CreateService\n" ); if (p_reg == NULL) { - GATT_TRACE_ERROR ("Inavlid gatt_if=%d\n", gatt_if); + GATT_TRACE_ERROR ("Invalid gatt_if=%d\n", gatt_if); return (0); } @@ -491,7 +491,7 @@ tGATT_STATUS GATTS_StartService (tGATT_IF gatt_if, UINT16 service_handle, return GATT_SERVICE_STARTED; } - /*this is a new application servoce start */ + /*this is a new application service start */ if ((i_sreg = gatt_sr_alloc_rcb(p_list)) == GATT_MAX_SR_PROFILES) { GATT_TRACE_ERROR ("GATTS_StartService: no free server registration block"); return GATT_NO_RESOURCES; @@ -1388,8 +1388,9 @@ void GATT_Deregister (tGATT_IF gatt_if) } } } - +#if (tGATT_BG_CONN_DEV == TRUE) gatt_deregister_bgdev_list(gatt_if); +#endif // #if (tGATT_BG_CONN_DEV == TRUE) /* update the listen mode */ #if (defined(BLE_PERIPHERAL_MODE_SUPPORT) && (BLE_PERIPHERAL_MODE_SUPPORT == TRUE)) GATT_Listen(gatt_if, FALSE, NULL); @@ -1468,9 +1469,12 @@ BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, tBLE_ADDR_TYPE bd_addr_ if (is_direct) { status = gatt_act_connect (p_reg, bd_addr, bd_addr_type, transport, is_aux); } else { +#if (tGATT_BG_CONN_DEV == TRUE) if (transport == BT_TRANSPORT_LE) { status = gatt_update_auto_connect_dev(gatt_if, TRUE, bd_addr, TRUE); - } else { + } else +#endif // #if (tGATT_BG_CONN_DEV == TRUE) + { GATT_TRACE_ERROR("Unsupported transport for background connection"); } } @@ -1483,7 +1487,7 @@ BOOLEAN GATT_Connect (tGATT_IF gatt_if, BD_ADDR bd_addr, tBLE_ADDR_TYPE bd_addr_ ** ** Function GATT_CancelConnect ** -** Description This function terminate the connection initaition to a remote +** Description This function terminate the connection initiation to a remote ** device on GATT channel. ** ** Parameters gatt_if: client interface. If 0 used as unconditionally disconnect, @@ -1527,6 +1531,7 @@ BOOLEAN GATT_CancelConnect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct status = gatt_cancel_open(gatt_if, bd_addr); } } else { +#if (tGATT_BG_CONN_DEV == TRUE) if (!gatt_if) { if (gatt_get_num_apps_for_bg_dev(bd_addr)) { while (gatt_find_app_for_bg_dev(bd_addr, &temp_gatt_if)) { @@ -1539,6 +1544,7 @@ BOOLEAN GATT_CancelConnect (tGATT_IF gatt_if, BD_ADDR bd_addr, BOOLEAN is_direct } else { status = gatt_remove_bg_dev_for_app(gatt_if, bd_addr); } +#endif // #if (tGATT_BG_CONN_DEV == TRUE) } return status; @@ -1628,7 +1634,7 @@ tGATT_STATUS GATT_SendServiceChangeIndication (BD_ADDR bd_addr) ** ** Function GATT_GetConnectionInfor ** -** Description This function use conn_id to find its associated BD address and applciation +** Description This function use conn_id to find its associated BD address and application ** interface ** ** Parameters conn_id: connection id (input) @@ -1665,7 +1671,7 @@ BOOLEAN GATT_GetConnectionInfor(UINT16 conn_id, tGATT_IF *p_gatt_if, BD_ADDR bd_ ** Function GATT_GetConnIdIfConnected ** ** Description This function find the conn_id if the logical link for BD address -** and applciation interface is connected +** and application interface is connected ** ** Parameters gatt_if: application interface (input) ** bd_addr: peer device address. (input) @@ -1720,7 +1726,9 @@ BOOLEAN GATT_Listen (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr) } if (bd_addr != NULL) { +#if (tGATT_BG_CONN_DEV == TRUE) gatt_update_auto_connect_dev(gatt_if, start, bd_addr, FALSE); +#endif // #if (tGATT_BG_CONN_DEV == TRUE) } else { p_reg->listening = start ? GATT_LISTEN_TO_ALL : GATT_LISTEN_TO_NONE; } diff --git a/lib/bt/host/bluedroid/stack/gatt/gatt_db.c b/lib/bt/host/bluedroid/stack/gatt/gatt_db.c index efae6413..8844ef5d 100644 --- a/lib/bt/host/bluedroid/stack/gatt/gatt_db.c +++ b/lib/bt/host/bluedroid/stack/gatt/gatt_db.c @@ -60,7 +60,7 @@ static BOOLEAN gatts_add_char_desc_value_check (tGATT_ATTR_VAL *attr_val, tGATTS ** Parameter p_db: database pointer. ** len: size of the memory space. ** -** Returns Status of te operation. +** Returns Status of the operation. ** *******************************************************************************/ BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN is_pri, @@ -94,7 +94,7 @@ BOOLEAN gatts_init_service_db (tGATT_SVC_DB *p_db, tBT_UUID *p_service, BOOLEAN ** Parameter p_db: database pointer. ** len: size of the memory space. ** -** Returns Status of te operation. +** Returns Status of the operation. ** *******************************************************************************/ tBT_UUID *gatts_get_service_uuid (tGATT_SVC_DB *p_db) @@ -497,14 +497,14 @@ UINT16 gatts_add_included_service (tGATT_SVC_DB *p_db, UINT16 s_handle, UINT16 e ** Function gatts_add_characteristic ** ** Description This function add a characteristics and its descriptor into -** a servce identified by the service database pointer. +** a service identified by the service database pointer. ** ** Parameter p_db: database pointer. ** perm: permission (authentication and key size requirements) ** property: property of the characteristic. ** p_char: characteristic value information. ** -** Returns Status of te operation. +** Returns Status of the operation. ** *******************************************************************************/ UINT16 gatts_add_characteristic (tGATT_SVC_DB *p_db, tGATT_PERM perm, @@ -1173,40 +1173,40 @@ tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code, if ((op_code == GATT_SIGN_CMD_WRITE) && !(perm & GATT_WRITE_SIGNED_PERM)) { status = GATT_WRITE_NOT_PERMIT; - GATT_TRACE_DEBUG( "gatts_write_attr_perm_check - sign cmd write not allowed,handle:0x%04x",handle); + GATT_TRACE_DEBUG( "gatts_write_attr_perm_check - sign cmd write not allowed,handle %04x,perm %04x", handle, perm); } if ((op_code == GATT_SIGN_CMD_WRITE) && (sec_flag & GATT_SEC_FLAG_ENCRYPTED)) { status = GATT_INVALID_PDU; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - Error!! sign cmd write sent on a encypted link,handle:0x%04x",handle); + GATT_TRACE_ERROR( "gatts_write_attr_perm_check - Error!! sign cmd write sent on a encrypted link,handle %04x,perm %04x", handle, perm); } else if (!(perm & GATT_WRITE_ALLOWED)) { status = GATT_WRITE_NOT_PERMIT; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_WRITE_NOT_PERMIT,handle:0x%04x",handle); + GATT_TRACE_ERROR("gatts_write_attr_perm_check - GATT_WRITE_NOT_PERMIT,handle %04x, perm %04x", handle, perm); } /* require authentication, but not been authenticated */ else if ((perm & GATT_WRITE_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED)) { status = GATT_INSUF_AUTHENTICATION; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION,handle:0x%04x",handle); + GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION,handle %04x, perm %04x", handle, perm); } else if ((perm & GATT_WRITE_MITM_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED)) { status = GATT_INSUF_AUTHENTICATION; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: MITM required,handle:0x%04x",handle); + GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: MITM required,handle %04x,perm %04x", handle, perm); } else if ((perm & GATT_WRITE_ENCRYPTED_PERM ) && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)) { status = GATT_INSUF_ENCRYPTION; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_ENCRYPTION,handle:0x%04x",handle); + GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_ENCRYPTION,handle:0x%04x, perm:0x%04x", handle, perm); } else if ((perm & GATT_WRITE_ENCRYPTED_PERM ) && (sec_flag & GATT_SEC_FLAG_ENCRYPTED) && (key_size < min_key_size)) { status = GATT_INSUF_KEY_SIZE; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_KEY_SIZE,handle:0x%04x",handle); + GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_KEY_SIZE,handle %04x,perm %04x", handle, perm); } /* LE Authorization check*/ else if ((perm & GATT_WRITE_AUTHORIZATION) && (!(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED) || !(sec_flag & GATT_SEC_FLAG_AUTHORIZATION))){ status = GATT_INSUF_AUTHORIZATION; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHORIZATION,handle:0x%04x",handle); + GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHORIZATION,handle %04x,perm %04x", handle, perm); } /* LE security mode 2 attribute */ else if (perm & GATT_WRITE_SIGNED_PERM && op_code != GATT_SIGN_CMD_WRITE && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED) && (perm & GATT_WRITE_ALLOWED) == 0) { status = GATT_INSUF_AUTHENTICATION; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: LE security mode 2 required,handle:0x%04x",handle); - } else { /* writable: must be char value declaration or char descritpors */ + GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: LE security mode 2 required,handle %04x,perm %04x", handle, perm); + } else { /* writable: must be char value declaration or char descriptors */ if (p_attr->uuid_type == GATT_ATTR_UUID_TYPE_16) { switch (p_attr->uuid) { case GATT_UUID_CHAR_PRESENT_FORMAT:/* should be readable only */ @@ -1215,13 +1215,19 @@ tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code, case GATT_UUID_CHAR_VALID_RANGE: status = GATT_WRITE_NOT_PERMIT; break; - + case GATT_UUID_GAP_ICON:/* The Appearance characteristic value shall be 2 octets in length */ case GATT_UUID_CHAR_CLIENT_CONFIG: /* coverity[MISSING_BREAK] */ /* intnended fall through, ignored */ /* fall through */ case GATT_UUID_CHAR_SRVR_CONFIG: max_size = 2; + status = GATT_SUCCESS; + break; + case GATT_UUID_CLIENT_SUP_FEAT: + max_size = 1; + status = GATT_SUCCESS; + break; case GATT_UUID_CHAR_DESCRIPTION: default: /* any other must be character value declaration */ status = GATT_SUCCESS; @@ -1242,17 +1248,17 @@ tGATT_STATUS gatts_write_attr_perm_check (tGATT_SVC_DB *p_db, UINT8 op_code, else if ( (p_attr->uuid_type == GATT_ATTR_UUID_TYPE_16) && (p_attr->uuid == GATT_UUID_CHAR_CLIENT_CONFIG || p_attr->uuid == GATT_UUID_CHAR_SRVR_CONFIG || - p_attr->uuid == GATT_UUID_CLIENT_SUP_FEAT || + p_attr->uuid == GATT_UUID_CLIENT_SUP_FEAT || p_attr->uuid == GATT_UUID_GAP_ICON ) ) // btla-specific -- { if (op_code == GATT_REQ_PREPARE_WRITE) { /* does not allow write blob */ status = GATT_REQ_NOT_SUPPORTED; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_REQ_NOT_SUPPORTED,handle:0x%04x",handle); + GATT_TRACE_ERROR("gatts_write_attr_perm_check - GATT_REQ_NOT_SUPPORTED,handle %04x,opcode %4x", handle, op_code); } else if (len != max_size) { /* data does not match the required format */ status = GATT_INVALID_ATTR_LEN; - GATT_TRACE_ERROR( "gatts_write_attr_perm_check - GATT_INVALID_ATTR_LEN,handle:0x%04x",handle); + GATT_TRACE_ERROR("gatts_write_attr_perm_check - GATT_INVALID_ATTR_LEN,handle %04x,op_code %04x,len %d,max_size %d", handle, op_code, len, max_size); } else { status = GATT_SUCCESS; } @@ -1554,7 +1560,7 @@ static BOOLEAN gatts_db_add_service_declaration(tGATT_SVC_DB *p_db, tBT_UUID *p_ uuid.uu.uuid16 = GATT_UUID_SEC_SERVICE; } - /* add service declration record */ + /* add service declaration record */ if ((p_attr = (tGATT_ATTR16 *)(allocate_attr_in_db(p_db, &uuid, GATT_PERM_READ))) != NULL) { if (copy_extra_byte_in_db (p_db, (void **)&p_attr->p_value, sizeof(tBT_UUID))) { if (p_service->len == LEN_UUID_16) { diff --git a/lib/bt/host/bluedroid/stack/gatt/gatt_main.c b/lib/bt/host/bluedroid/stack/gatt/gatt_main.c index d76aefe9..53d9be74 100644 --- a/lib/bt/host/bluedroid/stack/gatt/gatt_main.c +++ b/lib/bt/host/bluedroid/stack/gatt/gatt_main.c @@ -502,7 +502,7 @@ static void gatt_le_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connect #endif ///GATTS_INCLUDED == TRUE } } else { - GATT_TRACE_ERROR("CCB max out, no rsources"); + GATT_TRACE_ERROR("CCB max out, no resources"); } } } else { @@ -929,18 +929,23 @@ static void gatt_send_conn_cback(tGATT_TCB *p_tcb) { UINT8 i; tGATT_REG *p_reg; +#if (tGATT_BG_CONN_DEV == TRUE) tGATT_BG_CONN_DEV *p_bg_dev = NULL; +#endif // #if (tGATT_BG_CONN_DEV == TRUE) UINT16 conn_id; +#if (tGATT_BG_CONN_DEV == TRUE) p_bg_dev = gatt_find_bg_dev(p_tcb->peer_bda); +#endif // #if (tGATT_BG_CONN_DEV == TRUE) /* notifying all applications for the connection up event */ for (i = 0, p_reg = gatt_cb.cl_rcb ; i < GATT_MAX_APPS; i++, p_reg++) { if (p_reg->in_use) { +#if (tGATT_BG_CONN_DEV == TRUE) if (p_bg_dev && gatt_is_bg_dev_for_app(p_bg_dev, p_reg->gatt_if)) { gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, TRUE, TRUE); } - +#endif // #if (tGATT_BG_CONN_DEV == TRUE) if (p_reg->app_cb.p_conn_cb) { conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if); (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id, @@ -1239,7 +1244,8 @@ uint8_t gatt_tcb_active_count(void) for(p_node = list_begin(gatt_cb.p_tcb_list); p_node; p_node = list_next(p_node)) { p_tcb = list_node(p_node); - if (p_tcb && p_tcb->in_use && (p_tcb->ch_state != GATT_CH_CLOSE)) { + if (p_tcb && p_tcb->in_use && (p_tcb->transport == BT_TRANSPORT_LE) && + (p_tcb->ch_state != GATT_CH_CLOSE)) { count++; } } diff --git a/lib/bt/host/bluedroid/stack/gatt/gatt_sr.c b/lib/bt/host/bluedroid/stack/gatt/gatt_sr.c index 79e161c1..5947239c 100644 --- a/lib/bt/host/bluedroid/stack/gatt/gatt_sr.c +++ b/lib/bt/host/bluedroid/stack/gatt/gatt_sr.c @@ -200,7 +200,7 @@ static BOOLEAN process_read_multi_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS status, *p++ = GATT_RSP_READ_MULTI; p_buf->len = 1; - /* Now walk through the buffers puting the data into the response in order */ + /* Now walk through the buffers putting the data into the response in order */ list_t *list = NULL; const list_node_t *node = NULL; if (! fixed_queue_is_empty(p_cmd->multi_rsp_q)) { @@ -321,7 +321,7 @@ static BOOLEAN process_read_multi_var_rsp (tGATT_SR_CMD *p_cmd, tGATT_STATUS sta *p++ = GATT_RSP_READ_MULTI_VAR; p_buf->len = 1; - /* Now walk through the buffers puting the data into the response in order */ + /* Now walk through the buffers putting the data into the response in order */ list_t *list = NULL; const list_node_t *node = NULL; if (! fixed_queue_is_empty(p_cmd->multi_rsp_q)) { @@ -735,7 +735,7 @@ static tGATT_STATUS gatt_build_primary_service_rsp (BT_HDR *p_msg, tGATT_TCB *p_ handle_len = 4 + p_uuid->len; } - /* get the length byte in the repsonse */ + /* get the length byte in the response */ if (p_msg->offset == 0) { *p ++ = op_code + 1; p_msg->len ++; @@ -788,7 +788,7 @@ static tGATT_STATUS gatt_build_primary_service_rsp (BT_HDR *p_msg, tGATT_TCB *p_ ** buffer. ** ** Returns TRUE: if data filled successfully. -** FALSE: packet full, or format mismatch. +** FALSE: packet full. ** *******************************************************************************/ static tGATT_STATUS gatt_build_find_info_rsp(tGATT_SR_REG *p_rcb, BT_HDR *p_msg, UINT16 *p_len, @@ -831,10 +831,9 @@ static tGATT_STATUS gatt_build_find_info_rsp(tGATT_SR_REG *p_rcb, BT_HDR *p_msg, gatt_convert_uuid32_to_uuid128(p, ((tGATT_ATTR32 *) p_attr)->uuid); p += LEN_UUID_128; } else { - GATT_TRACE_ERROR("format mismatch"); - status = GATT_NO_RESOURCES; + // UUID format mismatch in sequential attributes + // A new request will be sent with the starting handle of the next attribute break; - /* format mismatch */ } p_msg->len += info_pair_len[p_msg->offset - 1]; len -= info_pair_len[p_msg->offset - 1]; @@ -889,7 +888,7 @@ static tGATT_STATUS gatts_validate_packet_format(UINT8 op_code, UINT16 *p_len, /* parse uuid now */ if (gatt_parse_uuid_from_cmd (p_uuid_filter, uuid_len, &p) == FALSE || p_uuid_filter->len == 0) { - GATT_TRACE_DEBUG("UUID filter does not exsit"); + GATT_TRACE_DEBUG("UUID filter does not exist"); reason = GATT_INVALID_PDU; } else { len -= p_uuid_filter->len; @@ -1042,7 +1041,7 @@ static void gatts_process_find_info(tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, ** ** Function gatts_process_mtu_req ** -** Description This function is called to process excahnge MTU request. +** Description This function is called to process exchange MTU request. ** Only used on LE. ** ** Returns void @@ -1055,7 +1054,7 @@ static void gatts_process_mtu_req (tGATT_TCB *p_tcb, UINT16 len, UINT8 *p_data) BT_HDR *p_buf; UINT16 conn_id; - /* BR/EDR conenction, send error response */ + /* BR/EDR connection, send error response */ if (p_tcb->att_lcid != L2CAP_ATT_CID) { gatt_send_error_rsp (p_tcb, GATT_REQ_NOT_SUPPORTED, GATT_REQ_MTU, 0, FALSE); } else if (len < GATT_MTU_REQ_MIN_LEN) { @@ -1081,7 +1080,7 @@ static void gatts_process_mtu_req (tGATT_TCB *p_tcb, UINT16 len, UINT8 *p_data) attp_send_sr_msg (p_tcb, p_buf); /* Notify all registered application with new MTU size. Us a transaction ID */ - /* of 0, as no response is allowed from applcations */ + /* of 0, as no response is allowed from applications */ for (i = 0; i < GATT_MAX_APPS; i ++) { if (gatt_cb.cl_rcb[i].in_use ) { @@ -1448,7 +1447,7 @@ void gatt_attr_process_prepare_write (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 hand } if ((prepare_record->error_code_app == GATT_SUCCESS) - // update prepare write status for excute write request + // update prepare write status for execute write request && (status == GATT_INVALID_OFFSET || status == GATT_INVALID_ATTR_LEN || status == GATT_REQ_NOT_SUPPORTED)) { prepare_record->error_code_app = status; } @@ -1855,7 +1854,7 @@ void gatt_server_handle_client_req (tGATT_TCB *p_tcb, UINT8 op_code, gatts_process_primary_service_req (p_tcb, op_code, len, p_data); break; - case GATT_REQ_FIND_INFO: /* discover char descrptor */ + case GATT_REQ_FIND_INFO: /* discover char descriptor */ gatts_process_find_info(p_tcb, op_code, len, p_data); break; diff --git a/lib/bt/host/bluedroid/stack/gatt/gatt_sr_hash.c b/lib/bt/host/bluedroid/stack/gatt/gatt_sr_hash.c index 79d09d7a..d5a4b3a5 100644 --- a/lib/bt/host/bluedroid/stack/gatt/gatt_sr_hash.c +++ b/lib/bt/host/bluedroid/stack/gatt/gatt_sr_hash.c @@ -189,7 +189,6 @@ tGATT_STATUS gatts_calculate_datebase_hash(BT_OCTET16 hash) #if SMP_INCLUDED == TRUE BT_OCTET16 key = {0}; aes_cipher_msg_auth_code(key, data_buf, len, 16, hash); - //ESP_LOG_BUFFER_HEX("db hash", hash, BT_OCTET16_LEN); #endif osi_free(data_buf); diff --git a/lib/bt/host/bluedroid/stack/gatt/gatt_utils.c b/lib/bt/host/bluedroid/stack/gatt/gatt_utils.c index 621b2468..0644ab70 100644 --- a/lib/bt/host/bluedroid/stack/gatt/gatt_utils.c +++ b/lib/bt/host/bluedroid/stack/gatt/gatt_utils.c @@ -108,7 +108,7 @@ void gatt_free_pending_ind(tGATT_TCB *p_tcb) ** ** Function gatt_free_pending_enc_queue ** -** Description Free all buffers in pending encyption queue +** Description Free all buffers in pending encryption queue ** ** Returns None ** @@ -222,7 +222,7 @@ void gatt_set_srv_chg(void) ** ** Description Find the app id in on the new service changed list ** -** Returns Pointer to the found new service changed item othwerwise NULL +** Returns Pointer to the found new service changed item otherwise NULL ** *******************************************************************************/ tGATTS_PENDING_NEW_SRV_START *gatt_sr_is_new_srv_chg(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst) @@ -299,7 +299,7 @@ tGATTS_PENDING_NEW_SRV_START *gatt_add_pending_new_srv_start(tGATTS_HNDL_RANGE * ** ** Function gatt_add_srv_chg_clt ** -** Description Add a service chnage client to the service change client queue +** Description Add a service change client to the service change client queue ** ** Returns Pointer to the service change client buffer; Null no buffer available ** @@ -682,7 +682,7 @@ BOOLEAN gatt_remove_a_srv_from_list(tGATT_SRV_LIST_INFO *p_list, tGATT_SRV_LIST_ ** ** Function gatt_add_an_item_to_list ** -** Description add an service handle range to the list in decending +** Description add an service handle range to the list in descending ** order of the start handle ** ** Returns BOOLEAN TRUE-if add is successful @@ -808,7 +808,7 @@ BOOLEAN gatt_find_the_connected_bda(UINT8 start_idx, BD_ADDR bda, UINT8 *p_found ** ** Function gatt_is_srv_chg_ind_pending ** -** Description Check whether a service chnaged is in the indication pending queue +** Description Check whether a service changed is in the indication pending queue ** or waiting for an Ack already ** ** Returns BOOLEAN @@ -846,9 +846,9 @@ BOOLEAN gatt_is_srv_chg_ind_pending (tGATT_TCB *p_tcb) ** ** Function gatt_is_bda_in_the_srv_chg_clt_list ** -** Description This function check the specified bda is in the srv chg clinet list or not +** Description This function check the specified bda is in the srv chg client list or not ** -** Returns pointer to the found elemenet otherwise NULL +** Returns pointer to the found element otherwise NULL ** *******************************************************************************/ tGATTS_SRV_CHG *gatt_is_bda_in_the_srv_chg_clt_list (BD_ADDR bda) @@ -1205,7 +1205,7 @@ UINT8 gatt_build_uuid_to_stream(UINT8 **p_dst, tBT_UUID uuid) if (uuid.len == LEN_UUID_16) { UINT16_TO_STREAM (p, uuid.uu.uuid16); len = LEN_UUID_16; - } else if (uuid.len == LEN_UUID_32) { /* always convert 32 bits into 128 bits as alwats */ + } else if (uuid.len == LEN_UUID_32) { /* always convert 32 bits into 128 bits as always */ gatt_convert_uuid32_to_uuid128(p, uuid.uu.uuid32); p += LEN_UUID_128; len = LEN_UUID_128; @@ -1465,7 +1465,7 @@ UINT8 gatt_sr_alloc_rcb(tGATT_HDL_LIST_ELEM *p_list ) UINT8 ii = 0; tGATT_SR_REG *p_sreg = NULL; - /*this is a new application servoce start */ + /*this is a new application service start */ for (ii = 0, p_sreg = gatt_cb.sr_reg; ii < GATT_MAX_SR_PROFILES; ii++, p_sreg++) { if (!p_sreg->in_use) { memset (p_sreg, 0, sizeof(tGATT_SR_REG)); @@ -1616,7 +1616,7 @@ UINT32 gatt_add_sdp_record (tBT_UUID *p_uuid, UINT16 start_hdl, UINT16 end_hdl) break; default: - GATT_TRACE_ERROR("inavlid UUID len=%d", p_uuid->len); + GATT_TRACE_ERROR("invalid UUID len=%d", p_uuid->len); SDP_DeleteRecord(sdp_handle); return 0; break; @@ -1633,7 +1633,7 @@ UINT32 gatt_add_sdp_record (tBT_UUID *p_uuid, UINT16 start_hdl, UINT16 end_hdl) SDP_AddProtocolList(sdp_handle, 2, proto_elem_list); - /* Make the service browseable */ + /* Make the service browsable */ SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &list); return (sdp_handle); @@ -1868,7 +1868,7 @@ UINT8 gatt_num_apps_hold_link(tGATT_TCB *p_tcb) ** ** Function gatt_num_clcb_by_bd_addr ** -** Description The function searches all LCB with macthing bd address +** Description The function searches all LCB with matching bd address ** ** Returns total number of clcb found. ** @@ -1892,7 +1892,7 @@ UINT8 gatt_num_clcb_by_bd_addr(BD_ADDR bda) ** ** Function gatt_sr_update_cback_cnt ** -** Description The function searches all LCB with macthing bd address +** Description The function searches all LCB with matching bd address ** ** Returns total number of clcb found. ** @@ -1916,7 +1916,7 @@ void gatt_sr_copy_prep_cnt_to_cback_cnt(tGATT_TCB *p_tcb ) ** ** Function gatt_sr_is_cback_cnt_zero ** -** Description The function searches all LCB with macthing bd address +** Description The function searches all LCB with matching bd address ** ** Returns True if thetotal application callback count is zero ** @@ -2015,7 +2015,7 @@ void gatt_sr_reset_prep_cnt(tGATT_TCB *p_tcb ) ** ** Function gatt_sr_update_cback_cnt ** -** Description Update the teh application callback count +** Description Update the the application callback count ** ** Returns None ** @@ -2045,7 +2045,7 @@ void gatt_sr_update_cback_cnt(tGATT_TCB *p_tcb, tGATT_IF gatt_if, BOOLEAN is_inc ** ** Function gatt_sr_update_prep_cnt ** -** Description Update the teh prepare write request count +** Description Update the the prepare write request count ** ** Returns None ** @@ -2461,7 +2461,7 @@ void gatt_dbg_display_uuid(tBT_UUID bt_uuid) } - +#if (tGATT_BG_CONN_DEV == TRUE) /******************************************************************************* ** ** Function gatt_is_bg_dev_for_app @@ -2552,7 +2552,7 @@ BOOLEAN gatt_add_bg_dev_list(tGATT_REG *p_reg, BD_ADDR bd_addr, BOOLEAN is_init for (i = 0; i < GATT_MAX_APPS; i ++) { if (is_initator) { if (p_dev->gatt_if[i] == gatt_if) { - GATT_TRACE_ERROR("device already in iniator white list"); + GATT_TRACE_ERROR("device already in initiator white list"); return TRUE; } else if (p_dev->gatt_if[i] == 0) { p_dev->gatt_if[i] = gatt_if; @@ -2618,9 +2618,9 @@ BOOLEAN gatt_remove_bg_dev_for_app(tGATT_IF gatt_if, BD_ADDR bd_addr) ** ** Function gatt_get_num_apps_for_bg_dev ** -** Description Gte the number of applciations for the specified background device +** Description Gte the number of applications for the specified background device ** -** Returns UINT8 total number fo applications +** Returns UINT8 total number for applications ** *******************************************************************************/ UINT8 gatt_get_num_apps_for_bg_dev(BD_ADDR bd_addr) @@ -2842,7 +2842,7 @@ BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_ } return ret; } - +#endif // #if (tGATT_BG_CONN_DEV == TRUE) /******************************************************************************* diff --git a/lib/bt/host/bluedroid/stack/gatt/include/gatt_int.h b/lib/bt/host/bluedroid/stack/gatt/include/gatt_int.h index 1161da62..f9d3cd8e 100644 --- a/lib/bt/host/bluedroid/stack/gatt/include/gatt_int.h +++ b/lib/bt/host/bluedroid/stack/gatt/include/gatt_int.h @@ -130,7 +130,7 @@ typedef union { tGATT_EXEC_FLAG exec_write; /* execute write */ } tGATT_CL_MSG; -/* error response strucutre */ +/* error response structure */ typedef struct { UINT16 handle; UINT8 cmd_code; @@ -480,12 +480,14 @@ typedef struct { UINT32 service_change; } tGATT_SVC_CHG; +#if (tGATT_BG_CONN_DEV == TRUE) typedef struct { tGATT_IF gatt_if[GATT_MAX_APPS]; tGATT_IF listen_gif[GATT_MAX_APPS]; BD_ADDR remote_bda; BOOLEAN in_use; } tGATT_BG_CONN_DEV; +#endif // #if (tGATT_BG_CONN_DEV == TRUE) #define GATT_SVC_CHANGED_CONNECTING 1 /* wait for connection */ #define GATT_SVC_CHANGED_SERVICE 2 /* GATT service discovery */ @@ -553,8 +555,9 @@ typedef struct { tGATT_HDL_CFG hdl_cfg; +#if (tGATT_BG_CONN_DEV == TRUE) tGATT_BG_CONN_DEV bgconn_dev[GATT_MAX_BG_CONN_DEV]; - +#endif // #if (tGATT_BG_CONN_DEV == TRUE) BOOLEAN auto_disc; /* internal use: true for auto discovering after connected */ UINT8 srv_chg_mode; /* internal use: service change mode */ tGATTS_RSP rsp; /* use to read internal service attribute */ @@ -667,6 +670,7 @@ extern BOOLEAN gatt_add_an_item_to_list(tGATT_HDL_LIST_INFO *p_list, tGATT_HDL_L extern BOOLEAN gatt_remove_an_item_from_list(tGATT_HDL_LIST_INFO *p_list, tGATT_HDL_LIST_ELEM *p_remove); extern tGATTS_SRV_CHG *gatt_add_srv_chg_clt(tGATTS_SRV_CHG *p_srv_chg); +#if (tGATT_BG_CONN_DEV == TRUE) /* for background connection */ extern BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr, BOOLEAN is_initiator); extern BOOLEAN gatt_is_bg_dev_for_app(tGATT_BG_CONN_DEV *p_dev, tGATT_IF gatt_if); @@ -676,6 +680,7 @@ extern BOOLEAN gatt_find_app_for_bg_dev(BD_ADDR bd_addr, tGATT_IF *p_gatt_if); extern tGATT_BG_CONN_DEV *gatt_find_bg_dev(BD_ADDR remote_bda); extern void gatt_deregister_bgdev_list(tGATT_IF gatt_if); extern void gatt_reset_bgdev_list(void); +#endif // #if (tGATT_BG_CONN_DEV == TRUE) /* server function */ extern UINT8 gatt_sr_find_i_rcb_by_handle(UINT16 handle); diff --git a/lib/bt/host/bluedroid/stack/goep/goepc_api.c b/lib/bt/host/bluedroid/stack/goep/goepc_api.c new file mode 100644 index 00000000..06be8f59 --- /dev/null +++ b/lib/bt/host/bluedroid/stack/goep/goepc_api.c @@ -0,0 +1,376 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "osi/osi.h" +#include "osi/allocator.h" +#include "common/bt_target.h" + +#include "stack/obex_api.h" +#include "stack/goep_common.h" +#include "stack/goepc_api.h" +#include "goep_int.h" + +#if (GOEPC_INCLUDED == TRUE) + +/******************************************************************************* +** +** Function GOEPC_Init +** +** Description Initialize GOEP Client role, must call before using any +** other GOEPC APIs +** +** Returns GOEP_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 GOEPC_Init(void) +{ +#if (GOEP_DYNAMIC_MEMORY) + if (!goepc_cb_ptr) { + goepc_cb_ptr = (tGOEPC_CB *)osi_malloc(sizeof(tGOEPC_CB)); + if (!goepc_cb_ptr) { + return GOEP_NO_RESOURCES; + } + } +#endif /* #if (GOEP_DYNAMIC_MEMORY) */ + memset(&goepc_cb, 0, sizeof(tGOEPC_CB)); + goepc_cb.trace_level = BT_TRACE_LEVEL_ERROR; + return GOEP_SUCCESS; +} + +/******************************************************************************* +** +** Function GOEPC_Deinit +** +** Description Deinit GOEP Client role, once deinit, can not use any other +** GOEPC APIs until call GOEPC_Init again +** +*******************************************************************************/ +void GOEPC_Deinit(void) +{ +#if (GOEP_DYNAMIC_MEMORY) + if (goepc_cb_ptr) { + osi_free(goepc_cb_ptr); + goepc_cb_ptr = NULL; + } +#endif /* #if (GOEP_DYNAMIC_MEMORY) */ +} + +/******************************************************************************* +** +** Function GOEPC_Open +** +** Description Start the progress to establish a GOEP connection to server +** +** Returns GOEP_SUCCESS if successful, otherwise failed, when the +** connection is established, GOEPC_OPENED_EVT will come +** +*******************************************************************************/ +UINT16 GOEPC_Open(tOBEX_SVR_INFO *svr, tGOEPC_EVT_CBACK callback, UINT16 *out_handle) +{ + UINT16 ret = GOEP_SUCCESS; + tGOEPC_CCB *p_ccb = NULL; + + do { + /* check parameter, allow out_handle to be NULL */ + if (svr == NULL || callback == NULL) { + ret = GOEP_INVALID_PARAM; + break; + } + + p_ccb = goepc_allocate_ccb(); + if (p_ccb == NULL) { + ret = GOEP_NO_RESOURCES; + break; + } + + if (OBEX_CreateConn(svr, goepc_obex_callback, &p_ccb->obex_handle) != OBEX_SUCCESS) { + ret = GOEP_TL_ERROR; + break; + } + + /* success */ + p_ccb->callback = callback; + p_ccb->state = GOEPC_STATE_OPENING; + if (out_handle) { + *out_handle = p_ccb->allocated; + } + } while (0); + + if (ret != GOEP_SUCCESS && p_ccb != NULL) { + goepc_free_ccb(p_ccb); + } + return ret; +} + +/******************************************************************************* +** +** Function GOEPC_Close +** +** Description Close a GOEP connection immediately +** +** Returns GOEP_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 GOEPC_Close(UINT16 handle) +{ + tGOEPC_CCB *p_ccb = NULL; + + UINT16 ccb_idx = handle - 1; + if (ccb_idx >= GOEPC_MAX_CONNECTION || !goepc_cb.ccb[ccb_idx].allocated) { + return GOEP_BAD_HANDLE; + } + + p_ccb = &goepc_cb.ccb[ccb_idx]; + if (p_ccb->obex_handle) { + OBEX_RemoveConn(p_ccb->obex_handle); + } + goepc_free_ccb(p_ccb); + + return GOEP_SUCCESS; +} + +/******************************************************************************* +** +** Function GOEPC_SendRequest +** +** Description Send the prepared request packet to server +** +** Returns GOEP_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 GOEPC_SendRequest(UINT16 handle) +{ + UINT16 ret = GOEP_SUCCESS; + tGOEPC_CCB *p_ccb = NULL; + BOOLEAN final = FALSE; + + do { + UINT16 ccb_idx = handle - 1; + if (ccb_idx >= GOEPC_MAX_CONNECTION || !goepc_cb.ccb[ccb_idx].allocated) { + ret = GOEP_BAD_HANDLE; + break; + } + p_ccb = &goepc_cb.ccb[ccb_idx]; + + if (p_ccb->pkt == NULL) { + ret = GOEP_INVALID_STATE; + break; + } + + final = OBEX_CheckFinalBit(p_ccb->pkt); + /* check whether state machine allow this operation */ + if (!goepc_check_obex_req_allow(p_ccb->state, final)) { + ret = GOEP_INVALID_STATE; + break; + } + + if (p_ccb->congest) { + ret = GOEP_CONGEST; + break; + } + + /* execute srm state machine */ + goepc_srm_sm_execute(p_ccb, TRUE, p_ccb->pkt_srm_en, p_ccb->pkt_srm_wait); + + tGOEPC_DATA data; + data.pkt = p_ccb->pkt; + + p_ccb->last_pkt_opcode = p_ccb->curr_pkt_opcode; + p_ccb->pkt = NULL; + p_ccb->pkt_srm_en = FALSE; + p_ccb->pkt_srm_wait = FALSE; + + /* execute main state machine */ + if (final) { + goepc_sm_execute(p_ccb, GOEPC_SM_EVENT_REQ_FB, &data); + } + else { + goepc_sm_execute(p_ccb, GOEPC_SM_EVENT_REQ, &data); + } + /* since goepc_sm_execute may free ccb, can not access ccb here */ + } while (0); + + return ret; +} + +/******************************************************************************* +** +** Function GOEPC_PrepareRequest +** +** Description Prepare a request packet, packet will be store internally +** +** Returns GOEP_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 GOEPC_PrepareRequest(UINT16 handle, tOBEX_PARSE_INFO *info, UINT16 buff_size) +{ + UINT16 ret = GOEP_SUCCESS; + tGOEPC_CCB *p_ccb = NULL; + BT_HDR *pkt = NULL; + + do { + UINT16 ccb_idx = handle - 1; + if (ccb_idx >= GOEPC_MAX_CONNECTION || !goepc_cb.ccb[ccb_idx].allocated) { + ret = GOEP_BAD_HANDLE; + break; + } + p_ccb = &goepc_cb.ccb[ccb_idx]; + + if (info == NULL || buff_size < OBEX_MIN_PACKET_SIZE) { + ret = GOEP_INVALID_PARAM; + break; + } + + if (p_ccb->pkt != NULL) { + ret = GOEP_INVALID_STATE; + break; + } + + if (!goepc_check_obex_req_param(info)) { + ret = GOEP_INVALID_PARAM; + break; + } + + if (OBEX_BuildRequest(info, buff_size, &pkt) != OBEX_SUCCESS) { + ret = GOEP_NO_RESOURCES; + break; + } + + p_ccb->curr_pkt_opcode = info->opcode; + p_ccb->pkt = pkt; + } while (0); + + return ret; +} + +/******************************************************************************* +** +** Function GOEPC_DropRequest +** +** Description Drop the prepared internal request packet +** +** Returns GOEP_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 GOEPC_DropRequest(UINT16 handle) +{ + UINT16 ccb_idx = handle - 1; + if (ccb_idx >= GOEPC_MAX_CONNECTION || !goepc_cb.ccb[ccb_idx].allocated) { + return GOEP_BAD_HANDLE; + } + + tGOEPC_CCB *p_ccb = &goepc_cb.ccb[ccb_idx]; + if (p_ccb->pkt == NULL) { + return GOEP_INVALID_STATE; + } + + osi_free(p_ccb->pkt); + p_ccb->pkt = NULL; + p_ccb->pkt_srm_en = FALSE; + p_ccb->pkt_srm_wait = FALSE; + return GOEP_SUCCESS; +} + +/******************************************************************************* +** +** Function GOEPC_RequestSetSRM +** +** Description Modify the prepared internal request packet, append SRM header +** or SRMP header +** +** Returns GOEP_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 GOEPC_RequestSetSRM(UINT16 handle, BOOLEAN srm_en, BOOLEAN srm_wait) +{ + UINT16 ret = GOEP_SUCCESS; + tGOEPC_CCB *p_ccb = NULL; + + do { + UINT16 ccb_idx = handle - 1; + if (ccb_idx >= GOEPC_MAX_CONNECTION || !goepc_cb.ccb[ccb_idx].allocated) { + ret = GOEP_BAD_HANDLE; + break; + } + p_ccb = &goepc_cb.ccb[ccb_idx]; + + if (!srm_en && !srm_wait) { + ret = GOEP_INVALID_PARAM; + break; + } + + if (p_ccb->pkt == NULL) { + ret = GOEP_INVALID_STATE; + break; + } + + if (srm_en) { + if (OBEX_AppendHeaderSRM(p_ccb->pkt, OBEX_SRM_ENABLE) == OBEX_SUCCESS) { + p_ccb->pkt_srm_en = TRUE; + } + else { + ret = GOEP_NO_RESOURCES; + break; + } + } + if (srm_wait) { + if (OBEX_AppendHeaderSRMP(p_ccb->pkt, OBEX_SRMP_WAIT) == OBEX_SUCCESS) { + p_ccb->pkt_srm_wait = TRUE; + } + else { + ret = GOEP_NO_RESOURCES; + break; + } + } + } while (0); + + return ret; +} + +/******************************************************************************* +** +** Function GOEPC_RequestAddHeader +** +** Description Modify the prepared internal request packet, append header +** +** Returns GOEP_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 GOEPC_RequestAddHeader(UINT16 handle, UINT8 header_id, const UINT8 *data, UINT16 data_len) +{ + UINT16 ret = GOEP_SUCCESS; + tGOEPC_CCB *p_ccb = NULL; + + do { + UINT16 ccb_idx = handle - 1; + if (ccb_idx >= GOEPC_MAX_CONNECTION || !goepc_cb.ccb[ccb_idx].allocated) { + ret = GOEP_BAD_HANDLE; + break; + } + p_ccb = &goepc_cb.ccb[ccb_idx]; + + if (p_ccb->pkt == NULL) { + ret = GOEP_INVALID_STATE; + break; + } + + if ((data == NULL && data_len != 0) || (data != NULL && data_len == 0)) { + ret = GOEP_INVALID_PARAM; + break; + } + + if (OBEX_AppendHeaderRaw(p_ccb->pkt, header_id, data, data_len) != OBEX_SUCCESS) { + ret = GOEP_NO_RESOURCES; + break; + } + } while (0); + + return ret; +} + +#endif /* #if (GOEPC_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/stack/goep/goepc_main.c b/lib/bt/host/bluedroid/stack/goep/goepc_main.c new file mode 100644 index 00000000..e0859580 --- /dev/null +++ b/lib/bt/host/bluedroid/stack/goep/goepc_main.c @@ -0,0 +1,528 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "osi/osi.h" +#include "osi/allocator.h" +#include "common/bt_target.h" + +#include "stack/obex_api.h" +#include "stack/goep_common.h" +#include "stack/goepc_api.h" +#include "goep_int.h" + +#if (GOEPC_INCLUDED == TRUE) + +#if GOEP_DYNAMIC_MEMORY == FALSE +tGOEPC_CB goepc_cb; +#else +tGOEPC_CB *goepc_cb_ptr = NULL; +#endif + +tGOEPC_CCB *goepc_allocate_ccb(void) +{ + tGOEPC_CCB *p_ccb = NULL; + for (int i = 0; i < GOEPC_MAX_CONNECTION; ++i) { + if (!goepc_cb.ccb[i].allocated) { + goepc_cb.ccb[i].allocated = i + 1; + p_ccb = &goepc_cb.ccb[i]; + break; + } + } + return p_ccb; +} + +void goepc_free_ccb(tGOEPC_CCB *p_ccb) +{ + if (p_ccb->pkt != NULL) { + osi_free(p_ccb->pkt); + } + memset(p_ccb, 0, sizeof(tGOEPC_CCB)); +} + +BOOLEAN goepc_check_obex_req_param(tOBEX_PARSE_INFO *info) +{ + BOOLEAN ret = TRUE; + switch (info->opcode) + { + case OBEX_OPCODE_CONNECT: + if (info->max_packet_length < 255 || info->obex_version_number == 0) { + ret = FALSE; + } + break; + case OBEX_OPCODE_DISCONNECT: + case OBEX_OPCODE_PUT: + case OBEX_OPCODE_PUT_FINAL: + case OBEX_OPCODE_GET: + case OBEX_OPCODE_GET_FINAL: + case OBEX_OPCODE_SETPATH: + case OBEX_OPCODE_ACTION: + case OBEX_OPCODE_SESSION: + /* opcode allowed */ + break; + case OBEX_OPCODE_ABORT: + default: + ret = FALSE; + /* opcode not allowed */ + break; + } + + return ret; +} + +static tGOEPC_CCB *find_ccb_by_obex_handle(UINT16 obex_handle) +{ + tGOEPC_CCB *p_ccb = NULL; + for (int i = 0; i < GOEPC_MAX_CONNECTION; ++i) { + if (goepc_cb.ccb[i].allocated && goepc_cb.ccb[i].obex_handle == obex_handle) { + p_ccb = &goepc_cb.ccb[i]; + } + } + return p_ccb; +} + +static void goepc_extra_srm_rsp(UINT8 opcode, BT_HDR *pkt, BOOLEAN *srm_en, BOOLEAN *srm_wait) +{ + tOBEX_PARSE_INFO info; + BOOLEAN srm_found = FALSE; + BOOLEAN srmp_found = FALSE; + if (OBEX_ParseResponse(pkt, opcode, &info) == OBEX_SUCCESS) { + UINT8 *header = NULL; + while((header = OBEX_GetNextHeader(pkt, &info)) != NULL) { + switch (*header) + { + case OBEX_HEADER_ID_SRM: + if (header[1] == OBEX_SRM_ENABLE) { + *srm_en = TRUE; + } + srm_found = TRUE; + break; + case OBEX_HEADER_ID_SRM_PARAM: + switch (header[1]) + { + case OBEX_SRMP_ADD_PKT: + /* goep should not use this */ + break; + case OBEX_SRMP_WAIT: + *srm_wait = TRUE; + break; + case OBEX_SRMP_ADD_PKT_WAIT: + /* goep should not use this */ + break; + default: + break; + } + srmp_found = TRUE; + break; + default: + break; + } + if (srm_found && srmp_found) { + break; + } + } + } +} + +static void goepc_act_congest(tGOEPC_CCB *p_ccb) +{ + p_ccb->congest = TRUE; + p_ccb->callback(p_ccb->allocated, GOEPC_CONGEST_EVT, NULL); +} + +static void goepc_act_uncongest(tGOEPC_CCB *p_ccb) +{ + p_ccb->congest = FALSE; + p_ccb->callback(p_ccb->allocated, GOEPC_UNCONGEST_EVT, NULL); +} + +static void goepc_act_mtu_chg(tGOEPC_CCB *p_ccb, tGOEPC_MTU_CHG *mtu_chg) +{ + tGOEPC_MSG msg; + msg.mtu_changed.peer_mtu = mtu_chg->peer_mtu; + msg.mtu_changed.our_mtu = mtu_chg->our_mtu; + p_ccb->peer_mtu = mtu_chg->peer_mtu; + p_ccb->our_mtu = mtu_chg->our_mtu; + p_ccb->callback(p_ccb->allocated, GOEPC_MTU_CHANGED_EVT, &msg); +} + +void goepc_obex_callback(UINT16 handle, UINT8 event, tOBEX_MSG *msg) +{ + tGOEPC_DATA data; + UINT8 goepc_sm_event = GOEPC_SM_EVENT_DISCONNECT; + BOOLEAN exec_sm = FALSE; + tGOEPC_CCB *p_ccb = find_ccb_by_obex_handle(handle); + if (p_ccb == NULL) { + GOEPC_TRACE_ERROR("goepc_obex_callback can not find a ccb\n"); + /* can not find a ccb in goepc, free resource and remove this connection */ + if (event == OBEX_DATA_EVT && msg->data.pkt) { + osi_free(msg->data.pkt); + } + OBEX_RemoveConn(handle); + return; + } + + switch (event) + { + case OBEX_CONNECT_EVT: + data.connected.peer_mtu = msg->connect.peer_mtu; + data.connected.our_mtu = msg->connect.our_mtu; + goepc_sm_event = GOEPC_SM_EVENT_CONNECT; + exec_sm = TRUE; + break; + case OBEX_MTU_CHANGE_EVT: + data.mtu_chg.peer_mtu = msg->mtu_change.peer_mtu; + data.mtu_chg.our_mtu = msg->mtu_change.our_mtu; + goepc_act_mtu_chg(p_ccb, &data.mtu_chg); + break; + case OBEX_DISCONNECT_EVT: + /* when we received this event, obex connection already disconnect */ + p_ccb->obex_handle = 0; + goepc_sm_event = GOEPC_SM_EVENT_DISCONNECT;; + exec_sm = TRUE; + break; + case OBEX_CONGEST_EVT: + goepc_act_congest(p_ccb); + break; + case OBEX_UNCONGEST_EVT: + goepc_act_uncongest(p_ccb); + break; + case OBEX_DATA_EVT: + data.pkt = msg->data.pkt; + if (OBEX_CheckContinueResponse(data.pkt)) { + /* in OBEX 1.0, final bit of response code will always set, we need to check this */ + goepc_sm_event = GOEPC_SM_EVENT_RSP; + } + else if (OBEX_CheckFinalBit(data.pkt)) { + goepc_sm_event = GOEPC_SM_EVENT_RSP_FB; + } + else { + goepc_sm_event = GOEPC_SM_EVENT_RSP; + } + exec_sm = TRUE; + break; + default: + /* other event, ignore */ + break; + } + + if (exec_sm) { + goepc_sm_execute(p_ccb, goepc_sm_event, &data); + } +} + +static void goepc_sm_act_connect(tGOEPC_CCB *p_ccb, tGOEPC_CONNECTED *connected) +{ + tGOEPC_MSG msg; + msg.opened.peer_mtu = connected->peer_mtu; + msg.opened.our_mtu = connected->our_mtu; + p_ccb->peer_mtu = connected->peer_mtu; + p_ccb->our_mtu = connected->our_mtu; + + /* main state machine transfer to OPENED_IDLE */ + p_ccb->state = GOEPC_STATE_OPENED_IDLE; + p_ccb->callback(p_ccb->allocated, GOEPC_OPENED_EVT, &msg); +} + +static void goepc_sm_act_disconnect(tGOEPC_CCB *p_ccb) +{ + tGOEPC_MSG msg; + if (p_ccb->obex_handle) { + OBEX_RemoveConn(p_ccb->obex_handle); + } + msg.closed.reason = GOEP_TL_ERROR; + p_ccb->callback(p_ccb->allocated, GOEPC_CLOSED_EVT, &msg); + /* free ccb, main state machine end */ + goepc_free_ccb(p_ccb); +} + +static void goepc_sm_act_send_req(tGOEPC_CCB *p_ccb, BT_HDR *pkt) +{ + UINT16 ret = OBEX_SendPacket(p_ccb->obex_handle, pkt); + if (ret == OBEX_SUCCESS) { + /* main state machine transfer to OPENED_REQ */ + p_ccb->state = GOEPC_STATE_OPENED_REQ; + } + else { + /* send failed, something error in transport layer, disconnect */ + goepc_sm_act_disconnect(p_ccb); + } +} + +static void goepc_sm_act_send_req_fb(tGOEPC_CCB *p_ccb, BT_HDR *pkt) +{ + UINT16 ret = OBEX_SendPacket(p_ccb->obex_handle, pkt); + if (ret == OBEX_SUCCESS) { + /* main state machine transfer to OPENED_RSP */ + p_ccb->state = GOEPC_STATE_OPENED_RSP; + } + else { + /* send failed, something error in transport layer, disconnect */ + goepc_sm_act_disconnect(p_ccb); + } +} + +static void goepc_sm_act_rsp(tGOEPC_CCB *p_ccb, BT_HDR *pkt) +{ + /* handle srm state transfer */ + BOOLEAN srm_en = FALSE; + BOOLEAN srm_wait = FALSE; + goepc_extra_srm_rsp(p_ccb->last_pkt_opcode, pkt, &srm_en, &srm_wait); + goepc_srm_sm_execute(p_ccb, FALSE, srm_en, srm_wait); + /* main state machine not change */ + + tGOEPC_MSG msg; + msg.response.opcode = p_ccb->last_pkt_opcode; + msg.response.final = FALSE; + msg.response.srm_en = (p_ccb->srm_state == GOEPC_SRM_STATE_ENABLE_WAIT || p_ccb->srm_state == GOEPC_SRM_STATE_ENABLE); + msg.response.srm_wait = (p_ccb->srm_state == GOEPC_SRM_STATE_ENABLE_WAIT); + msg.response.pkt = pkt; + p_ccb->callback(p_ccb->allocated, GOEPC_RESPONSE_EVT, &msg); +} + +static void goepc_sm_act_rsp_fb(tGOEPC_CCB *p_ccb, BT_HDR *pkt) +{ + tGOEPC_MSG msg; + msg.response.opcode = p_ccb->last_pkt_opcode; + msg.response.final = TRUE; + msg.response.srm_en = FALSE; + msg.response.srm_wait = FALSE; + msg.response.pkt = pkt; + /* operation complete, reset srm state */ + p_ccb->srm_state = GOEPC_SRM_STATE_IDLE; + /* main state machine transfer to OPENED_IDLE */ + p_ccb->state = GOEPC_STATE_OPENED_IDLE; + p_ccb->callback(p_ccb->allocated, GOEPC_RESPONSE_EVT, &msg); +} + + +static void goepc_sm_state_opening(tGOEPC_CCB *p_ccb, UINT8 event, tGOEPC_DATA *p_data) +{ + switch (event) + { + case GOEPC_SM_EVENT_CONNECT: + goepc_sm_act_connect(p_ccb, &p_data->connected); + break; + case GOEPC_SM_EVENT_DISCONNECT: + goepc_sm_act_disconnect(p_ccb); + break; + case GOEPC_SM_EVENT_RSP: + case GOEPC_SM_EVENT_RSP_FB: + GOEPC_TRACE_ERROR("goepc_sm_state_opening received unexpected response from peer\n"); + if (p_data->pkt != NULL) { + osi_free(p_data->pkt); + } + goepc_sm_act_disconnect(p_ccb); + break; + default: + GOEPC_TRACE_ERROR("goepc_sm_state_opening unexpected event: 0x%x\n", event); + break; + } +} + +static void goepc_sm_state_opened_idle(tGOEPC_CCB *p_ccb, UINT8 event, tGOEPC_DATA *p_data) +{ + switch (event) + { + case GOEPC_SM_EVENT_DISCONNECT: + goepc_sm_act_disconnect(p_ccb); + break; + case GOEPC_SM_EVENT_REQ: + goepc_sm_act_send_req(p_ccb, p_data->pkt); + break; + case GOEPC_SM_EVENT_REQ_FB: + goepc_sm_act_send_req_fb(p_ccb, p_data->pkt); + break; + case GOEPC_SM_EVENT_RSP: + case GOEPC_SM_EVENT_RSP_FB: + GOEPC_TRACE_ERROR("goepc_sm_state_opened_idle received unexpected response from peer\n"); + /* peer sent a packet to us when we didn't request */ + if (p_data->pkt != NULL) { + osi_free(p_data->pkt); + } + goepc_sm_act_disconnect(p_ccb); + break; + default: + GOEPC_TRACE_ERROR("goepc_sm_state_opened_idle unexpected event: 0x%x\n", event); + break; + } +} + +static void goepc_sm_state_opened_req(tGOEPC_CCB *p_ccb, UINT8 event, tGOEPC_DATA *p_data) +{ + switch (event) + { + case GOEPC_SM_EVENT_DISCONNECT: + goepc_sm_act_disconnect(p_ccb); + break; + case GOEPC_SM_EVENT_REQ: + goepc_sm_act_send_req(p_ccb, p_data->pkt); + break; + case GOEPC_SM_EVENT_REQ_FB: + goepc_sm_act_send_req_fb(p_ccb, p_data->pkt); + break; + case GOEPC_SM_EVENT_RSP: + goepc_sm_act_rsp(p_ccb, p_data->pkt); + break; + case GOEPC_SM_EVENT_RSP_FB: + goepc_sm_act_rsp_fb(p_ccb, p_data->pkt); + break; + default: + GOEPC_TRACE_ERROR("goepc_sm_state_opened_req unexpected event: 0x%x\n", event); + break; + } +} + +static void goepc_sm_state_opened_rsp(tGOEPC_CCB *p_ccb, UINT8 event, tGOEPC_DATA *p_data) +{ + switch (event) + { + case GOEPC_SM_EVENT_DISCONNECT: + goepc_sm_act_disconnect(p_ccb); + break; + case GOEPC_SM_EVENT_REQ_FB: + goepc_sm_act_send_req_fb(p_ccb, p_data->pkt); + break; + case GOEPC_SM_EVENT_RSP: + goepc_sm_act_rsp(p_ccb, p_data->pkt); + break; + case GOEPC_SM_EVENT_RSP_FB: + goepc_sm_act_rsp_fb(p_ccb, p_data->pkt); + break; + default: + GOEPC_TRACE_ERROR("goepc_sm_state_opened_rsp unexpected event: 0x%x\n", event); + break; + } +} + +BOOLEAN goepc_check_obex_req_allow(UINT8 state, BOOLEAN final) +{ + BOOLEAN ret = FALSE; + if (final) { + switch (state) + { + case GOEPC_STATE_OPENED_IDLE: + case GOEPC_STATE_OPENED_REQ: + case GOEPC_STATE_OPENED_RSP: + ret = TRUE; + break; + default: + break; + } + } + else { + switch (state) + { + case GOEPC_STATE_OPENED_IDLE: + case GOEPC_STATE_OPENED_REQ: + ret = TRUE; + break; + default: + break; + } + } + return ret; +} + +void goepc_sm_execute(tGOEPC_CCB *p_ccb, UINT8 event, tGOEPC_DATA *p_data) +{ + switch (p_ccb->state) + { + case GOEPC_STATE_INIT: + /* do nothing */ + break; + case GOEPC_STATE_OPENING: + goepc_sm_state_opening(p_ccb, event, p_data); + break; + case GOEPC_STATE_OPENED_IDLE: + goepc_sm_state_opened_idle(p_ccb, event, p_data); + break; + case GOEPC_STATE_OPENED_REQ: + goepc_sm_state_opened_req(p_ccb, event, p_data); + break; + case GOEPC_STATE_OPENED_RSP: + goepc_sm_state_opened_rsp(p_ccb, event, p_data); + break; + default: + GOEPC_TRACE_ERROR("goepc_sm_execute unexpected state: 0x%x\n", p_ccb->state); + break; + } +} + +static void goepc_srm_sm_act_req(tGOEPC_CCB *p_ccb, BOOLEAN srm_en, BOOLEAN srm_wait) +{ + switch (p_ccb->srm_state) + { + case GOEPC_SRM_STATE_IDLE: + if (srm_en) { + p_ccb->srm_state = GOEPC_SRM_STATE_REQ; + p_ccb->srm_wait = srm_wait; + } + else { + p_ccb->srm_state = GOEPC_SRM_STATE_DISABLE; + } + break; + case GOEPC_SRM_STATE_ENABLE_WAIT: + if (!srm_wait) { + p_ccb->srm_wait = FALSE; + } + if (!p_ccb->srm_wait && !p_ccb->srm_peer_wait) { + /* no more wait, transfer to ENABLE */ + p_ccb->srm_state = GOEPC_SRM_STATE_ENABLE; + } + break; + default: + break; + } +} + +static void goepc_srm_sm_act_rsp(tGOEPC_CCB *p_ccb, BOOLEAN srm_en, BOOLEAN srm_wait) +{ + switch (p_ccb->srm_state) + { + case GOEPC_SRM_STATE_IDLE: + /* peer can not request to enable srm, ignore */ + break; + case GOEPC_SRM_STATE_REQ: + if (srm_en) { + p_ccb->srm_peer_wait = srm_wait; + if (p_ccb->srm_wait || p_ccb->srm_peer_wait) { + p_ccb->srm_state = GOEPC_SRM_STATE_ENABLE_WAIT; + } + else { + p_ccb->srm_state = GOEPC_SRM_STATE_ENABLE; + } + } + else { + p_ccb->srm_state = GOEPC_SRM_STATE_DISABLE; + } + break; + case GOEPC_SRM_STATE_ENABLE_WAIT: + if (!srm_wait) { + p_ccb->srm_peer_wait = FALSE; + } + if (!p_ccb->srm_wait && !p_ccb->srm_peer_wait) { + /* no more wait, transfer to ENABLE */ + p_ccb->srm_state = GOEPC_SRM_STATE_ENABLE; + } + break; + default: + break; + } +} + +void goepc_srm_sm_execute(tGOEPC_CCB *p_ccb, BOOLEAN is_req, BOOLEAN srm_en, BOOLEAN srm_wait) +{ + if (is_req) { + goepc_srm_sm_act_req(p_ccb, srm_en, srm_wait); + } + else { + goepc_srm_sm_act_rsp(p_ccb, srm_en, srm_wait); + } +} + +#endif /* #if (GOEPC_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/stack/goep/include/goep_int.h b/lib/bt/host/bluedroid/stack/goep/include/goep_int.h new file mode 100644 index 00000000..0c1915f6 --- /dev/null +++ b/lib/bt/host/bluedroid/stack/goep/include/goep_int.h @@ -0,0 +1,103 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "common/bt_target.h" + +#include "stack/obex_api.h" +#include "stack/goep_common.h" +#include "stack/goepc_api.h" + +#if (GOEPC_INCLUDED == TRUE) + +/* GOEPC state machine events */ +enum { + GOEPC_SM_EVENT_CONNECT = 0, + GOEPC_SM_EVENT_DISCONNECT, + GOEPC_SM_EVENT_REQ, + GOEPC_SM_EVENT_REQ_FB, + GOEPC_SM_EVENT_RSP, + GOEPC_SM_EVENT_RSP_FB, +}; + +/* GOEPC state machine states */ +enum { + GOEPC_STATE_INIT = 0, + GOEPC_STATE_OPENING, + GOEPC_STATE_OPENED_IDLE, + GOEPC_STATE_OPENED_REQ, + GOEPC_STATE_OPENED_RSP, +}; + +/* GOEPC srm state machine states */ +enum { + GOEPC_SRM_STATE_IDLE = 0, + GOEPC_SRM_STATE_REQ, + GOEPC_SRM_STATE_ENABLE_WAIT, + GOEPC_SRM_STATE_ENABLE, + GOEPC_SRM_STATE_DISABLE, +}; + +/* GOEPC Connection Control block */ +typedef struct { + tGOEPC_EVT_CBACK *callback; /* GOEP event callback function */ + UINT16 obex_handle; /* OBEX connection handle */ + UINT16 peer_mtu; /* lower layer connection peer MTU */ + UINT16 our_mtu; /* lower layer connection our MTU */ + BOOLEAN congest; /* lower layer connection congestion status */ + + BT_HDR *pkt; /* packet prepared in this GOEP client */ + BOOLEAN pkt_srm_en; /* whether prepared packet had set SRM to enable */ + BOOLEAN pkt_srm_wait; /* whether prepared packet had set SRMP to wait */ + UINT8 curr_pkt_opcode; /* prepared packet opcode */ + + UINT8 last_pkt_opcode; /* last sent packet opcode */ + BOOLEAN srm_wait; /* whether we had set SRMP to wait */ + BOOLEAN srm_peer_wait; /* whether peer had set SRMP to wait */ + UINT8 srm_state; /* SRM state machine */ + UINT8 state; /* main state machine */ + UINT8 allocated; /* 0, not allocated. index+1, otherwise. equal to api handle */ +} tGOEPC_CCB; + +/* GOEPC Control block */ +typedef struct { + tGOEPC_CCB ccb[GOEPC_MAX_CONNECTION]; /* connection control blocks */ + UINT8 trace_level; /* trace level */ +} tGOEPC_CB; + +#if GOEP_DYNAMIC_MEMORY == FALSE +extern tGOEPC_CB goepc_cb; +#else +extern tGOEPC_CB *goepc_cb_ptr; +#define goepc_cb (*goepc_cb_ptr) +#endif + +typedef struct { + UINT16 peer_mtu; + UINT16 our_mtu; +} tGOEPC_CONNECTED; + +typedef struct { + UINT16 peer_mtu; + UINT16 our_mtu; +} tGOEPC_MTU_CHG; + +typedef union { + tGOEPC_CONNECTED connected; + tGOEPC_MTU_CHG mtu_chg; + BT_HDR *pkt; +} tGOEPC_DATA; + +tGOEPC_CCB *goepc_allocate_ccb(void); +void goepc_free_ccb(tGOEPC_CCB *p_ccb); +void goepc_obex_callback(UINT16 handle, UINT8 event, tOBEX_MSG *msg); +BOOLEAN goepc_check_obex_req_allow(UINT8 state, BOOLEAN final); +BOOLEAN goepc_check_obex_req_param(tOBEX_PARSE_INFO *info); +void goepc_sm_execute(tGOEPC_CCB *p_ccb, UINT8 event, tGOEPC_DATA *p_data); +void goepc_srm_sm_execute(tGOEPC_CCB *p_ccb, BOOLEAN is_req, BOOLEAN srm_en, BOOLEAN srm_wait); + +#endif /* #if (GOEPC_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/stack/hcic/hciblecmds.c b/lib/bt/host/bluedroid/stack/hcic/hciblecmds.c index 52a2b2dc..5ad13216 100644 --- a/lib/bt/host/bluedroid/stack/hcic/hciblecmds.c +++ b/lib/bt/host/bluedroid/stack/hcic/hciblecmds.c @@ -349,8 +349,8 @@ BOOLEAN btsnd_hcic_ble_create_ll_conn (UINT16 scan_int, UINT16 scan_win, UINT16_TO_STREAM (pp, conn_latency); UINT16_TO_STREAM (pp, conn_timeout); - UINT16_TO_STREAM (pp, min_ce_len); - UINT16_TO_STREAM (pp, max_ce_len); + UINT16_TO_STREAM (pp, min_ce_len ? min_ce_len : BLE_CE_LEN_MIN); + UINT16_TO_STREAM (pp, max_ce_len ? max_ce_len : BLE_CE_LEN_MIN); btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p); return (TRUE); @@ -686,6 +686,7 @@ BOOLEAN btsnd_hcic_ble_ltk_req_neg_reply (UINT16 handle) return (TRUE); } +#if (BLE_42_DTM_TEST_EN == TRUE) BOOLEAN btsnd_hcic_ble_receiver_test(UINT8 rx_freq) { BT_HDR *p; @@ -733,7 +734,9 @@ BOOLEAN btsnd_hcic_ble_transmitter_test(UINT8 tx_freq, UINT8 test_data_len, UINT btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p); return (TRUE); } +#endif // // #if (BLE_42_DTM_TEST_EN == TRUE) +#if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) BOOLEAN btsnd_hcic_ble_test_end(void) { BT_HDR *p; @@ -754,6 +757,7 @@ BOOLEAN btsnd_hcic_ble_test_end(void) btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p); return (TRUE); } +#endif // #if ((BLE_42_DTM_TEST_EN == TRUE) || (BLE_50_DTM_TEST_EN == TRUE)) BOOLEAN btsnd_hcic_ble_read_host_supported (void) { @@ -1084,27 +1088,6 @@ BOOLEAN btsnd_hcic_ble_set_channels (BLE_CHANNELS channels) return (TRUE); } -BOOLEAN btsnd_hcic_ble_clear_adv (void) -{ - BT_HDR *p; - UINT8 *pp; - - if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_CLEAR_ADV)) == NULL) { - return (FALSE); - } - - pp = (UINT8 *)(p + 1); - - p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_CLEAR_ADV; - p->offset = 0; - - UINT16_TO_STREAM (pp, HCI_VENDOR_BLE_CLEAR_ADV); - UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_CLEAR_ADV); - - btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p); - return TRUE; -} - #define HCIC_BLE_CMD_CREATED(p, pp, size) do{\ if ((p = HCI_GET_CMD_BUF(size)) == NULL) { \ return FALSE; \ @@ -1174,6 +1157,7 @@ BOOLEAN btsnd_hcic_ble_set_phy(UINT16 conn_handle, return TRUE; } +#if (BLE_50_DTM_TEST_EN == TRUE) UINT8 btsnd_hcic_ble_enhand_rx_test(UINT8 rx_channel, UINT8 phy, UINT8 modulation_idx) { @@ -1218,7 +1202,9 @@ UINT8 btsnd_hcic_ble_enhand_tx_test(UINT8 tx_channel, UINT8 len, return TRUE; } +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) UINT8 btsnd_hcic_ble_set_extend_rand_address(UINT8 adv_handle, BD_ADDR rand_addr) { BT_HDR *p; @@ -1432,7 +1418,9 @@ UINT8 btsnd_hcic_ble_clear_adv_set(void) return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); } +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) UINT8 btsnd_hcic_ble_set_periodic_adv_params(UINT8 adv_handle, UINT16 interval_min, UINT16 interval_max, @@ -1507,7 +1495,9 @@ UINT8 btsnd_hcic_ble_periodic_adv_enable(UINT8 enable, UINT8 adv_handle) return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); } +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SCAN_EN == TRUE) UINT8 btsnd_hcic_ble_set_ext_scan_params(UINT8 own_addr_type, UINT8 filter_policy, UINT8 phy_mask, UINT8 phy_count, tHCI_EXT_SCAN_PARAMS *params) @@ -1555,6 +1545,7 @@ UINT8 btsnd_hcic_ble_ext_scan_enable(UINT8 enable, UINT8 filter_dups, return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); } +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) BOOLEAN btsnd_hcic_ble_create_ext_conn(tHCI_CreatExtConn *p_conn) { @@ -1594,8 +1585,8 @@ BOOLEAN btsnd_hcic_ble_create_ext_conn(tHCI_CreatExtConn *p_conn) UINT16_TO_STREAM(pp, params->conn_interval_max); UINT16_TO_STREAM(pp, params->conn_latency); UINT16_TO_STREAM(pp, params->sup_timeout); - UINT16_TO_STREAM(pp, BLE_CE_LEN_MIN); - UINT16_TO_STREAM(pp, BLE_CE_LEN_MIN); + UINT16_TO_STREAM(pp, params->min_ce_len ? params->min_ce_len : BLE_CE_LEN_MIN); + UINT16_TO_STREAM(pp, params->max_ce_len ? params->max_ce_len : BLE_CE_LEN_MIN); } if (p_conn->init_phy_mask & 0x02) { @@ -1606,8 +1597,8 @@ BOOLEAN btsnd_hcic_ble_create_ext_conn(tHCI_CreatExtConn *p_conn) UINT16_TO_STREAM(pp, params->conn_interval_max); UINT16_TO_STREAM(pp, params->conn_latency); UINT16_TO_STREAM(pp, params->sup_timeout); - UINT16_TO_STREAM(pp, BLE_CE_LEN_MIN); - UINT16_TO_STREAM(pp, BLE_CE_LEN_MIN); + UINT16_TO_STREAM(pp, params->min_ce_len ? params->min_ce_len : BLE_CE_LEN_MIN); + UINT16_TO_STREAM(pp, params->max_ce_len ? params->max_ce_len : BLE_CE_LEN_MIN); } if (p_conn->init_phy_mask & 0x04) { @@ -1618,8 +1609,8 @@ BOOLEAN btsnd_hcic_ble_create_ext_conn(tHCI_CreatExtConn *p_conn) UINT16_TO_STREAM(pp, params->conn_interval_max); UINT16_TO_STREAM(pp, params->conn_latency); UINT16_TO_STREAM(pp, params->sup_timeout); - UINT16_TO_STREAM(pp, BLE_CE_LEN_MIN); - UINT16_TO_STREAM(pp, BLE_CE_LEN_MIN); + UINT16_TO_STREAM(pp, params->min_ce_len ? params->min_ce_len : BLE_CE_LEN_MIN); + UINT16_TO_STREAM(pp, params->max_ce_len ? params->max_ce_len : BLE_CE_LEN_MIN); } btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); @@ -1627,14 +1618,15 @@ BOOLEAN btsnd_hcic_ble_create_ext_conn(tHCI_CreatExtConn *p_conn) } +#if (BLE_50_EXTEND_SYNC_EN == TRUE) BOOLEAN btsnd_hcic_ble_periodic_adv_create_sync(UINT8 option, UINT8 adv_sid, UINT8 adv_addr_type, BD_ADDR adv_addr, - UINT16 sync_timeout, UINT8 unused) + UINT16 sync_timeout, UINT8 sync_cte_type) { BT_HDR *p; UINT8 *pp; - HCI_TRACE_EVENT("%s, option = %d, adv_sid = %d, adv_addr_type = %d, sync_timeout = %d, unused = %d", - __func__, option, adv_sid, adv_addr_type, sync_timeout, unused); + HCI_TRACE_EVENT("%s, option = %d, adv_sid = %d, adv_addr_type = %d, sync_timeout = %d, sync_cte_type = %d", + __func__, option, adv_sid, adv_addr_type, sync_timeout, sync_cte_type); HCI_TRACE_EVENT("addr %02x %02x %02x %02x %02x %02x", adv_addr[0], adv_addr[1], adv_addr[2], adv_addr[3], adv_addr[4], adv_addr[5]); uint16_t skip = 0; @@ -1648,7 +1640,7 @@ BOOLEAN btsnd_hcic_ble_periodic_adv_create_sync(UINT8 option, UINT8 adv_sid, BDADDR_TO_STREAM(pp, adv_addr); UINT16_TO_STREAM(pp, skip); UINT16_TO_STREAM(pp, sync_timeout); - UINT8_TO_STREAM(pp, unused); + UINT8_TO_STREAM(pp, sync_cte_type); btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); return TRUE; @@ -1750,6 +1742,7 @@ UINT8 btsnd_hcic_ble_read_periodic_adv_list_size(void) return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); } +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) UINT8 btsnd_hcic_ble_read_trans_power(void) { @@ -1910,7 +1903,7 @@ UINT8 btsnd_hcic_ble_set_default_periodic_adv_sync_trans_params(UINT8 mode, UINT } #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) -UINT8 btsnd_hcic_ble_set_privacy_mode(UINT8 addr_type, BD_ADDR addr, UINT8 privacy_mode) +BOOLEAN btsnd_hcic_ble_set_privacy_mode(UINT8 addr_type, BD_ADDR addr, UINT8 privacy_mode) { BT_HDR *p; UINT8 *pp; @@ -1933,4 +1926,885 @@ UINT8 btsnd_hcic_ble_set_privacy_mode(UINT8 addr_type, BD_ADDR addr, UINT8 priva btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); return (TRUE); } + +#if (BLE_VENDOR_HCI_EN == TRUE) +BOOLEAN btsnd_hcic_ble_clear_adv (void) +{ + BT_HDR *p; + UINT8 *pp; + + if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_CLEAR_ADV)) == NULL) { + return (FALSE); + } + + pp = (UINT8 *)(p + 1); + + p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_CLEAR_ADV; + p->offset = 0; + + UINT16_TO_STREAM (pp, HCI_VENDOR_BLE_CLEAR_ADV); + UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_CLEAR_ADV); + + btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p); + return TRUE; +} + +BOOLEAN btsnd_hcic_ble_set_csa_support (UINT8 csa_select) +{ + BT_HDR *p; + UINT8 *pp; + + if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_SET_CSA_SUPPORT)) == NULL) { + return (FALSE); + } + + pp = (UINT8 *)(p + 1); + + p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_SET_CSA_SUPPORT; + p->offset = 0; + + UINT16_TO_STREAM (pp, HCI_VENDOR_BLE_SET_CSA_SUPPORT); + UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_SET_CSA_SUPPORT); + UINT8_TO_STREAM (pp, csa_select); + + btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p); + return TRUE; +} + +BOOLEAN btsnd_hcic_ble_set_vendor_evt_mask (UINT32 evt_mask) +{ + BT_HDR *p; + UINT8 *pp; + + if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_SET_VENDOR_EVT_MASK)) == NULL) { + return (FALSE); + } + + pp = (UINT8 *)(p + 1); + + p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_SET_VENDOR_EVT_MASK; + p->offset = 0; + + UINT16_TO_STREAM (pp, HCI_VENDOR_BLE_SET_EVT_MASK); + UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_SET_VENDOR_EVT_MASK); + UINT32_TO_STREAM (pp, evt_mask); + + btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p); + return TRUE; +} +#endif // #if (BLE_VENDOR_HCI_EN == TRUE) #endif + +#if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +UINT8 btsnd_hcic_ble_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, + uint32_t sdu_interval, uint16_t max_sdu, uint16_t max_transport_latency, + uint8_t rtn, uint8_t phy, uint8_t packing, uint8_t framing, + uint8_t encryption, uint8_t *broadcast_code) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci big create: big_handle %d, adv_handle %d, num_bis %d sdu_interval %d max_sdu %d max_transport_latency %d \ + rtn %d phy %d packing %d framing %d encryption %d", big_handle, adv_handle, num_bis, sdu_interval, max_sdu,\ + max_transport_latency, rtn, phy, packing, framing, encryption); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_BIG_CREATE_PARAMS); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_CREATE_BIG); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_BIG_CREATE_PARAMS); + + UINT8_TO_STREAM(pp, big_handle); + UINT8_TO_STREAM(pp, adv_handle); + UINT8_TO_STREAM(pp, num_bis); + UINT24_TO_STREAM(pp, sdu_interval); + UINT16_TO_STREAM(pp, max_sdu); + UINT16_TO_STREAM(pp, max_transport_latency); + UINT8_TO_STREAM(pp, rtn); + UINT8_TO_STREAM(pp, phy); + UINT8_TO_STREAM(pp, packing); + UINT8_TO_STREAM(pp, framing); + UINT8_TO_STREAM(pp, encryption); + ARRAY_TO_STREAM(pp, broadcast_code, 16); + + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + return TRUE; +} + +UINT8 btsnd_hcic_ble_big_create_test(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, + uint32_t sdu_interval, uint16_t iso_interval, uint8_t nse, + uint16_t max_sdu, uint16_t max_pdu, uint8_t phy, + uint8_t packing, uint8_t framing, uint8_t bn, uint8_t irc, + uint8_t pto, uint8_t encryption, uint8_t *broadcast_code) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("%s big_handle %d, adv_handle %d, num_bis %d sdu_interval %d max_sdu %d max_pdu %d iso_interval %d \ + nse %d phy %d packing %d framing %d bn %d irc %dencryption %d", __func__, big_handle, adv_handle, num_bis, sdu_interval, max_sdu, max_pdu, \ + iso_interval, nse, phy, packing, framing, bn, irc, encryption); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_BIG_CREATE_TEST_PARAMS); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_CREATE_BIG_TEST); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_BIG_CREATE_TEST_PARAMS); + + UINT8_TO_STREAM(pp, big_handle); + UINT8_TO_STREAM(pp, adv_handle); + UINT8_TO_STREAM(pp, num_bis); + UINT24_TO_STREAM(pp, sdu_interval); + UINT16_TO_STREAM(pp, iso_interval); + UINT8_TO_STREAM(pp, nse); + UINT16_TO_STREAM(pp, max_sdu); + UINT16_TO_STREAM(pp, max_pdu); + UINT8_TO_STREAM(pp, phy); + UINT8_TO_STREAM(pp, packing); + UINT8_TO_STREAM(pp, framing); + UINT8_TO_STREAM(pp, bn); + UINT8_TO_STREAM(pp, irc); + UINT8_TO_STREAM(pp, pto); + UINT8_TO_STREAM(pp, encryption); + ARRAY_TO_STREAM(pp, broadcast_code, 16); + + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + return TRUE; +} + +UINT8 btsnd_hcic_ble_big_terminate(uint8_t big_handle, uint8_t reason) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("%s big_handle %d reason 0x%x", __func__, big_handle, reason); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_BIG_TERMINATE_PARAMS); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_TERMINATE_BIG); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_BIG_TERMINATE_PARAMS); + + UINT8_TO_STREAM(pp, big_handle); + UINT8_TO_STREAM(pp, reason); + + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + return TRUE; +} +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +UINT8 btsnd_hcic_ble_big_sync_create(uint8_t big_handle, uint16_t sync_handle, + uint8_t encryption, uint8_t *bc_code, + uint8_t mse, uint16_t big_sync_timeout, + uint8_t num_bis, uint8_t *bis) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("big sync create: big_handle %d sync_handle %d encryption %d mse %d big_sync_timeout %d", big_handle, sync_handle, encryption, mse, big_sync_timeout); + + // for (uint8_t i = 0; i < num_bis; i++) + // { + // HCI_TRACE_ERROR("i %d bis %d", bis[i]); + // } + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_BIG_SYNC_CREATE_PARAMS); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_BIG_CREATE_SYNC); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_BIG_SYNC_CREATE_PARAMS); + + UINT8_TO_STREAM(pp, big_handle); + UINT16_TO_STREAM(pp, sync_handle); + UINT8_TO_STREAM(pp, encryption); + ARRAY_TO_STREAM(pp, bc_code, 16); + UINT8_TO_STREAM(pp, mse); + UINT16_TO_STREAM(pp, big_sync_timeout); + UINT8_TO_STREAM(pp, num_bis); + ARRAY_TO_STREAM(pp, bis, num_bis); + + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + return TRUE; +} + +UINT8 btsnd_hcic_ble_big_sync_terminate(uint8_t big_handle) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("%s big_handle %d", __func__, big_handle); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_BIG_SYNC_TERMINATE_PARAMS); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_BIG_TERMINATE_SYNC); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_BIG_SYNC_TERMINATE_PARAMS); + + UINT8_TO_STREAM(pp, big_handle); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +UINT8 btsnd_hcic_ble_iso_set_data_path(uint16_t conn_handle, uint8_t data_path_dir, uint8_t data_path_id, uint8_t coding_fmt, + uint16_t company_id, uint16_t vs_codec_id, uint32_t controller_delay, uint8_t codec_len, + uint8_t *codec_cfg) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set data path: conn_handle %d data_path_dir %d data_path_id %d coding_fmt %d company_id 0x%x vs_codec_id %d controller_delay %ld codec_len %d", + conn_handle, data_path_dir, data_path_id, coding_fmt, company_id, vs_codec_id, controller_delay, codec_len); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_ISO_SET_DATA_PATH_PARAMS + codec_len); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_ISO_SET_DATA_PATH); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ISO_SET_DATA_PATH_PARAMS + codec_len); + + UINT16_TO_STREAM(pp, conn_handle); + UINT8_TO_STREAM(pp, data_path_dir); + UINT8_TO_STREAM(pp, data_path_id); + UINT8_TO_STREAM(pp, coding_fmt); + UINT16_TO_STREAM(pp, company_id); + UINT16_TO_STREAM(pp, vs_codec_id); + UINT24_TO_STREAM(pp, controller_delay); + UINT8_TO_STREAM(pp, codec_len); + if (codec_len && codec_cfg) { + ARRAY_TO_STREAM(pp, codec_cfg, codec_len); + } + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_iso_remove_data_path(uint16_t conn_handle, uint8_t data_path_dir) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci remove data path: conn_handle %d data_path_dir %d", conn_handle, data_path_dir); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_ISO_REMOVE_DATA_PATH_PARAMS); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_ISO_REMOVE_DATA_PATH); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ISO_REMOVE_DATA_PATH_PARAMS); + + UINT16_TO_STREAM(pp, conn_handle); + UINT8_TO_STREAM(pp, data_path_dir); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_iso_read_tx_sync(uint16_t iso_hdl) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci read iso tx sync: iso_hdl %d", iso_hdl); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_ISO_READ_TX_SYNC_PARAMS); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_ISO_READ_TX_SYNC); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ISO_READ_TX_SYNC_PARAMS); + // Bit_Number V1 + UINT16_TO_STREAM(pp, iso_hdl); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +UINT8 btsnd_hcic_ble_iso_set_cig_params(uint8_t cig_id, uint32_t sdu_int_c_to_p, uint32_t sdu_int_p_to_c, uint8_t worse_case_SCA, uint8_t packing, + uint8_t framing, uint16_t mtl_c_to_p, uint16_t mtl_p_to_c, uint8_t cis_cnt, struct ble_hci_le_cis_params *cis_params) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set cig params: cig_id %d sdu_int_c_to_p %d sdu_int_p_to_c %d worse_case_SCA %d packing %d framing %d mtl_c_to_p %d mtl_p_to_c %d cis_cnt %d", + cig_id, sdu_int_c_to_p, sdu_int_p_to_c, worse_case_SCA, packing, framing, mtl_c_to_p, mtl_p_to_c, cis_cnt); + UINT8 cis_param_len = cis_cnt * 9; + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_ISO_SET_CIG_PARAMS + cis_param_len); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_ISO_SET_CIG_PARAMS); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ISO_SET_CIG_PARAMS + cis_param_len); + + UINT8_TO_STREAM(pp, cig_id); + UINT24_TO_STREAM(pp, sdu_int_c_to_p); + UINT24_TO_STREAM(pp, sdu_int_p_to_c); + UINT8_TO_STREAM(pp, worse_case_SCA); + UINT8_TO_STREAM(pp, packing); + UINT8_TO_STREAM(pp, framing); + UINT16_TO_STREAM(pp, mtl_c_to_p); + UINT16_TO_STREAM(pp, mtl_p_to_c); + UINT8_TO_STREAM(pp, cis_cnt); + + for (uint8_t i = 0; i < cis_cnt; i++) + { + UINT8_TO_STREAM(pp, cis_params[i].cis_id); + UINT16_TO_STREAM(pp, cis_params[i].max_sdu_c_to_p); + UINT16_TO_STREAM(pp, cis_params[i].max_sdu_p_to_c); + UINT8_TO_STREAM(pp, cis_params[i].phy_c_to_p); + UINT8_TO_STREAM(pp, cis_params[i].phy_p_to_c); + UINT8_TO_STREAM(pp, cis_params[i].rtn_c_to_p); + UINT8_TO_STREAM(pp, cis_params[i].rtn_p_to_c); + } + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_iso_set_cig_params_test(uint8_t cig_id, uint32_t sdu_int_c_to_p, uint32_t sdu_int_p_to_c, uint8_t ft_c_to_p, uint8_t ft_p_to_c, + uint16_t iso_interval, uint8_t worse_case_SCA, uint8_t packing, uint8_t framing, uint8_t cis_cnt, + struct ble_hci_le_cis_params_test *cis_params_test) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set cig params test: cig_id %d sdu_int_c_to_p %d sdu_int_p_to_c %d ft_c_to_p %d ft_p_to_c %d iso_interval %d worse_case_SCA %d packing %d framing %d cis_cnt %d", + cig_id, sdu_int_c_to_p, sdu_int_p_to_c, ft_c_to_p, ft_p_to_c, iso_interval, worse_case_SCA, packing, framing, cis_cnt); + UINT8 cis_param_len = cis_cnt * 14; + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_ISO_SET_CIG_TEST_PARAMS + cis_param_len); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_ISO_SET_CIG_PARAMS_TEST); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ISO_SET_CIG_TEST_PARAMS + cis_param_len); + + UINT8_TO_STREAM(pp, cig_id); + UINT24_TO_STREAM(pp, sdu_int_c_to_p); + UINT24_TO_STREAM(pp, sdu_int_p_to_c); + UINT8_TO_STREAM(pp, ft_c_to_p); + UINT8_TO_STREAM(pp, ft_p_to_c); + UINT16_TO_STREAM(pp, iso_interval); + UINT8_TO_STREAM(pp, worse_case_SCA); + UINT8_TO_STREAM(pp, packing); + UINT8_TO_STREAM(pp, framing); + UINT8_TO_STREAM(pp, cis_cnt); + + for (uint8_t i = 0; i < cis_cnt; i++) + { + UINT8_TO_STREAM(pp, cis_params_test[i].cis_id); + UINT8_TO_STREAM(pp, cis_params_test[i].nse); + UINT16_TO_STREAM(pp, cis_params_test[i].max_sdu_c_to_p); + UINT16_TO_STREAM(pp, cis_params_test[i].max_sdu_p_to_c); + UINT16_TO_STREAM(pp, cis_params_test[i].max_pdu_c_to_p); + UINT16_TO_STREAM(pp, cis_params_test[i].max_pdu_p_to_c); + UINT8_TO_STREAM(pp, cis_params_test[i].phy_c_to_p); + UINT8_TO_STREAM(pp, cis_params_test[i].phy_p_to_c); + UINT8_TO_STREAM(pp, cis_params_test[i].bn_c_to_p); + UINT8_TO_STREAM(pp, cis_params_test[i].bn_p_to_c); + } + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_iso_create_cis(uint8_t cis_count, struct ble_hci_cis_hdls *cis_hdls) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci create cis: cig_id ", cis_count); + // for (uint8_t i = 0; i < cis_count; i++) + // { + // HCI_TRACE_ERROR("i %d cis_hdl %d acl_hdl %d", i, cis_hdls[i].cis_hdl, cis_hdls[i].acl_hdl); + // } + + UINT8 cis_param_len = cis_count * 4; + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_ISO_CREATE_CIS_PARAMS + cis_param_len); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_ISO_CREATE_CIS); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ISO_CREATE_CIS_PARAMS + cis_param_len); + + UINT8_TO_STREAM(pp, cis_count); + + for (uint8_t i = 0; i < cis_count; i++) + { + UINT16_TO_STREAM(pp, cis_hdls[i].cis_hdl); + UINT16_TO_STREAM(pp, cis_hdls[i].acl_hdl); + } + + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + + return TRUE; +} + +UINT8 btsnd_hcic_ble_iso_remove_cig(uint8_t cig_id) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci remove cig: cig_id %d", cig_id); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_ISO_REMOVE_CIG_PARAMS); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_ISO_REMOVE_CIG); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ISO_REMOVE_CIG_PARAMS); + + UINT8_TO_STREAM(pp, cig_id); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +UINT8 btsnd_hcic_ble_iso_accept_cis_req(uint16_t cis_handle) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci accept cis req: cis_handle %d", cis_handle); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_ISO_ACCEPT_CIS_REQ_PARAMS); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_ISO_ACCEPT_CIS_REQ); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ISO_ACCEPT_CIS_REQ_PARAMS); + + UINT16_TO_STREAM(pp, cis_handle); + + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + + return TRUE; +} + +UINT8 btsnd_hcic_ble_iso_reject_cis_req(uint16_t cis_handle, uint8_t reason) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci reject cis req: cis_handle %d reason %d", cis_handle, reason); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_ISO_REJECT_CIS_REQ_PARAMS); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_ISO_REJECT_CIS_REQ); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ISO_REJECT_CIS_REQ_PARAMS); + + UINT16_TO_STREAM(pp, cis_handle); + UINT8_TO_STREAM(pp, reason); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + +UINT8 btsnd_hcic_ble_iso_read_iso_link_quality(uint16_t iso_handle) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci read iso link quality: cis_handle %d", iso_handle); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_ISO_READ_LINK_QUALITY_PARAMS); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_ISO_READ_ISO_LINK_QUALITY); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ISO_READ_LINK_QUALITY_PARAMS); + + UINT16_TO_STREAM(pp, iso_handle); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +UINT8 btsnd_hcic_ble_set_connless_cte_trans_params(uint8_t adv_hdl, uint8_t cte_len, uint8_t cte_type, + uint8_t cte_cnt, uint8_t switching_pattern_len, uint8_t *antenna_ids) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set connless cte trans: adv_hdl %d cte_len %d cte_type %d cte_cnt %d", adv_hdl, cte_len, cte_type, cte_cnt); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_CONNLESS_CTE_TRANS_PARAMS + switching_pattern_len); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_CONNLESS_CTE_TRANS_PARAMS); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_CONNLESS_CTE_TRANS_PARAMS + switching_pattern_len); + + UINT8_TO_STREAM(pp, adv_hdl); + UINT8_TO_STREAM(pp, cte_len); + UINT8_TO_STREAM(pp, cte_type); + UINT8_TO_STREAM(pp, cte_cnt); + UINT8_TO_STREAM(pp, switching_pattern_len); + for (uint8_t i = 0; i < switching_pattern_len; i++) + { + UINT8_TO_STREAM(pp, antenna_ids[i]); + } + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_set_connless_cte_enable(uint8_t adv_hdl, uint8_t cte_en) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set connect cte enable: adv_hdl %d cte_en %d", adv_hdl, cte_en); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_CONNLESS_CTE_TRANS_ENABLE); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_CONNLESS_CTE_TRANS_ENABLE); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_CONNLESS_CTE_TRANS_ENABLE); + + UINT8_TO_STREAM(pp, adv_hdl); + UINT8_TO_STREAM(pp, cte_en); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_set_connless_iq_sampling_enable(uint16_t sync_hdl, uint8_t sampling_en, uint8_t slot_dur, + uint8_t max_sampled_ctes, uint8_t switching_pattern_len, uint8_t *antenna_ids) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci enable IQ sampling: sync_hdl %d sampling_en %d slot_dur %d", sync_hdl, sampling_en, slot_dur); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_CONNLESS_IQ_SAMPLING_ENABLE + switching_pattern_len); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_CONNLESS_IQ_SAMPLING_ENABLE); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_CONNLESS_IQ_SAMPLING_ENABLE + switching_pattern_len); + + UINT16_TO_STREAM(pp, sync_hdl); + UINT8_TO_STREAM(pp, sampling_en); + UINT8_TO_STREAM(pp, slot_dur); + UINT8_TO_STREAM(pp, max_sampled_ctes); + UINT8_TO_STREAM(pp, switching_pattern_len); + for (uint8_t i = 0; i < switching_pattern_len; i++) + { + UINT8_TO_STREAM(pp, antenna_ids[i]); + } + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +UINT8 btsnd_hcic_ble_set_conn_cte_receive_params(uint16_t conn_hdl, uint8_t sampling_en, uint8_t slot_dur, + uint8_t switching_pattern_len, uint8_t *antenna_ids) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set connection cte receive params: conn_hdl %d sampling_en %d slot_dur %d", conn_hdl, sampling_en, slot_dur); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_CONN_CTE_RECEIVE_PARAMS + switching_pattern_len); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_CONN_CTE_RECEIVE_PARAMS); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_CONN_CTE_RECEIVE_PARAMS + switching_pattern_len); + + UINT16_TO_STREAM(pp, conn_hdl); + UINT8_TO_STREAM(pp, sampling_en); + UINT8_TO_STREAM(pp, slot_dur); + UINT8_TO_STREAM(pp, switching_pattern_len); + for (uint8_t i = 0; i < switching_pattern_len; i++) + { + UINT8_TO_STREAM(pp, antenna_ids[i]); + } + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_set_conn_cte_trans_params(uint16_t conn_hdl, uint8_t cte_type, uint8_t switching_pattern_len, uint8_t *antenna_ids) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set connection cte trans params: conn_hdl %d cte_type %d len %d", conn_hdl, cte_type, switching_pattern_len); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_CONN_CTE_TRANS_PARAMS + switching_pattern_len); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_CONN_CTE_TRANS_PARAMS); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_CONN_CTE_TRANS_PARAMS + switching_pattern_len); + + UINT16_TO_STREAM(pp, conn_hdl); + UINT8_TO_STREAM(pp, cte_type); + UINT8_TO_STREAM(pp, switching_pattern_len); + for (uint8_t i = 0; i < switching_pattern_len; i++) + { + UINT8_TO_STREAM(pp, antenna_ids[i]); + } + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_conn_cte_req_enable(uint16_t conn_hdl, uint8_t enable, uint16_t cte_req_int, uint8_t req_cte_len, uint8_t req_cte_type) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set connect cte request enable: conn_hdl %d enable %d cte_req_int %d req_cte_len %d req_cte_type %d", conn_hdl, enable, cte_req_int, req_cte_len, req_cte_type); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_CONN_CTE_REQ_ENABLE); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_CONN_CTE_REQ_ENABLE); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CONN_CTE_REQ_ENABLE); + + UINT16_TO_STREAM(pp, conn_hdl); + UINT8_TO_STREAM(pp, enable); + UINT16_TO_STREAM(pp, cte_req_int); + UINT8_TO_STREAM(pp, req_cte_len); + UINT8_TO_STREAM(pp, req_cte_type); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_conn_cte_rsp_enable(uint16_t conn_hdl, uint8_t enable) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set connect cte response enable: conn_hdl %d enable %d", conn_hdl, enable); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_CONN_CTE_RSP_ENABLE); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_CONN_CTE_RSP_ENABLE); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CONN_CTE_RSP_ENABLE); + + UINT16_TO_STREAM(pp, conn_hdl); + UINT8_TO_STREAM(pp, enable); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + +UINT8 btsnd_hcic_ble_read_antenna_info(void) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci read antenna information"); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_READ_ANT_INFO); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_READ_ANT_INFOR); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_READ_ANT_INFO); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} +#endif // #if (BLE_FEAT_CTE_EN == TRUE) + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +UINT8 btsnd_hcic_ble_enh_read_trans_power_level(uint16_t conn_handle, uint8_t phy) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci enh read trans power level, conn_handle %d phy %d", conn_handle, phy); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_ENH_READ_TRANS_PWR_LEVEL); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_ENH_READ_TRANS_POWER_LEVEL); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ENH_READ_TRANS_PWR_LEVEL); + + UINT16_TO_STREAM(pp, conn_handle); + UINT8_TO_STREAM(pp, phy); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_read_remote_trans_power_level(uint16_t conn_handle, uint8_t phy) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci read remote trans power level, conn_handle %d phy %d", conn_handle, phy); + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_READ_REMOTE_TRANS_PWR_LEVEL); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_READ_REMOTE_TRANS_POWER_LEVEL); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_READ_REMOTE_TRANS_PWR_LEVEL); + + UINT16_TO_STREAM(pp, conn_handle); + UINT8_TO_STREAM(pp, phy); + + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + + return TRUE; +} + +UINT8 btsnd_hcic_ble_set_path_loss_rpt_params(uint16_t conn_handle, uint8_t high_threshold, uint8_t high_hysteresis, + uint8_t low_threshold, uint8_t low_hysteresis, uint16_t min_time_spent) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set path loss rpt params, conn_handle %d high_threshold %d high_hysteresis %d low_threshold %d low_hysteresis %d min_time_spent %d", + conn_handle, high_threshold, high_hysteresis, low_threshold, + low_hysteresis, min_time_spent); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_PATH_LOSS_REPORTING_PARAMS); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_PATH_LOSS_REPORTING_PARAMS); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_PATH_LOSS_REPORTING_PARAMS); + + UINT16_TO_STREAM(pp, conn_handle); + UINT8_TO_STREAM(pp, high_threshold); + UINT8_TO_STREAM(pp, high_hysteresis); + UINT8_TO_STREAM(pp, low_threshold); + UINT8_TO_STREAM(pp, low_hysteresis); + UINT16_TO_STREAM(pp, min_time_spent); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_set_path_loss_rpt_enable(uint16_t conn_handle, uint8_t enable) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set path loss rpt en, conn_handle %d enable %d", conn_handle, enable); + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_PATH_LOSS_REPORTING_ENABLE); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_PATH_LOSS_REPORTING_ENABLE); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_PATH_LOSS_REPORTING_ENABLE); + + UINT16_TO_STREAM(pp, conn_handle); + UINT8_TO_STREAM(pp, enable); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_set_trans_pwr_rpt_enable(uint16_t conn_handle, uint8_t local_enable, uint8_t remote_enable) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set trans power rpt en, conn_handle %d local_enable %d remote_enable %d", conn_handle, local_enable, remote_enable); + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_TRANS_PWR_REPORTING_ENABLE); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_TRANS_POWER_REPORTING_ENABLE); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_TRANS_PWR_REPORTING_ENABLE); + + UINT16_TO_STREAM(pp, conn_handle); + UINT8_TO_STREAM(pp, local_enable); + UINT8_TO_STREAM(pp, remote_enable); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +UINT8 btsnd_hcic_ble_set_default_subrate(UINT16 subrate_min, UINT16 subrate_max, UINT16 max_latency, + UINT16 continuation_number, UINT16 supervision_timeout) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set default subrate, subrate_min %d subrate_max %d max_latency %d continuation_number %d supervision_timeout %d", + subrate_min, subrate_max, max_latency, continuation_number, supervision_timeout); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_DEFAULT_SUBRATE_PARAMS_LEN); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_SET_DEFAULT_SUBRATE); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_DEFAULT_SUBRATE_PARAMS_LEN); + + UINT16_TO_STREAM(pp, subrate_min); + UINT16_TO_STREAM(pp, subrate_max); + UINT16_TO_STREAM(pp, max_latency); + UINT16_TO_STREAM(pp, continuation_number); + UINT16_TO_STREAM(pp, supervision_timeout); + + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} + +UINT8 btsnd_hcic_ble_subrate_request(UINT16 conn_handle, UINT16 subrate_min, UINT16 subrate_max, UINT16 max_latency, + UINT16 continuation_number, UINT16 supervision_timeout) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci subrate req, conn_handle %d subrate_min %d subrate_max %d max_latency %d continuation_number %d supervision_timeout %d", + conn_handle, subrate_min, subrate_max, max_latency, continuation_number, supervision_timeout); + + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SUBRATE_REQ_LENGTH_PARAMS_LEN); + + pp = (UINT8 *)(p + 1); + + UINT16_TO_STREAM(pp, HCI_BLE_SUBRATE_REQUEST); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SUBRATE_REQ_LENGTH_PARAMS_LEN); + + UINT16_TO_STREAM(pp, conn_handle); + UINT16_TO_STREAM(pp, subrate_min); + UINT16_TO_STREAM(pp, subrate_max); + UINT16_TO_STREAM(pp, max_latency); + UINT16_TO_STREAM(pp, continuation_number); + UINT16_TO_STREAM(pp, supervision_timeout); + + btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p); + return TRUE; +} +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + +#if (BLE_50_FEATURE_SUPPORT == TRUE) +UINT8 btsnd_hcic_ble_set_host_feature(uint16_t bit_num, uint8_t bit_val) +{ + BT_HDR *p; + UINT8 *pp; + + HCI_TRACE_DEBUG("hci set host feature: bit_num %d bit_val %d", bit_num, bit_val); +#if (BLE_FEAT_ISO_60_EN == TRUE) + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_HOST_FEATURE_PARAMS_V2); +#else + HCIC_BLE_CMD_CREATED(p, pp, HCIC_PARAM_SIZE_SET_HOST_FEATURE_PARAMS); +#endif // #if (BLE_FEAT_ISO_60_EN == TRUE) + pp = (UINT8 *)(p + 1); +#if (BLE_FEAT_ISO_60_EN == TRUE) + UINT16_TO_STREAM(pp, HCI_BLE_SET_HOST_FEATURE_V2); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_HOST_FEATURE_PARAMS_V2); + // Bit_Number V1 + UINT16_TO_STREAM(pp, bit_num); +#else + UINT16_TO_STREAM(pp, HCI_BLE_SET_HOST_FEATURE); + UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_SET_HOST_FEATURE_PARAMS); + // Bit_Number V1 + UINT8_TO_STREAM(pp, bit_num); +#endif // #if (BLE_FEAT_ISO_60_EN == TRUE) + UINT8_TO_STREAM(pp, bit_val); + return btu_hcif_send_cmd_sync(LOCAL_BR_EDR_CONTROLLER_ID, p); +} +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) diff --git a/lib/bt/host/bluedroid/stack/include/stack/a2d_sbc.h b/lib/bt/host/bluedroid/stack/include/stack/a2d_sbc.h index 065f264f..088d11ab 100644 --- a/lib/bt/host/bluedroid/stack/include/stack/a2d_sbc.h +++ b/lib/bt/host/bluedroid/stack/include/stack/a2d_sbc.h @@ -30,7 +30,12 @@ /* the length of the SBC Media Payload header. */ #define A2D_SBC_MPL_HDR_LEN 1 -/* the LOSC of SBC media codec capabilitiy */ +/* CIE offset in the info byte sequence */ +#define A2D_SBC_CIE_OFF 3 +/* CIE length in the info byte sequence */ +#define A2D_SBC_CIE_LEN 4 + +/* the LOSC of SBC media codec capability */ #define A2D_SBC_INFO_LEN 6 /* for Codec Specific Information Element */ diff --git a/lib/bt/host/bluedroid/stack/include/stack/acl_hci_link_interface.h b/lib/bt/host/bluedroid/stack/include/stack/acl_hci_link_interface.h index f62c654f..60c0f26a 100644 --- a/lib/bt/host/bluedroid/stack/include/stack/acl_hci_link_interface.h +++ b/lib/bt/host/bluedroid/stack/include/stack/acl_hci_link_interface.h @@ -10,6 +10,6 @@ #include "bt_common.h" void btm_acl_connected(BD_ADDR bda, UINT16 handle, UINT8 link_type, UINT8 enc_mode, UINT8 status); -void btm_acl_disconnected(UINT16 handle, UINT8 reason); +BOOLEAN btm_acl_disconnected(UINT16 handle, UINT8 reason); #endif /* ACL_HCI_LINK_INTERFACE_H */ diff --git a/lib/bt/host/bluedroid/stack/include/stack/avdt_api.h b/lib/bt/host/bluedroid/stack/include/stack/avdt_api.h index 42a1f855..00c16f49 100644 --- a/lib/bt/host/bluedroid/stack/include/stack/avdt_api.h +++ b/lib/bt/host/bluedroid/stack/include/stack/avdt_api.h @@ -517,6 +517,18 @@ extern void AVDT_AbortReq(UINT8 handle); *******************************************************************************/ extern UINT16 AVDT_CreateStream(UINT8 *p_handle, tAVDT_CS *p_cs); +/******************************************************************************* +** +** Function AVDT_UpdateCodecInfo +** +** Description Update codec capability for a stream endpoint. +** +** +** Returns AVDT_SUCCESS if successful, otherwise error. +** +*******************************************************************************/ +extern UINT16 AVDT_UpdateCodecInfo(UINT8 handle, UINT8 num_codec, UINT8 *codec_info, UINT16 codec_info_len); + /******************************************************************************* ** ** Function AVDT_RemoveStream diff --git a/lib/bt/host/bluedroid/stack/include/stack/avrc_api.h b/lib/bt/host/bluedroid/stack/include/stack/avrc_api.h index 21f4bee5..2985c65c 100644 --- a/lib/bt/host/bluedroid/stack/include/stack/avrc_api.h +++ b/lib/bt/host/bluedroid/stack/include/stack/avrc_api.h @@ -99,6 +99,9 @@ #define AVRC_SUPF_CT_CAT3 0x0004 /* Category 3 */ #define AVRC_SUPF_CT_CAT4 0x0008 /* Category 4 */ #define AVRC_SUPF_CT_BROWSE 0x0040 /* Browsing */ +#define AVRC_SUPF_CT_COVER_ART_GIP 0x0080 /* Cover Art GetImageProperties */ +#define AVRC_SUPF_CT_COVER_ART_GI 0x0100 /* Cover Art GetImage */ +#define AVRC_SUPF_CT_COVER_ART_GLT 0x0200 /* Cover Art GetLinkedThumbnail */ #define AVRC_SUPF_TG_CAT1 0x0001 /* Category 1 */ #define AVRC_SUPF_TG_CAT2 0x0002 /* Category 2 */ @@ -107,7 +110,8 @@ #define AVRC_SUPF_TG_APP_SETTINGS 0x0010 /* Player Application Settings */ #define AVRC_SUPF_TG_GROUP_NAVI 0x0020 /* Group Navigation */ #define AVRC_SUPF_TG_BROWSE 0x0040 /* Browsing */ -#define AVRC_SUPF_TG_MULTI_PLAYER 0x0080 /* Muliple Media Player */ +#define AVRC_SUPF_TG_MULTI_PLAYER 0x0080 /* Multiple Media Player */ +#define AVRC_SUPF_TG_COVER_ART 0x0100 /* Cover Art */ #define AVRC_META_SUCCESS AVRC_SUCCESS #define AVRC_META_FAIL AVRC_FAIL @@ -561,7 +565,7 @@ extern bt_status_t AVRC_Init(void); ** ** Function AVRC_Deinit ** -** Description This function is called at stack shotdown to free the +** Description This function is called at stack shutdown to free the ** control block (if using dynamic memory), and deinitializes the ** control block and tracing level. ** diff --git a/lib/bt/host/bluedroid/stack/include/stack/avrc_defs.h b/lib/bt/host/bluedroid/stack/include/stack/avrc_defs.h index c90fa6cf..06f73c29 100644 --- a/lib/bt/host/bluedroid/stack/include/stack/avrc_defs.h +++ b/lib/bt/host/bluedroid/stack/include/stack/avrc_defs.h @@ -35,6 +35,7 @@ #define AVRC_REV_1_3 0x0103 #define AVRC_REV_1_4 0x0104 #define AVRC_REV_1_5 0x0105 +#define AVRC_REV_1_6 0x0106 #define AVRC_PACKET_LEN 512 /* Per the spec, you must support 512 byte RC packets */ @@ -185,7 +186,7 @@ #define AVRC_PKT_END 3 #define AVRC_PKT_TYPE_MASK 3 -/* Define the PDUs carried in the vendor dependant data +/* Define the PDUs carried in the vendor dependent data */ #define AVRC_PDU_GET_CAPABILITIES 0x10 #define AVRC_PDU_LIST_PLAYER_APP_ATTR 0x11 @@ -297,7 +298,7 @@ typedef UINT8 tAVRC_BATTERY_STATUS; #define AVRC_MEDIA_ATTR_ID_TRACK_NUM 0x00000004 #define AVRC_MEDIA_ATTR_ID_NUM_TRACKS 0x00000005 #define AVRC_MEDIA_ATTR_ID_GENRE 0x00000006 -#define AVRC_MEDIA_ATTR_ID_PLAYING_TIME 0x00000007 /* in miliseconds */ +#define AVRC_MEDIA_ATTR_ID_PLAYING_TIME 0x00000007 /* in milliseconds */ #define AVRC_MAX_NUM_MEDIA_ATTR_ID 7 /* Define the possible values of play state diff --git a/lib/bt/host/bluedroid/stack/include/stack/bt_types.h b/lib/bt/host/bluedroid/stack/include/stack/bt_types.h index 5d817632..4050b79d 100644 --- a/lib/bt/host/bluedroid/stack/include/stack/bt_types.h +++ b/lib/bt/host/bluedroid/stack/include/stack/bt_types.h @@ -486,6 +486,7 @@ typedef struct { #define BLE_ADDR_RANDOM_ID 0x03 #define BLE_ADDR_TYPE_MAX BLE_ADDR_RANDOM_ID #define BLE_ADDR_UNKNOWN_TYPE 0XFF +#define BLE_ADDR_ANONYMOUS 0xFF typedef UINT8 tBLE_ADDR_TYPE; #define BLE_ADDR_TYPE_MASK (BLE_ADDR_RANDOM | BLE_ADDR_PUBLIC) diff --git a/lib/bt/host/bluedroid/stack/include/stack/btm_api.h b/lib/bt/host/bluedroid/stack/include/stack/btm_api.h index 32420f75..3415df5d 100644 --- a/lib/bt/host/bluedroid/stack/include/stack/btm_api.h +++ b/lib/bt/host/bluedroid/stack/include/stack/btm_api.h @@ -75,6 +75,7 @@ enum { BTM_SET_STATIC_RAND_ADDR_FAIL, /* 25 Command failed */ BTM_INVALID_STATIC_RAND_ADDR, /* 26 invalid static rand addr */ BTM_SEC_DEV_REC_REMOVED, /* 27 Device record relate to the bd_addr is removed */ + BTM_HCI_ERROR = 128, /* 128 HCI error code from controller (0x80) */ }; typedef uint8_t tBTM_STATUS; @@ -200,6 +201,8 @@ typedef void (tBTM_SET_LOCAL_PRIVACY_CBACK) (UINT8 status); typedef void (tBTM_SET_RPA_TIMEOUT_CMPL_CBACK) (UINT8 status); typedef void (tBTM_ADD_DEV_TO_RESOLVING_LIST_CMPL_CBACK) (UINT8 status); + +typedef void (tBTM_BLE_VENDOR_HCI_EVT_CBACK) (UINT8 subevt_code, UINT8 param_len, UINT8 *params); /******************************* ** Device Coexist status ********************************/ @@ -456,22 +459,22 @@ typedef enum { #define BTM_COD_SERVICE_INFORMATION 0x8000 /* class of device field macros */ -#define BTM_COD_FORMAT_TYPE(u8, pd) {u8 = pd[2]&0x03;} +#define BTM_COD_RESERVED_2(u8, pd) {u8 = pd[2]&0x03;} #define BTM_COD_MINOR_CLASS(u8, pd) {u8 = pd[2]&0xFC;} #define BTM_COD_MAJOR_CLASS(u8, pd) {u8 = pd[1]&0x1F;} #define BTM_COD_SERVICE_CLASS(u16, pd) {u16 = pd[0]; u16<<=8; u16 += pd[1]&0xE0;} /* to set the fields (assumes that format type is always 0) */ -#define FIELDS_TO_COD(pd, mn, mj, sv) {pd[2] = mn; pd[1] = \ - mj+ ((sv)&BTM_COD_SERVICE_CLASS_LO_B); \ - pd[0] = (sv) >> 8;} +#define FIELDS_TO_COD(pd, rs, mn, mj, sv) {pd[2] = (mn & BTM_COD_MINOR_CLASS_MASK) + (rs & BTM_COD_RESERVED_2_MASK); \ + pd[1] = mj+ ((sv)&BTM_COD_SERVICE_CLASS_LO_B); \ + pd[0] = (sv) >> 8;} /* the COD masks */ -#define BTM_COD_FORMAT_TYPE_MASK 0x03 #define BTM_COD_MINOR_CLASS_MASK 0xFC #define BTM_COD_MAJOR_CLASS_MASK 0x1F #define BTM_COD_SERVICE_CLASS_LO_B 0x00E0 #define BTM_COD_SERVICE_CLASS_MASK 0xFFE0 +#define BTM_COD_RESERVED_2_MASK 0x03 /* BTM service definitions ** Used for storing EIR data to bit mask @@ -808,6 +811,16 @@ typedef struct { BD_ADDR rem_bda; } tBTM_RSSI_RESULTS; +/* Structure returned with read channel map event (in tBTM_CMPL_CB callback function) +** in response to BTM_ReadChannelMap call. +*/ +typedef struct { + tBTM_STATUS status; /* BTM operation status */ + UINT8 hci_status; /* HCI command complete status */ + UINT8 channel_map[5]; /* Channel map (5 bytes) */ + BD_ADDR rem_bda; /* Remote device Bluetooth address */ +} tBTM_BLE_CH_MAP_RESULTS; + /* Structure returned with read current TX power event (in tBTM_CMPL_CB callback function) ** in response to BTM_ReadTxPower call. */ @@ -1027,9 +1040,6 @@ typedef void (tBTM_ACL_DB_CHANGE_CB) (BD_ADDR p_bda, DEV_CLASS p_dc, #define BTM_INVALID_SCO_INDEX 0xFFFF #define BTM_INVALID_HCI_HANDLE 0xFFFF -/* Define an invalid SCO disconnect reason */ -#define BTM_INVALID_SCO_DISC_REASON 0xFFFF - /* Define first active SCO index */ #define BTM_FIRST_ACTIVE_SCO_INDEX BTM_MAX_SCO_LINKS @@ -3024,7 +3034,19 @@ tBTM_STATUS BTM_SwitchRole (BD_ADDR remote_bd_addr, //extern tBTM_STATUS BTM_ReadRSSI (BD_ADDR remote_bda, tBT_TRANSPORT transport, tBTM_CMPL_CB *p_cb); - +/******************************************************************************* +** +** Function BTM_ReadChannelMap +** +** Description This function is called to read the current channel map +** for the given connection. The results are returned via +** the callback (tBTM_BLE_CH_MAP_RESULTS). +** +** Returns BTM_CMD_STARTED if successfully initiated or error code +** +*******************************************************************************/ +tBTM_STATUS BTM_ReadChannelMap(BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb); +#if (BLE_HOST_READ_TX_POWER_EN == TRUE) /******************************************************************************* ** ** Function BTM_ReadTxPower @@ -3045,10 +3067,13 @@ tBTM_STATUS BTM_ReadTxPower (BD_ADDR remote_bda, tBT_TRANSPORT transport, tBTM_CMPL_CB *p_cb); tBTM_STATUS BTM_BleReadAdvTxPower(tBTM_CMPL_CB *p_cb); +#endif // #if (BLE_HOST_READ_TX_POWER_EN == TRUE) void BTM_BleGetWhiteListSize(uint16_t *length); - +#if (BLE_50_EXTEND_SYNC_EN == TRUE) +void BTM_BleGetPeriodicAdvListSize(uint8_t *size); +#endif //#if (BLE_50_EXTEND_SYNC_EN == TRUE) /******************************************************************************* ** ** Function BTM_ReadLinkQuality @@ -3260,21 +3285,6 @@ UINT16 BTM_ReadScoHandle (UINT16 sco_inx); UINT8 *BTM_ReadScoBdAddr (UINT16 sco_inx); -/******************************************************************************* -** -** Function BTM_ReadScoDiscReason -** -** Description This function is returns the reason why an (e)SCO connection -** has been removed. It contains the value until read, or until -** another (e)SCO connection has disconnected. -** -** Returns HCI reason or BTM_INVALID_SCO_DISC_REASON if not set. -** -*******************************************************************************/ -//extern -UINT16 BTM_ReadScoDiscReason (void); - - /******************************************************************************* ** ** Function BTM_SetEScoMode diff --git a/lib/bt/host/bluedroid/stack/include/stack/btm_ble_api.h b/lib/bt/host/bluedroid/stack/include/stack/btm_ble_api.h index 1bea9908..7ec384ef 100644 --- a/lib/bt/host/bluedroid/stack/include/stack/btm_ble_api.h +++ b/lib/bt/host/bluedroid/stack/include/stack/btm_ble_api.h @@ -367,7 +367,6 @@ typedef UINT32 tBTM_BLE_AD_MASK; #define BTM_BLE_AD_TYPE_MANU HCI_EIR_MANUFACTURER_SPECIFIC_TYPE /* 0xff */ typedef UINT8 tBTM_BLE_AD_TYPE; -#define BTM_BLE_LONG_ADV_MAX_LEN 249 /* Security settings used with L2CAP LE COC */ #define BTM_SEC_LE_LINK_ENCRYPTED 0x01 @@ -395,7 +394,9 @@ typedef UINT8 tBTM_BLE_ADV_TX_POWER; /* adv tx power in dBm */ typedef struct { +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) UINT8 adv_inst_max; /* max adv instance supported in controller */ +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) UINT8 rpa_offloading; UINT16 tot_scan_results_strg; UINT8 max_irk_list_sz; @@ -499,6 +500,7 @@ typedef struct { tBTM_BLE_ADV_TX_POWER tx_power; } tBTM_BLE_ADV_PARAMS; +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) typedef struct { UINT8 *p_sub_code; /* dynamic array to store sub code */ UINT8 *p_inst_id; /* dynamic array to store instance id */ @@ -530,6 +532,7 @@ typedef struct { tBTM_BLE_MULTI_ADV_INST *p_adv_inst; /* dynamic array to store adv instance */ tBTM_BLE_MULTI_ADV_OPQ op_q; } tBTM_BLE_MULTI_ADV_CB; +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) typedef UINT8 tGATT_IF; @@ -810,15 +813,16 @@ typedef struct { typedef struct { UINT8 filter_policy; - #if (CONFIG_BT_BLE_FEAT_CREATE_SYNC_ENH) +#if (BLE_FEAT_CREATE_SYNC_ENH == TRUE) UINT8 reports_disabled; UINT8 filter_duplicates; - #endif +#endif // (BLE_FEAT_CREATE_SYNC_ENH == TRUE) UINT8 sid; tBLE_ADDR_TYPE addr_type; BD_ADDR addr; UINT16 skip; UINT16 sync_timeout; + UINT8 sync_cte_type; } tBTM_BLE_Periodic_Sync_Params; typedef struct { @@ -944,6 +948,7 @@ typedef UINT8 tBTM_BLE_CONN_TYPE; #define ADV_INFO_PRESENT 0x00 #define NO_ADV_INFO_PRESENT 0x01 +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) typedef btgatt_track_adv_info_t tBTM_BLE_TRACK_ADV_DATA; typedef void (tBTM_BLE_TRACK_ADV_CBACK)(tBTM_BLE_TRACK_ADV_DATA *p_track_adv_data); @@ -961,6 +966,7 @@ enum { }; typedef UINT8 tBTM_BLE_TRACK_ADV_ACTION; +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) #define BTM_BLE_MULTI_ADV_INVALID 0 @@ -1007,11 +1013,14 @@ typedef void (tBTM_START_STOP_ADV_CMPL_CBACK) (UINT8 status); typedef void (tBTM_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_CMPL_CBACK) (tBTM_STATUS status, uint8_t subcode, uint32_t length, uint8_t *device_info); typedef void (tBTM_CLEAR_ADV_CMPL_CBACK) (UINT8 status); typedef void (tBTM_SET_PRIVACY_MODE_CMPL_CBACK) (tBTM_STATUS status); +typedef void (tBTM_SET_CSA_SUPPORT_CMPL_CBACK) (tBTM_STATUS status); +typedef void (tBTM_SET_VENDOR_EVT_MASK_CBACK) (tBTM_STATUS status); #if (BLE_50_FEATURE_SUPPORT == TRUE) #define BTM_BLE_5_GAP_READ_PHY_COMPLETE_EVT 1 #define BTM_BLE_5_GAP_SET_PREFERED_DEFAULT_PHY_COMPLETE_EVT 2 #define BTM_BLE_5_GAP_SET_PREFERED_PHY_COMPLETE_EVT 3 +#if (BLE_50_EXTEND_ADV_EN == TRUE) #define BTM_BLE_5_GAP_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT 4 #define BTM_BLE_5_GAP_EXT_ADV_SET_PARAMS_COMPLETE_EVT 5 #define BTM_BLE_5_GAP_EXT_ADV_DATA_SET_COMPLETE_EVT 6 @@ -1020,29 +1029,42 @@ typedef void (tBTM_SET_PRIVACY_MODE_CMPL_CBACK) (tBTM_STATUS status); #define BTM_BLE_5_GAP_EXT_ADV_STOP_COMPLETE_EVT 9 #define BTM_BLE_5_GAP_EXT_ADV_SET_REMOVE_COMPLETE_EVT 10 #define BTM_BLE_5_GAP_EXT_ADV_SET_CLEAR_COMPLETE_EVT 11 +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) #define BTM_BLE_5_GAP_PERIODIC_ADV_SET_PARAMS_COMPLETE_EVT 12 #define BTM_BLE_5_GAP_PERIODIC_ADV_DATA_SET_COMPLETE_EVT 13 #define BTM_BLE_5_GAP_PERIODIC_ADV_START_COMPLETE_EVT 14 #define BTM_BLE_5_GAP_PERIODIC_ADV_STOP_COMPLETE_EVT 15 +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) #define BTM_BLE_5_GAP_PERIODIC_ADV_CREATE_SYNC_COMPLETE_EVT 16 #define BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_CANCEL_COMPLETE_EVT 17 #define BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_TERMINATE_COMPLETE_EVT 18 #define BTM_BLE_5_GAP_PERIODIC_ADV_ADD_DEV_COMPLETE_EVT 19 #define BTM_BLE_5_GAP_PERIODIC_ADV_REMOVE_DEV_COMPLETE_EVT 20 #define BTM_BLE_5_GAP_PERIODIC_ADV_CLEAR_DEV_COMPLETE_EVT 21 +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if (BLE_50_EXTEND_SCAN_EN == TRUE) #define BTM_BLE_5_GAP_SET_EXT_SCAN_PARAMS_COMPLETE_EVT 22 #define BTM_BLE_5_GAP_EXT_SCAN_START_COMPLETE_EVT 23 #define BTM_BLE_5_GAP_EXT_SCAN_STOP_COMPLETE_EVT 24 +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) #define BTM_BLE_5_GAP_PREFER_EXT_CONN_PARAMS_SET_COMPLETE_EVT 25 #define BTM_BLE_5_GAP_PHY_UPDATE_COMPLETE_EVT 26 +#if (BLE_50_EXTEND_SCAN_EN == TRUE) #define BTM_BLE_5_GAP_EXT_ADV_REPORT_EVT 27 #define BTM_BLE_5_GAP_SCAN_TIMEOUT_EVT 28 +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) #define BTM_BLE_5_GAP_ADV_TERMINATED_EVT 29 #define BTM_BLE_5_GAP_SCAN_REQ_RECEIVED_EVT 30 +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) #define BTM_BLE_5_GAP_CHANNEL_SELETE_ALGORITHM_EVT 31 +#if (BLE_50_EXTEND_SYNC_EN == TRUE) #define BTM_BLE_5_GAP_PERIODIC_ADV_REPORT_EVT 32 #define BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_LOST_EVT 33 #define BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_ESTAB_EVT 34 +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) #define BTM_BLE_GAP_PERIODIC_ADV_RECV_ENABLE_COMPLETE_EVT 35 #define BTM_BLE_GAP_PERIODIC_ADV_SYNC_TRANS_COMPLETE_EVT 36 @@ -1051,9 +1073,76 @@ typedef void (tBTM_SET_PRIVACY_MODE_CMPL_CBACK) (tBTM_STATUS status); #define BTM_BLE_GAP_PERIODIC_ADV_SYNC_TRANS_RECV_EVT 39 #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) #define BTM_BLE_GAP_SET_PRIVACY_MODE_COMPLETE_EVT 40 -#define BTM_BLE_5_GAP_UNKNOWN_EVT 41 +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#define BTM_BLE_GAP_ENH_READ_TRANS_POWER_LEVEL_EVT 41 +#define BTM_BLE_GAP_READ_REMOTE_TRANS_POWER_LEVEL_EVT 42 +#define BTM_BLE_GAP_SET_PATH_LOSS_REPORTING_PARAMS_EVT 43 +#define BTM_BLE_GAP_SET_PATH_LOSS_REPORTING_ENABLE_EVT 44 +#define BTM_BLE_GAP_SET_TRANS_POWER_REPORTING_ENABLE_EVT 45 +#define BTM_BLE_GAP_PATH_LOSS_THRESHOLD_EVT 46 +#define BTM_BLE_GAP_TRANMIT_POWER_REPORTING_EVT 47 +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +#define BTM_BLE_GAP_SET_DEFAULT_SUBRATE_EVT 48 +#define BTM_BLE_GAP_SUBRATE_REQUEST_EVT 49 +#define BTM_BLE_GAP_SUBRATE_CHANGE_EVT 50 +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) +#define BTM_BLE_GAP_SET_HOST_FEATURE_EVT 51 +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#define BTM_BLE_5_GAP_UNKNOWN_EVT 52 typedef UINT8 tBTM_BLE_5_GAP_EVENT; +#if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#define BTM_BLE_ISO_BIG_CREATE_COMPLETE_EVT 1 +#define BTM_BLE_ISO_BIG_TERMINATE_COMPLETE_EVT 2 +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +#define BTM_BLE_ISO_BIG_SYNC_ESTABLISHED_EVT 3 +#define BTM_BLE_ISO_BIG_SYNC_LOST_EVT 4 +#define BTM_BLE_ISO_BIG_SYNC_TERMINATE_COMPLETE_EVT 5 +#define BTM_BLE_ISO_BIGINFO_ADV_REPORT_EVT 6 +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +#define BTM_BLE_ISO_DATA_PATH_UPFATE_EVT 7 +#define BTM_BLE_ISO_READ_TX_SYNC_EVT 9 +#define BTM_BLE_ISO_READ_LINK_QUALITY_EVT 10 +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#define BTM_BLE_ISO_SET_CIG_PARAMS_EVT 11 +#define BTM_BLE_ISO_CREATE_CIS_EVT 12 +#define BTM_BLE_ISO_REMOVE_CIG_EVT 13 +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#define BTM_BLE_ISO_ACCEPT_CIS_REQ_EVT 14 +#define BTM_BLE_ISO_REJECT_CIS_REQ_EVT 15 +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#define BTM_BLE_ISO_CIS_ESTABLISHED_EVT 16 +#define BTM_BLE_ISO_CIS_REQUEST_EVT 17 +#define BTM_BLE_ISO_CIS_DISCONNECTED_EVT 18 +#define BTM_BLE_ISO_UNKNOWN_EVT 19 +typedef UINT8 tBTM_BLE_ISO_EVENT; +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#define BTM_BLE_CTE_SET_TRANS_PARAMS_EVT 1 +#define BTM_BLE_CTE_SET_TRANS_ENABLE_EVT 2 +#define BTM_BLE_CTE_SET_IQ_SAMP_ENABLE_EVT 3 +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +#define BTM_BLE_CTE_SET_CONN_RECV_PARAMS_EVT 4 +#define BTM_BLE_CTE_SET_CONN_TRANS_PARAMS_EVT 5 +#define BTM_BLE_CTE_SET_CONN_REQ_ENABLE_EVT 6 +#define BTM_BLE_CTE_SET_CONN_RSP_ENABLE_EVT 7 +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +#define BTM_BLE_CTE_READ_ANT_INFOR_EVT 8 +#define BTM_BLE_CTE_CONNLESS_IQ_REPORT_EVT 9 +#define BTM_BLE_CTE_CONN_IQ_REPORT_EVT 10 +#define BTM_BLE_CTE_REQUEST_FAILED_EVT 11 +typedef UINT8 tBTM_BLE_CTE_EVENT; +#endif // #if (BLE_FEAT_CTE_EN == TRUE) + #define BTM_BLE_EXT_ADV_DATA_COMPLETE 0x00 #define BTM_BLE_EXT_ADV_DATA_INCOMPLETE 0x01 #define BTM_BLE_EXT_ADV_DATA_TRUNCATED 0x02 @@ -1100,46 +1189,58 @@ typedef struct { typedef struct { UINT8 status; + UINT8 instance; } tBTM_BLE_SET_PERF_PHY_CMPL; typedef struct { UINT8 status; + UINT8 instance; } tBTM_BLE_EXT_ADV_SET_RAND_ADDR_CMPL; typedef struct { UINT8 status; + UINT8 instance; } tBTM_BLE_EXT_ADV_SET_PARAMS_CMPL; typedef struct { UINT8 status; + UINT8 instance; } tBTM_BLE_EXT_ADV_DATA_SET_CMPL; typedef struct { UINT8 status; + UINT8 instance; } tBTM_BLE_EXT_ADV_SCAN_RSP_DATA_SET_CMPL; typedef struct { UINT8 status; + UINT8 instance_num; + UINT8 instance[10]; } tBTM_BLE_EXT_ADV_START_CMPL; typedef struct { UINT8 status; + UINT8 instance; } tBTM_BLE_EXT_ADV_STOP_CMPL; typedef struct { UINT8 status; + UINT8 instance; } tBTM_BLE_PERIOD_ADV_SET_PARAMS_CMPL; typedef struct { UINT8 status; + UINT8 instance; } tBTM_BLE_PERIOD_ADV_DATA_SET_CMPL; typedef struct { UINT8 status; + UINT8 instance; } tBTM_BLE_PERIOD_ADV_START_CMPL; typedef struct { UINT8 status; + UINT8 instance; } tBTM_BLE_PERIOD_ADV_STOP_CMPL; typedef struct { @@ -1230,6 +1331,7 @@ typedef struct { UINT16 sync_handle; UINT8 tx_power; INT8 rssi; + UINT8 cte_type; tBTM_BLE_EXT_ADV_DATA_STATUS data_status; UINT8 data_length; UINT8 *data; @@ -1295,39 +1397,409 @@ typedef struct { } tBTM_BLE_PERIOD_ADV_SYNC_TRANS_RECV; #endif //#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +typedef struct { + UINT8 status; + UINT16 conn_handle; + UINT8 phy; + INT8 cur_tx_pwr_level; + INT8 max_tx_pwr_level; +} __attribute__((packed)) tBTM_BLE_ENH_TRANS_PWR_LEVEL_CMPL; + +typedef struct { + UINT8 status; +} __attribute__((packed)) tBTM_BLE_REMOTE_TRANS_PWR_LEVEL_CMPL; + +typedef struct { + UINT8 status; + UINT16 conn_handle; +} __attribute__((packed)) tBTM_BLE_SET_PATH_LOSS_RPTING_PARAMS; + +typedef struct { + UINT8 status; + UINT16 conn_handle; +} __attribute__((packed)) tBTM_BLE_SET_PATH_LOSS_RPTING_ENABLE; + +typedef struct { + UINT8 status; + UINT16 conn_handle; +} __attribute__((packed)) tBTM_BLE_SET_TRANS_POWER_RPTING_ENABLE; + +typedef struct { + UINT16 conn_handle; + UINT8 cur_path_loss; + UINT8 zone_entered; +} __attribute__((packed)) tBTM_BLE_PATH_LOSS_THRESHOLD_EVT; + +typedef struct { + UINT8 status; + UINT16 conn_handle; + UINT8 reason; + UINT8 phy; + INT8 tx_power_level; + UINT8 tx_power_level_flag; + INT8 delta; +} __attribute__((packed)) tBTM_BLE_TRANS_POWER_REPORT_EVT; +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +typedef struct { + UINT8 status; + UINT16 conn_handle; + UINT16 subrate_factor; + UINT16 peripheral_latency; + UINT16 continuation_number; + UINT16 supervision_timeout; +} __attribute__((packed)) tBTM_BLE_SUBRATE_CHANGE_EVT; +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + +#if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +typedef struct { + UINT8 status; + UINT8 big_handle; + UINT32 big_sync_delay; + UINT32 transport_latency; + UINT8 phy; + UINT8 nse; + UINT8 bn; + UINT8 pto; + UINT8 irc; + UINT16 max_pdu; + UINT16 iso_interval; + UINT8 num_bis; + UINT16 bis_handle[BLE_ISO_BIS_MAX_COUNT]; +} tBTM_BLE_BIG_CREATE_CMPL; + +typedef struct { + UINT8 status; + UINT8 big_handle; + UINT8 reason; +} tBTM_BLE_BIG_TERMINATE_CMPL; +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +typedef struct { + UINT8 status; + UINT8 big_handle; + UINT32 transport_latency_big; + UINT8 nse; + UINT8 bn; + UINT8 pto; + UINT8 irc; + UINT16 max_pdu; + UINT16 iso_interval; + uint8_t num_bis; + uint16_t bis_handle[BLE_ISO_BIS_MAX_COUNT]; +} tBTM_BLE_BIG_SYNC_ESTAB_CMPL; + +typedef struct { + UINT8 big_handle; + UINT8 reason; +} tBTM_BLE_BIG_SYNC_LOST_EVT; + +typedef struct { + UINT16 sync_handle; + UINT8 num_bis; + UINT8 nse; + UINT16 iso_interval; + UINT8 bn; + UINT8 pto; + UINT8 irc; + UINT16 max_pdu; + UINT32 sdu_interval; + UINT32 max_sdu; + UINT8 phy; + UINT8 framing; + UINT8 encryption; +} tBTM_BLE_BIGINFO_ADV_REPORT_EVT; + +typedef struct { + UINT8 status; + UINT16 big_hdl; +} tBTM_BLE_BIG_SYNC_TERMINATE_EVT; + +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_EN == TRUE) +typedef struct { + UINT8 status; + UINT16 conn_handle; + UINT32 cig_sync_delay; + UINT32 cis_sync_delay; + UINT32 trans_lat_c_to_p; + UINT32 trans_lat_p_to_c; + UINT8 phy_c_to_p; + UINT8 phy_p_to_c; + UINT8 nse; + UINT8 bn_c_to_p; + UINT8 bn_p_to_c; + UINT8 ft_c_to_p; + UINT8 ft_p_to_c; + UINT16 max_pdu_c_to_p; + UINT16 max_pdu_p_to_c; + UINT16 iso_interval; +#if (BLE_FEAT_ISO_60_EN == TRUE) + UINT32 sub_interval; + UINT16 max_sdu_c_to_p; + UINT16 max_sdu_p_to_c; + UINT32 sdu_int_c_to_p; + UINT32 sdu_int_p_to_c; + UINT8 framing; +#endif // #if (BLE_FEAT_ISO_60_EN == TRUE) +} tBTM_BLE_CIS_ESTABLISHED_CMPL; + +typedef struct { + UINT16 cis_handle; + UINT8 reason; +} tBTM_BLE_CIS_DISCON_CMPL; + +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +typedef struct { + UINT8 status; + UINT16 cis_handle; +} tBTM_BLE_ISO_REJECT_CIS_REQ_EVT; + + +typedef struct { + UINT16 acl_handle; + UINT16 cis_handle; + UINT8 cig_id; + UINT8 cis_id; +} tBTM_BLE_CIS_REQUEST_CMPL; +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + +typedef enum { + BTM_BLE_ISO_DATA_PATH_UNKNOWN = 0, + BTM_BLE_ISO_DATA_PATH_SETUP = 1, + BTM_BLE_ISO_DATA_PATH_REMOVE = 2, + BTM_BLE_ISO_DATA_PATH_MAX, +} tBTM_BLE_ISO_DATA_PATH_UPDATE_TYPE; + +typedef struct { + UINT8 status; + tBTM_BLE_ISO_DATA_PATH_UPDATE_TYPE op_type; + UINT16 conn_hdl; +} tBTM_BLE_ISO_DATA_PATH_UPDATE_EVT; + +typedef struct { + UINT8 status; + UINT16 conn_hdl; + UINT16 pkt_seq_num; + UINT32 tx_time_stamp; + UINT32 time_offset; +} tBTM_BLE_ISO_READ_TX_SYNC_EVT; + +typedef struct { + UINT8 status; + UINT16 conn_hdl; + UINT32 tx_unacked_pkts; + UINT32 tx_flushed_pkts; + UINT32 tx_last_subevt_pkts; + UINT32 retransmitted_pkts; + UINT32 crc_error_pkts; + UINT32 rx_unreceived_pkts; + UINT32 duplicate_pkts; +} tBTM_BLE_ISO_READ_LINK_QUALITY_EVT; + +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +typedef struct { + UINT8 status; + UINT8 cig_id; + UINT8 cis_count; + UINT16 conn_hdl[BLE_ISO_CIS_MAX_COUNT]; +} tBTM_BLE_ISO_SET_CIG_PARAMS_EVT; + +typedef struct { + UINT8 status; + UINT8 cig_id; +} tBTM_BLE_ISO_REMOVE_CIG_EVT; + +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +typedef union { + UINT8 status; +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + tBTM_BLE_BIG_CREATE_CMPL btm_big_cmpl; + tBTM_BLE_BIG_TERMINATE_CMPL btm_big_term; +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + tBTM_BLE_BIG_SYNC_ESTAB_CMPL btm_big_sync_estab; + tBTM_BLE_BIG_SYNC_LOST_EVT btm_big_sync_lost; + tBTM_BLE_BIGINFO_ADV_REPORT_EVT btm_biginfo_report; + tBTM_BLE_BIG_SYNC_TERMINATE_EVT btm_big_sync_ter; +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + tBTM_BLE_ISO_DATA_PATH_UPDATE_EVT btm_data_path_update; + tBTM_BLE_ISO_READ_TX_SYNC_EVT btm_read_tx_sync; + tBTM_BLE_ISO_READ_LINK_QUALITY_EVT btm_read_link_quality; +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + tBTM_BLE_ISO_SET_CIG_PARAMS_EVT btm_set_cig_params; + tBTM_BLE_ISO_REMOVE_CIG_EVT btm_remove_cig; +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + tBTM_BLE_ISO_REJECT_CIS_REQ_EVT btm_reject_cis_req; + tBTM_BLE_CIS_REQUEST_CMPL btm_cis_request_evt; +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_EN == TRUE) + tBTM_BLE_CIS_ESTABLISHED_CMPL btm_cis_established_evt; + tBTM_BLE_CIS_DISCON_CMPL btm_cis_disconnectd_evt; +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) +} tBTM_BLE_ISO_CB_PARAMS; + +typedef void (*tBTM_BLE_ISO_CBACK)(tBTM_BLE_ISO_EVENT event, tBTM_BLE_ISO_CB_PARAMS *params); +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_CTE_EN == TRUE) +typedef struct { + UINT8 status; +} __attribute__((packed)) tBTM_BLE_CTE_SET_TRANS_PARAMS_CMPL; + +typedef struct { + UINT8 status; +} __attribute__((packed)) tBTM_BLE_CTE_SET_TRANS_EN_CMPL; + +typedef struct { + UINT8 status; + UINT16 sync_handle; +} __attribute__((packed)) tBTM_BLE_CTE_IQ_SAMP_EN_CMPL; + +typedef struct { + UINT8 status; + UINT16 conn_handle; +} __attribute__((packed)) tBTM_BLE_CTE_CONN_RECV_PARAMS_CMPL; + +typedef struct { + UINT8 status; + UINT16 conn_handle; +} __attribute__((packed)) tBTM_BLE_CTE_CONN_TRANS_PARAMS_CMPL; + +typedef struct { + UINT8 status; + UINT16 conn_handle; +} __attribute__((packed)) tBTM_BLE_CTE_CONN_REQ_ENABLE_CMPL; + +typedef struct { + UINT8 status; + UINT16 conn_handle; +} __attribute__((packed)) tBTM_BLE_CTE_CONN_RSP_ENABLE_CMPL; + +typedef struct { + UINT8 status; + UINT8 supported_switching_sampling_rates; + UINT8 num_ant; + UINT8 max_switching_pattern_len; + UINT8 max_cte_len; +} __attribute__((packed)) tBTM_BLE_CTE_READ_ANT_INFOR_CMPL; + +typedef struct { + UINT16 sync_handle; + UINT8 channel_idx; + INT16 rssi; + UINT8 rssi_ant_id; + UINT8 cte_type; + UINT8 slot_dur; + UINT8 pkt_status; + UINT16 periodic_evt_counter; + UINT8 sample_count; + UINT8 i_sample[0x52]; + UINT8 q_sample[0x52]; +} __attribute__((packed)) tBTM_BLE_CTE_CONNLESS_IQ_REPORT_EVT; + +typedef struct { + UINT16 conn_handle; + UINT8 rx_phy; + UINT8 data_channel_idx; + INT16 rssi; + UINT8 rssi_ant_id; + UINT8 cte_type; + UINT8 slot_dur; + UINT8 pkt_status; + UINT16 conn_evt_counter; + UINT8 sample_count; + UINT8 i_sample[0x52]; + UINT8 q_sample[0x52]; +} __attribute__((packed)) tBTM_BLE_CTE_CONN_IQ_REPORT_EVT; + +typedef struct { + UINT8 status; + UINT16 conn_handle; +} __attribute__((packed)) tBTM_BLE_CTE_REQ_FAILED_EVT; + +typedef union { + UINT8 status; +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + tBTM_BLE_CTE_SET_TRANS_PARAMS_CMPL cte_trans_params_cmpl; + tBTM_BLE_CTE_SET_TRANS_EN_CMPL cte_trans_en_cmpl; + tBTM_BLE_CTE_IQ_SAMP_EN_CMPL cte_iq_samp_en_cmpl; +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + tBTM_BLE_CTE_CONN_RECV_PARAMS_CMPL cte_recv_params_cmpl; + tBTM_BLE_CTE_CONN_TRANS_PARAMS_CMPL cte_conn_trans_params_cmpl; + tBTM_BLE_CTE_CONN_REQ_ENABLE_CMPL cte_conn_req_en_cmpl; + tBTM_BLE_CTE_CONN_RSP_ENABLE_CMPL cte_conn_rsp_en_cmpl; +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + tBTM_BLE_CTE_READ_ANT_INFOR_CMPL cte_read_ant_infor_cmpl; +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + tBTM_BLE_CTE_CONNLESS_IQ_REPORT_EVT cte_connless_iq_rpt; +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + tBTM_BLE_CTE_CONN_IQ_REPORT_EVT cte_conn_iq_rpt; + tBTM_BLE_CTE_REQ_FAILED_EVT cte_req_failed; +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +} tBTM_BLE_CTE_CB_PARAMS; + +typedef void (*tBTM_BLE_CTE_CBACK)(tBTM_BLE_CTE_EVENT event, tBTM_BLE_CTE_CB_PARAMS *params); +#endif // #if (BLE_FEAT_CTE_EN == TRUE) + typedef union { UINT8 status; tBTM_BLE_READ_PHY_CMPL read_phy; tBTM_BLE_SET_PREF_DEF_PHY_CMPL set_perf_def_phy; tBTM_BLE_SET_PERF_PHY_CMPL set_perf_phy; +#if (BLE_50_EXTEND_ADV_EN == TRUE) tBTM_BLE_EXT_ADV_SET_RAND_ADDR_CMPL set_ext_rand_addr; tBTM_BLE_EXT_ADV_SET_PARAMS_CMPL set_params; tBTM_BLE_EXT_ADV_DATA_SET_CMPL adv_data_set; tBTM_BLE_EXT_ADV_SCAN_RSP_DATA_SET_CMPL scan_rsp_data_set; tBTM_BLE_EXT_ADV_START_CMPL adv_start; tBTM_BLE_EXT_ADV_STOP_CMPL adv_stop; +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) +#if (BLE_50_PERIODIC_ADV_EN == TRUE) tBTM_BLE_PERIOD_ADV_SET_PARAMS_CMPL per_adv_set_params; tBTM_BLE_PERIOD_ADV_DATA_SET_CMPL per_adv_data_set; tBTM_BLE_PERIOD_ADV_START_CMPL per_adv_start; tBTM_BLE_PERIOD_ADV_STOP_CMPL per_adv_stop; +#endif // #if (BLE_50_PERIODIC_ADV_EN == TRUE) +#if (BLE_50_EXTEND_SYNC_EN == TRUE) tBTM_BLE_PERIOD_ADV_SYNC_CREATE_CMPL per_adv_sync_create; tBTM_BLE_PERIOD_ADV_SYNC_CANCEL_CMPL per_adv_sync_cancel; tBTM_BLE_PERIOD_ADV_SYNC_TEMINAT_CMPL per_adv_sync_term; tBTM_BLE_PERIOD_ADV_ADD_DEV_CMPL per_adv_add_dev; tBTM_BLE_PERIOD_ADV_REMOVE_DEV_CMPL per_adv_remove_dev; tBTM_BLE_PEROID_ADV_CLEAR_DEV_CMPL per_adv_clear_dev; +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) +#if (BLE_50_EXTEND_SCAN_EN == TRUE) tBTM_BLE_SET_EXT_SCAN_PARAMS_CMPL ext_scan; tBTM_BLE_EXT_SCAN_START_CMPL scan_start; tBTM_BLE_EXT_SCAN_STOP_CMPL scan_stop; +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) tBTM_BLE_PREF_EXT_CONN_SET_PARAMS_CMPL ext_conn_set_params; tBTM_BLE_PHY_UPDATE_CMPL phy_update; +#if (BLE_50_EXTEND_SCAN_EN == TRUE) tBTM_BLE_EXT_ADV_REPORT ext_adv_report; +#endif // #if (BLE_50_EXTEND_SCAN_EN == TRUE) +#if (BLE_50_EXTEND_ADV_EN == TRUE) tBTM_BLE_ADV_TERMINAT adv_term; tBTM_BLE_SCAN_REQ_RECEIVED scan_req; +#endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) tBTM_BLE_CHANNEL_SEL_ALG channel_sel; +#if (BLE_50_EXTEND_SYNC_EN == TRUE) tBTM_PERIOD_ADV_REPORT period_adv_report; tBTM_BLE_PERIOD_ADV_SYNC_LOST sync_lost; tBTM_BLE_PERIOD_ADV_SYNC_ESTAB sync_estab; +#endif // #if (BLE_50_EXTEND_SYNC_EN == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) tBTM_BLE_PERIOD_ADV_RECV_ENABLE_CMPL per_adv_recv_enable; tBTM_BLE_PERIOD_ADV_SYNC_TRANS_CMPL per_adv_sync_trans; @@ -1335,6 +1807,18 @@ typedef union { tBTM_BLE_SET_PERIOD_ADV_SYNC_TRANS_PARAMS_CMPL set_past_params; tBTM_BLE_PERIOD_ADV_SYNC_TRANS_RECV past_recv; #endif //#if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + tBTM_BLE_ENH_TRANS_PWR_LEVEL_CMPL enh_trans_pwr_level_cmpl; + tBTM_BLE_REMOTE_TRANS_PWR_LEVEL_CMPL remote_pwr_level_cmpl; + tBTM_BLE_SET_PATH_LOSS_RPTING_PARAMS path_loss_rpting_params; + tBTM_BLE_SET_PATH_LOSS_RPTING_ENABLE path_loss_rpting_enable; + tBTM_BLE_SET_TRANS_POWER_RPTING_ENABLE trans_pwr_rpting_enable; + tBTM_BLE_PATH_LOSS_THRESHOLD_EVT path_loss_thres_evt; + tBTM_BLE_TRANS_POWER_REPORT_EVT trans_pwr_report_evt; +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#if (BLE_FEAT_CONN_SUBRATING == TRUE) + tBTM_BLE_SUBRATE_CHANGE_EVT subrate_change_evt; +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) } tBTM_BLE_5_GAP_CB_PARAMS; typedef struct { @@ -1370,6 +1854,7 @@ extern "C" { *******************************************************************************/ void BTM_BleRegiseterConnParamCallback(tBTM_UPDATE_CONN_PARAM_CBACK *update_conn_param_cb); void BTM_BleRegiseterPktLengthChangeCallback(tBTM_SET_PKT_DATA_LENGTH_CBACK *ptk_len_chane_cb); +void BTM_BleRegisterVendorHciEventCallback(tBTM_BLE_VENDOR_HCI_EVT_CBACK *vendor_hci_evt_cb); /******************************************************************************* ** @@ -1411,23 +1896,6 @@ BOOLEAN BTM_SecAddBleDevice (BD_ADDR bd_addr, BD_NAME bd_name, BOOLEAN BTM_SecAddBleKey (BD_ADDR bd_addr, tBTM_LE_KEY_VALUE *p_le_key, tBTM_LE_KEY_TYPE key_type); -/******************************************************************************* -** -** Function BTM_BleSetAdvParams -** -** Description This function is called to set advertising parameters. -** -** Parameters: None. -** -** Returns void -** -*******************************************************************************/ -//extern -tBTM_STATUS BTM_BleSetAdvParams(UINT16 adv_int_min, UINT16 adv_int_max, - tBLE_BD_ADDR *p_dir_bda, tBTM_BLE_ADV_CHNL_MAP chnl_map); - - - /******************************************************************************* ** ** Function BTM_BleSetAdvParamsAll @@ -1472,20 +1940,6 @@ tBTM_STATUS BTM_BleStartAdv(void); tBTM_STATUS BTM_BleWriteAdvData(tBTM_BLE_AD_MASK data_mask, tBTM_BLE_ADV_DATA *p_data); -/******************************************************************************* -** -** Function BTM_BleWriteLongAdvData -** -** Description This function is called to write long advertising data. -** -** Parameters: adv_data: long advertising data -** adv_data_len: the length of long advertising data -** -** Returns void -** -*******************************************************************************/ -tBTM_STATUS BTM_BleWriteLongAdvData(uint8_t *adv_data, uint8_t adv_data_len); - /******************************************************************************* ** ** Function BTM_BleWriteAdvDataRaw @@ -1539,6 +1993,7 @@ void BTM_BleReadAdvParams (UINT16 *adv_int_min, UINT16 *adv_int_max, //extern void BTM_BleObtainVendorCapabilities(tBTM_BLE_VSC_CB *p_cmn_vsc_cb); +#if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) /******************************************************************************* ** ** Function BTM_BleSetScanParams @@ -1559,7 +2014,7 @@ void BTM_BleSetScanParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_window, tBLE_SCAN_MODE scan_type, tBLE_SCAN_PARAM_SETUP_CBACK scan_setup_status_cback); - +#endif // #if (BLE_HOST_BLE_SCAN_PARAM_UNUSED == TRUE) /******************************************************************************* ** @@ -1658,6 +2113,7 @@ tBTM_STATUS BTM_BleEnableBatchScan(tBTM_BLE_BATCH_SCAN_MODE scan_mode, //extern tBTM_STATUS BTM_BleDisableBatchScan(tBTM_BLE_REF_VALUE ref_value); +#if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleReadScanReports @@ -1673,7 +2129,9 @@ tBTM_STATUS BTM_BleDisableBatchScan(tBTM_BLE_REF_VALUE ref_value); //extern tBTM_STATUS BTM_BleReadScanReports(tBLE_SCAN_MODE scan_mode, tBTM_BLE_REF_VALUE ref_value); +#endif // #if (BLE_HOST_READ_SCAN_REPORTS_EN == TRUE) +#if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleTrackAdvertiser @@ -1689,6 +2147,7 @@ tBTM_STATUS BTM_BleReadScanReports(tBLE_SCAN_MODE scan_mode, //extern tBTM_STATUS BTM_BleTrackAdvertiser(tBTM_BLE_TRACK_ADV_CBACK *p_track_cback, tBTM_BLE_REF_VALUE ref_value); +#endif // #if (BLE_HOST_TRACK_ADVERTISER_EN == TRUE) /******************************************************************************* ** @@ -2100,7 +2559,7 @@ void BTM_BleReadControllerFeatures(tBTM_BLE_CTRL_FEATURES_CBACK *p_vsc_cback); ** *******************************************************************************/ //extern -UINT8 *BTM_CheckAdvData( UINT8 *p_adv, UINT8 type, UINT8 *p_length); +UINT8 *BTM_CheckAdvData( UINT8 *p_adv, UINT16 adv_data_len, UINT8 type, UINT8 *p_length); /******************************************************************************* ** @@ -2259,6 +2718,7 @@ BOOLEAN BTM_BleLocalPrivacyEnabled(void); //extern void BTM_BleEnableMixedPrivacyMode(BOOLEAN mixed_on); +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) /******************************************************************************* ** ** Function BTM_BleMaxMultiAdvInstanceCount @@ -2270,6 +2730,7 @@ void BTM_BleEnableMixedPrivacyMode(BOOLEAN mixed_on); *******************************************************************************/ //extern UINT8 BTM_BleMaxMultiAdvInstanceCount(void); +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) /******************************************************************************* ** @@ -2450,6 +2911,7 @@ BOOLEAN BTM_BleSecurityProcedureIsRunning (BD_ADDR bd_addr); //extern UINT8 BTM_BleGetSupportedKeySize (BD_ADDR bd_addr); +#if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) /*******************************************************************************/ /* Multi ADV API */ /******************************************************************************* @@ -2522,6 +2984,8 @@ tBTM_STATUS BTM_BleCfgAdvInstData (UINT8 inst_id, BOOLEAN is_scan_rsp, //extern tBTM_STATUS BTM_BleDisableAdvInstance (UINT8 inst_id); +#endif // #if (BLE_HOST_BLE_MULTI_ADV_EN == TRUE) + /******************************************************************************* ** ** Function BTM_BleAdvFilterParamSetup @@ -2712,6 +3176,33 @@ BOOLEAN BTM_BleSetPrivacyMode(UINT8 addr_type, UINT8 privacy_mode, tBTM_SET_PRIVACY_MODE_CMPL_CBACK *p_callback); +/******************************************************************************* +** +** Function BTM_BleSetCsaSupport +** +** Description This function is called to set the ChSel field of Advertising or Initiating PDUs +** +** Parameters csa_select - Select LE Channel Selection Algorithm. +** p_callback - Callback function to be called when the operation is completed. +** +** Returns TRUE if the operation was successful, otherwise FALSE. +** +*******************************************************************************/ +BOOLEAN BTM_BleSetCsaSupport (UINT8 csa_select, tBTM_SET_CSA_SUPPORT_CMPL_CBACK *p_callback); + +/******************************************************************************* +** +** Function BTM_BleSetVendorEventMask +** +** Description This function is called to set the vendor HCI event mask +** +** Parameters evt_mask - vendor HCI event mask. +** p_callback - Callback function to be called when the operation is completed. +** +** Returns TRUE if the operation was successful, otherwise FALSE. +** +*******************************************************************************/ +BOOLEAN BTM_BleSetVendorEventMask(UINT32 evt_mask, tBTM_SET_VENDOR_EVT_MASK_CBACK *p_callback); /* #ifdef __cplusplus } @@ -2762,12 +3253,13 @@ tBTM_STATUS BTM_BleSetExtendedScanParams(tBTM_BLE_EXT_SCAN_PARAMS *params); tBTM_STATUS BTM_BleExtendedScan(BOOLEAN enable, UINT16 duration, UINT16 period); void BTM_BleSetPreferExtenedConnParams(BD_ADDR bd_addr, tBTM_EXT_CONN_PARAMS *params); +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_DTM_TEST_EN == TRUE) void BTM_BleEnhancedReceiverTest(UINT8 rx_freq, UINT8 phy, UINT8 modulation_index, tBTM_CMPL_CB *p_cmd_cmpl_cback); void BTM_BleEnhancedTransmitterTest(UINT8 tx_freq, UINT8 test_data_len, UINT8 packet_payload, UINT8 phy, tBTM_CMPL_CB *p_cmd_cmpl_cback); - -#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) void BTM_BlePeriodicAdvRecvEnable(UINT16 sync_handle, UINT8 enable); @@ -2779,4 +3271,93 @@ void BTM_BlePeriodicAdvSetInfoTrans(BD_ADDR bd_addr, UINT16 service_data, UINT8 void BTM_BleSetPeriodicAdvSyncTransParams(BD_ADDR bd_addr, UINT8 mode, UINT16 skip, UINT16 sync_timeout, UINT8 cte_type); #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_FEAT_ISO_EN == TRUE) +void BTM_BleIsoRegisterCallback(tBTM_BLE_ISO_CBACK cb); +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +tBTM_STATUS BTM_BleBigCreate(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, + uint32_t sdu_interval, uint16_t max_sdu, uint16_t max_transport_latency, + uint8_t rtn, uint8_t phy, uint8_t packing, uint8_t framing, + uint8_t encryption, uint8_t *broadcast_code); + +tBTM_STATUS BTM_BleBigCreateTest(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, + uint32_t sdu_interval, uint16_t iso_interval, uint8_t nse, + uint16_t max_sdu, uint16_t max_pdu, uint8_t phy, + uint8_t packing, uint8_t framing, uint8_t bn, uint8_t irc, + uint8_t pto, uint8_t encryption, uint8_t *broadcast_code); + +tBTM_STATUS BTM_BleBigTerminate(UINT8 big_handle, UINT8 reason); +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +tBTM_STATUS BTM_BleBigSyncCreate(uint8_t big_handle, uint16_t sync_handle, + uint8_t encryption, uint8_t *bc_code, + uint8_t mse, uint16_t big_sync_timeout, + uint8_t num_bis, uint8_t *bis); + +tBTM_STATUS BTM_BleBigSyncTerminate(uint8_t big_handle); +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +tBTM_STATUS BTM_BleIsoSetDataPath(uint16_t conn_handle, uint8_t data_path_dir, uint8_t data_path_id, uint8_t coding_fmt, + uint16_t company_id, uint16_t vs_codec_id, uint32_t controller_delay, uint8_t codec_len, + uint8_t *codec_cfg); +tBTM_STATUS BTM_BleIsoRemoveDataPath(uint16_t conn_handle, uint8_t data_path_dir); + +tBTM_STATUS BTM_BleIsoReadTxSync(uint16_t iso_hdl); +tBTM_STATUS BTM_BleIsoReadLinkQuality(uint16_t iso_hdl); + +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +tBTM_STATUS BTM_BleSetCigParams(uint8_t cig_id, uint32_t sdu_int_c_to_p, uint32_t sdu_int_p_to_c, uint8_t worse_case_SCA, uint8_t packing, + uint8_t framing, uint16_t mtl_c_to_p, uint16_t mtl_p_to_c, uint8_t cis_cnt, uint8_t *cis_params); +tBTM_STATUS BTM_BleSetCigParamsTest(uint8_t cig_id, uint32_t sdu_int_c_to_p, uint32_t sdu_int_p_to_c, uint8_t ft_c_to_p, uint8_t ft_p_to_c, uint16_t iso_interval, + uint8_t worse_case_SCA, uint8_t packing, uint8_t framing, uint8_t cis_cnt, uint8_t *cis_params); +tBTM_STATUS BTM_BleCreateCis(uint8_t cis_count, uint8_t *cis_hdls); +tBTM_STATUS BTM_BleRemoveCig(uint8_t cig_id); +#endif // #if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +tBTM_STATUS BTM_BleAcceptCisReq(uint16_t cis_handle); +tBTM_STATUS BTM_BleRejectCisReq(uint16_t cis_handle, uint8_t reason); +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +#if (BLE_FEAT_ISO_CIG_EN == TRUE) +tBTM_STATUS BTM_BleDisconCis(uint16_t cis_handle, uint8_t reason); +#endif // #if (BLE_FEAT_ISO_CIG_EN == TRUE) +#endif // #if (BLE_FEAT_ISO_EN == TRUE) +#if (BLE_FEAT_CTE_EN == TRUE) +void BTM_BleCteRegisterCallback(tBTM_BLE_CTE_CBACK cb); +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +tBTM_STATUS BTM_BleSetCteTransParams(uint8_t adv_handle, uint8_t cte_len, uint8_t cte_type, uint8_t cte_count, uint8_t switching_pattern_len, uint8_t *antenna_ids); +tBTM_STATUS BTM_BleCteSetConnectionlessTransEnable(uint8_t adv_handle, uint8_t cte_en); +tBTM_STATUS BTM_BleCteSetConnectionlessIqSamplingEnable(uint16_t sync_handle, uint8_t sampling_en, uint8_t slot_dur, + uint8_t max_sampled_ctes, uint8_t switching_pattern_len, uint8_t *ant_ids); +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) + +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +tBTM_STATUS BTM_BleCteSetConnectionReceiveParams(uint16_t conn_handle, uint8_t sampling_en, uint8_t slot_dur, + uint8_t switching_pattern_len, uint8_t *ant_ids); +tBTM_STATUS BTM_BleCteSetConnectionTransParams(uint16_t conn_handle, uint8_t cte_types, uint8_t switching_pattern_len, uint8_t *ant_ids); +tBTM_STATUS BTM_BleCteSetConnectionRequestEnable(uint16_t conn_handle, uint8_t enable, uint16_t cte_req_int, + uint8_t req_cte_len, uint8_t req_cte_type); +tBTM_STATUS BTM_BleCteSetConnectionRspEnable(uint16_t conn_handle, uint8_t enable); +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) + +tBTM_STATUS BTM_BleCteReadAntInfor(void); + +#endif // #if (BLE_FEAT_CTE_EN == TRUE) + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +void BTM_BleEnhReadTransPowerLevel(uint16_t conn_handle, uint8_t phy); +void BTM_BleReadRemoteTransPwrLevel(uint16_t conn_handle, uint8_t phy); +void BTM_BleSetPathLossRptParams(uint16_t conn_handle, uint8_t high_threshold, uint8_t high_hysteresis, + uint8_t low_threshold, uint8_t low_hysteresis, uint16_t min_time_spent); +void BTM_BleSetPathLossRptEnable(uint16_t conn_handle, uint8_t enable); +void BTM_BleSetTransPwrRptEnable(uint16_t conn_handle, uint8_t local_enable, uint8_t remote_enable); +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +void BTM_BleSetDefaultSubrate(UINT16 subrate_min, UINT16 subrate_max, UINT16 max_latency, + UINT16 continuation_number, UINT16 supervision_timeout); + +void BTM_BleSubrateRequest(UINT16 conn_handle, UINT16 subrate_min, UINT16 subrate_max, + UINT16 max_latency, UINT16 continuation_number, UINT16 supervision_timeout); +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) +tBTM_STATUS BTM_BleSetHostFeature(uint16_t bit_num, uint8_t bit_val); +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #endif diff --git a/lib/bt/host/bluedroid/stack/include/stack/dyn_mem.h b/lib/bt/host/bluedroid/stack/include/stack/dyn_mem.h index fa1ed498..7c208d8c 100644 --- a/lib/bt/host/bluedroid/stack/include/stack/dyn_mem.h +++ b/lib/bt/host/bluedroid/stack/include/stack/dyn_mem.h @@ -45,6 +45,8 @@ #define HCRP_DYNAMIC_MEMORY TRUE #define HFP_DYNAMIC_MEMORY TRUE #define HID_DYNAMIC_MEMORY TRUE +#define OBEX_DYNAMIC_MEMORY TRUE +#define GOEP_DYNAMIC_MEMORY TRUE #define HSP2_DYNAMIC_MEMORY TRUE #define ICP_DYNAMIC_MEMORY TRUE #define OPP_DYNAMIC_MEMORY TRUE @@ -53,6 +55,8 @@ #define SLIP_DYNAMIC_MEMORY TRUE #define LLCP_DYNAMIC_MEMORY TRUE #define BTC_SBC_DEC_DYNAMIC_MEMORY TRUE +#define BTC_GAP_BT_DYNAMIC_MEMORY TRUE +#define L2CAP_DYNAMIC_MEMORY TRUE #else /* #if UC_BT_BLE_DYNAMIC_ENV_MEMORY */ #define BTU_DYNAMIC_MEMORY FALSE @@ -79,6 +83,8 @@ #define HCRP_DYNAMIC_MEMORY FALSE #define HFP_DYNAMIC_MEMORY FALSE #define HID_DYNAMIC_MEMORY FALSE +#define OBEX_DYNAMIC_MEMORY FALSE +#define GOEP_DYNAMIC_MEMORY FALSE #define HSP2_DYNAMIC_MEMORY FALSE #define ICP_DYNAMIC_MEMORY FALSE #define OPP_DYNAMIC_MEMORY FALSE @@ -87,6 +93,8 @@ #define SLIP_DYNAMIC_MEMORY FALSE #define LLCP_DYNAMIC_MEMORY FALSE #define BTC_SBC_DEC_DYNAMIC_MEMORY FALSE +#define BTC_GAP_BT_DYNAMIC_MEMORY FALSE +#define L2CAP_DYNAMIC_MEMORY FALSE #endif /* #if UC_BT_BLE_DYNAMIC_ENV_MEMORY */ @@ -191,6 +199,14 @@ #define HID_DYNAMIC_MEMORY FALSE #endif +#ifndef OBEX_DYNAMIC_MEMORY +#define OBEX_DYNAMIC_MEMORY FALSE +#endif + +#ifndef GOEP_DYNAMIC_MEMORY +#define GOEP_DYNAMIC_MEMORY FALSE +#endif + #ifndef HSP2_DYNAMIC_MEMORY #define HSP2_DYNAMIC_MEMORY FALSE #endif diff --git a/lib/bt/host/bluedroid/stack/include/stack/gatt_api.h b/lib/bt/host/bluedroid/stack/include/stack/gatt_api.h index fed2ea9a..6c63db62 100644 --- a/lib/bt/host/bluedroid/stack/include/stack/gatt_api.h +++ b/lib/bt/host/bluedroid/stack/include/stack/gatt_api.h @@ -139,7 +139,7 @@ typedef UINT16 tGATT_DISCONN_REASON; /* max length of an attribute value */ #ifndef GATT_MAX_ATTR_LEN -#define GATT_MAX_ATTR_LEN 512 +#define GATT_MAX_ATTR_LEN GATT_MAX_MTU_SIZE #endif /* default GATT MTU size over LE link diff --git a/lib/bt/host/bluedroid/stack/include/stack/goep_common.h b/lib/bt/host/bluedroid/stack/include/stack/goep_common.h new file mode 100644 index 00000000..74cb3ca8 --- /dev/null +++ b/lib/bt/host/bluedroid/stack/include/stack/goep_common.h @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "common/bt_target.h" + +/* GOEP Client or Server(not supported yet) API return code */ +#define GOEP_SUCCESS 0x00 /* Operation successful */ +#define GOEP_FAILURE 0x01 /* Operation failed */ +#define GOEP_NO_RESOURCES 0x02 /* Not enough resources */ +#define GOEP_BAD_HANDLE 0x04 /* Bad handle */ +#define GOEP_INVALID_PARAM 0x08 /* Invalid parameter */ +#define GOEP_INVALID_STATE 0x10 /* Operation not allow in current state */ +#define GOEP_CONGEST 0x20 /* Congest */ +#define GOEP_TL_ERROR 0x40 /* Lower transport layer error */ diff --git a/lib/bt/host/bluedroid/stack/include/stack/goepc_api.h b/lib/bt/host/bluedroid/stack/include/stack/goepc_api.h new file mode 100644 index 00000000..f2b93f86 --- /dev/null +++ b/lib/bt/host/bluedroid/stack/include/stack/goepc_api.h @@ -0,0 +1,82 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "common/bt_target.h" + +#include "stack/goep_common.h" +#include "stack/obex_api.h" + +#if (GOEPC_INCLUDED == TRUE) + +enum { + GOEPC_OPENED_EVT, /* connection open */ + GOEPC_CLOSED_EVT, /* disconnect unexpected */ + GOEPC_MTU_CHANGED_EVT, /* lower layer MTU change */ + GOEPC_CONGEST_EVT, /* lower layer connection congest */ + GOEPC_UNCONGEST_EVT, /* lower layer connection uncongest */ + GOEPC_RESPONSE_EVT /* response from server */ +}; + +typedef struct { + UINT16 peer_mtu; /* peer mtu of lower level connection */ + UINT16 our_mtu; /* our mtu of lower level connection */ +} tGOEPC_MSG_OPENED; + +typedef struct { + UINT8 reason; /* connection close reason */ +} tGOEPC_MSG_CLOSED; + +typedef struct { + UINT16 peer_mtu; /* peer mtu of lower level connection */ + UINT16 our_mtu; /* our mtu of lower level connection */ +} tGOEPC_MSG_MTU_CHANGED; + +typedef struct { + UINT8 opcode; /* which opcode that this packet response to */ + BOOLEAN final; /* whether this is a final packet */ + BOOLEAN srm_en; /* whether srm is enable */ + BOOLEAN srm_wait; /* whether srm wait is set, set by peer or by us */ + BT_HDR *pkt; /* pointer to response packet */ +} tGOEPC_MSG_RESPONSE; + +typedef union { + tGOEPC_MSG_OPENED opened; + tGOEPC_MSG_CLOSED closed; + tGOEPC_MSG_MTU_CHANGED mtu_changed; + tGOEPC_MSG_RESPONSE response; +} tGOEPC_MSG; + +typedef void (tGOEPC_EVT_CBACK)(UINT16 handle, UINT8 event, tGOEPC_MSG *msg); + +/******************************************************************************* +* The following APIs are called by bluetooth stack automatically +*******************************************************************************/ + +extern UINT16 GOEPC_Init(void); + +extern void GOEPC_Deinit(void); + +/******************************************************************************* +* The following APIs must be executed in btu task +*******************************************************************************/ + +extern UINT16 GOEPC_Open(tOBEX_SVR_INFO *p_svr, tGOEPC_EVT_CBACK callback, UINT16 *out_handle); + +extern UINT16 GOEPC_Close(UINT16 handle); + +extern UINT16 GOEPC_SendRequest(UINT16 handle); + +extern UINT16 GOEPC_PrepareRequest(UINT16 handle, tOBEX_PARSE_INFO *info, UINT16 buff_size); + +extern UINT16 GOEPC_DropRequest(UINT16 handle); + +extern UINT16 GOEPC_RequestSetSRM(UINT16 handle, BOOLEAN srm_en, BOOLEAN srm_wait); + +extern UINT16 GOEPC_RequestAddHeader(UINT16 handle, UINT8 header_id, const UINT8 *data, UINT16 data_len); + +#endif /* #if (GOEPC_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/stack/include/stack/hcidefs.h b/lib/bt/host/bluedroid/stack/include/stack/hcidefs.h index 21b14881..23f9b3e6 100644 --- a/lib/bt/host/bluedroid/stack/include/stack/hcidefs.h +++ b/lib/bt/host/bluedroid/stack/include/stack/hcidefs.h @@ -357,8 +357,12 @@ #define HCI_BLE_READ_PHY (0x0030 | HCI_GRP_BLE_CMDS) #define HCI_BLE_SET_DEFAULT_PHY (0x0031 | HCI_GRP_BLE_CMDS) #define HCI_BLE_SET_PHY (0x0032 | HCI_GRP_BLE_CMDS) +#endif +#if (BLE_50_DTM_TEST_EN == TRUE) #define HCI_BLE_ENH_RX_TEST (0x0033 | HCI_GRP_BLE_CMDS) #define HCI_BLE_ENH_TX_TEST (0x0034 | HCI_GRP_BLE_CMDS) +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) #define HCI_BLE_SET_ADV_RAND_ADDR (0x0035 | HCI_GRP_BLE_CMDS) #define HCI_BLE_SET_EXT_ADV_PARAM (0x0036 | HCI_GRP_BLE_CMDS) #define HCI_BLE_SET_EXT_ADV_DATA (0x0037 | HCI_GRP_BLE_CMDS) @@ -386,6 +390,20 @@ #define HCI_BLE_WR_RF_PATH_COMPENSATION (0x004D | HCI_GRP_BLE_CMDS) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #define HCI_BLE_SET_PRIVACY_MODE (0x004E | HCI_GRP_BLE_CMDS) +#if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#define HCI_BLE_SET_CONNLESS_CTE_TRANS_PARAMS (0x0051 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_SET_CONNLESS_CTE_TRANS_ENABLE (0x0052 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_SET_CONNLESS_IQ_SAMPLING_ENABLE (0x0053 | HCI_GRP_BLE_CMDS) +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +#define HCI_BLE_SET_CONN_CTE_RECEIVE_PARAMS (0x0054 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_SET_CONN_CTE_TRANS_PARAMS (0x0055 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_SET_CONN_CTE_REQ_ENABLE (0x0056 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_SET_CONN_CTE_RSP_ENABLE (0x0057 | HCI_GRP_BLE_CMDS) +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +#define HCI_BLE_READ_ANT_INFOR (0x0058 | HCI_GRP_BLE_CMDS) +#endif // #if (BLE_FEAT_CTE_EN == TRUE) #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) #define HCI_BLE_SET_PERIOD_ADV_RECV_ENABLE (0x0059 | HCI_GRP_BLE_CMDS) #define HCI_BLE_PERIOD_ADV_SYNC_TRANS (0x005A | HCI_GRP_BLE_CMDS) @@ -393,6 +411,38 @@ #define HCI_BLE_SET_PAST_PARAMS (0x005C | HCI_GRP_BLE_CMDS) #define HCI_BLE_SET_DEFAULT_PAST_PARAMS (0x005D | HCI_GRP_BLE_CMDS) #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#define HCI_BLE_READ_BUFFER_SZIE_V2 (0x0060 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_ISO_READ_TX_SYNC (0x0061 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_ISO_SET_CIG_PARAMS (0x0062 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_ISO_SET_CIG_PARAMS_TEST (0x0063 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_ISO_CREATE_CIS (0x0064 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_ISO_REMOVE_CIG (0x0065 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_ISO_ACCEPT_CIS_REQ (0x0066 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_ISO_REJECT_CIS_REQ (0x0067 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_CREATE_BIG (0x0068 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_CREATE_BIG_TEST (0x0069 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_TERMINATE_BIG (0x006A | HCI_GRP_BLE_CMDS) +#define HCI_BLE_BIG_CREATE_SYNC (0x006B | HCI_GRP_BLE_CMDS) +#define HCI_BLE_BIG_TERMINATE_SYNC (0x006C | HCI_GRP_BLE_CMDS) +#define HCI_BLE_ISO_SET_DATA_PATH (0x006E | HCI_GRP_BLE_CMDS) +#define HCI_BLE_ISO_REMOVE_DATA_PATH (0x006F | HCI_GRP_BLE_CMDS) +#define HCI_BLE_SET_HOST_FEATURE (0x0074 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_ISO_READ_ISO_LINK_QUALITY (0x0075 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_SET_HOST_FEATURE_V2 (0x0097 | HCI_GRP_BLE_CMDS) + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#define HCI_BLE_ENH_READ_TRANS_POWER_LEVEL (0x0076 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_READ_REMOTE_TRANS_POWER_LEVEL (0x0077 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_SET_PATH_LOSS_REPORTING_PARAMS (0x0078 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_SET_PATH_LOSS_REPORTING_ENABLE (0x0079 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_SET_TRANS_POWER_REPORTING_ENABLE (0x007A | HCI_GRP_BLE_CMDS) +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +#define HCI_BLE_SET_DEFAULT_SUBRATE (0x007D | HCI_GRP_BLE_CMDS) +#define HCI_BLE_SUBRATE_REQUEST (0x007E | HCI_GRP_BLE_CMDS) +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + // Vendor OGF define #define HCI_VENDOR_OGF 0x3F @@ -422,11 +472,20 @@ #define HCI_SUBCODE_BLE_ADV_REPORT_FLOW_CONTROL 0x0A #define HCI_SUBCODE_BLE_RD_STATIC_ADDR 0x0B #define HCI_SUBCODE_BLE_CLEAR_ADV 0x0C +#define HCI_SUBCODE_BLE_SET_CSA_SUPPORT 0x12 +#define HCI_SUBCODE_BLE_SET_VENDOR_EVT_MASK 0x16 #define HCI_SUBCODE_BLE_MAX 0x7F //ESP BT subcode define #define HCI_SUBCODE_BT_INIT 0x00 +#define HCI_SUBCODE_BT_WRITE_DM1_ENABLE 0x01 #define HCI_SUBCODE_BT_SET_MIN_ENC_KEY_SIZE 0x02 +#define HCI_SUBCODE_BT_CLK_UPD 0x03 +#define HCI_SUBCODE_BT_SET_AFH 0x07 +#define HCI_SUBCODE_BT_SET_EVT_MASK 0x08 +#define HCI_SUBCODE_BT_SET_AFH_REPORTING_MODE 0x09 +#define HCI_SUBCODE_BT_MASK_RMT_AFH_CH_CLASS 0x0A +#define HCI_SUBCODE_BT_WR_AUTO_RATE_INIT_ENABLE 0x0B #define HCI_SUBCODE_BT_MAX 0x7F #define HCI_ESP_VENDOR_OPCODE_BUILD(ogf, group, subcode) ((ogf << 10) | (group <<7) | (subcode << 0)) @@ -460,16 +519,25 @@ #define HCI_BLE_ENERGY_INFO_OCF HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_ENERGY_INFO) /* Extended BLE Scan parameters OCF */ #define HCI_BLE_EXTENDED_SCAN_PARAMS_OCF HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_EXTENDED_SCAN_PARAMS) -/* Long BLE Adv data OCF */ -#define HCI_VENDOR_BLE_LONG_ADV_DATA HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_LONG_ADV) /* BLE update duplicate scan exceptional list */ #define HCI_VENDOR_BLE_UPDATE_DUPLICATE_EXCEPTIONAL_LIST HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_DUPLICATE_EXCEPTIONAL_LIST) #define HCI_VENDOR_BLE_SET_ADV_FLOW_CONTROL HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_SET_ADV_FLOW_CONTROL) #define HCI_VENDOR_BLE_ADV_REPORT_FLOW_CONTROL HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_ADV_REPORT_FLOW_CONTROL) /* BLE clear legacy advertising */ #define HCI_VENDOR_BLE_CLEAR_ADV HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_CLEAR_ADV) +/* BLE set CSA support */ +#define HCI_VENDOR_BLE_SET_CSA_SUPPORT HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_SET_CSA_SUPPORT) +/* BLE set vendor event mask */ +#define HCI_VENDOR_BLE_SET_EVT_MASK HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BLE, HCI_SUBCODE_BLE_SET_VENDOR_EVT_MASK) //ESP BT HCI CMD -#define HCI_VENDOR_BT_SET_MIN_ENC_KEY_SIZE HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_SET_MIN_ENC_KEY_SIZE) +#define HCI_VENDOR_BT_WRITE_DM1_ENABLE HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_WRITE_DM1_ENABLE) +#define HCI_VENDOR_BT_SET_MIN_ENC_KEY_SIZE HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_SET_MIN_ENC_KEY_SIZE) +#define HCI_VENDOR_BT_CLK_UPD HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_CLK_UPD) +#define HCI_VENDOR_BT_SET_AFH HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_SET_AFH) +#define HCI_VENDOR_BT_SET_EVT_MASK HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_SET_EVT_MASK) +#define HCI_VENDOR_BT_SET_AFH_REPORTING_MODE HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_SET_AFH_REPORTING_MODE) +#define HCI_VENDOR_BT_MASK_RMT_AFH_CH_CLASS HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_MASK_RMT_AFH_CH_CLASS) +#define HCI_VENDOR_BT_WR_AUTO_RATE_INIT_ENABLE HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_WR_AUTO_RATE_INIT_ENABLE) /* subcode for multi adv feature */ #define BTM_BLE_MULTI_ADV_SET_PARAM 0x01 @@ -820,10 +888,48 @@ #define HCI_BLE_PERIOD_ADV_SYNC_TRANS_RECV_EVT 0x18 #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_FEAT_CTE_EN == TRUE) +#define HCI_BLE_CONNLESS_IQ_REPORT_EVT 0x15 +#define HCI_BLE_CONN_IQ_REPORT_EVT 0x16 +#define HCI_BLE_CTE_REQUEST_FAILED_EVT 0x17 +#endif // #if (BLE_FEAT_CTE_EN == TRUE) + +#if (BLE_FEAT_ISO_EN == TRUE) +#define HCI_BLE_CIS_ESTABLISHED_V1_EVT 0x19 +#define HCI_BLE_CIS_REQUEST_EVT 0x1A +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#define HCI_BLE_BIG_CREATE_COMPLETE_EVT 0x1B +#define HCI_BLE_BIG_TERMINATE_COMPLETE_EVT 0x1C +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +#define HCI_BLE_BIG_SYNC_ESTABLISHED_EVT 0x1D +#define HCI_BLE_BIG_SYNC_LOST_EVT 0x1E +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +#define HCI_BLE_BIGINFO_ADV_REPORT_EVT 0x22 +#define HCI_BLE_CIS_ESTABLISHED_V2_EVT 0x2A +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#define HCI_BLE_PATH_LOSS_THRESHOLD_EVT 0x20 +#define HCI_BLE_TRANS_POWER_REPORTING_EVT 0x21 +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +#define HCI_BLE_SUBRATE_CHANGE_EVT 0x23 +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + /* Definitions for LE Channel Map */ #define HCI_BLE_CHNL_MAP_SIZE 5 +#define HCI_VENDOR_SPECIFIC_EVT 0xFF /* Vendor specific events */ +#define HCI_VENDOR_LEGACY_REM_AUTH_EVT_SUBCODE 0x03 +#define HCI_VENDOR_AFH_CHG_EVT_SUBCODE 0x05 +#define HCI_VENDOR_CH_CLASSIFICATION_EVT_SUBCODE 0x06 +#define HCI_VENDOR_CH_CLASSIFICATION_REPORTING_MODE_EVT_SUBCODE 0x07 + #define HCI_VENDOR_SPECIFIC_EVT 0xFF /* Vendor specific events */ +#define HCI_VSE_LE_SUBEVT_BASE 0xC0 /* BLE vendor event code base */ +#define HCI_VSE_LE_EVT_MAX 0xFF /* BLE vendor event code max */ #define HCI_NAP_TRACE_EVT 0xFF /* was define 0xFE, 0xFD, change to 0xFF because conflict w/ TCI_EVT and per specification compliant */ @@ -1871,42 +1977,50 @@ typedef struct { #define HCI_PING_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_PING_OFF] & HCI_EXT_FEATURE_PING_MASK) /* -** LE features encoding - page 0 (the only page for now) +** LE features encoding - page 0 */ -/* LE Encryption */ +/* LE Encryption: bit 0 */ #define HCI_LE_FEATURE_LE_ENCRYPTION_MASK 0x01 #define HCI_LE_FEATURE_LE_ENCRYPTION_OFF 0 #define HCI_LE_ENCRYPTION_SUPPORTED(x) ((x)[HCI_LE_FEATURE_LE_ENCRYPTION_OFF] & HCI_LE_FEATURE_LE_ENCRYPTION_MASK) -/* Connection Parameters Request Procedure */ +/* Connection Parameters Request Procedure: bit 1 */ #define HCI_LE_FEATURE_CONN_PARAM_REQ_MASK 0x02 #define HCI_LE_FEATURE_CONN_PARAM_REQ_OFF 0 #define HCI_LE_CONN_PARAM_REQ_SUPPORTED(x) ((x)[HCI_LE_FEATURE_CONN_PARAM_REQ_OFF] & HCI_LE_FEATURE_CONN_PARAM_REQ_MASK) -/* Extended Reject Indication */ +/* Extended Reject Indication: bit 2 */ #define HCI_LE_FEATURE_EXT_REJ_IND_MASK 0x04 #define HCI_LE_FEATURE_EXT_REJ_IND_OFF 0 #define HCI_LE_EXT_REJ_IND_SUPPORTED(x) ((x)[HCI_LE_FEATURE_EXT_REJ_IND_OFF] & HCI_LE_FEATURE_EXT_REJ_IND_MASK) -/* Slave-initiated Features Exchange */ +/* Slave-initiated Features Exchange: bit 3 */ #define HCI_LE_FEATURE_SLAVE_INIT_FEAT_EXC_MASK 0x08 #define HCI_LE_FEATURE_SLAVE_INIT_FEAT_EXC_OFF 0 #define HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(x) ((x)[HCI_LE_FEATURE_SLAVE_INIT_FEAT_EXC_OFF] & HCI_LE_FEATURE_SLAVE_INIT_FEAT_EXC_MASK) +/* LE Data Packet Length Extension: bit 5 */ +#define HCI_LE_FEATURE_DATA_LEN_EXT_MASK 0x20 +#define HCI_LE_FEATURE_DATA_LEN_EXT_OFF 0 +#define HCI_LE_DATA_LEN_EXT_SUPPORTED(x) ((x)[HCI_LE_FEATURE_DATA_LEN_EXT_OFF] & HCI_LE_FEATURE_DATA_LEN_EXT_MASK) + /* Enhanced privacy Feature: bit 6 */ #define HCI_LE_FEATURE_ENHANCED_PRIVACY_MASK 0x40 #define HCI_LE_FEATURE_ENHANCED_PRIVACY_OFF 0 #define HCI_LE_ENHANCED_PRIVACY_SUPPORTED(x) ((x)[HCI_LE_FEATURE_ENHANCED_PRIVACY_OFF] & HCI_LE_FEATURE_ENHANCED_PRIVACY_MASK) -/* Extended scanner filter policy : 7 */ +/* Extended scanner filter policy: bit 7 */ #define HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_MASK 0x80 #define HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_OFF 0 #define HCI_LE_EXT_SCAN_FILTER_POLICY_SUPPORTED(x) ((x)[HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_OFF] & HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_MASK) -/* Slave-initiated Features Exchange */ -#define HCI_LE_FEATURE_DATA_LEN_EXT_MASK 0x20 -#define HCI_LE_FEATURE_DATA_LEN_EXT_OFF 0 -#define HCI_LE_DATA_LEN_EXT_SUPPORTED(x) ((x)[HCI_LE_FEATURE_DATA_LEN_EXT_OFF] & HCI_LE_FEATURE_DATA_LEN_EXT_MASK) +/* +** LE features encoding - page 1 +*/ +/* LE Extended Advertising: bit 12 */ +#define HCI_LE_FEATURE_EXT_ADV_MASK 0x10 +#define HCI_LE_FEATURE_EXT_ADV_OFF 1 +#define HCI_LE_EXT_ADV_SUPPORTED(x) ((x)[HCI_LE_FEATURE_EXT_ADV_OFF] & HCI_LE_FEATURE_EXT_ADV_MASK) /* ** Local Supported Commands encoding diff --git a/lib/bt/host/bluedroid/stack/include/stack/hcimsgs.h b/lib/bt/host/bluedroid/stack/include/stack/hcimsgs.h index 951e5b70..4ee07b4d 100644 --- a/lib/bt/host/bluedroid/stack/include/stack/hcimsgs.h +++ b/lib/bt/host/bluedroid/stack/include/stack/hcimsgs.h @@ -759,12 +759,18 @@ void btsnd_hcic_vendor_spec_cmd (BT_HDR *buffer, UINT16 opcode, #define HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL 2 #define HCIC_PARAM_SIZE_BLE_CLEAR_ADV 0 #define HCIC_PARAM_SIZE_SET_PRIVACY_MODE 8 +#define HCIC_PARAM_SIZE_BLE_SET_CSA_SUPPORT 1 +#define HCIC_PARAM_SIZE_BLE_SET_VENDOR_EVT_MASK 4 #if (BLE_50_FEATURE_SUPPORT == TRUE) #define HCIC_PARAM_SIZE_BLE_READ_PHY 2 #define HCIC_PARAM_SIZE_BLE_SET_DEF_PHY 3 #define HCIC_PARAM_SIZE_BLE_SET_PHY 7 +#endif +#if (BLE_50_DTM_TEST_EN == TRUE) #define HCIC_PARAM_SIZE_ENH_RX_TEST 3 #define HCIC_PARAM_SIZE_ENH_TX_TEST 4 +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) #define HCIC_PARAM_SIZE_EXT_RAND_ADDR 7 #define HCIC_PARAM_SIZE_EXT_ADV_SET_PARAMS 25 #define HCIC_PARAM_SIZE_EXT_ADV_WRITE_DATA 251 @@ -914,7 +920,14 @@ BOOLEAN btsnd_hcic_ble_set_rand_priv_addr_timeout (UINT16 rpa_timout); BOOLEAN btsnd_hcic_ble_clear_adv(void); +BOOLEAN btsnd_hcic_ble_set_privacy_mode(UINT8 addr_type, BD_ADDR addr, UINT8 privacy_mode); + +BOOLEAN btsnd_hcic_ble_set_csa_support (UINT8 csa_select); + +BOOLEAN btsnd_hcic_ble_set_vendor_evt_mask (UINT32 evt_mask); + #endif /* BLE_INCLUDED */ + #if (BLE_50_FEATURE_SUPPORT == TRUE) typedef struct { UINT8 scan_type; @@ -957,14 +970,17 @@ UINT8 btsnd_hcic_ble_set_prefered_default_phy(UINT8 all_phys, BOOLEAN btsnd_hcic_ble_set_phy(UINT16 conn_handle, UINT8 all_phys, UINT8 tx_phys, UINT8 rx_phys, UINT16 phy_options); - +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) +#if (BLE_50_DTM_TEST_EN == TRUE) UINT8 btsnd_hcic_ble_enhand_rx_test(UINT8 rx_channel, UINT8 phy, UINT8 modulation_idx); UINT8 btsnd_hcic_ble_enhand_tx_test(UINT8 tx_channel, UINT8 len, UINT8 packect, UINT8 phy); +#endif // #if (BLE_50_DTM_TEST_EN == TRUE) +#if (BLE_50_FEATURE_SUPPORT == TRUE) UINT8 btsnd_hcic_ble_set_extend_rand_address(UINT8 adv_handle, BD_ADDR rand_addr); UINT8 btsnd_hcic_ble_set_ext_adv_params(UINT8 adv_handle, UINT16 properties, UINT32 interval_min, @@ -1018,7 +1034,7 @@ BOOLEAN btsnd_hcic_ble_create_ext_conn(tHCI_CreatExtConn *p_conn); BOOLEAN btsnd_hcic_ble_periodic_adv_create_sync(UINT8 filter_policy, UINT8 adv_sid, UINT8 adv_addr_type, BD_ADDR adv_addr, - UINT16 sync_timeout, UINT8 unused); + UINT16 sync_timeout, UINT8 sync_cte_type); UINT8 btsnd_hcic_ble_periodic_adv_create_sync_cancel(void); @@ -1042,8 +1058,6 @@ UINT8 btsnd_hcic_ble_write_rf_path_compensation(UINT16 rf_tx_path, UINT16 rf_rx_ #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) -UINT8 btsnd_hcic_ble_set_privacy_mode(UINT8 addr_type, BD_ADDR addr, UINT8 privacy_mode); - #define HCIC_PARAM_SIZE_WRITE_AUTHENT_PAYLOAD_TOUT 4 #define HCI__WRITE_AUTHENT_PAYLOAD_TOUT_HANDLE_OFF 0 @@ -1069,4 +1083,164 @@ BOOLEAN btsnd_hcic_ble_set_periodic_adv_sync_trans_params(UINT16 conn_handle, UI UINT8 btsnd_hcic_ble_set_default_periodic_adv_sync_trans_params(UINT8 mode, UINT16 skip, UINT16 sync_timeout, UINT8 cte_type); #endif // #if (BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER == TRUE) +#if (BLE_FEAT_ISO_EN == TRUE) +#define HCIC_PARAM_SIZE_ISO_READ_TX_SYNC_PARAMS 2 +#define HCIC_PARAM_SIZE_ISO_SET_CIG_PARAMS 15 +#define HCIC_PARAM_SIZE_ISO_SET_CIG_TEST_PARAMS 15 +#define HCIC_PARAM_SIZE_ISO_CREATE_CIS_PARAMS 1 +#define HCIC_PARAM_SIZE_ISO_REMOVE_CIG_PARAMS 1 +#define HCIC_PARAM_SIZE_ISO_ACCEPT_CIS_REQ_PARAMS 2 +#define HCIC_PARAM_SIZE_ISO_REJECT_CIS_REQ_PARAMS 3 +#define HCIC_PARAM_SIZE_ISO_READ_LINK_QUALITY_PARAMS 2 +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#define HCIC_PARAM_SIZE_BIG_CREATE_PARAMS 31 +#define HCIC_PARAM_SIZE_BIG_CREATE_TEST_PARAMS 36 +#define HCIC_PARAM_SIZE_BIG_TERMINATE_PARAMS 2 +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +#define HCIC_PARAM_SIZE_BIG_SYNC_CREATE_PARAMS 55 +#define HCIC_PARAM_SIZE_BIG_SYNC_TERMINATE_PARAMS 1 +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +#define HCIC_PARAM_SIZE_ISO_SET_DATA_PATH_PARAMS 13 +#define HCIC_PARAM_SIZE_ISO_REMOVE_DATA_PATH_PARAMS 3 + +#if (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) +struct ble_hci_le_cis_params { + uint8_t cis_id; + uint16_t max_sdu_c_to_p; + uint16_t max_sdu_p_to_c; + uint8_t phy_c_to_p; + uint8_t phy_p_to_c; + uint8_t rtn_c_to_p; + uint8_t rtn_p_to_c; +} __attribute__((packed)); +struct ble_hci_le_cis_params_test { + uint8_t cis_id; + uint8_t nse; + uint16_t max_sdu_c_to_p; + uint16_t max_sdu_p_to_c; + uint16_t max_pdu_c_to_p; + uint16_t max_pdu_p_to_c; + uint8_t phy_c_to_p; + uint8_t phy_p_to_c; + uint8_t bn_c_to_p; + uint8_t bn_p_to_c; +} __attribute__((packed)); + + +struct ble_hci_cis_hdls { + uint16_t cis_hdl; + uint16_t acl_hdl; +}__attribute__((packed)); + +UINT8 btsnd_hcic_ble_iso_set_cig_params(uint8_t cig_id, uint32_t sdu_int_c_to_p, uint32_t sdu_int_p_to_c, uint8_t worse_case_SCA, uint8_t packing, + uint8_t framing, uint16_t mtl_c_to_p, uint16_t mtl_p_to_c, uint8_t cis_cnt, struct ble_hci_le_cis_params *cis_params); +UINT8 btsnd_hcic_ble_iso_set_cig_params_test(uint8_t cig_id, uint32_t sdu_int_c_to_p, uint32_t sdu_int_p_to_c, uint8_t ft_c_to_p, uint8_t ft_p_to_c, + uint16_t iso_interval, uint8_t worse_case_SCA, uint8_t packing, uint8_t framing, uint8_t cis_cnt, + struct ble_hci_le_cis_params_test *cis_params_test); +UINT8 btsnd_hcic_ble_iso_create_cis(uint8_t cis_count, struct ble_hci_cis_hdls *cis_hdls); +UINT8 btsnd_hcic_ble_iso_remove_cig(uint8_t cig_id); +#endif // (BLE_FEAT_ISO_CIG_CENTRAL_EN == TRUE) + +#if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) +UINT8 btsnd_hcic_ble_iso_accept_cis_req(uint16_t cis_handle); +UINT8 btsnd_hcic_ble_iso_reject_cis_req(uint16_t cis_handle, uint8_t reason); +#endif // #if (BLE_FEAT_ISO_CIG_PERIPHERAL_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) +UINT8 btsnd_hcic_ble_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, + uint32_t sdu_interval, uint16_t max_sdu, uint16_t max_transport_latency, + uint8_t rtn, uint8_t phy, uint8_t packing, uint8_t framing, + uint8_t encryption, uint8_t *broadcast_code); + +UINT8 btsnd_hcic_ble_big_create_test(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, + uint32_t sdu_interval, uint16_t iso_interval, uint8_t nse, + uint16_t max_sdu, uint16_t max_pdu, uint8_t phy, + uint8_t packing, uint8_t framing, uint8_t bn, uint8_t irc, + uint8_t pto, uint8_t encryption, uint8_t *broadcast_code); + +UINT8 btsnd_hcic_ble_big_terminate(uint8_t big_handle, uint8_t reason); +#endif // #if (BLE_FEAT_ISO_BIG_BROCASTER_EN == TRUE) + +#if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) +UINT8 btsnd_hcic_ble_big_sync_create(uint8_t big_handle, uint16_t sync_handle, + uint8_t encryption, uint8_t *bc_code, + uint8_t mse, uint16_t big_sync_timeout, + uint8_t num_bis, uint8_t *bis); + +UINT8 btsnd_hcic_ble_big_sync_terminate(uint8_t big_handle); +#endif // #if (BLE_FEAT_ISO_BIG_SYNCER_EN == TRUE) + +UINT8 btsnd_hcic_ble_iso_set_data_path(uint16_t conn_handle, uint8_t data_path_dir, uint8_t data_path_id, uint8_t coding_fmt, + uint16_t company_id, uint16_t vs_codec_id, uint32_t controller_delay, uint8_t codec_len, + uint8_t *codec_cfg); +UINT8 btsnd_hcic_ble_iso_remove_data_path(uint16_t conn_handle, uint8_t data_path_dir); + +UINT8 btsnd_hcic_ble_iso_read_tx_sync(uint16_t iso_hdl); + +UINT8 btsnd_hcic_ble_iso_read_iso_link_quality(uint16_t iso_hdl); + +#endif // #if (BLE_FEAT_ISO_EN == TRUE) + +#if (BLE_FEAT_CTE_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#define HCIC_PARAM_SIZE_SET_CONNLESS_CTE_TRANS_PARAMS 5 +#define HCIC_PARAM_SIZE_SET_CONNLESS_CTE_TRANS_ENABLE 2 +#define HCIC_PARAM_SIZE_SET_CONNLESS_IQ_SAMPLING_ENABLE 6 +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +#define HCIC_PARAM_SIZE_SET_CONN_CTE_RECEIVE_PARAMS 5 +#define HCIC_PARAM_SIZE_SET_CONN_CTE_TRANS_PARAMS 4 +#define HCIC_PARAM_SIZE_CONN_CTE_REQ_ENABLE 7 +#define HCIC_PARAM_SIZE_CONN_CTE_RSP_ENABLE 3 +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +#define HCIC_PARAM_SIZE_READ_ANT_INFO 0 +#if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +UINT8 btsnd_hcic_ble_set_connless_cte_trans_params(uint8_t adv_hdl, uint8_t cte_len, uint8_t cte_type, + uint8_t cte_cnt, uint8_t switching_pattern_len, uint8_t *antenna_ids); +UINT8 btsnd_hcic_ble_set_connless_cte_enable(uint8_t adv_hdl, uint8_t cte_en); +UINT8 btsnd_hcic_ble_set_connless_iq_sampling_enable(uint16_t sync_hdl, uint8_t sampling_en, uint8_t slot_dur, + uint8_t max_sampled_ctes, uint8_t switching_pattern_len, uint8_t *antenna_ids); +#endif // #if (BLE_FEAT_CTE_CONNECTIONLESS_EN == TRUE) +#if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +UINT8 btsnd_hcic_ble_set_conn_cte_receive_params(uint16_t conn_hdl, uint8_t sampling_en, uint8_t slot_dur, + uint8_t switching_pattern_len, uint8_t *antenna_ids); +UINT8 btsnd_hcic_ble_set_conn_cte_trans_params(uint16_t conn_hdl, uint8_t cte_type, uint8_t switching_pattern_len, uint8_t *antenna_ids); +UINT8 btsnd_hcic_ble_conn_cte_req_enable(uint16_t conn_hdl, uint8_t enable, uint16_t cte_req_int, uint8_t req_cte_len, uint8_t req_cte_type); +UINT8 btsnd_hcic_ble_conn_cte_rsp_enable(uint16_t conn_hdl, uint8_t enable); +#endif // #if (BLE_FEAT_CTE_CONNECTION_EN == TRUE) +UINT8 btsnd_hcic_ble_read_antenna_info(void); +#endif // #if (BLE_FEAT_CTE_EN == TRUE) + +#if (BLE_FEAT_POWER_CONTROL_EN == TRUE) +#define HCIC_PARAM_SIZE_ENH_READ_TRANS_PWR_LEVEL 3 +#define HCIC_PARAM_SIZE_READ_REMOTE_TRANS_PWR_LEVEL 3 +#define HCIC_PARAM_SIZE_SET_PATH_LOSS_REPORTING_PARAMS 8 +#define HCIC_PARAM_SIZE_SET_PATH_LOSS_REPORTING_ENABLE 3 +#define HCIC_PARAM_SIZE_SET_TRANS_PWR_REPORTING_ENABLE 4 + +UINT8 btsnd_hcic_ble_enh_read_trans_power_level(uint16_t conn_handle, uint8_t phy); +UINT8 btsnd_hcic_ble_read_remote_trans_power_level(uint16_t conn_handle, uint8_t phy); +UINT8 btsnd_hcic_ble_set_path_loss_rpt_params(uint16_t conn_handle, uint8_t high_threshold, uint8_t high_hysteresis, + uint8_t low_threshold, uint8_t low_hysteresis, uint16_t min_time_spent); +UINT8 btsnd_hcic_ble_set_path_loss_rpt_enable(uint16_t conn_handle, uint8_t enable); +UINT8 btsnd_hcic_ble_set_trans_pwr_rpt_enable(uint16_t conn_handle, uint8_t local_enable, uint8_t remote_enable); +#endif // #if (BLE_FEAT_POWER_CONTROL_EN == TRUE) + +#if (BLE_FEAT_CONN_SUBRATING == TRUE) +#define HCIC_PARAM_SIZE_SET_DEFAULT_SUBRATE_PARAMS_LEN 10 +#define HCIC_PARAM_SIZE_SUBRATE_REQ_LENGTH_PARAMS_LEN 12 +UINT8 btsnd_hcic_ble_set_default_subrate(UINT16 subrate_min, UINT16 subrate_max, UINT16 max_latency, + UINT16 continuation_number, UINT16 supervision_timeout); + +UINT8 btsnd_hcic_ble_subrate_request(UINT16 conn_handle, UINT16 subrate_min, UINT16 subrate_max, UINT16 max_latency, + UINT16 continuation_number, UINT16 supervision_timeout); +#endif // #if (BLE_FEAT_CONN_SUBRATING == TRUE) + +#if (BLE_50_FEATURE_SUPPORT == TRUE) +#define HCIC_PARAM_SIZE_SET_HOST_FEATURE_PARAMS 2 +#define HCIC_PARAM_SIZE_SET_HOST_FEATURE_PARAMS_V2 3 +UINT8 btsnd_hcic_ble_set_host_feature(uint16_t bit_num, uint8_t bit_val); +#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) + #endif diff --git a/lib/bt/host/bluedroid/stack/include/stack/obex_api.h b/lib/bt/host/bluedroid/stack/include/stack/obex_api.h new file mode 100644 index 00000000..d22cd33c --- /dev/null +++ b/lib/bt/host/bluedroid/stack/include/stack/obex_api.h @@ -0,0 +1,271 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "common/bt_target.h" + +#if (OBEX_INCLUDED == TRUE) + +/* API function return value result codes. */ +#define OBEX_SUCCESS 0 /* Operation successful */ +#define OBEX_FAILURE 1 /* Operation failed */ +#define OBEX_NO_RESOURCES 3 /* Not enough resources */ +#define OBEX_BAD_HANDLE 4 /* Bad handle */ +#define OBEX_INVALID_PARAM 5 /* Invalid parameter */ +#define OBEX_NOT_OPEN 6 /* Connection not open */ +#define OBEX_PACKET_TOO_LARGE 7 /* Packet size large than MTU */ +#define OBEX_ERROR_TL 8 /* Operation failed in transport layer */ + +/* +* OBEX profile definitions +*/ +#define OBEX_OPCODE_CONNECT 0x80 +#define OBEX_OPCODE_DISCONNECT 0x81 +#define OBEX_OPCODE_PUT 0x02 +#define OBEX_OPCODE_PUT_FINAL 0x82 +#define OBEX_OPCODE_GET 0x03 +#define OBEX_OPCODE_GET_FINAL 0x83 +#define OBEX_OPCODE_SETPATH 0x85 +#define OBEX_OPCODE_ACTION 0x06 +#define OBEX_OPCODE_SESSION 0x87 +#define OBEX_OPCODE_ABORT 0xFF + +#define OBEX_RESPONSE_CODE_CONTINUE 0x10 +#define OBEX_RESPONSE_CODE_OK 0x20 +#define OBEX_RESPONSE_CODE_CREATED 0x21 +#define OBEX_RESPONSE_CODE_ACCEPTED 0x22 +#define OBEX_RESPONSE_CODE_NON_AUTHORITATIVE_INFO 0x23 +#define OBEX_RESPONSE_CODE_NO_CONTENT 0x24 +#define OBEX_RESPONSE_CODE_RESET_CONTENT 0x25 +#define OBEX_RESPONSE_CODE_PARTIAL_CONTENT 0x26 +#define OBEX_RESPONSE_CODE_MULTIPLE_CHOICES 0x30 +#define OBEX_RESPONSE_CODE_MOVED_PERMANENTLY 0x31 +#define OBEX_RESPONSE_CODE_MOVED_TEMPORARILY 0x31 +#define OBEX_RESPONSE_CODE_SEE_OHTER 0x33 +#define OBEX_RESPONSE_CODE_NOT_MODIFIED 0x34 +#define OBEX_RESPONSE_CODE_USE_PROXY 0x35 +#define OBEX_RESPONSE_CODE_BAD_REQUEST 0x40 +#define OBEX_RESPONSE_CODE_UNAUTHORIZED 0x41 +#define OBEX_RESPONSE_CODE_PAYMENT_REQUIRED 0x42 +#define OBEX_RESPONSE_CODE_FORBIDDEN 0x43 +#define OBEX_RESPONSE_CODE_NOT_FOUND 0x44 +#define OBEX_RESPONSE_CODE_METHOD_NOT_ALLOWED 0x45 +#define OBEX_RESPONSE_CODE_NOT_ACCEPTABLE 0x46 +#define OBEX_RESPONSE_CODE_PROXY_AUTHENTICATION_REQUIRED 0x47 +#define OBEX_RESPONSE_CODE_REQUEST_TIME_OUT 0x48 +#define OBEX_RESPONSE_CODE_CONFLICT 0x49 +#define OBEX_RESPONSE_CODE_GONE 0x4A +#define OBEX_RESPONSE_CODE_LENGTH_REQUIRED 0x4B +#define OBEX_RESPONSE_CODE_PRECONDITION_FAILED 0x4C +#define OBEX_RESPONSE_CODE_REQUESTED_ENTITY_TOO_LARGE 0x4D +#define OBEX_RESPONSE_CODE_REQUEST_URL_TOO_LARGE 0x4E +#define OBEX_RESPONSE_CODE_UNSUPPORTED_MEDIA_TYPE 0x4F +#define OBEX_RESPONSE_CODE_INTERNAL_SERVER_ERROR 0x50 +#define OBEX_RESPONSE_CODE_NOT_IMPLEMENTED 0x51 +#define OBEX_RESPONSE_CODE_BAD_GATEWAY 0x52 +#define OBEX_RESPONSE_CODE_SERVICE_UNAVAILABLE 0x53 +#define OBEX_RESPONSE_CODE_GATEWAY_TIMEOUT 0x54 +#define OBEX_RESPONSE_CODE_HTTP_VERSION_NOT_SUPPORTED 0x55 +#define OBEX_RESPONSE_CODE_DATABASE_FULL 0x60 +#define OBEX_RESPONSE_CODE_DATABASE_LOCKED 0x61 + +#define OBEX_FINAL_BIT_MASK 0x80 + +#define OBEX_CONNECT_FLAGS 0x01 /* support multiple link */ +#define OBEX_SETPATH_FLAGS 0x03 /* default flags */ + +#define OBEX_PACKET_LENGTH_MAX (0xFFFF-1) +#define OBEX_PACKET_LENGTH_MIN 255 + +#define OBEX_VERSION_NUMBER 0x15 + +/* Header identifiers */ +#define OBEX_HEADER_ID_U2B_MASK 0xC0 /* upper 2 bits of header ID are user to indicate the header encoding */ +#define OBEX_HEADER_ID_U2B_TYPE1 0x00 /* null terminated Unicode text, length prefixed with 2 byte unsigned integer */ +#define OBEX_HEADER_ID_U2B_TYPE2 0x40 /* byte sequence, length prefixed with 2 byte unsigned integer */ +#define OBEX_HEADER_ID_U2B_TYPE3 0x80 /* 1 byte quantity */ +#define OBEX_HEADER_ID_U2B_TYPE4 0xC0 /* 4 byte quantity - transmitted in network byte order (high byte first) */ + +#define OBEX_HEADER_ID_COUNT 0xC0 +#define OBEX_HEADER_ID_NAME 0x01 +#define OBEX_HEADER_ID_TYPE 0x42 +#define OBEX_HEADER_ID_LENGTH 0xC3 +#define OBEX_HEADER_ID_TIME_ISO8601 0x44 +#define OBEX_HEADER_ID_TIME_4BYTE 0xC4 +#define OBEX_HEADER_ID_DESCRIPTION 0x05 +#define OBEX_HEADER_ID_TARGET 0x46 +#define OBEX_HEADER_ID_HTTP 0x47 +#define OBEX_HEADER_ID_BODY 0x48 +#define OBEX_HEADER_ID_END_OF_BODY 0x49 +#define OBEX_HEADER_ID_WHO 0x4A +#define OBEX_HEADER_ID_CONNECTION_ID 0xCB +#define OBEX_HEADER_ID_APP_PARAM 0x4C +#define OBEX_HEADER_ID_AUTH_CHALLENGE 0x4D +#define OBEX_HEADER_ID_AUTH_RESPONSE 0x4E +#define OBEX_HEADER_ID_CREATOR_ID 0xCF +#define OBEX_HEADER_ID_WAN_UUID 0x50 +#define OBEX_HEADER_ID_OBJECT_CLASS 0x51 +#define OBEX_HEADER_ID_SESSION_PARAM 0x52 +#define OBEX_HEADER_ID_SESSION_SEQ_NUM 0x93 +#define OBEX_HEADER_ID_ACTION_ID 0x94 +#define OBEX_HEADER_ID_DESTNAME 0x15 +#define OBEX_HEADER_ID_PERMISSIONS 0xD6 +#define OBEX_HEADER_ID_SRM 0x97 +#define OBEX_HEADER_ID_SRM_PARAM 0x98 +/* Reserved for future use: 0x19 to 0x2F */ +/* User defined: 0x30 to 0x3F */ + +#define OBEX_ACTION_ID_COPY 0x00 +#define OBEX_ACTION_ID_MOVE_RENAME 0x01 +#define OBEX_ACTION_ID_SET_PERMISSIONS 0x02 + +#define OBEX_SRM_DISABLE 0x00 +#define OBEX_SRM_ENABLE 0x01 +#define OBEX_SRM_SUPPORT 0x02 + +#define OBEX_SRMP_ADD_PKT 0x00 +#define OBEX_SRMP_WAIT 0x01 +#define OBEX_SRMP_ADD_PKT_WAIT 0x02 + +#define OBEX_MIN_PACKET_SIZE 3 + +enum { + /* client event */ + OBEX_CONNECT_EVT, /* connection opened */ + OBEX_DISCONNECT_EVT, /* connection disconnected */ + /* server event */ + OBEX_CONN_INCOME_EVT, /* an incoming connection */ + /* client or server event */ + OBEX_MTU_CHANGE_EVT, /* connection mtu changed */ + OBEX_CONGEST_EVT, /* connection congested */ + OBEX_UNCONGEST_EVT, /* connection is not congested */ + OBEX_DATA_EVT /* data received */ +}; + +enum { + OBEX_OVER_L2CAP = 0, + OBEX_OVER_RFCOMM, + OBEX_NUM_TL +}; + +typedef struct +{ + UINT16 psm; /* l2cap psm */ + UINT16 sec_mask; /* security mask */ + UINT16 pref_mtu; /* preferred mtu, limited by L2CAP_MTU_SIZE */ + BD_ADDR addr; /* peer bluetooth device address */ +} tOBEX_OVER_L2CAP_SVR; + +typedef struct +{ + UINT8 scn; /* service channel number */ + UINT16 sec_mask; /* security mask */ + UINT16 pref_mtu; /* preferred mtu, limited by rfcomm mtu */ + BD_ADDR addr; /* peer bluetooth device address */ +} tOBEX_OVER_RFCOMM_SVR; + +typedef struct +{ + UINT8 tl; /* transport type, OBEX_OVER_L2CAP or OBEX_OVER_RFCOMM */ + union + { + tOBEX_OVER_L2CAP_SVR l2cap; + tOBEX_OVER_RFCOMM_SVR rfcomm; + }; +} tOBEX_SVR_INFO; + +typedef struct { + UINT8 opcode; + UINT8 response_code; + /* Connect */ + UINT8 obex_version_number; + UINT16 max_packet_length; + /* Connect or SetPath */ + UINT8 flags; + /* Internal use */ + UINT16 next_header_pos; +} tOBEX_PARSE_INFO; + +typedef union { + struct { + UINT16 peer_mtu; + UINT16 our_mtu; + } connect; + + struct { + UINT16 svr_handle; + UINT16 peer_mtu; + UINT16 our_mtu; + } conn_income; + + struct { + UINT16 peer_mtu; + UINT16 our_mtu; + } mtu_change; + + struct { + BT_HDR *pkt; + } data; +} tOBEX_MSG; + +typedef void (tOBEX_MSG_CBACK)(UINT16 handle, UINT8 event, tOBEX_MSG *msg); + +/******************************************************************************* +* The following APIs are called by bluetooth stack automatically +*******************************************************************************/ + +extern UINT16 OBEX_Init(void); + +extern void OBEX_Deinit(void); + +/******************************************************************************* +* The following APIs must be executed in btu task +*******************************************************************************/ + +extern UINT16 OBEX_CreateConn(tOBEX_SVR_INFO *server, tOBEX_MSG_CBACK callback, UINT16 *out_handle); + +extern UINT16 OBEX_RemoveConn(UINT16 handle); + +extern UINT16 OBEX_SendPacket(UINT16 handle, BT_HDR *pkt); + +extern UINT16 OBEX_RegisterServer(tOBEX_SVR_INFO *server, tOBEX_MSG_CBACK callback, UINT16 *out_svr_handle); + +extern UINT16 OBEX_DeregisterServer(UINT16 svr_handle); + +/******************************************************************************* +* The following APIs are util function, can be executed in btu or btc task +*******************************************************************************/ + +extern UINT16 OBEX_BuildRequest(tOBEX_PARSE_INFO *info, UINT16 buff_size, BT_HDR **out_pkt); + +extern UINT16 OBEX_BuildResponse(tOBEX_PARSE_INFO *info, UINT16 buff_size, BT_HDR **out_pkt); + +extern UINT16 OBEX_AppendHeader(BT_HDR *pkt, const UINT8 *header); + +extern UINT16 OBEX_AppendHeaderRaw(BT_HDR *pkt, UINT8 header_id, const UINT8 *data, UINT16 data_len); + +extern UINT16 OBEX_AppendHeaderSRM(BT_HDR *pkt, UINT8 value); + +extern UINT16 OBEX_AppendHeaderSRMP(BT_HDR *pkt, UINT8 value); + +extern UINT16 OBEX_GetPacketFreeSpace(BT_HDR *pkt); + +extern UINT16 OBEX_GetPacketLength(BT_HDR *pkt); + +extern UINT16 OBEX_ParseRequest(BT_HDR *pkt, tOBEX_PARSE_INFO *info); + +extern UINT16 OBEX_ParseResponse(BT_HDR *pkt, UINT8 opcode, tOBEX_PARSE_INFO *info); + +extern BOOLEAN OBEX_CheckFinalBit(BT_HDR *pkt); + +extern BOOLEAN OBEX_CheckContinueResponse(BT_HDR *pkt); + +extern UINT8 *OBEX_GetNextHeader(BT_HDR *pkt, tOBEX_PARSE_INFO *info); + +extern UINT16 OBEX_GetHeaderLength(UINT8 *header); + +#endif /* #if (OBEX_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/stack/include/stack/sdp_api.h b/lib/bt/host/bluedroid/stack/include/stack/sdp_api.h index 70da3182..7075e8bb 100644 --- a/lib/bt/host/bluedroid/stack/include/stack/sdp_api.h +++ b/lib/bt/host/bluedroid/stack/include/stack/sdp_api.h @@ -365,6 +365,20 @@ extern BOOLEAN SDP_FindProtocolListElemInRec (tSDP_DISC_REC *p_rec, UINT16 layer_uuid, tSDP_PROTOCOL_ELEM *p_elem); +/******************************************************************************* +** +** Function SDP_FindProtocolListElem +** +** Description This function looks at the protocol list for a specific protocol +** list element. +** +** Returns TRUE if found, FALSE if not +** If found, the passed protocol list element is filled in. +** +*******************************************************************************/ +extern BOOLEAN SDP_FindProtocolListElem (tSDP_DISC_ATTR *p_protocol_list, + UINT16 layer_uuid, + tSDP_PROTOCOL_ELEM *p_elem); /******************************************************************************* ** @@ -409,7 +423,7 @@ extern BOOLEAN SDP_FindProfileVersionInRec (tSDP_DISC_REC *p_rec, ** ** Description This function is called to create a record in the database. ** This would be through the SDP database maintenance API. The -** record is created empty, teh application should then call +** record is created empty, the application should then call ** "add_attribute" to add the record's attributes. ** ** Returns Record handle if OK, else 0. diff --git a/lib/bt/host/bluedroid/stack/l2cap/include/l2c_int.h b/lib/bt/host/bluedroid/stack/l2cap/include/l2c_int.h index 045fb10d..88eac86b 100644 --- a/lib/bt/host/bluedroid/stack/l2cap/include/l2c_int.h +++ b/lib/bt/host/bluedroid/stack/l2cap/include/l2c_int.h @@ -65,7 +65,7 @@ #define L2CAP_WAIT_UNPARK_TOUT 2 /* 2 seconds */ #define L2CAP_LINK_INFO_RESP_TOUT 2 /* 2 seconds */ #define L2CAP_UPDATE_CONN_PARAM_TOUT 6 /* 6 seconds */ -#define L2CAP_BLE_LINK_CONNECT_TOUT BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT // configed in menuconfig +#define L2CAP_BLE_LINK_CONNECT_TOUT BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT // configured in menuconfig #define L2CAP_BLE_CONN_PARAM_UPD_TOUT 30 /* 30 seconds */ /* quick timer uses millisecond unit */ @@ -80,10 +80,10 @@ ** the Bluetooth specification. */ typedef enum { - CST_CLOSED, /* Channel is in clodes state */ + CST_CLOSED, /* Channel is in closed state */ CST_ORIG_W4_SEC_COMP, /* Originator waits security clearence */ CST_TERM_W4_SEC_COMP, /* Acceptor waits security clearence */ - CST_W4_L2CAP_CONNECT_RSP, /* Waiting for peer conenct response */ + CST_W4_L2CAP_CONNECT_RSP, /* Waiting for peer connect response */ CST_W4_L2CA_CONNECT_RSP, /* Waiting for upper layer connect rsp */ CST_CONFIG, /* Negotiating configuration */ CST_OPEN, /* Data transfer state */ @@ -208,8 +208,8 @@ typedef struct { UINT32 controller_idle; /* # of times less than 2 packets in controller */ /* when the xmit window was closed */ UINT32 pkts_retransmitted; /* # of packets that were retransmitted */ - UINT32 retrans_touts; /* # of retransmission timouts */ - UINT32 xmit_ack_touts; /* # of xmit ack timouts */ + UINT32 retrans_touts; /* # of retransmission timeouts */ + UINT32 xmit_ack_touts; /* # of xmit ack timeouts */ #define L2CAP_ERTM_STATS_NUM_AVG 10 #define L2CAP_ERTM_STATS_AVG_NUM_SAMPLES 100 @@ -386,7 +386,7 @@ typedef struct t_l2c_linkcb { tL2C_CCB *p_pending_ccb; /* ccb of waiting channel during link disconnect */ TIMER_LIST_ENT info_timer_entry; /* Timer entry for info resp timeout evt */ - TIMER_LIST_ENT upda_con_timer; /* Timer entry for update connection parametr */ + TIMER_LIST_ENT upda_con_timer; /* Timer entry for update connection parameter */ BD_ADDR remote_bd_addr; /* The BD address of the remote */ UINT8 link_role; /* Master or slave */ @@ -599,7 +599,7 @@ extern BOOLEAN l2cu_start_post_bond_timer (UINT16 handle); extern void l2cu_release_lcb (tL2C_LCB *p_lcb); extern tL2C_LCB *l2cu_find_lcb_by_bd_addr (BD_ADDR p_bd_addr, tBT_TRANSPORT transport); extern tL2C_LCB *l2cu_find_lcb_by_handle (UINT16 handle); -extern uint8_t l2cu_plcb_active_count(void); +extern uint8_t l2cu_ble_plcb_active_count(void); extern void l2cu_update_lcb_4_bonding (BD_ADDR p_bd_addr, BOOLEAN is_bonding); extern UINT8 l2cu_get_conn_role (tL2C_LCB *p_this_lcb); diff --git a/lib/bt/host/bluedroid/stack/l2cap/l2c_ble.c b/lib/bt/host/bluedroid/stack/l2cap/l2c_ble.c index 956a4b7f..3ce25ab9 100644 --- a/lib/bt/host/bluedroid/stack/l2cap/l2c_ble.c +++ b/lib/bt/host/bluedroid/stack/l2cap/l2c_ble.c @@ -111,7 +111,7 @@ BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda) p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE); /* Do not remove lcb if an LE link is already up as a peripheral */ if (p_lcb != NULL && - !(p_lcb->link_role == HCI_ROLE_SLAVE && BTM_ACL_IS_CONNECTED(rem_bda))) { + !(p_lcb->link_role == HCI_ROLE_SLAVE && BTM_LE_ACL_IS_CONNECTED(rem_bda))) { p_lcb->disc_reason = L2CAP_CONN_CANCEL; l2cu_release_lcb (p_lcb); } @@ -242,7 +242,7 @@ BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable) return (FALSE); } bool is_disable = (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE); - if(l2cu_plcb_active_count() >1 && !(enable && is_disable)) { + if(l2cu_ble_plcb_active_count() >1 && !(enable && is_disable)) { return FALSE; } @@ -376,6 +376,7 @@ void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type, p_lcb->waiting_update_conn_latency = p_lcb->current_used_conn_latency = conn_latency; p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM; p_lcb->updating_param_flag = false; + p_lcb->ble_addr_type = type; /* If there are any preferred connection parameters, set them now */ if ( (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN ) && @@ -476,6 +477,7 @@ void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE typ p_lcb->waiting_update_conn_latency = p_lcb->current_used_conn_latency = conn_latency; p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM; p_lcb->updating_param_flag = false; + p_lcb->ble_addr_type = type; /* Tell BTM Acl management about the link */ p_dev_rec = btm_find_or_alloc_dev (bda); @@ -900,6 +902,12 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb) scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int; scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win; + if (p_dev_rec->conn_params.scan_interval && p_dev_rec->conn_params.scan_interval != BTM_BLE_CONN_PARAM_UNDEF) { + scan_int = p_dev_rec->conn_params.scan_interval; + } + if (p_dev_rec->conn_params.scan_window && p_dev_rec->conn_params.scan_window != BTM_BLE_CONN_PARAM_UNDEF) { + scan_win = p_dev_rec->conn_params.scan_window; + } peer_addr_type = p_lcb->ble_addr_type; memcpy(peer_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN); @@ -964,22 +972,24 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb) } if (!p_lcb->is_aux) { - if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int */ - scan_win, /* UINT16 scan_win */ - FALSE, /* UINT8 white_list */ - peer_addr_type, /* UINT8 addr_type_peer */ - peer_addr, /* BD_ADDR bda_peer */ - own_addr_type, /* UINT8 addr_type_own */ + if (!btsnd_hcic_ble_create_ll_conn (scan_int, /* UINT16 scan_int */ + scan_win, /* UINT16 scan_win */ + FALSE, /* UINT8 white_list */ + peer_addr_type, /* UINT8 addr_type_peer */ + peer_addr, /* BD_ADDR bda_peer */ + own_addr_type, /* UINT8 addr_type_own */ (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? - p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF), /* UINT16 conn_int_min */ + p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF), /* UINT16 conn_int_min */ (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? - p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF), /* UINT16 conn_int_max */ + p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF), /* UINT16 conn_int_max */ (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? - p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency */ + p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency */ (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? - p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */ - BLE_CE_LEN_MIN, /* UINT16 min_len */ - BLE_CE_LEN_MIN)) { /* UINT16 max_len */ + p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* UINT16 conn_timeout */ + (UINT16) ((p_dev_rec->conn_params.min_ce_len != BTM_BLE_CONN_PARAM_UNDEF) ? + p_dev_rec->conn_params.min_ce_len : BLE_CE_LEN_MIN), /* UINT16 min_ce_len */ + (UINT16) ((p_dev_rec->conn_params.max_ce_len != BTM_BLE_CONN_PARAM_UNDEF) ? + p_dev_rec->conn_params.max_ce_len : BLE_CE_LEN_MIN) /* UINT16 max_ce_len */)) { l2cu_release_lcb (p_lcb); L2CAP_TRACE_ERROR("initiate direct connection fail, no resources"); return (FALSE); @@ -1063,11 +1073,11 @@ BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb) L2CAP_TRACE_WARNING ("L2CAP - LE - cannot start new connection at conn st: %d", conn_st); btm_ble_enqueue_direct_conn_req(p_lcb); - +#if (tGATT_BG_CONN_DEV == TRUE) if (conn_st == BLE_BG_CONN) { btm_ble_suspend_bg_conn(); } - +#endif // #if (tGATT_BG_CONN_DEV == TRUE) rt = TRUE; } return rt; diff --git a/lib/bt/host/bluedroid/stack/l2cap/l2c_link.c b/lib/bt/host/bluedroid/stack/l2cap/l2c_link.c index c3118fdd..1af7e8b3 100644 --- a/lib/bt/host/bluedroid/stack/l2cap/l2c_link.c +++ b/lib/bt/host/bluedroid/stack/l2cap/l2c_link.c @@ -368,9 +368,11 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason) BTM_Recovery_Pre_State(); } #if (BLE_50_FEATURE_SUPPORT == TRUE) + #if (BLE_50_EXTEND_ADV_EN == TRUE) if(btm_ble_inter_get() && reason == HCI_ERR_CONN_FAILED_ESTABLISHMENT) { BTM_BleStartExtAdvRestart(handle); } + #endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #endif ///BLE_INCLUDED == TRUE status = FALSE; @@ -478,24 +480,36 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason) if (l2cu_create_conn(p_lcb, BT_TRANSPORT_LE)) { btm_acl_removed (p_lcb->remote_bd_addr, BT_TRANSPORT_LE); lcb_is_free = FALSE; /* still using this lcb */ + } else { + L2CAP_TRACE_ERROR("master retry connect failed"); } } #endif // (GATTC_CONNECT_RETRY_EN == TRUE) #if (BLE_50_FEATURE_SUPPORT == TRUE) + #if (BLE_50_EXTEND_ADV_EN == TRUE) if(btm_ble_inter_get() && p_lcb->link_role == HCI_ROLE_SLAVE) { p_lcb->retry_create_con ++; L2CAP_TRACE_DEBUG("slave restart extend adv, retry count %d reason 0x%x\n", p_lcb->retry_create_con, reason); - BTM_BleStartExtAdvRestart(handle); + tBTM_STATUS start_adv_status = BTM_BleStartExtAdvRestart(handle); + if (start_adv_status != BTM_SUCCESS) { + L2CAP_TRACE_ERROR("slave restart extend adv failed (err 0x%x)", start_adv_status); + } } + #endif // #if (BLE_50_EXTEND_ADV_EN == TRUE) #endif // #if (BLE_50_FEATURE_SUPPORT == TRUE) #if (BLE_42_FEATURE_SUPPORT == TRUE) + #if (BLE_42_ADV_EN == TRUE) if(!btm_ble_inter_get() && p_lcb->link_role == HCI_ROLE_SLAVE) { p_lcb->retry_create_con ++; L2CAP_TRACE_DEBUG("slave resatrt adv, retry count %d reason 0x%x\n", p_lcb->retry_create_con, reason); - btm_ble_start_adv(); + tBTM_STATUS start_adv_status = btm_ble_start_adv(); + if (start_adv_status != BTM_SUCCESS) { + L2CAP_TRACE_ERROR("slave resatrt adv failed (err 0x%x)", start_adv_status); + } } + #endif // #if (BLE_42_ADV_EN == TRUE) #endif // #if (BLE_42_FEATURE_SUPPORT == TRUE) } @@ -1078,7 +1092,9 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf) p_lcb_cur = list_node(p_node); if (p_lcb_cur == p_lcb) { p_node = list_next(p_node); - p_lcb = list_node(p_node); + if (p_node) { + p_lcb = list_node(p_node); + } break; } } diff --git a/lib/bt/host/bluedroid/stack/l2cap/l2c_utils.c b/lib/bt/host/bluedroid/stack/l2cap/l2c_utils.c index 992d4b68..e4bf8a08 100644 --- a/lib/bt/host/bluedroid/stack/l2cap/l2c_utils.c +++ b/lib/bt/host/bluedroid/stack/l2cap/l2c_utils.c @@ -336,14 +336,14 @@ tL2C_LCB *l2cu_find_free_lcb (void) return (NULL); } -uint8_t l2cu_plcb_active_count(void) +uint8_t l2cu_ble_plcb_active_count(void) { list_node_t *p_node = NULL; tL2C_LCB *p_lcb = NULL; uint8_t active_count = 0; for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) { p_lcb = list_node(p_node); - if (p_lcb && p_lcb->in_use) { + if (p_lcb && p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE) { active_count ++; } } @@ -615,7 +615,7 @@ void l2cu_send_peer_connect_rsp (tL2C_CCB *p_ccb, UINT16 result, UINT16 status) ** ** Description Build and send an L2CAP "connection response neg" message ** to the peer. This function is called when there is no peer -** CCB (non-existant PSM or no resources). +** CCB (non-existent PSM or no resources). ** ** Returns void ** @@ -1737,7 +1737,7 @@ void l2cu_release_ccb (tL2C_CCB *p_ccb) ) { l2cu_dequeue_ccb (p_ccb); - /* Delink the CCB from the LCB */ + /* Unlink the CCB from the LCB */ p_ccb->p_lcb = NULL; } @@ -1960,7 +1960,7 @@ tL2C_RCB *l2cu_find_ble_rcb_by_psm (UINT16 psm) ** ** Returns UINT8 - L2CAP_PEER_CFG_OK if passed to upper layer, ** L2CAP_PEER_CFG_UNACCEPTABLE if automatically responded to -** because parameters are unnacceptable from a specification +** because parameters are unacceptable from a specification ** point of view. ** L2CAP_PEER_CFG_DISCONNECT if no compatible channel modes ** between the two devices, and shall be closed. @@ -2558,7 +2558,7 @@ BOOLEAN l2cu_set_acl_priority (BD_ADDR bd_addr, UINT8 priority, BOOLEAN reset_af ** ** Function l2cu_set_non_flushable_pbf ** -** Description set L2CAP_PKT_START_NON_FLUSHABLE if controller supoorts +** Description set L2CAP_PKT_START_NON_FLUSHABLE if controller supports ** ** Returns void ** @@ -3328,7 +3328,7 @@ static tL2C_CCB *l2cu_get_next_channel_in_rr(tL2C_LCB *p_lcb) for ( i = 0; (i < L2CAP_NUM_CHNL_PRIORITY) && (!p_serve_ccb); i++ ) { /* scan all channel within serving priority group until finding a channel to serve */ for ( j = 0; (j < p_lcb->rr_serv[p_lcb->rr_pri].num_ccb) && (!p_serve_ccb); j++) { - /* scaning from next serving channel */ + /* scanning from next serving channel */ p_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb; if (!p_ccb) { diff --git a/lib/bt/host/bluedroid/stack/obex/include/obex_int.h b/lib/bt/host/bluedroid/stack/obex/include/obex_int.h new file mode 100644 index 00000000..28c4eab4 --- /dev/null +++ b/lib/bt/host/bluedroid/stack/obex/include/obex_int.h @@ -0,0 +1,76 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "common/bt_target.h" + +#include "stack/obex_api.h" +#include "obex_tl.h" +#include "obex_tl_l2cap.h" + +#if (OBEX_INCLUDED == TRUE) + +#if (RFCOMM_INCLUDED == TRUE) +#define OBEX_BT_HDR_MIN_OFFSET OBEX_TL_RFCOMM_BT_HDR_MIN_OFFSET /* should set to max value of all transport layer */ +#define OBEX_BT_HDR_RESERVE_LEN OBEX_TL_RFCOMM_BT_HDR_RESERVE_LEN /* should set to max value of all transport layer */ +#else +#define OBEX_BT_HDR_MIN_OFFSET OBEX_TL_L2CAP_BT_HDR_OFFSET_MIN +#define OBEX_BT_HDR_RESERVE_LEN OBEX_TL_L2CAP_BT_HDR_RESERVE_LEN +#endif + +#define OBEX_ROLE_CLIENT 0x01 +#define OBEX_ROLE_SERVER 0x02 + +/* OBEX connection state */ +#define OBEX_STATE_IDLE 0 /* No connection */ +#define OBEX_STATE_OPENING 1 /* Starting to open a connection */ +#define OBEX_STATE_OPENED 2 /* Connection opened */ + +/* OBEX Connection Control block */ +typedef struct { + tOBEX_MSG_CBACK *callback; /* Connection msg callback function */ + UINT16 tl_hdl; /* Transport layer non-zeros connection handle*/ + UINT16 tl_peer_mtu; /* Transport layer peer mtu */ + UINT16 tl_our_mtu; /* Transport layer our mtu */ + UINT8 tl_cong; /* 1 if transport layer congestion, otherwise 0 */ + UINT8 tl; /* OBEX_OVER_L2CAP or OBEX_OVER_RFCOMM */ + UINT8 allocated; /* 0, not allocated. index+1, otherwise. equal to api handle */ + UINT8 state; /* This OBEX connection state */ + UINT8 role; /* This OBEX connection role */ +} tOBEX_CCB; + +/* OBEX Server Control block */ +typedef struct { + tOBEX_MSG_CBACK *callback; /* Connection msg callback function */ + UINT16 tl_hdl; /* Transport layer non-zeros server handle*/ + UINT8 tl; /* OBEX_OVER_L2CAP or OBEX_OVER_RFCOMM */ + UINT8 allocated; /* 0, not allocated. index+1, otherwise. */ +} tOBEX_SCB; + +/* OBEX Control block */ +typedef struct { + tOBEX_CCB ccb[OBEX_MAX_CONNECTION]; /* connection control blocks */ + tOBEX_SCB scb[OBEX_MAX_SERVER]; /* server control blocks */ + tOBEX_TL_OPS *tl_ops[OBEX_NUM_TL]; /* transport operation function pointer */ + UINT8 trace_level; /* trace level */ +} tOBEX_CB; + +#if OBEX_DYNAMIC_MEMORY == FALSE +extern tOBEX_CB obex_cb; +#else +extern tOBEX_CB *obex_cb_ptr; +#define obex_cb (*obex_cb_ptr) +#endif + +void obex_tl_l2cap_callback(tOBEX_TL_EVT evt, tOBEX_TL_MSG *msg); +void obex_tl_rfcomm_callback(tOBEX_TL_EVT evt, tOBEX_TL_MSG *msg); +tOBEX_CCB *obex_allocate_ccb(void); +tOBEX_SCB *obex_allocate_scb(void); +void obex_free_ccb(tOBEX_CCB *p_ccb); +void obex_free_scb(tOBEX_SCB *p_scb); + +#endif /* #if (OBEX_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/stack/obex/include/obex_tl.h b/lib/bt/host/bluedroid/stack/obex/include/obex_tl.h new file mode 100644 index 00000000..9211b9b0 --- /dev/null +++ b/lib/bt/host/bluedroid/stack/obex/include/obex_tl.h @@ -0,0 +1,97 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "common/bt_target.h" + +#if (OBEX_INCLUDED == TRUE) + +/* Return code of obex_tl_send_data */ +#define OBEX_TL_FAILED FALSE +#define OBEX_TL_SUCCESS TRUE +#define OBEX_TL_CONGESTED 2 + +typedef enum { + OBEX_TL_CONN_OPEN_EVT, + OBEX_TL_CONN_INCOME_EVT, + OBEX_TL_DIS_CONN_EVT, + OBEX_TL_CONGEST_EVT, + OBEX_TL_UNCONGEST_EVT, + OBEX_TL_MTU_CHANGE_EVT, + OBEX_TL_DATA_EVT +} tOBEX_TL_EVT; + +typedef union { + /* general struct, used to retrieve handle */ + struct { + UINT16 hdl; + } any; + + /* struct for OBEX_TL_CONN_OPEN_EVT */ + struct { + UINT16 hdl; + UINT16 peer_mtu; + UINT16 our_mtu; + } conn_open; + + /* struct for OBEX_TL_CONN_INCOME_EVT */ + struct { + UINT16 hdl; + UINT16 peer_mtu; + UINT16 our_mtu; + UINT16 svr_hdl; + } conn_income; + + /* struct for OBEX_TL_MTU_CHANGE_EVT */ + struct { + UINT16 hdl; + UINT16 peer_mtu; + UINT16 our_mtu; + } mtu_chg; + + /* struct for OBEX_TL_DATA_EVT */ + struct { + UINT16 hdl; + BT_HDR *p_buf; + } data; +} tOBEX_TL_MSG; + +typedef struct +{ + UINT16 psm; /* l2cap psm */ + UINT16 sec_mask; /* security mask */ + UINT16 pref_mtu; /* preferred mtu, limited by L2CAP_MTU_SIZE */ + BD_ADDR addr; /* peer bluetooth device address */ +} tOBEX_TL_L2CAP_SVR; + +typedef struct +{ + UINT8 scn; /* service channel number */ + UINT16 sec_mask; /* security mask */ + UINT16 pref_mtu; /* preferred mtu, limited by rfcomm mtu */ + BD_ADDR addr; /* peer bluetooth device address */ +} tOBEX_TL_RFCOMM_SVR; + +typedef union +{ + tOBEX_TL_L2CAP_SVR l2cap; + tOBEX_TL_RFCOMM_SVR rfcomm; +} tOBEX_TL_SVR_INFO; + +typedef void (tOBEX_TL_CBACK)(tOBEX_TL_EVT evt, tOBEX_TL_MSG *msg); + +typedef struct { + void (*init)(tOBEX_TL_CBACK *callback); + void (*deinit)(void); + UINT16 (*connect)(tOBEX_TL_SVR_INFO *server); + void (*disconnect)(UINT16 tl_hdl); + UINT16 (*send)(UINT16 tl_hdl, BT_HDR *p_buf); + UINT16 (*bind)(tOBEX_TL_SVR_INFO *server); + void (*unbind)(UINT16 tl_hdl); +} tOBEX_TL_OPS; + +#endif /* #if (OBEX_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/stack/obex/include/obex_tl_l2cap.h b/lib/bt/host/bluedroid/stack/obex/include/obex_tl_l2cap.h new file mode 100644 index 00000000..32667766 --- /dev/null +++ b/lib/bt/host/bluedroid/stack/obex/include/obex_tl_l2cap.h @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "obex_tl.h" + +#if (OBEX_INCLUDED == TRUE) + +#define OBEX_TL_L2CAP_BT_HDR_MIN_OFFSET 13 /* equal to L2CAP_MIN_OFFSET */ +#define OBEX_TL_L2CAP_BT_HDR_RESERVE_LEN 0 /* not require any additional byte */ + +tOBEX_TL_OPS *obex_tl_l2cap_ops_get(void); + +#endif /* #if (OBEX_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/stack/obex/include/obex_tl_rfcomm.h b/lib/bt/host/bluedroid/stack/obex/include/obex_tl_rfcomm.h new file mode 100644 index 00000000..61b9d295 --- /dev/null +++ b/lib/bt/host/bluedroid/stack/obex/include/obex_tl_rfcomm.h @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "obex_tl.h" + +#if (OBEX_INCLUDED == TRUE && RFCOMM_INCLUDED == TRUE) + +#define OBEX_TL_RFCOMM_BT_HDR_MIN_OFFSET 18 /* RFCOMM_MIN_OFFSET + L2CAP_MIN_OFFSET */ +#define OBEX_TL_RFCOMM_BT_HDR_RESERVE_LEN 1 /* reserve 1 byte for rfcomm fcs */ + +tOBEX_TL_OPS *obex_tl_rfcomm_ops_get(void); + +#endif /* #if (OBEX_INCLUDED == TRUE && RFCOMM_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/stack/obex/obex_api.c b/lib/bt/host/bluedroid/stack/obex/obex_api.c new file mode 100644 index 00000000..99276a93 --- /dev/null +++ b/lib/bt/host/bluedroid/stack/obex/obex_api.c @@ -0,0 +1,776 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "osi/osi.h" +#include "osi/allocator.h" +#include "common/bt_target.h" + +#include "stack/obex_api.h" +#include "obex_int.h" +#include "obex_tl.h" +#include "obex_tl_l2cap.h" +#include "obex_tl_rfcomm.h" + +#if (OBEX_INCLUDED == TRUE) + +static inline void obex_server_to_tl_server(tOBEX_SVR_INFO *server, tOBEX_TL_SVR_INFO *tl_server) +{ + if (server->tl == OBEX_OVER_L2CAP) { + tl_server->l2cap.psm = server->l2cap.psm; + tl_server->l2cap.sec_mask = server->l2cap.sec_mask; + tl_server->l2cap.pref_mtu = server->l2cap.pref_mtu; + bdcpy(tl_server->l2cap.addr, server->l2cap.addr); + } + else if (server->tl == OBEX_OVER_RFCOMM) { + tl_server->rfcomm.scn = server->rfcomm.scn; + tl_server->rfcomm.sec_mask = server->rfcomm.sec_mask; + tl_server->rfcomm.pref_mtu = server->rfcomm.pref_mtu; + bdcpy(tl_server->rfcomm.addr, server->rfcomm.addr); + } + else { + OBEX_TRACE_ERROR("Unsupported OBEX transport type\n"); + assert(0); + } +} + +static inline void obex_updata_packet_length(BT_HDR *p_buf, UINT16 len) +{ + UINT8 *p_pkt_len = (UINT8 *)(p_buf + 1) + p_buf->offset + 1; + UINT16_TO_BE_FIELD(p_pkt_len, len); +} + +/******************************************************************************* +** +** Function OBEX_Init +** +** Description Initialize OBEX Profile, must call before using any other +** OBEX APIs +** +** Returns OBEX_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 OBEX_Init(void) +{ +#if (OBEX_DYNAMIC_MEMORY) + if (!obex_cb_ptr) { + obex_cb_ptr = (tOBEX_CB *)osi_malloc(sizeof(tOBEX_CB)); + if (!obex_cb_ptr) { + return OBEX_NO_RESOURCES; + } + } +#endif /* #if (OBEX_DYNAMIC_MEMORY) */ + memset(&obex_cb, 0, sizeof(tOBEX_CB)); + obex_cb.tl_ops[OBEX_OVER_L2CAP] = obex_tl_l2cap_ops_get(); + if (obex_cb.tl_ops[OBEX_OVER_L2CAP]->init != NULL) { + obex_cb.tl_ops[OBEX_OVER_L2CAP]->init(obex_tl_l2cap_callback); + } +#if (RFCOMM_INCLUDED == TRUE) + obex_cb.tl_ops[OBEX_OVER_RFCOMM] = obex_tl_rfcomm_ops_get(); + if (obex_cb.tl_ops[OBEX_OVER_RFCOMM]->init != NULL) { + obex_cb.tl_ops[OBEX_OVER_RFCOMM]->init(obex_tl_rfcomm_callback); + } +#endif + obex_cb.trace_level = BT_TRACE_LEVEL_ERROR; + return OBEX_SUCCESS; +} + +/******************************************************************************* +** +** Function OBEX_Deinit +** +** Description Deinit OBEX profile, once deinit, can not use any other +** APIs until call OBEX_Init again +** +*******************************************************************************/ +void OBEX_Deinit(void) +{ + if (obex_cb.tl_ops[OBEX_OVER_L2CAP]->deinit != NULL) { + obex_cb.tl_ops[OBEX_OVER_L2CAP]->deinit(); + } +#if (RFCOMM_INCLUDED == TRUE) + if (obex_cb.tl_ops[OBEX_OVER_RFCOMM]->deinit != NULL) { + obex_cb.tl_ops[OBEX_OVER_RFCOMM]->deinit(); + } +#endif +#if (OBEX_DYNAMIC_MEMORY) + if (obex_cb_ptr) { + osi_free(obex_cb_ptr); + obex_cb_ptr = NULL; + } +#endif /* #if (OBEX_DYNAMIC_MEMORY) */ +} + +/******************************************************************************* +** +** Function OBEX_CreateConn +** +** Description Start the progress of creating an OBEX connection +** +** Returns OBEX_SUCCESS if successful, otherwise failed, when the +** connection is opened, an OBEX_CONNECT_EVT will come +** +*******************************************************************************/ +UINT16 OBEX_CreateConn(tOBEX_SVR_INFO *server, tOBEX_MSG_CBACK callback, UINT16 *out_handle) +{ + UINT16 ret = OBEX_SUCCESS; + tOBEX_CCB *p_ccb = NULL; + + do { + if (server->tl >= OBEX_NUM_TL) { + ret = OBEX_INVALID_PARAM; + break; + } + + p_ccb = obex_allocate_ccb(); + if (p_ccb == NULL) { + ret = OBEX_NO_RESOURCES; + break; + } + + tOBEX_TL_SVR_INFO tl_server = {0}; + obex_server_to_tl_server(server, &tl_server); + p_ccb->tl = server->tl; + p_ccb->tl_hdl = obex_cb.tl_ops[p_ccb->tl]->connect(&tl_server); + if (p_ccb->tl_hdl == 0) { + ret = OBEX_ERROR_TL; + break; + } + + p_ccb->callback = callback; + p_ccb->role = OBEX_ROLE_CLIENT; + p_ccb->state = OBEX_STATE_OPENING; + *out_handle = p_ccb->allocated; + } while (0); + + if (ret != OBEX_SUCCESS && p_ccb != NULL) { + obex_free_ccb(p_ccb); + } + return ret; +} + +/******************************************************************************* +** +** Function OBEX_RemoveConn +** +** Description Remove an OBEX connection +** +** Returns OBEX_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 OBEX_RemoveConn(UINT16 handle) +{ + tOBEX_CCB *p_ccb = NULL; + + UINT16 ccb_idx = handle - 1; + if (ccb_idx >= OBEX_MAX_CONNECTION || !obex_cb.ccb[ccb_idx].allocated) { + return OBEX_BAD_HANDLE; + } + + p_ccb = &obex_cb.ccb[ccb_idx]; + obex_cb.tl_ops[p_ccb->tl]->disconnect(p_ccb->tl_hdl); + obex_free_ccb(p_ccb); + + return OBEX_SUCCESS; +} + +/******************************************************************************* +** +** Function OBEX_RegisterServer +** +** Description Register an OBEX server and listen the incoming connection +** +** Returns OBEX_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 OBEX_RegisterServer(tOBEX_SVR_INFO *server, tOBEX_MSG_CBACK callback, UINT16 *out_svr_handle) +{ + UINT8 ret = OBEX_SUCCESS; + tOBEX_SCB *p_scb = NULL; + + do { + if (server->tl >= OBEX_NUM_TL) { + ret = OBEX_INVALID_PARAM; + break; + } + + p_scb = obex_allocate_scb(); + if (p_scb == NULL) { + ret = OBEX_NO_RESOURCES; + break; + } + + tOBEX_TL_SVR_INFO tl_server = {0}; + obex_server_to_tl_server(server, &tl_server); + p_scb->tl = server->tl; + p_scb->tl_hdl = obex_cb.tl_ops[p_scb->tl]->bind(&tl_server); + if (p_scb->tl_hdl == 0) { + ret = OBEX_ERROR_TL; + break; + } + p_scb->callback = callback; + + if (out_svr_handle) { + /* To avoid confuse with connection handle, left shift 8 bit */ + *out_svr_handle = p_scb->allocated << 8; + } + } while (0); + + if (ret != OBEX_SUCCESS && p_scb != NULL) { + obex_free_scb(p_scb); + } + return ret; +} + +/******************************************************************************* +** +** Function OBEX_DeregisterServer +** +** Description Deregister an OBEX server, if there are still a connection +** alive, the behavior depend on the implementation of transport +** layer +** +** Returns OBEX_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 OBEX_DeregisterServer(UINT16 svr_handle) +{ + tOBEX_SCB *p_scb = NULL; + + UINT16 scb_idx = (svr_handle >> 8) - 1; + if (scb_idx >= OBEX_MAX_SERVER || !obex_cb.scb[scb_idx].allocated) { + return OBEX_BAD_HANDLE; + } + + p_scb = &obex_cb.scb[scb_idx]; + obex_cb.tl_ops[p_scb->tl]->unbind(p_scb->tl_hdl); + obex_free_scb(p_scb); + return OBEX_SUCCESS; +} + +/******************************************************************************* +** +** Function OBEX_SendPacket +** +** Description Send a packet to peer OBEX server or client, once call +** this function, the ownership of pkt is lost, do not free +** or modify the pkt any more +** +** Returns OBEX_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 OBEX_SendPacket(UINT16 handle, BT_HDR *pkt) +{ + UINT16 ret = OBEX_SUCCESS; + BOOLEAN free_pkt = true; + tOBEX_CCB *p_ccb = NULL; + do { + if (pkt == NULL) { + ret = OBEX_INVALID_PARAM; + break; + } + + UINT16 ccb_idx = handle - 1; + if (ccb_idx >= OBEX_MAX_CONNECTION || !obex_cb.ccb[ccb_idx].allocated) { + ret = OBEX_BAD_HANDLE; + break; + } + + p_ccb = &obex_cb.ccb[ccb_idx]; + if (p_ccb->state != OBEX_STATE_OPENED) { + ret = OBEX_NOT_OPEN; + break; + } + + if (pkt->len > p_ccb->tl_peer_mtu) { + ret = OBEX_PACKET_TOO_LARGE; + break; + } + + ret = obex_cb.tl_ops[p_ccb->tl]->send(p_ccb->tl_hdl, pkt); + /* packet has pass to lower layer, do not free it */ + free_pkt = false; + if (ret == OBEX_TL_SUCCESS || ret == OBEX_TL_CONGESTED) { + ret = OBEX_SUCCESS; + } + else { + ret = OBEX_ERROR_TL; + } + } while (0); + + if (free_pkt) { + osi_free(pkt); + } + return ret; +} + +/******************************************************************************* +** +** Function OBEX_BuildRequest +** +** Description Build a request packet with opcode and additional info, +** packet can free by osi_free +** +** Returns OBEX_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 OBEX_BuildRequest(tOBEX_PARSE_INFO *info, UINT16 buff_size, BT_HDR **out_pkt) +{ + if (buff_size < OBEX_MIN_PACKET_SIZE || info == NULL || out_pkt == NULL) { + return OBEX_INVALID_PARAM; + } + buff_size += sizeof(BT_HDR) + OBEX_BT_HDR_MIN_OFFSET + OBEX_BT_HDR_RESERVE_LEN; + + BT_HDR *p_buf= (BT_HDR *)osi_malloc(buff_size); + if (p_buf == NULL) { + return OBEX_NO_RESOURCES; + } + + UINT16 pkt_len = OBEX_MIN_PACKET_SIZE; + p_buf->offset = OBEX_BT_HDR_MIN_OFFSET; + /* use layer_specific to store the max data length allowed */ + p_buf->layer_specific = buff_size - sizeof(BT_HDR) - OBEX_BT_HDR_MIN_OFFSET - OBEX_BT_HDR_RESERVE_LEN; + UINT8 *p_data = (UINT8 *)(p_buf + 1) + p_buf->offset; + /* byte 0: opcode */ + *p_data++ = info->opcode; + /* byte 1, 2: packet length, skip, we will update at last */ + UINT8 *p_pkt_len = p_data; + p_data += 2; + + switch (info->opcode) + { + case OBEX_OPCODE_CONNECT: + /* byte 3: OBEX version number */ + *p_data++ = info->obex_version_number; + /* byte 4: flags */ + *p_data++ = info->flags; + /* byte 5, 6: maximum OBEX packet length, recommend to set as our mtu*/ + UINT16_TO_BE_FIELD(p_data, info->max_packet_length); + pkt_len += 4; + break; + case OBEX_OPCODE_SETPATH: + /* byte 3: flags */ + *p_data++ = info->flags; + /* byte 4: constants, reserved, must be zero */ + *p_data++ = 0; + pkt_len += 2; + break; + default: + break; + } + + UINT16_TO_BE_FIELD(p_pkt_len, pkt_len); + p_buf->len = pkt_len; + *out_pkt = p_buf; + return OBEX_SUCCESS; +} + +/******************************************************************************* +** +** Function OBEX_BuildResponse +** +** Description Build a response packet with opcode and response and additional +** info, packet can by free by osi_free +** +** Returns OBEX_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 OBEX_BuildResponse(tOBEX_PARSE_INFO *info, UINT16 buff_size, BT_HDR **out_pkt) +{ + if (buff_size < OBEX_MIN_PACKET_SIZE || info == NULL || out_pkt == NULL) { + return OBEX_INVALID_PARAM; + } + buff_size += sizeof(BT_HDR) + OBEX_BT_HDR_MIN_OFFSET + OBEX_BT_HDR_RESERVE_LEN; + + BT_HDR *p_buf= (BT_HDR *)osi_malloc(buff_size); + if (p_buf == NULL) { + return OBEX_NO_RESOURCES; + } + + UINT16 pkt_len = OBEX_MIN_PACKET_SIZE; + p_buf->offset = OBEX_BT_HDR_MIN_OFFSET; + /* use layer_specific to store the max data length allowed */ + p_buf->layer_specific = buff_size - sizeof(BT_HDR) - OBEX_BT_HDR_MIN_OFFSET - OBEX_BT_HDR_RESERVE_LEN; + UINT8 *p_data = (UINT8 *)(p_buf + 1) + p_buf->offset; + /* byte 0: response code */ + *p_data++ = info->response_code; + /* byte 1, 2: packet length, skip, we will update at last */ + UINT8 *p_pkt_len = p_data; + p_data += 2; + + /* we need to use opcode to decide the response format */ + switch (info->opcode) + { + case OBEX_OPCODE_CONNECT: + /* byte 3: OBEX version number */ + *p_data++ = info->obex_version_number; + /* byte 4: flags */ + *p_data++ = info->flags; + /* byte 5, 6: maximum OBEX packet length, recommend to set as our mtu */ + UINT16_TO_BE_FIELD(p_data, info->max_packet_length); + pkt_len += 4; + break; + default: + break; + } + + UINT16_TO_BE_FIELD(p_pkt_len, pkt_len); + p_buf->len = pkt_len; + *out_pkt = p_buf; + return OBEX_SUCCESS; +} + +/******************************************************************************* +** +** Function OBEX_AppendHeader +** +** Description Append a header to specific packet, packet can be request +** or response, the format of header must be valid +** +** Returns OBEX_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 OBEX_AppendHeader(BT_HDR *pkt, const UINT8 *header) +{ + if (pkt == NULL || header == NULL) { + return OBEX_INVALID_PARAM; + } + + UINT16 header_len = 0; + UINT8 header_id = *header; + switch (header_id & OBEX_HEADER_ID_U2B_MASK) + { + case OBEX_HEADER_ID_U2B_TYPE1: + case OBEX_HEADER_ID_U2B_TYPE2: + header_len = (header[1] << 8) + header[2]; + break; + case OBEX_HEADER_ID_U2B_TYPE3: + header_len = 2; + break; + case OBEX_HEADER_ID_U2B_TYPE4: + header_len = 5; + break; + default: + break; + } + if (header_len == 0) { + return OBEX_INVALID_PARAM; + } + + if (pkt->layer_specific - pkt->len < header_len) { + /* the packet can not hold this header */ + return OBEX_NO_RESOURCES; + } + UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset; + UINT8 *p_start = p_data + pkt->len; + memcpy(p_start, header, header_len); + pkt->len += header_len; + /* point to packet len */ + p_data++; + UINT16_TO_BE_FIELD(p_data, pkt->len); + return OBEX_SUCCESS; +} + +/******************************************************************************* +** +** Function OBEX_AppendHeaderRaw +** +** Description Append a header to specific packet, packet can be request +** or response, data not include 2 byte length prefixed +** +** Returns OBEX_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 OBEX_AppendHeaderRaw(BT_HDR *pkt, UINT8 header_id, const UINT8 *data, UINT16 data_len) +{ + if (pkt == NULL) { + return OBEX_INVALID_PARAM; + } + + if ((data == NULL && data_len != 0) || (data != NULL && data_len == 0)) { + return OBEX_INVALID_PARAM; + } + + UINT16 header_len = 0; + BOOLEAN store_header_len = FALSE; + switch (header_id & OBEX_HEADER_ID_U2B_MASK) + { + case OBEX_HEADER_ID_U2B_TYPE1: + case OBEX_HEADER_ID_U2B_TYPE2: + /* header id + 2 byte length prefixed + data */ + header_len = data_len + 3; + store_header_len = TRUE; + break; + case OBEX_HEADER_ID_U2B_TYPE3: + header_len = 2; + if (data_len != 1) { + return OBEX_INVALID_PARAM; + } + break; + case OBEX_HEADER_ID_U2B_TYPE4: + header_len = 5; + if (data_len != 4) { + return OBEX_INVALID_PARAM; + } + break; + default: + break; + } + if (header_len == 0) { + return OBEX_INVALID_PARAM; + } + + if (pkt->layer_specific - pkt->len < header_len) { + /* the packet can not hold this header */ + return OBEX_NO_RESOURCES; + } + UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset; + UINT8 *p_start = p_data + pkt->len; + /* store header id */ + *p_start++ = header_id; + if (store_header_len) { + /* store header length */ + UINT16_TO_BE_FIELD(p_start, header_len); + p_start+= 2; + } + if (data != NULL) { + /* store data */ + memcpy(p_start, data, data_len); + } + pkt->len += header_len; + /* point to packet len */ + p_data++; + UINT16_TO_BE_FIELD(p_data, pkt->len); + return OBEX_SUCCESS; +} + +/******************************************************************************* +** +** Function OBEX_AppendHeaderSRM +** +** Description Append a Single Response Mode header +** +** Returns OBEX_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 OBEX_AppendHeaderSRM(BT_HDR *pkt, UINT8 value) +{ + return OBEX_AppendHeaderRaw(pkt, OBEX_HEADER_ID_SRM, &value, 1); +} + +/******************************************************************************* +** +** Function OBEX_AppendHeaderSRMP +** +** Description Append a Single Response Mode Parameters header +** +** Returns OBEX_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 OBEX_AppendHeaderSRMP(BT_HDR *pkt, UINT8 value) +{ + return OBEX_AppendHeaderRaw(pkt, OBEX_HEADER_ID_SRM_PARAM, &value, 1); +} + +/******************************************************************************* +** +** Function OBEX_GetPacketFreeSpace +** +** Description Get the current free space of a packet, use this to check +** if a packet can hold a header +** +** Returns Current free space of a packet, in bytes +** +*******************************************************************************/ +UINT16 OBEX_GetPacketFreeSpace(BT_HDR *pkt) +{ + if (pkt == NULL) { + return 0; + } + return pkt->layer_specific - pkt->len; +} + +/******************************************************************************* +** +** Function OBEX_GetPacketLength +** +** Description Get the current packet length +** +** Returns Current packet length, in bytes +** +*******************************************************************************/ +UINT16 OBEX_GetPacketLength(BT_HDR *pkt) +{ + if (pkt == NULL) { + return 0; + } + return pkt->len; +} + +/******************************************************************************* +** +** Function OBEX_ParseRequest +** +** Description Parse a request packet +** +** Returns OBEX_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 OBEX_ParseRequest(BT_HDR *pkt, tOBEX_PARSE_INFO *info) +{ + if (pkt == NULL || info == NULL) { + return OBEX_INVALID_PARAM; + } + + UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset; + info->opcode = *p_data; + switch (info->opcode) + { + case OBEX_OPCODE_CONNECT: + info->obex_version_number = p_data[3]; + info->flags = p_data[4]; + info->max_packet_length = (p_data[5] << 8) + p_data[6]; + info->next_header_pos = 7; + break; + case OBEX_OPCODE_SETPATH: + info->flags = p_data[3]; + info->next_header_pos = 5; + break; + default: + info->next_header_pos = 3; + break; + } + return OBEX_SUCCESS; +} + +/******************************************************************************* +** +** Function OBEX_ParseResponse +** +** Description Parse a request response packet +** +** Returns OBEX_SUCCESS if successful, otherwise failed +** +*******************************************************************************/ +UINT16 OBEX_ParseResponse(BT_HDR *pkt, UINT8 opcode, tOBEX_PARSE_INFO *info) +{ + if (pkt == NULL || info == NULL) { + return OBEX_INVALID_PARAM; + } + + UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset; + info->opcode = opcode; + info->response_code = *p_data; + switch (opcode) + { + case OBEX_OPCODE_CONNECT: + info->obex_version_number = p_data[3]; + info->flags = p_data[4]; + info->max_packet_length = (p_data[5] << 8) + p_data[6]; + info->next_header_pos = 7; + break; + default: + info->next_header_pos = 3; + break; + } + return OBEX_SUCCESS; +} + +/******************************************************************************* +** +** Function OBEX_CheckFinalBit +** +** Description Check whether a packet had set the final bit +** +** Returns TRUE if final bit set, otherwise, false +** +*******************************************************************************/ +BOOLEAN OBEX_CheckFinalBit(BT_HDR *pkt) +{ + if (pkt == NULL) { + return FALSE; + } + UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset; + return (*p_data) & OBEX_FINAL_BIT_MASK; +} + +/******************************************************************************* +** +** Function OBEX_CheckContinueResponse +** +** Description Check whether a packet is continue response +** +** Returns TRUE if continue response, otherwise, false +** +*******************************************************************************/ +BOOLEAN OBEX_CheckContinueResponse(BT_HDR *pkt) +{ + if (pkt == NULL) { + return FALSE; + } + UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset; + return (*p_data == 0x90) || (*p_data == 0x10); +} + +/******************************************************************************* +** +** Function OBEX_GetHeaderLength +** +** Description Get header length +** +** Returns header length +** +*******************************************************************************/ +UINT16 OBEX_GetHeaderLength(UINT8 *header) +{ + UINT16 header_len = 0; + UINT8 header_id = *header; + switch (header_id & OBEX_HEADER_ID_U2B_MASK) + { + case OBEX_HEADER_ID_U2B_TYPE1: + case OBEX_HEADER_ID_U2B_TYPE2: + header_len = (header[1] << 8) + header[2]; + break; + case OBEX_HEADER_ID_U2B_TYPE3: + header_len = 2; + break; + case OBEX_HEADER_ID_U2B_TYPE4: + header_len = 5; + break; + default: + /* unreachable */ + break; + } + return header_len; +} + +/******************************************************************************* +** +** Function OBEX_GetNextHeader +** +** Description Get next header pointer from a packet +** +** Returns Pointer to start address of a header, NULL if no more header +** or failed +** +*******************************************************************************/ +UINT8 *OBEX_GetNextHeader(BT_HDR *pkt, tOBEX_PARSE_INFO *info) +{ + if (pkt == NULL || info == NULL) { + return NULL; + } + UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset; + if (info->next_header_pos == 0 || info->next_header_pos >= pkt->len) { + return NULL; + } + UINT8 *header = p_data + info->next_header_pos; + UINT16 header_len = OBEX_GetHeaderLength(header); + info->next_header_pos += header_len; + return header; +} + +#endif /* #if (OBEX_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/stack/obex/obex_main.c b/lib/bt/host/bluedroid/stack/obex/obex_main.c new file mode 100644 index 00000000..7810ff3c --- /dev/null +++ b/lib/bt/host/bluedroid/stack/obex/obex_main.c @@ -0,0 +1,216 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "osi/osi.h" +#include "osi/allocator.h" +#include "common/bt_target.h" + +#include "stack/obex_api.h" +#include "obex_int.h" +#include "obex_tl.h" + +#if (OBEX_INCLUDED == TRUE) + +#if OBEX_DYNAMIC_MEMORY == FALSE +tOBEX_CB obex_cb; +#else +tOBEX_CB *obex_cb_ptr = NULL; +#endif + +static tOBEX_CCB *obex_find_ccb_by_tl_hdl(UINT8 tl, UINT16 tl_hdl) +{ + tOBEX_CCB *p_ccb = NULL; + for (int i = 0; i < OBEX_MAX_CONNECTION; ++i) { + if (obex_cb.ccb[i].allocated && obex_cb.ccb[i].tl == tl && obex_cb.ccb[i].tl_hdl == tl_hdl) { + p_ccb = &obex_cb.ccb[i]; + break; + } + } + return p_ccb; +} + +static tOBEX_SCB *obex_find_scb_by_tl_hdl(UINT8 tl, UINT16 tl_hdl) +{ + tOBEX_SCB *p_scb = NULL; + for (int i = 0; i < OBEX_MAX_SERVER; ++i) { + if (obex_cb.scb[i].allocated && obex_cb.scb[i].tl == tl && obex_cb.scb[i].tl_hdl == tl_hdl) { + p_scb = &obex_cb.scb[i]; + break; + } + } + return p_scb; +} + +tOBEX_CCB *obex_allocate_ccb(void) +{ + tOBEX_CCB *p_ccb = NULL; + for (int i = 0; i < OBEX_MAX_CONNECTION; ++i) { + if (!obex_cb.ccb[i].allocated) { + obex_cb.ccb[i].allocated = i + 1; + p_ccb = &obex_cb.ccb[i]; + break; + } + } + return p_ccb; +} + +void obex_free_ccb(tOBEX_CCB *p_ccb) +{ + assert(p_ccb->allocated != 0); + memset(p_ccb, 0, sizeof(tOBEX_CCB)); +} + +tOBEX_SCB *obex_allocate_scb(void) +{ + tOBEX_SCB *p_scb = NULL; + for (int i = 0; i < OBEX_MAX_SERVER; ++i) { + if (!obex_cb.scb[i].allocated) { + obex_cb.scb[i].allocated = i + 1; + p_scb = &obex_cb.scb[i]; + break; + } + } + return p_scb; +} + +void obex_free_scb(tOBEX_SCB *p_scb) +{ + assert(p_scb->allocated != 0); + memset(p_scb, 0, sizeof(tOBEX_SCB)); +} + +/* check whether connection mtu is valid, if not, disconnect it */ +static bool check_conn_mtu_valid(tOBEX_CCB *p_ccb, BOOLEAN call_cb) +{ + if (p_ccb->tl_our_mtu < 255 || p_ccb->tl_peer_mtu < 255) { + if (call_cb && p_ccb->callback) { + p_ccb->callback(p_ccb->allocated, OBEX_DISCONNECT_EVT, NULL); + } + OBEX_TRACE_ERROR("Check OBEX transport layer MTU failed, disconnect"); + obex_cb.tl_ops[p_ccb->tl]->disconnect(p_ccb->tl_hdl); + obex_free_ccb(p_ccb); + return false; + } + return true; +} + +void obex_tl_evt_handler(UINT8 tl, tOBEX_TL_EVT evt, tOBEX_TL_MSG *msg) +{ + UINT16 tl_hdl = msg->any.hdl; + tOBEX_CCB *p_ccb = obex_find_ccb_by_tl_hdl(tl, tl_hdl); + tOBEX_SCB *p_scb = NULL; + tOBEX_MSG cb_msg = {0}; + + switch (evt) + { + case OBEX_TL_CONN_OPEN_EVT: + assert(p_ccb != NULL); + p_ccb->tl_peer_mtu = msg->conn_open.peer_mtu; + p_ccb->tl_our_mtu = msg->conn_open.our_mtu; + if (!check_conn_mtu_valid(p_ccb, TRUE)) { + break; + } + p_ccb->state = OBEX_STATE_OPENED; + if (p_ccb->callback) { + cb_msg.connect.peer_mtu = msg->conn_open.peer_mtu; + cb_msg.connect.our_mtu = msg->conn_open.our_mtu; + p_ccb->callback(p_ccb->allocated, OBEX_CONNECT_EVT, &cb_msg); + } + break; + case OBEX_TL_DIS_CONN_EVT: + if (p_ccb != NULL) { + if (p_ccb->callback) { + p_ccb->callback(p_ccb->allocated, OBEX_DISCONNECT_EVT, NULL); + } + obex_free_ccb(p_ccb); + } + break; + case OBEX_TL_CONGEST_EVT: + assert(p_ccb != NULL); + if (p_ccb->callback) { + p_ccb->callback(p_ccb->allocated, OBEX_CONGEST_EVT, NULL); + } + break; + case OBEX_TL_UNCONGEST_EVT: + assert(p_ccb != NULL); + if (p_ccb->callback) { + p_ccb->callback(p_ccb->allocated, OBEX_UNCONGEST_EVT, NULL); + } + break; + case OBEX_TL_MTU_CHANGE_EVT: + assert(p_ccb != NULL); + p_ccb->tl_peer_mtu = msg->mtu_chg.peer_mtu; + p_ccb->tl_our_mtu = msg->mtu_chg.our_mtu; + if (!check_conn_mtu_valid(p_ccb, TRUE)) { + break; + } + if (p_ccb->callback) { + cb_msg.mtu_change.peer_mtu = msg->mtu_chg.peer_mtu; + cb_msg.mtu_change.our_mtu = msg->mtu_chg.our_mtu; + p_ccb->callback(p_ccb->allocated, OBEX_MTU_CHANGE_EVT, &cb_msg); + } + break; + case OBEX_TL_DATA_EVT: + assert(p_ccb != NULL); + if (p_ccb->callback) { + cb_msg.data.pkt = msg->data.p_buf; + p_ccb->callback(p_ccb->allocated, OBEX_DATA_EVT, &cb_msg); + } + else { + /* No callback, just free the packet */ + osi_free(msg->data.p_buf); + } + break; + case OBEX_TL_CONN_INCOME_EVT: + /* New connection, p_ccb should be NULL */ + assert(p_ccb == NULL); + p_scb = obex_find_scb_by_tl_hdl(tl, msg->conn_income.svr_hdl); + if (p_scb == NULL) { + obex_cb.tl_ops[tl]->disconnect(tl_hdl); + break; + } + + if ((p_ccb = obex_allocate_ccb()) == NULL) { + obex_cb.tl_ops[tl]->disconnect(tl_hdl); + break; + } + + p_ccb->tl = tl; + p_ccb->tl_hdl = tl_hdl; + p_ccb->role = OBEX_ROLE_SERVER; + p_ccb->tl_peer_mtu = msg->conn_income.peer_mtu; + p_ccb->tl_our_mtu = msg->conn_income.our_mtu; + if (!check_conn_mtu_valid(p_ccb, FALSE)) { + break; + } + p_ccb->state = OBEX_STATE_OPENED; + p_ccb->callback = p_scb->callback; + if (p_ccb->callback) { + cb_msg.conn_income.svr_handle = p_scb->allocated << 8; + cb_msg.conn_income.peer_mtu = msg->conn_income.peer_mtu; + cb_msg.conn_income.our_mtu = msg->conn_income.our_mtu; + p_ccb->callback(p_ccb->allocated, OBEX_CONN_INCOME_EVT, &cb_msg); + } + break; + default: + OBEX_TRACE_ERROR("Unknown OBEX transport event: 0x%x\n", evt); + break; + } +} + +void obex_tl_l2cap_callback(tOBEX_TL_EVT evt, tOBEX_TL_MSG *msg) +{ + obex_tl_evt_handler(OBEX_OVER_L2CAP, evt, msg); +} + +void obex_tl_rfcomm_callback(tOBEX_TL_EVT evt, tOBEX_TL_MSG *msg) +{ + obex_tl_evt_handler(OBEX_OVER_RFCOMM, evt, msg); +} + +#endif /* #if (OBEX_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/stack/obex/obex_tl_l2cap.c b/lib/bt/host/bluedroid/stack/obex/obex_tl_l2cap.c new file mode 100644 index 00000000..d509b4cf --- /dev/null +++ b/lib/bt/host/bluedroid/stack/obex/obex_tl_l2cap.c @@ -0,0 +1,811 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "osi/osi.h" +#include "osi/allocator.h" +#include "common/bt_target.h" + +#include "stack/l2c_api.h" +#include "stack/l2cdefs.h" +#include "stack/btm_api.h" +#include "btm_int.h" +#include "obex_tl.h" +#include "obex_tl_l2cap.h" + +#if (OBEX_INCLUDED == TRUE) + +#define OBEX_TL_L2CAP_NUM_CONN 4 +#define OBEX_TL_L2CAP_NUM_SERVER 2 + +#define OBEX_TL_L2CAP_STATUS_FLAG_CFG_DONE 0x01 +#define OBEX_TL_L2CAP_STATUS_FLAG_PEER_CFG_DONE 0x02 +#define OBEX_TL_L2CAP_STATUS_FLAG_CONNECTED 0x80 + +/* ERTM Tx window size */ +#define OBEX_TL_L2CAP_FCR_OPT_TX_WINDOW_SIZE 10 + +/* ERTM Maximum transmissions before disconnecting */ +#define OBEX_TL_L2CAP_FCR_OPT_MAX_TX_B4_DISCNT 20 + +/* ERTM Retransmission timeout (2 secs) */ +#define OBEX_TL_L2CAP_FCR_OPT_RETX_TOUT 2000 + +/* ERTM Monitor timeout (12 secs) */ +#define OBEX_TL_L2CAP_FCR_OPT_MONITOR_TOUT 12000 + +/* ERTM ERTM MPS segment size */ +#define OBEX_TL_L2CAP_FCR_OPT_MAX_PDU_SIZE 1010 + +typedef struct { + UINT16 vpsm; /* psm in our side */ + UINT16 lcid; /* local channel id */ + UINT16 peer_mtu; /* MTU that peer device set */ + UINT16 our_mtu; /* MTU that we set to peer device */ + BOOLEAN initiator; /* TRUE if is initiator, otherwise FALSE */ + UINT8 id; /* remote channel id */ + UINT8 status_flag; /* status flag used in config procedure */ + UINT8 allocated; /* 0 if not allocated, otherwise, index + 1, equal to handle */ + BD_ADDR addr; /* peer bluetooth device address */ +} tOBEX_TL_L2CAP_CCB; + +typedef struct { + UINT16 psm; /* psm in our side */ + UINT16 pref_mtu; /* preferred mtu */ + UINT8 allocated; /* 0 if not allocated, otherwise, index + 1, handle of server will left shift 8 bits */ +} tOBEX_TL_L2CAP_SCB; + +typedef struct { + tOBEX_TL_CBACK *callback; /* Upper layer callback */ + tOBEX_TL_L2CAP_CCB ccb[OBEX_TL_L2CAP_NUM_CONN]; + tOBEX_TL_L2CAP_SCB scb[OBEX_TL_L2CAP_NUM_SERVER]; + tL2CAP_APPL_INFO l2cap_reg_info; /* Default L2CAP Registration info */ + UINT8 trace_level; /* trace level */ +} tOBEX_TL_L2CAP_CB; + +#if OBEX_DYNAMIC_MEMORY == FALSE +static tOBEX_TL_L2CAP_CB obex_tl_l2cap_cb; +#else +static tOBEX_TL_L2CAP_CB *obex_tl_l2cap_cb_ptr = NULL; +#define obex_tl_l2cap_cb (*obex_tl_l2cap_cb_ptr) +#endif + +static tL2CAP_ERTM_INFO obex_tl_l2cap_etm_opts = +{ + L2CAP_FCR_ERTM_MODE, + L2CAP_FCR_CHAN_OPT_ERTM | L2CAP_FCR_CHAN_OPT_BASIC, /* Some devices do not support ERTM */ + L2CAP_USER_RX_BUF_SIZE, + L2CAP_USER_TX_BUF_SIZE, + L2CAP_FCR_RX_BUF_SIZE, + L2CAP_FCR_TX_BUF_SIZE +}; + +static tL2CAP_FCR_OPTS obex_tl_l2cap_fcr_opts = +{ + L2CAP_FCR_ERTM_MODE, + OBEX_TL_L2CAP_FCR_OPT_TX_WINDOW_SIZE, /* Tx window size */ + OBEX_TL_L2CAP_FCR_OPT_MAX_TX_B4_DISCNT, /* Maximum transmissions before disconnecting */ + OBEX_TL_L2CAP_FCR_OPT_RETX_TOUT, /* Retransmission timeout (2 secs) */ + OBEX_TL_L2CAP_FCR_OPT_MONITOR_TOUT, /* Monitor timeout (12 secs) */ + OBEX_TL_L2CAP_FCR_OPT_MAX_PDU_SIZE /* MPS segment size */ +}; + +static tOBEX_TL_L2CAP_CCB *allocate_ccb(void) +{ + tOBEX_TL_L2CAP_CCB *p_ccb = NULL; + for(int i = 0; i < OBEX_TL_L2CAP_NUM_CONN; ++i) { + if (obex_tl_l2cap_cb.ccb[i].allocated == 0) { + obex_tl_l2cap_cb.ccb[i].allocated = i + 1; + p_ccb = &obex_tl_l2cap_cb.ccb[i]; + break; + } + } + return p_ccb; +} + +static void free_ccb(tOBEX_TL_L2CAP_CCB *p_ccb) +{ + memset(p_ccb, 0, sizeof(tOBEX_TL_L2CAP_CCB)); +} + +static tOBEX_TL_L2CAP_CCB *find_ccb_by_lcid(UINT16 lcid) +{ + tOBEX_TL_L2CAP_CCB *p_ccb = NULL; + for (int i = 0; i < OBEX_TL_L2CAP_NUM_CONN; ++i) { + if (obex_tl_l2cap_cb.ccb[i].allocated && obex_tl_l2cap_cb.ccb[i].lcid == lcid) { + p_ccb = &obex_tl_l2cap_cb.ccb[i]; + break; + } + } + return p_ccb; +} + +static tOBEX_TL_L2CAP_CCB *find_ccb_by_hdl(UINT16 hdl) +{ + tOBEX_TL_L2CAP_CCB *p_ccb = NULL; + if (hdl > 0 && hdl <= OBEX_TL_L2CAP_NUM_CONN) { + if (obex_tl_l2cap_cb.ccb[hdl-1].allocated == hdl) { + p_ccb = &obex_tl_l2cap_cb.ccb[hdl-1]; + } + } + return p_ccb; +} + +static tOBEX_TL_L2CAP_CCB *find_ccb_by_psm(UINT16 psm) +{ + tOBEX_TL_L2CAP_CCB *p_ccb = NULL; + for(int i = 0; i < OBEX_TL_L2CAP_NUM_CONN; ++i) { + if (obex_tl_l2cap_cb.ccb[i].allocated && obex_tl_l2cap_cb.ccb[i].vpsm == psm) { + p_ccb = &obex_tl_l2cap_cb.ccb[i]; + break; + } + } + return p_ccb; +} + +static tOBEX_TL_L2CAP_SCB *allocate_scb(void) +{ + tOBEX_TL_L2CAP_SCB *p_scb = NULL; + for(int i = 0; i < OBEX_TL_L2CAP_NUM_SERVER; ++i) { + if (obex_tl_l2cap_cb.scb[i].allocated == 0) { + obex_tl_l2cap_cb.scb[i].allocated = i + 1; + p_scb = &obex_tl_l2cap_cb.scb[i]; + break; + } + } + return p_scb; +} + +static tOBEX_TL_L2CAP_SCB *find_scb_by_psm(UINT16 psm) +{ + tOBEX_TL_L2CAP_SCB *p_scb = NULL; + for(int i = 0; i < OBEX_TL_L2CAP_NUM_SERVER; ++i) { + if (obex_tl_l2cap_cb.scb[i].allocated && obex_tl_l2cap_cb.scb[i].psm == psm) { + p_scb = &obex_tl_l2cap_cb.scb[i]; + break; + } + } + return p_scb; +} + +static void free_scb(tOBEX_TL_L2CAP_SCB *p_scb) +{ + memset(p_scb, 0, sizeof(tOBEX_TL_L2CAP_SCB)); +} + +static tOBEX_TL_L2CAP_SCB *find_scb_by_hdl(UINT16 hdl) +{ + tOBEX_TL_L2CAP_SCB *p_scb = NULL; + hdl = hdl >> 8; + if (hdl > 0 && hdl <= OBEX_TL_L2CAP_NUM_SERVER) { + if (obex_tl_l2cap_cb.scb[hdl-1].allocated == hdl) { + p_scb = &obex_tl_l2cap_cb.scb[hdl-1]; + } + } + return p_scb; +} + +/******************************************************************************* + * + * Function obex_tl_l2cap_sec_check_complete_term + * + * Description OBEX over L2CAP security check complete callback function + * (terminated). + * + ******************************************************************************/ +static void l2cap_sec_check_complete_term(BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, UINT8 res) +{ + tOBEX_TL_L2CAP_CCB *p_ccb = (tOBEX_TL_L2CAP_CCB *)p_ref_data; + + if (res == BTM_SUCCESS) { + L2CA_ErtmConnectRsp(p_ccb->addr, p_ccb->id, p_ccb->lcid, L2CAP_CONN_OK, 0, &obex_tl_l2cap_etm_opts); + tL2CAP_CFG_INFO cfg = {0}; + cfg.mtu_present = TRUE; + cfg.mtu = p_ccb->our_mtu; + cfg.fcr_present = TRUE; + cfg.fcr = obex_tl_l2cap_fcr_opts; + L2CA_ConfigReq(p_ccb->lcid, &cfg); + } + else{ + L2CA_ErtmConnectRsp(p_ccb->addr, p_ccb->id, p_ccb->lcid, L2CAP_CONN_SECURITY_BLOCK, 0, &obex_tl_l2cap_etm_opts); + tOBEX_TL_MSG msg = {0}; + msg.any.hdl = p_ccb->allocated; + obex_tl_l2cap_cb.callback(OBEX_TL_DIS_CONN_EVT, &msg); + free_ccb(p_ccb); + } +} + +/******************************************************************************* + * + * Function obex_tl_l2cap_sec_check_complete_orig + * + * Description OBEX over L2CAP security check complete callback function + * (originated). + * + ******************************************************************************/ +static void l2cap_sec_check_complete_orig(BD_ADDR bd_addr, tBT_TRANSPORT transport, void *p_ref_data, UINT8 res) +{ + tOBEX_TL_L2CAP_CCB *p_ccb = (tOBEX_TL_L2CAP_CCB *)p_ref_data; + + if (res == BTM_SUCCESS) { + tL2CAP_CFG_INFO cfg = {0}; + cfg.mtu_present = TRUE; + cfg.mtu = p_ccb->our_mtu; + cfg.fcr_present = TRUE; + cfg.fcr = obex_tl_l2cap_fcr_opts; + L2CA_ConfigReq(p_ccb->lcid, &cfg); + } else { + L2CA_DisconnectReq(p_ccb->lcid); + tOBEX_TL_MSG msg = {0}; + msg.any.hdl = p_ccb->allocated; + obex_tl_l2cap_cb.callback(OBEX_TL_DIS_CONN_EVT, &msg); + free_ccb(p_ccb); + } +} + +/******************************************************************************* +** +** Function obex_tl_l2cap_connect_ind +** +** Description This is a callback function called by L2CAP when +** L2CA_ConnectInd received. +** +*******************************************************************************/ +void obex_tl_l2cap_connect_ind(BD_ADDR addr, UINT16 lcid, UINT16 psm, UINT8 id) +{ + tOBEX_TL_L2CAP_SCB *p_scb = find_scb_by_psm(psm); + if (p_scb == NULL) { + /* An incoming connection, but no corresponding server found, reject */ + L2CA_ErtmConnectRsp (addr, id, lcid, L2CAP_CONN_NO_PSM, 0, &obex_tl_l2cap_etm_opts); + OBEX_TL_L2CAP_TRACE_WARNING("No corresponding server found, reject incoming connection\n"); + return; + } + + tOBEX_TL_L2CAP_CCB *p_ccb = allocate_ccb(); + if (p_ccb == NULL) { + /* No resource, can not allocate ccb, reject */ + L2CA_ErtmConnectRsp (addr, id, lcid, L2CAP_CONN_NO_RESOURCES, 0, &obex_tl_l2cap_etm_opts); + OBEX_TL_L2CAP_TRACE_WARNING("Can not allocate a ccb for new connection\n"); + return; + } + + bdcpy(p_ccb->addr, addr); + p_ccb->initiator = FALSE; + p_ccb->lcid = lcid; + p_ccb->id = id; + p_ccb->vpsm = psm; + p_ccb->our_mtu = p_scb->pref_mtu; + if (btm_sec_mx_access_request(p_ccb->addr, p_ccb->vpsm, + FALSE, BTM_SEC_PROTO_OBEX, + OBEX_TL_L2CAP_NUM_CONN + p_scb->allocated - 1, + &l2cap_sec_check_complete_term, p_ccb) == BTM_CMD_STARTED) { + L2CA_ErtmConnectRsp(addr, id, lcid, L2CAP_CONN_PENDING, 0, &obex_tl_l2cap_etm_opts); + } +} + +/******************************************************************************* +** +** Function obex_tl_l2cap_connect_cfm +** +** Description This is a callback function called by L2CAP when +** ConnectCfm received. +** +*******************************************************************************/ +void obex_tl_l2cap_connect_cfm(UINT16 lcid, UINT16 result) +{ + tOBEX_TL_L2CAP_CCB *p_ccb = find_ccb_by_lcid(lcid); + if (p_ccb == NULL) { + OBEX_TL_L2CAP_TRACE_ERROR("l2cap_connect_cfm but no ccb found\n"); + return; + } + + if (result == L2CAP_CONN_OK) { + btm_sec_mx_access_request(p_ccb->addr, p_ccb->vpsm, + TRUE, BTM_SEC_PROTO_OBEX, + p_ccb->allocated - 1, + &l2cap_sec_check_complete_orig, p_ccb); + } else { + OBEX_TL_L2CAP_TRACE_WARNING("l2cap_connect_cfm result != L2CAP_CONN_OK: result: 0x%x\n", result); + tOBEX_TL_MSG msg = {0}; + msg.any.hdl = p_ccb->allocated; + obex_tl_l2cap_cb.callback(OBEX_TL_DIS_CONN_EVT, &msg); + free_ccb(p_ccb); + } +} + + +/******************************************************************************* +** +** Function obex_tl_l2cap_config_ind +** +** Description This is a callback function called by L2CAP when +** L2CA_ConfigInd received. +** +*******************************************************************************/ +void obex_tl_l2cap_config_ind(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg) +{ + tOBEX_TL_L2CAP_CCB *p_ccb = find_ccb_by_lcid(lcid); + if (p_ccb == NULL) { + OBEX_TL_L2CAP_TRACE_ERROR("l2cap_config_ind but no ccb found\n"); + return; + } + + tOBEX_TL_L2CAP_SCB *p_scb = find_scb_by_psm(p_ccb->vpsm); + if (p_ccb->initiator == FALSE && p_scb == NULL) { + /* not a initiator, but can not find corresponding server */ + OBEX_TL_L2CAP_TRACE_ERROR("l2cap_config_ind, not a initiator, but can not find corresponding server\n"); + return; + } + + /* save peer mtu if present */ + UINT16 peer_mtu = L2CAP_DEFAULT_MTU; + if (p_cfg->mtu_present) { + peer_mtu = p_cfg->mtu; + } + + p_cfg->mtu_present = FALSE; + p_cfg->flush_to_present = FALSE; + p_cfg->qos_present = FALSE; + p_cfg->result = L2CAP_CFG_OK; + L2CA_ConfigRsp(p_ccb->lcid, p_cfg); + + if (p_ccb->status_flag & OBEX_TL_L2CAP_STATUS_FLAG_CONNECTED) { + /* reconfig l2cap channel */ + if (p_ccb->peer_mtu != peer_mtu) { + /* only report to upper if mtu change */ + p_ccb->peer_mtu = peer_mtu; + tOBEX_TL_MSG msg = {0}; + msg.mtu_chg.hdl = p_ccb->allocated; + msg.mtu_chg.peer_mtu = peer_mtu; + msg.mtu_chg.our_mtu = p_ccb->our_mtu; + obex_tl_l2cap_cb.callback(OBEX_TL_MTU_CHANGE_EVT, &msg); + } + return; + } + + p_ccb->peer_mtu = peer_mtu; + p_ccb->status_flag |= OBEX_TL_L2CAP_STATUS_FLAG_PEER_CFG_DONE; + if (p_ccb->status_flag & OBEX_TL_L2CAP_STATUS_FLAG_CFG_DONE) { + p_ccb->status_flag |= OBEX_TL_L2CAP_STATUS_FLAG_CONNECTED; + } + + if ((p_ccb->status_flag & OBEX_TL_L2CAP_STATUS_FLAG_CONNECTED)) { + tOBEX_TL_MSG msg = {0}; + if (p_ccb->initiator) { + msg.conn_open.hdl = p_ccb->allocated; + msg.conn_open.peer_mtu = p_ccb->peer_mtu; + msg.conn_open.our_mtu = p_ccb->our_mtu; + obex_tl_l2cap_cb.callback(OBEX_TL_CONN_OPEN_EVT, &msg); + } + else { + msg.conn_income.hdl = p_ccb->allocated; + msg.conn_income.peer_mtu = p_ccb->peer_mtu; + msg.conn_income.our_mtu = p_ccb->our_mtu; + msg.conn_income.svr_hdl = p_scb->allocated << 8; + obex_tl_l2cap_cb.callback(OBEX_TL_CONN_INCOME_EVT, &msg); + } + } +} + + +/******************************************************************************* +** +** Function obex_tl_l2cap_config_cfm +** +** Description This is a callback function called by L2CAP when +** L2CA_ConfigCnf received. +** +*******************************************************************************/ +void obex_tl_l2cap_config_cfm(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg) +{ + tOBEX_TL_L2CAP_CCB *p_ccb = find_ccb_by_lcid(lcid); + if (p_ccb == NULL) { + OBEX_TL_L2CAP_TRACE_ERROR("l2cap_config_cfm but no ccb found\n"); + return; + } + + tOBEX_TL_L2CAP_SCB *p_scb = find_scb_by_psm(p_ccb->vpsm); + if (p_ccb->initiator == FALSE && p_scb == NULL) { + /* not a initiator, but can not find corresponding server */ + OBEX_TL_L2CAP_TRACE_ERROR("l2cap_config_cfm, not a initiator, but can not find corresponding server\n"); + return; + } + + if (p_cfg->result != L2CAP_CFG_OK) { + OBEX_TL_L2CAP_TRACE_WARNING("l2cap_config_cfm result != L2CAP_CFG_OK: result: 0x%x\n", p_cfg->result); + L2CA_DisconnectReq(p_ccb->lcid); + tOBEX_TL_MSG msg = {0}; + msg.any.hdl = p_ccb->allocated; + obex_tl_l2cap_cb.callback(OBEX_TL_DIS_CONN_EVT, &msg); + free_ccb(p_ccb); + return; + } + + p_ccb->status_flag |= OBEX_TL_L2CAP_STATUS_FLAG_CFG_DONE; + if (p_ccb->status_flag & OBEX_TL_L2CAP_STATUS_FLAG_PEER_CFG_DONE) { + p_ccb->status_flag |= OBEX_TL_L2CAP_STATUS_FLAG_CONNECTED; + } + + if (p_ccb->status_flag & OBEX_TL_L2CAP_STATUS_FLAG_CONNECTED) { + tOBEX_TL_MSG msg = {0}; + if (p_ccb->initiator) { + msg.conn_open.hdl = p_ccb->allocated; + msg.conn_open.peer_mtu = p_ccb->peer_mtu; + msg.conn_open.our_mtu = p_ccb->our_mtu; + obex_tl_l2cap_cb.callback(OBEX_TL_CONN_OPEN_EVT, &msg); + } + else { + msg.conn_income.hdl = p_ccb->allocated; + msg.conn_income.peer_mtu = p_ccb->peer_mtu; + msg.conn_income.our_mtu = p_ccb->our_mtu; + msg.conn_income.svr_hdl = p_scb->allocated << 8; + obex_tl_l2cap_cb.callback(OBEX_TL_CONN_INCOME_EVT, &msg); + } + } +} + + +/******************************************************************************* +** +** Function obex_tl_l2cap_qos_violation_ind +** +** Description This is a callback function called by L2CAP when +** L2CA_QoSViolationIndInd received. +** +*******************************************************************************/ +void obex_tl_l2cap_qos_violation_ind(BD_ADDR addr) +{ + UNUSED(addr); +} + + +/******************************************************************************* +** +** Function obex_tl_l2cap_disconnect_ind +** +** Description This is a callback function called by L2CAP when +** L2CA_DisconnectInd received. +** +*******************************************************************************/ +void obex_tl_l2cap_disconnect_ind(UINT16 lcid, BOOLEAN is_conf_needed) +{ + tOBEX_TL_L2CAP_CCB *p_ccb = find_ccb_by_lcid(lcid); + + if (is_conf_needed) { + L2CA_DisconnectRsp(lcid); + } + + if (p_ccb == NULL) { + OBEX_TL_L2CAP_TRACE_ERROR("l2cap_disconnect_ind but no ccb found\n"); + return; + } + + if (p_ccb->initiator && find_scb_by_psm(p_ccb->vpsm) == NULL) { + L2CA_Deregister(p_ccb->vpsm); + } + + tOBEX_TL_MSG msg = {0}; + msg.any.hdl = p_ccb->allocated; + obex_tl_l2cap_cb.callback(OBEX_TL_DIS_CONN_EVT, &msg); + free_ccb(p_ccb); +} + + +/******************************************************************************* +** +** Function obex_tl_l2cap_buf_data_ind +** +** Description This is a callback function called by L2CAP when +** data frame is received. +** +*******************************************************************************/ +void obex_tl_l2cap_buf_data_ind(UINT16 lcid, BT_HDR *p_buf) +{ + tOBEX_TL_L2CAP_CCB *p_ccb = find_ccb_by_lcid(lcid); + if (p_ccb == NULL) { + OBEX_TL_L2CAP_TRACE_ERROR("l2cap_buf_data_ind but no ccb found\n"); + osi_free(p_buf); + return; + } + + tOBEX_TL_MSG msg = {0}; + msg.data.hdl = p_ccb->allocated; + msg.data.p_buf = p_buf; + obex_tl_l2cap_cb.callback(OBEX_TL_DATA_EVT, &msg); +} + +/******************************************************************************* +** +** Function obex_tl_l2cap_congestion_status_ind +** +** Description This is a callback function called by L2CAP when +** L2CAP channel congestion status changes +** +*******************************************************************************/ +void obex_tl_l2cap_congestion_status_ind(UINT16 lcid, BOOLEAN is_congested) +{ + tOBEX_TL_L2CAP_CCB *p_ccb = find_ccb_by_lcid(lcid); + + if (p_ccb == NULL) { + OBEX_TL_L2CAP_TRACE_ERROR("l2cap_congestion_status_ind but no ccb found\n"); + return; + } + + tOBEX_TL_MSG msg = {0}; + msg.any.hdl = p_ccb->allocated; + if (is_congested) { + obex_tl_l2cap_cb.callback(OBEX_TL_CONGEST_EVT, &msg); + } + else { + obex_tl_l2cap_cb.callback(OBEX_TL_UNCONGEST_EVT, &msg); + } +} + +/******************************************************************************* +** +** Function obex_tl_l2cap_init +** +** Description Initialize OBEX over L2CAP transport layer, callback +** can not be NULL, must be called once before using any +** other APIs +** +*******************************************************************************/ +void obex_tl_l2cap_init(tOBEX_TL_CBACK callback) +{ + assert(callback != NULL); +#if (OBEX_DYNAMIC_MEMORY) + if (!obex_tl_l2cap_cb_ptr) { + obex_tl_l2cap_cb_ptr = (tOBEX_TL_L2CAP_CB *)osi_malloc(sizeof(tOBEX_TL_L2CAP_CB)); + if (!obex_tl_l2cap_cb_ptr) { + OBEX_TL_L2CAP_TRACE_ERROR("OBEX over L2CAP transport layer initialize failed, no memory\n"); + assert(0); + } + } +#endif /* #if (OBEX_DYNAMIC_MEMORY) */ + memset(&obex_tl_l2cap_cb, 0, sizeof(tOBEX_TL_L2CAP_CB)); + obex_tl_l2cap_cb.callback = callback; + obex_tl_l2cap_cb.trace_level = BT_TRACE_LEVEL_ERROR; + + tL2CAP_APPL_INFO *p_reg_info = &obex_tl_l2cap_cb.l2cap_reg_info; + + p_reg_info->pL2CA_ConnectInd_Cb = NULL; /* obex_tl_l2cap_connect_ind or NULL, depend on server or not */ + p_reg_info->pL2CA_ConnectCfm_Cb = obex_tl_l2cap_connect_cfm; + p_reg_info->pL2CA_ConnectPnd_Cb = NULL; + p_reg_info->pL2CA_ConfigInd_Cb = obex_tl_l2cap_config_ind; + p_reg_info->pL2CA_ConfigCfm_Cb = obex_tl_l2cap_config_cfm; + p_reg_info->pL2CA_DisconnectInd_Cb = obex_tl_l2cap_disconnect_ind; + p_reg_info->pL2CA_DisconnectCfm_Cb = NULL; + p_reg_info->pL2CA_QoSViolationInd_Cb = obex_tl_l2cap_qos_violation_ind; + p_reg_info->pL2CA_DataInd_Cb = obex_tl_l2cap_buf_data_ind; + p_reg_info->pL2CA_CongestionStatus_Cb = obex_tl_l2cap_congestion_status_ind; + p_reg_info->pL2CA_TxComplete_Cb = NULL; +} + +/******************************************************************************* +** +** Function obex_tl_l2cap_init +** +** Description Deinitialize OBEX over L2CAP transport layer +** +*******************************************************************************/ +void obex_tl_l2cap_deinit(void) +{ +#if (OBEX_DYNAMIC_MEMORY) + if (obex_tl_l2cap_cb_ptr) { + osi_free(obex_tl_l2cap_cb_ptr); + obex_tl_l2cap_cb_ptr = NULL; + } +#endif /* #if (OBEX_DYNAMIC_MEMORY) */ +} + +/******************************************************************************* +** +** Function obex_tl_l2cap_connect +** +** Description Start the process of establishing a L2CAP connection +** +** Returns Non-zeros handle, 0 while failed +** +*******************************************************************************/ +UINT16 obex_tl_l2cap_connect(tOBEX_TL_SVR_INFO *server) +{ + tOBEX_TL_L2CAP_CCB *p_ccb = allocate_ccb(); + if (p_ccb == NULL) { + /* can not allocate a ccb */ + return 0; + } + + if (find_scb_by_psm(server->l2cap.psm) == NULL) { + /* if the psm not register by a server, we register it as outgoing only record */ + tL2CAP_APPL_INFO *p_reg_info = &obex_tl_l2cap_cb.l2cap_reg_info; + p_reg_info->pL2CA_ConnectInd_Cb = NULL; + p_ccb->vpsm = L2CA_Register(server->l2cap.psm, p_reg_info); + if (p_ccb->vpsm == 0) { + free_ccb(p_ccb); + return 0; + } + /* set security level */ + BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_OBEX, server->l2cap.sec_mask, p_ccb->vpsm, BTM_SEC_PROTO_OBEX, p_ccb->allocated - 1); + } + else { + p_ccb->vpsm = server->l2cap.psm; + } + + if (server->l2cap.pref_mtu == 0 || server->l2cap.pref_mtu > L2CAP_MTU_SIZE) { + p_ccb->our_mtu = L2CAP_MTU_SIZE; + } + else { + p_ccb->our_mtu = server->l2cap.pref_mtu; + } + p_ccb->initiator = TRUE; + p_ccb->lcid = L2CA_ErtmConnectReq(p_ccb->vpsm, server->l2cap.addr, &obex_tl_l2cap_etm_opts); + if (p_ccb->lcid == 0) { + free_ccb(p_ccb); + return 0; + } + + return p_ccb->allocated; +} + +/******************************************************************************* +** +** Function obex_tl_l2cap_disconnect +** +** Description Disconnect a L2CAP connection +** +*******************************************************************************/ +void obex_tl_l2cap_disconnect(UINT16 hdl) +{ + tOBEX_TL_L2CAP_CCB *p_ccb = find_ccb_by_hdl(hdl); + if (p_ccb != NULL) { + L2CA_DisconnectReq(p_ccb->lcid); + if (p_ccb->initiator && find_scb_by_psm(p_ccb->vpsm) == NULL) { + L2CA_Deregister(p_ccb->vpsm); + } + free_ccb(p_ccb); + } +} + +/******************************************************************************* +** +** Function obex_tl_l2cap_send_data +** +** Description Start the process of establishing a L2CAP connection +** +** Returns OBEX_TL_SUCCESS, if data accepted +** OBEX_TL_CONGESTED, if data accepted and the channel is congested +** OBEX_TL_FAILED, if error +** +*******************************************************************************/ +UINT16 obex_tl_l2cap_send_data(UINT16 hdl, BT_HDR *p_buf) +{ + UINT16 ret = OBEX_TL_FAILED; + tOBEX_TL_L2CAP_CCB *p_ccb = find_ccb_by_hdl(hdl); + if (p_ccb == NULL) { + osi_free(p_buf); + return ret; + } + + /* Can not send data size larger than peer MTU */ + /* Offset should not smaller than L2CAP_MIN_OFFSET */ + if (p_buf->len > p_ccb->peer_mtu || p_buf->offset < L2CAP_MIN_OFFSET) { + osi_free(p_buf); + return ret; + } + + UINT16 status = L2CA_DataWrite(p_ccb->lcid, p_buf); + switch (status) + { + case L2CAP_DW_SUCCESS: + ret = OBEX_TL_SUCCESS; + break; + case L2CAP_DW_CONGESTED: + ret = OBEX_TL_CONGESTED; + break; + default: + ret = OBEX_TL_FAILED; + break; + } + return ret; +} + +/******************************************************************************* +** +** Function obex_tl_l2cap_bind +** +** Description Register a server in L2CAP module +** +** Returns Non-zeros handle, 0 while failed +** +*******************************************************************************/ +UINT16 obex_tl_l2cap_bind(tOBEX_TL_SVR_INFO *server) +{ + tOBEX_TL_L2CAP_SCB *p_scb = find_scb_by_psm(server->l2cap.psm); + + if (p_scb != NULL) { + /* psm already used */ + return 0; + } + + p_scb = allocate_scb(); + if (p_scb == NULL) { + /* can not allocate a new scb */ + return 0; + } + + if (server->l2cap.pref_mtu == 0 || server->l2cap.pref_mtu > L2CAP_MTU_SIZE) { + p_scb->pref_mtu= L2CAP_MTU_SIZE; + } + else { + p_scb->pref_mtu = server->l2cap.pref_mtu; + } + + tL2CAP_APPL_INFO *p_reg_info = &obex_tl_l2cap_cb.l2cap_reg_info; + p_reg_info->pL2CA_ConnectInd_Cb = obex_tl_l2cap_connect_ind; + /* Register a l2cap server, in this case, L2CA_Register always return the same psm as input */ + p_scb->psm = L2CA_Register(server->l2cap.psm, p_reg_info); + if (p_scb->psm == 0) { + free_scb(p_scb); + return 0; + } + /* set security level */ + BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_OBEX, server->l2cap.sec_mask, p_scb->psm, BTM_SEC_PROTO_OBEX, OBEX_TL_L2CAP_NUM_CONN + p_scb->allocated - 1); + BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_OBEX, server->l2cap.sec_mask, p_scb->psm, BTM_SEC_PROTO_OBEX, OBEX_TL_L2CAP_NUM_CONN + p_scb->allocated - 1); + /* left shift 8 bits to avoid confuse with connection handle */ + return p_scb->allocated << 8; +} + +/******************************************************************************* +** +** Function obex_tl_l2cap_unbind +** +** Description Deregister a server in L2CAP module +** +*******************************************************************************/ +void obex_tl_l2cap_unbind(UINT16 tl_hdl) +{ + tOBEX_TL_L2CAP_SCB *p_scb = find_scb_by_hdl(tl_hdl); + if (p_scb) { + tOBEX_TL_L2CAP_CCB *p_ccb = NULL; + while ((p_ccb = find_ccb_by_psm(p_scb->psm)) != NULL) { + L2CA_DisconnectReq(p_ccb->lcid); + tOBEX_TL_MSG msg = {0}; + msg.any.hdl = p_ccb->allocated; + obex_tl_l2cap_cb.callback(OBEX_TL_DIS_CONN_EVT, &msg); + free_ccb(p_ccb); + } + L2CA_Deregister(p_scb->psm); + free_scb(p_scb); + } +} + +static tOBEX_TL_OPS obex_tl_l2cap_ops = { + .init = obex_tl_l2cap_init, + .deinit = obex_tl_l2cap_deinit, + .connect = obex_tl_l2cap_connect, + .disconnect = obex_tl_l2cap_disconnect, + .bind = obex_tl_l2cap_bind, + .unbind = obex_tl_l2cap_unbind, + .send = obex_tl_l2cap_send_data +}; + +/******************************************************************************* +** +** Function obex_tl_l2cap_ops_get +** +** Description Get the operation function structure pointer of OBEX over +** L2CAP transport layer +** +** Returns Pointer to operation function structure +** +*******************************************************************************/ +tOBEX_TL_OPS *obex_tl_l2cap_ops_get(void) +{ + return &obex_tl_l2cap_ops; +} + +#endif /* #if (OBEX_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/stack/obex/obex_tl_rfcomm.c b/lib/bt/host/bluedroid/stack/obex/obex_tl_rfcomm.c new file mode 100644 index 00000000..ce7799c8 --- /dev/null +++ b/lib/bt/host/bluedroid/stack/obex/obex_tl_rfcomm.c @@ -0,0 +1,439 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "osi/osi.h" +#include "osi/allocator.h" +#include "common/bt_target.h" + +#include "stack/port_api.h" +#include "stack/btm_api.h" +#include "stack/sdpdefs.h" +#include "obex_tl.h" +#include "obex_tl_rfcomm.h" + +#if (OBEX_INCLUDED == TRUE && RFCOMM_INCLUDED == TRUE) + +#define OBEX_TL_RFCOMM_NUM_CONN 4 +#define OBEX_TL_RFCOMM_NUM_SERVER 2 + +#define OBEX_TL_RFCOMM_EVENT_MARK (PORT_EV_FC | PORT_EV_FCS) + +typedef struct { + UINT16 rfc_handle; /* rfcomm handle */ + UINT16 mtu; /* rfcomm mtu */ + BOOLEAN initiator; /* TRUE if is initiator, otherwise FALSE */ + UINT8 scn; /* service channel number */ + BD_ADDR addr; /* peer bluetooth device address */ + UINT8 allocated; /* 0 if not allocated, otherwise, index + 1, equal to handle */ +} tOBEX_TL_RFCOMM_CCB; + +typedef struct { + UINT16 rfc_handle; /* rfcomm handle */ + UINT8 scn; /* service channel number */ + UINT8 allocated; /* 0 if not allocated, otherwise, index + 1, handle of server will left shift 8 bits */ +} tOBEX_TL_RFCOMM_SCB; + +typedef struct { + tOBEX_TL_CBACK *callback; /* Upper layer callback */ + tOBEX_TL_RFCOMM_CCB ccb[OBEX_TL_RFCOMM_NUM_CONN]; + tOBEX_TL_RFCOMM_SCB scb[OBEX_TL_RFCOMM_NUM_SERVER]; + UINT8 trace_level; /* trace level */ +} tOBEX_TL_RFCOMM_CB; + +#if OBEX_DYNAMIC_MEMORY == FALSE +static tOBEX_TL_RFCOMM_CB obex_tl_rfcomm_cb; +#else +static tOBEX_TL_RFCOMM_CB *obex_tl_rfcomm_cb_ptr = NULL; +#define obex_tl_rfcomm_cb (*obex_tl_rfcomm_cb_ptr) +#endif + +static tOBEX_TL_RFCOMM_CCB *allocate_ccb(void) +{ + tOBEX_TL_RFCOMM_CCB *p_ccb = NULL; + for(int i = 0; i < OBEX_TL_RFCOMM_NUM_CONN; ++i) { + if (obex_tl_rfcomm_cb.ccb[i].allocated == 0) { + obex_tl_rfcomm_cb.ccb[i].allocated = i + 1; + p_ccb = &obex_tl_rfcomm_cb.ccb[i]; + break; + } + } + return p_ccb; +} + +static tOBEX_TL_RFCOMM_SCB *allocate_scb(void) +{ + tOBEX_TL_RFCOMM_SCB *p_scb = NULL; + for(int i = 0; i < OBEX_TL_RFCOMM_NUM_SERVER; ++i) { + if (obex_tl_rfcomm_cb.scb[i].allocated == 0) { + obex_tl_rfcomm_cb.scb[i].allocated = i + 1; + p_scb = &obex_tl_rfcomm_cb.scb[i]; + break; + } + } + return p_scb; +} + +static void free_ccb(tOBEX_TL_RFCOMM_CCB *p_ccb) +{ + memset(p_ccb, 0, sizeof(tOBEX_TL_RFCOMM_CCB)); +} + +static void free_scb(tOBEX_TL_RFCOMM_SCB *p_scb) +{ + memset(p_scb, 0, sizeof(tOBEX_TL_RFCOMM_SCB)); +} + +static tOBEX_TL_RFCOMM_CCB *find_ccb_by_handle(UINT16 handle) +{ + tOBEX_TL_RFCOMM_CCB *p_ccb = NULL; + if (handle > 0 && handle <= OBEX_TL_RFCOMM_NUM_CONN) { + if (obex_tl_rfcomm_cb.ccb[handle-1].allocated == handle) { + p_ccb = &obex_tl_rfcomm_cb.ccb[handle-1]; + } + } + return p_ccb; +} + +static tOBEX_TL_RFCOMM_CCB *find_ccb_by_rfc_handle(UINT16 rfc_handle) +{ + tOBEX_TL_RFCOMM_CCB *p_ccb = NULL; + for(int i = 0; i < OBEX_TL_RFCOMM_NUM_CONN; ++i) { + if (obex_tl_rfcomm_cb.ccb[i].allocated && obex_tl_rfcomm_cb.ccb[i].rfc_handle == rfc_handle) { + p_ccb = &obex_tl_rfcomm_cb.ccb[i]; + break; + } + } + return p_ccb; +} + +static tOBEX_TL_RFCOMM_SCB *find_scb_by_handle(UINT16 handle) +{ + tOBEX_TL_RFCOMM_SCB *p_scb = NULL; + handle = handle >> 8; + if (handle > 0 && handle <= OBEX_TL_RFCOMM_NUM_SERVER) { + if (obex_tl_rfcomm_cb.scb[handle-1].allocated == handle) { + p_scb = &obex_tl_rfcomm_cb.scb[handle-1]; + } + } + return p_scb; +} + +static tOBEX_TL_RFCOMM_SCB *find_scb_by_rfc_handle(UINT16 rfc_handle) +{ + tOBEX_TL_RFCOMM_SCB *p_scb = NULL; + for(int i = 0; i < OBEX_TL_RFCOMM_NUM_SERVER; ++i) { + if (obex_tl_rfcomm_cb.scb[i].allocated && obex_tl_rfcomm_cb.scb[i].rfc_handle == rfc_handle) { + p_scb = &obex_tl_rfcomm_cb.scb[i]; + break; + } + } + return p_scb; +} + +static tOBEX_TL_RFCOMM_SCB *find_scb_by_scn(UINT16 scn) +{ + tOBEX_TL_RFCOMM_SCB *p_scb = NULL; + for(int i = 0; i < OBEX_TL_RFCOMM_NUM_SERVER; ++i) { + if (obex_tl_rfcomm_cb.scb[i].allocated && obex_tl_rfcomm_cb.scb[i].scn == scn) { + p_scb = &obex_tl_rfcomm_cb.scb[i]; + break; + } + } + return p_scb; +} + +static void rfcomm_mgmt_event_handler(tOBEX_TL_RFCOMM_CCB *p_ccb, UINT32 code) +{ + tOBEX_TL_MSG msg = {0}; + msg.any.hdl = p_ccb->allocated; + switch (code) + { + case PORT_SUCCESS: + /* event already handled, do nothing */ + break; + default: + /* other event, disconnect */ + obex_tl_rfcomm_cb.callback(OBEX_TL_DIS_CONN_EVT, &msg); + free_ccb(p_ccb); + break; + } +} + +static void rfcomm_client_mgmt_callback(UINT32 code, UINT16 rfc_handle, void* data) +{ + tOBEX_TL_RFCOMM_CCB *p_ccb = find_ccb_by_rfc_handle(rfc_handle); + if (p_ccb == NULL) { + OBEX_TL_RFCOMM_TRACE_DEBUG("No ccb to handle rfcomm event\n"); + return; + } + /* connection opened, handle event here */ + if (code == PORT_SUCCESS) { + assert(data != NULL); + tPORT_MGMT_CL_CALLBACK_ARG *cl_mgmt_cb_arg = (tPORT_MGMT_CL_CALLBACK_ARG *)data; + p_ccb->mtu = cl_mgmt_cb_arg->peer_mtu; + + tOBEX_TL_MSG msg = {0}; + msg.conn_open.hdl = p_ccb->allocated; + msg.conn_open.peer_mtu = p_ccb->mtu; + msg.conn_open.our_mtu = p_ccb->mtu; + obex_tl_rfcomm_cb.callback(OBEX_TL_CONN_OPEN_EVT, &msg); + } + rfcomm_mgmt_event_handler(p_ccb, code); +} + +static void rfcomm_server_mgmt_callback(UINT32 code, UINT16 rfc_handle, void* data) +{ + tOBEX_TL_RFCOMM_CCB *p_ccb = NULL; + /* incoming connection, handle event here */ + if (code == PORT_SUCCESS) { + assert(data != NULL); + tOBEX_TL_RFCOMM_SCB *p_scb = find_scb_by_rfc_handle(rfc_handle); + tPORT_MGMT_SR_CALLBACK_ARG *sr_mgmt_cb_arg = (tPORT_MGMT_SR_CALLBACK_ARG *)data; + if (p_scb == NULL) { + OBEX_TL_RFCOMM_TRACE_WARNING("No scb to this rfcomm connection\n"); + /* tell rfcomm to reject this connection */ + sr_mgmt_cb_arg->accept = FALSE; + return; + } + + /* try to find p_ccb with this rfc_handle, we expect to get a NULL */ + p_ccb = find_ccb_by_rfc_handle(rfc_handle); + if (p_ccb == NULL) { + p_ccb = allocate_ccb(); + if (p_ccb == NULL) { + OBEX_TL_RFCOMM_TRACE_WARNING("can not allocate a ccb for new connection\n"); + sr_mgmt_cb_arg->accept = FALSE; + return; + } + } + else { + OBEX_TL_RFCOMM_TRACE_WARNING("found duplicate rfcomm connection\n"); + } + + p_ccb->initiator = FALSE; + p_ccb->rfc_handle = rfc_handle; + p_ccb->scn = p_scb->scn; + p_ccb->mtu = sr_mgmt_cb_arg->peer_mtu; + /* get peer bd_addr */ + PORT_CheckConnection(rfc_handle, FALSE, p_ccb->addr, NULL); + + tOBEX_TL_MSG msg = {0}; + msg.conn_income.hdl = p_ccb->allocated; + msg.conn_income.peer_mtu = p_ccb->mtu; + msg.conn_income.our_mtu = p_ccb->mtu; + msg.conn_income.svr_hdl = (p_scb->allocated << 8); + obex_tl_rfcomm_cb.callback(OBEX_TL_CONN_INCOME_EVT, &msg); + } + else { + /* other event, it means server is connected */ + p_ccb = find_ccb_by_rfc_handle(rfc_handle); + if (p_ccb == NULL) { + OBEX_TL_RFCOMM_TRACE_DEBUG("No ccb to handle rfcomm event\n"); + return; + } + } + rfcomm_mgmt_event_handler(p_ccb, code); +} + +static int rfcomm_data_callback(UINT16 rfc_handle, UINT8 *p_buf, UINT16 len, int type) +{ + tOBEX_TL_RFCOMM_CCB *p_ccb = find_ccb_by_rfc_handle(rfc_handle); + if (p_ccb != NULL && type == DATA_CO_CALLBACK_TYPE_INCOMING) { + tOBEX_TL_MSG msg = {0}; + msg.data.hdl = p_ccb->allocated; + msg.data.p_buf = (BT_HDR *)p_buf; + obex_tl_rfcomm_cb.callback(OBEX_TL_DATA_EVT, &msg); + PORT_FlowControl_GiveCredit(rfc_handle, TRUE, 1); + } + else if(p_buf != NULL) { + osi_free(p_buf); + } + return 1; +} + +static void rfcomm_event_callback(UINT32 code, UINT16 rfc_handle) +{ + tOBEX_TL_RFCOMM_CCB *p_ccb = find_ccb_by_rfc_handle(rfc_handle); + if (p_ccb == NULL) { + OBEX_TL_RFCOMM_TRACE_WARNING("No ccb to handle rfcomm event\n"); + return; + } + + if (code & PORT_EV_FC) { + tOBEX_TL_MSG msg = {0}; + msg.any.hdl = p_ccb->allocated; + if (code & PORT_EV_FCS) { + obex_tl_rfcomm_cb.callback(OBEX_TL_UNCONGEST_EVT, &msg); + } + else { + obex_tl_rfcomm_cb.callback(OBEX_TL_CONGEST_EVT, &msg); + } + } +} + +void obex_tl_rfcomm_init(tOBEX_TL_CBACK *callback) +{ + assert(callback != NULL); +#if (OBEX_DYNAMIC_MEMORY) + if (!obex_tl_rfcomm_cb_ptr) { + obex_tl_rfcomm_cb_ptr = (tOBEX_TL_RFCOMM_CB *)osi_malloc(sizeof(tOBEX_TL_RFCOMM_CB)); + if (!obex_tl_rfcomm_cb_ptr) { + OBEX_TL_RFCOMM_TRACE_ERROR("OBEX over RFCOMM transport layer initialize failed, no memory\n"); + assert(0); + } + } +#endif /* #if (OBEX_DYNAMIC_MEMORY) */ + memset(&obex_tl_rfcomm_cb, 0, sizeof(tOBEX_TL_RFCOMM_CB)); + obex_tl_rfcomm_cb.callback = callback; + obex_tl_rfcomm_cb.trace_level = BT_TRACE_LEVEL_ERROR; +} + +void obex_tl_rfcomm_deinit(void) +{ +#if (OBEX_DYNAMIC_MEMORY) + if (obex_tl_rfcomm_cb_ptr) { + osi_free(obex_tl_rfcomm_cb_ptr); + obex_tl_rfcomm_cb_ptr = NULL; + } +#endif /* #if (OBEX_DYNAMIC_MEMORY) */ +} + +UINT16 obex_tl_rfcomm_connect(tOBEX_TL_SVR_INFO *server) +{ + tOBEX_TL_RFCOMM_CCB *p_ccb = allocate_ccb(); + if (p_ccb == NULL) { + return 0; + } + + BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_OBEX, server->rfcomm.sec_mask, BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, server->rfcomm.scn); + if (RFCOMM_CreateConnection(UUID_PROTOCOL_OBEX, server->rfcomm.scn, FALSE, server->rfcomm.pref_mtu, + server->rfcomm.addr, &p_ccb->rfc_handle, rfcomm_client_mgmt_callback) != PORT_SUCCESS) { + free_ccb(p_ccb); + return 0; + } + + /* set up data callback, event mask and event callback */ + PORT_SetDataCOCallback(p_ccb->rfc_handle, rfcomm_data_callback); + PORT_SetEventMask(p_ccb->rfc_handle, OBEX_TL_RFCOMM_EVENT_MARK); + PORT_SetEventCallback(p_ccb->rfc_handle, rfcomm_event_callback); + + bdcpy(p_ccb->addr, server->rfcomm.addr); + p_ccb->scn = server->rfcomm.scn; + p_ccb->initiator = TRUE; + + return p_ccb->allocated; +} + +void obex_tl_rfcomm_disconnect(UINT16 handle) +{ + tOBEX_TL_RFCOMM_CCB *p_ccb = find_ccb_by_handle(handle); + if (p_ccb != NULL) { + RFCOMM_RemoveConnection(p_ccb->rfc_handle); + free_ccb(p_ccb); + } +} + +UINT16 obex_tl_rfcomm_send(UINT16 handle, BT_HDR *p_buf) +{ + UINT16 ret = OBEX_TL_FAILED; + tOBEX_TL_RFCOMM_CCB *p_ccb = find_ccb_by_handle(handle); + do { + if (p_ccb == NULL) { + osi_free(p_buf); + break; + } + + /* Can not send data size larger than MTU */ + /* Offset should not smaller than OBEX_TL_RFCOMM_BT_HDR_MIN_OFFSET */ + if (p_buf->len > p_ccb->mtu || p_buf->offset < OBEX_TL_RFCOMM_BT_HDR_MIN_OFFSET) { + osi_free(p_buf); + break; + } + + if (PORT_Write(p_ccb->rfc_handle, p_buf) == PORT_SUCCESS) { + ret = OBEX_TL_SUCCESS; + } + } while (0); + return ret; +} + +UINT16 obex_tl_rfcomm_bind(tOBEX_TL_SVR_INFO *server) +{ + tOBEX_TL_RFCOMM_SCB *p_scb = find_scb_by_scn(server->rfcomm.scn); + if (p_scb != NULL) { + /* scn already used */ + return 0; + } + + p_scb = allocate_scb(); + if (p_scb == NULL) { + OBEX_TL_RFCOMM_TRACE_WARNING("Can not allocate scb, out of number\n"); + return 0; + } + + BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_OBEX, server->rfcomm.sec_mask, BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, server->rfcomm.scn); + if (RFCOMM_CreateConnection(UUID_PROTOCOL_OBEX, server->rfcomm.scn, TRUE, server->rfcomm.pref_mtu, + server->rfcomm.addr, &p_scb->rfc_handle, rfcomm_server_mgmt_callback) != PORT_SUCCESS) { + free_scb(p_scb); + return 0; + } + + /* set up data callback, event mask and event callback */ + PORT_SetDataCOCallback(p_scb->rfc_handle, rfcomm_data_callback); + PORT_SetEventMask(p_scb->rfc_handle, OBEX_TL_RFCOMM_EVENT_MARK); + PORT_SetEventCallback(p_scb->rfc_handle, rfcomm_event_callback); + + p_scb->scn = server->rfcomm.scn; + + /* left shift 8 bits as server handle, avoid confuse with connection handle */ + return (p_scb->allocated << 8); +} + +void obex_tl_rfcomm_unbind(UINT16 handle) +{ + tOBEX_TL_RFCOMM_SCB *p_scb = find_scb_by_handle(handle); + if (p_scb) { + tOBEX_TL_RFCOMM_CCB *p_ccb = NULL; + while ((p_ccb = find_ccb_by_rfc_handle(p_scb->rfc_handle)) != NULL) { + RFCOMM_RemoveConnection(p_ccb->rfc_handle); + tOBEX_TL_MSG msg = {0}; + msg.any.hdl = p_ccb->allocated; + obex_tl_rfcomm_cb.callback(OBEX_TL_DIS_CONN_EVT, &msg); + free_ccb(p_ccb); + } + RFCOMM_RemoveServer(p_scb->rfc_handle); + free_scb(p_scb); + } +} + +static tOBEX_TL_OPS obex_tl_rfcomm_ops = { + .init = obex_tl_rfcomm_init, + .deinit = obex_tl_rfcomm_deinit, + .connect = obex_tl_rfcomm_connect, + .disconnect = obex_tl_rfcomm_disconnect, + .bind = obex_tl_rfcomm_bind, + .unbind = obex_tl_rfcomm_unbind, + .send = obex_tl_rfcomm_send +}; + +/******************************************************************************* +** +** Function obex_tl_rfcomm_ops_get +** +** Description Get the operation function structure pointer of OBEX over +** RFCOMM transport layer +** +** Returns Pointer to operation function structure +** +*******************************************************************************/ +tOBEX_TL_OPS *obex_tl_rfcomm_ops_get(void) +{ + return &obex_tl_rfcomm_ops; +} + +#endif /* #if (OBEX_INCLUDED == TRUE && RFCOMM_INCLUDED == TRUE) */ diff --git a/lib/bt/host/bluedroid/stack/sdp/sdp_api.c b/lib/bt/host/bluedroid/stack/sdp/sdp_api.c index 0103e4de..9b477a1c 100644 --- a/lib/bt/host/bluedroid/stack/sdp/sdp_api.c +++ b/lib/bt/host/bluedroid/stack/sdp/sdp_api.c @@ -372,7 +372,7 @@ BOOLEAN SDP_FindServiceUUIDInRec(tSDP_DISC_REC *p_rec, tBT_UUID *p_uuid) if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE) { /* Look through data element sequence until no more UUIDs */ for (p_extra_sattr = p_sattr->attr_value.v.p_sub_attr; p_extra_sattr; p_extra_sattr = p_extra_sattr->p_next_attr) { - /* Increment past this to see if the next attribut is UUID */ + /* Increment past this to see if the next attribute is UUID */ if ((SDP_DISC_ATTR_TYPE(p_extra_sattr->attr_len_type) == UUID_DESC_TYPE) /* only support 16 bits UUID for now */ && (SDP_DISC_ATTR_LEN(p_extra_sattr->attr_len_type) == 2)) { @@ -522,7 +522,7 @@ tSDP_DISC_REC *SDP_FindServiceInDb (tSDP_DISCOVERY_DB *p_db, UINT16 service_uuid if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE) { /* Look through data element sequence until no more UUIDs */ for (p_extra_sattr = p_sattr->attr_value.v.p_sub_attr; p_extra_sattr; p_extra_sattr = p_extra_sattr->p_next_attr) { - /* Increment past this to see if the next attribut is UUID */ + /* Increment past this to see if the next attribute is UUID */ if ((SDP_DISC_ATTR_TYPE(p_extra_sattr->attr_len_type) == UUID_DESC_TYPE) && (SDP_DISC_ATTR_LEN(p_extra_sattr->attr_len_type) == 2) /* for a specific uuid, or any one */ @@ -768,6 +768,28 @@ BOOLEAN SDP_FindProtocolListElemInRec (tSDP_DISC_REC *p_rec, UINT16 layer_uuid, return (FALSE); } +/******************************************************************************* +** +** Function SDP_FindProtocolListElem +** +** Description This function looks at the protocol list for a specific protocol +** list element. +** +** Returns TRUE if found, FALSE if not +** If found, the passed protocol list element is filled in. +** +*******************************************************************************/ +BOOLEAN SDP_FindProtocolListElem (tSDP_DISC_ATTR *p_protocol_list, UINT16 layer_uuid, tSDP_PROTOCOL_ELEM *p_elem) +{ +#if SDP_CLIENT_ENABLED == TRUE + /* don't check the input protocol descriptor list id, this api may be use in additional protocol descriptor list */ + if ((SDP_DISC_ATTR_TYPE(p_protocol_list->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE)) { + return sdp_fill_proto_elem(p_protocol_list, layer_uuid, p_elem); + } +#endif + /* If here, no match found */ + return (FALSE); +} /******************************************************************************* ** diff --git a/lib/bt/host/bluedroid/stack/sdp/sdp_db.c b/lib/bt/host/bluedroid/stack/sdp/sdp_db.c index a9b3daa4..60dd04a6 100644 --- a/lib/bt/host/bluedroid/stack/sdp/sdp_db.c +++ b/lib/bt/host/bluedroid/stack/sdp/sdp_db.c @@ -276,7 +276,7 @@ static int sdp_compose_proto_list( UINT8 *p, UINT16 num_elem, ** ** Description This function is called to create a record in the database. ** This would be through the SDP database maintenance API. The -** record is created empty, teh application should then call +** record is created empty, the application should then call ** "add_attribute" to add the record's attributes. ** ** Returns Record handle if OK, else 0. @@ -293,15 +293,15 @@ UINT32 SDP_CreateRecord (void) /* First, check if there is a free record */ if (p_db->num_records < SDP_MAX_RECORDS) { - p_rec =(tSDP_RECORD *)osi_malloc(sizeof(tSDP_RECORD)); - if (p_rec) { - memset(p_rec, 0, sizeof(tSDP_RECORD)); - /* Save previous rec */ - if (p_db->num_records) { - p_rec_prev = list_back(p_db->p_record_list); - } - /* Append new record */ - list_append(p_db->p_record_list, p_rec); + p_rec = (tSDP_RECORD *)osi_malloc(sizeof(tSDP_RECORD)); + if (p_rec) { + memset(p_rec, 0, sizeof(tSDP_RECORD)); + /* Save previous rec */ + if (p_db->num_records) { + p_rec_prev = list_back(p_db->p_record_list); + } + /* Append new record */ + list_append(p_db->p_record_list, p_rec); /* We will use a handle of the first unreserved handle plus last record ** number + 1 */ @@ -321,10 +321,12 @@ UINT32 SDP_CreateRecord (void) 4, buf); return (p_rec->record_handle); - } else { + } + else { SDP_TRACE_ERROR("SDP_CreateRecord fail, memory allocation failed\n"); - } - } else { + } + } + else { SDP_TRACE_ERROR("SDP_CreateRecord fail, exceed maximum records:%d\n", SDP_MAX_RECORDS); } #endif @@ -354,17 +356,17 @@ BOOLEAN SDP_DeleteRecord (UINT32 handle) if (handle == 0 || sdp_cb.server_db.num_records == 0) { /* Delete all records in the database */ sdp_cb.server_db.num_records = 0; - for(p_node = list_begin(sdp_cb.server_db.p_record_list); p_node; p_node = list_next(p_node)) { - list_remove(sdp_cb.server_db.p_record_list, p_node); - } + for (p_node = list_begin(sdp_cb.server_db.p_record_list); p_node; p_node = list_next(p_node)) { + list_remove(sdp_cb.server_db.p_record_list, p_node); + } /* require new DI record to be created in SDP_SetLocalDiRecord */ sdp_cb.server_db.di_primary_handle = 0; return (TRUE); } else { /* Find the record in the database */ - for(p_node = list_begin(sdp_cb.server_db.p_record_list); p_node; p_node = list_next(p_node)) { - p_rec = list_node(p_node); + for (p_node = list_begin(sdp_cb.server_db.p_record_list); p_node; p_node = list_next(p_node)) { + p_rec = list_node(p_node); if (p_rec->record_handle == handle) { /* Found it. Shift everything up one */ list_remove(sdp_cb.server_db.p_record_list, p_rec); @@ -374,7 +376,7 @@ BOOLEAN SDP_DeleteRecord (UINT32 handle) SDP_TRACE_DEBUG("SDP_DeleteRecord ok, num_records:%d\n", sdp_cb.server_db.num_records); /* if we're deleting the primary DI record, clear the */ /* value in the control block */ - if ( sdp_cb.server_db.di_primary_handle == handle ) { + if (sdp_cb.server_db.di_primary_handle == handle) { sdp_cb.server_db.di_primary_handle = 0; } diff --git a/lib/bt/host/bluedroid/stack/sdp/sdp_discovery.c b/lib/bt/host/bluedroid/stack/sdp/sdp_discovery.c index d63b164d..31ab11f4 100644 --- a/lib/bt/host/bluedroid/stack/sdp/sdp_discovery.c +++ b/lib/bt/host/bluedroid/stack/sdp/sdp_discovery.c @@ -453,7 +453,7 @@ static void process_service_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply) } } - /* Now, ask for the next handle. Re-use the buffer we just got. */ + /* Now, ask for the next handle. Reuse the buffer we just got. */ if (p_ccb->cur_handle < p_ccb->num_handles) { BT_HDR *p_msg = (BT_HDR *) osi_malloc(SDP_DATA_BUF_SIZE); UINT8 *p; @@ -669,6 +669,7 @@ static void process_service_search_attr_rsp (tCONN_CB *p_ccb, UINT8 *p_reply) if ((type >> 3) != DATA_ELE_SEQ_DESC_TYPE) { SDP_TRACE_WARNING ("SDP - Wrong type: 0x%02x in attr_rsp\n", type); + sdp_disconnect (p_ccb, SDP_ILLEGAL_PARAMETER); return; } p = sdpu_get_len_from_type (p, type, &seq_len); diff --git a/lib/bt/host/bluedroid/stack/smp/smp_act.c b/lib/bt/host/bluedroid/stack/smp/smp_act.c index 0e7dcd5b..43b2e476 100644 --- a/lib/bt/host/bluedroid/stack/smp/smp_act.c +++ b/lib/bt/host/bluedroid/stack/smp/smp_act.c @@ -1553,7 +1553,7 @@ void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) } /* Disable L2CAP connection parameter updates while bonding since some peripherals are not able to revert to fast connection parameters - during the start of service discovery. Connection paramter updates + during the start of service discovery. Connection parameter updates get enabled again once service discovery completes. */ #if (BT_MULTI_CONNECTION_ENBALE == FALSE) L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE); @@ -1648,6 +1648,8 @@ void smp_process_local_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) /* slave calculates and sends local commitment */ smp_calculate_local_commitment(p_cb); smp_send_commitment(p_cb, NULL); + /* Ensure the connection is still active */ + if (smp_get_state() == SMP_STATE_IDLE) return; /* slave has to wait for peer nonce */ smp_set_state(SMP_STATE_WAIT_NONCE); } else { /* i.e. master */ @@ -1658,6 +1660,8 @@ void smp_process_local_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) p_cb->selected_association_model); p_cb->flags &= ~SMP_PAIR_FLAG_HAVE_PEER_COMM; smp_send_rand(p_cb, NULL); + /* Ensure the connection is still active */ + if (smp_get_state() == SMP_STATE_IDLE) return; smp_set_state(SMP_STATE_WAIT_NONCE); } } @@ -1672,6 +1676,8 @@ void smp_process_local_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) if (p_cb->flags & SMP_PAIR_FLAG_HAVE_PEER_COMM) { /* master commitment is already received */ smp_send_commitment(p_cb, NULL); + /* Ensure the connection is still active */ + if (smp_get_state() == SMP_STATE_IDLE) return; smp_set_state(SMP_STATE_WAIT_NONCE); } } @@ -1679,6 +1685,8 @@ void smp_process_local_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data) case SMP_MODEL_SEC_CONN_OOB: if (p_cb->role == HCI_ROLE_MASTER) { smp_send_rand(p_cb, NULL); + /* Ensure the connection is still active */ + if (smp_get_state() == SMP_STATE_IDLE) return; } smp_set_state(SMP_STATE_WAIT_NONCE); @@ -2002,7 +2010,7 @@ void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable) SMP_TRACE_DEBUG("%s encr_enable=%d\n", __func__, encr_enable); if (memcmp(&smp_cb.pairing_bda[0], bda, BD_ADDR_LEN) == 0) { - /* encryption completed with STK, remmeber the key size now, could be overwite + /* encryption completed with STK, remember the key size now, could be overwrite * when key exchange happens */ if (p_cb->loc_enc_size != 0 && encr_enable) { /* update the link encryption key size if a SMP pairing just performed */ diff --git a/lib/bt/host/bluedroid/stack/smp/smp_utils.c b/lib/bt/host/bluedroid/stack/smp/smp_utils.c index 2e9fac77..48ba6c0a 100644 --- a/lib/bt/host/bluedroid/stack/smp/smp_utils.c +++ b/lib/bt/host/bluedroid/stack/smp/smp_utils.c @@ -331,8 +331,7 @@ BOOLEAN smp_send_msg_to_L2CAP(BD_ADDR rem_bda, BT_HDR *p_toL2CAP) if ((l2cap_ret = L2CA_SendFixedChnlData (fixed_cid, rem_bda, p_toL2CAP)) == L2CAP_DW_FAILED) { smp_cb.total_tx_unacked -= 1; - SMP_TRACE_ERROR("SMP failed to pass msg:0x%0x to L2CAP", - *((UINT8 *)(p_toL2CAP + 1) + p_toL2CAP->offset)); + SMP_TRACE_ERROR("SMP failed to pass msg to L2CAP"); return FALSE; } else { return TRUE; @@ -1125,7 +1124,7 @@ BOOLEAN smp_pairing_request_response_parameters_are_valid(tSMP_CB *p_cb) SMP_TRACE_DEBUG("%s for cmd code 0x%02x\n", __func__, p_cb->rcvd_cmd_code); if (io_caps >= BTM_IO_CAP_MAX) { - SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with IO Capabilty \ + SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with IO Capability \ value (0x%02x) out of range).\n", p_cb->rcvd_cmd_code, io_caps); return FALSE; diff --git a/lib/bt/host/nimble/Kconfig.in b/lib/bt/host/nimble/Kconfig.in index d02293a8..3ea05578 100644 --- a/lib/bt/host/nimble/Kconfig.in +++ b/lib/bt/host/nimble/Kconfig.in @@ -65,7 +65,7 @@ config BT_NIMBLE_LOG_LEVEL config BT_NIMBLE_MAX_CONNECTIONS int "Maximum number of concurrent connections" range 1 2 if IDF_TARGET_ESP32C2 - range 1 70 if IDF_TARGET_ESP32C6 + range 1 70 if IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32C5 || IDF_TARGET_ESP32C61 range 1 35 if IDF_TARGET_ESP32H2 range 1 9 default 2 if IDF_TARGET_ESP32C2 @@ -100,6 +100,14 @@ config BT_NIMBLE_L2CAP_COC_MAX_NUM help Defines maximum number of BLE Connection Oriented Channels. When set to (0), BLE COC is not compiled in +config BT_NIMBLE_L2CAP_ENHANCED_COC + bool "L2CAP Enhanced Connection Oriented Channel" + depends on BT_NIMBLE_ENABLED && (BT_NIMBLE_L2CAP_COC_MAX_NUM >= 1) + default 0 + help + Enable Enhanced Credit Based Flow Control Mode + + choice BT_NIMBLE_PINNED_TO_CORE_CHOICE prompt "The CPU core on which NimBLE host will run" depends on BT_NIMBLE_ENABLED && !FREERTOS_UNICORE @@ -148,7 +156,7 @@ config BT_NIMBLE_ROLE_BROADCASTER depends on BT_NIMBLE_ENABLED default y help - Enables broadcaster role + Enables broadcaster role config BT_NIMBLE_ROLE_OBSERVER bool "Enable BLE Observer role" @@ -157,6 +165,20 @@ config BT_NIMBLE_ROLE_OBSERVER help Enables observer role +config BT_NIMBLE_GATT_CLIENT + bool "Enable BLE GATT Client support" + depends on BT_NIMBLE_ROLE_CENTRAL + default y + help + Enables support for GATT Client + +config BT_NIMBLE_GATT_SERVER + bool "Enable BLE GATT Server support" + depends on BT_NIMBLE_ROLE_PERIPHERAL + default y + help + Enables support for GATT Server + config BT_NIMBLE_NVS_PERSIST bool "Persist the BLE Bonding keys in NVS" depends on BT_NIMBLE_ENABLED @@ -164,6 +186,16 @@ config BT_NIMBLE_NVS_PERSIST help Enable this flag to make bonding persistent across device reboots +config BT_NIMBLE_SMP_ID_RESET + bool "Reset device identity when all bonding records are deleted" + default n + help + There are tracking risks associated with using a fixed or static IRK. + If enabled this option, NimBLE will assign a new randomly-generated IRK + when all pairing and bonding records are deleted. This would decrease the ability + of a previously paired peer to be used to determine whether a device + with which it previously shared an IRK is within range. + menuconfig BT_NIMBLE_SECURITY_ENABLE bool "Enable BLE SM feature" depends on BT_NIMBLE_ENABLED @@ -212,6 +244,20 @@ config BT_NIMBLE_SM_LVL 3. Authenticated pairing with encryption 4. Authenticated LE Secure Connections pairing with encryption using a 128-bit strength encryption key. +config BT_NIMBLE_SM_SC_ONLY + int "Enable Secure Connections Only Mode" + depends on BT_NIMBLE_SECURITY_ENABLE + default 0 + help + Enable Secure Connections Only Mode + +config BT_NIMBLE_PRINT_ERR_NAME + bool "Enable feature to print Error description" + depends on BT_NIMBLE_ENABLED + default y + help + Enable feature to give useful explanation for HCI errors + config BT_NIMBLE_DEBUG bool "Enable extra runtime asserts and host debugging" default n @@ -249,6 +295,13 @@ config BT_NIMBLE_ATT_PREFERRED_MTU This is the default value of ATT MTU indicated by the device during an ATT MTU exchange. This value can be changed using API ble_att_set_preferred_mtu() +config BT_NIMBLE_ATT_MAX_PREP_ENTRIES + int "Max Prepare write entries" + depends on BT_NIMBLE_ENABLED + default 64 + help + This is the default value of ATT Maximum prepare entries + config BT_NIMBLE_SVC_GAP_APPEARANCE hex "External appearance of the device" depends on BT_NIMBLE_ENABLED @@ -359,7 +412,7 @@ config BT_NIMBLE_GATT_MAX_PROCS config BT_NIMBLE_HS_FLOW_CTRL bool "Enable Host Flow control" - depends on BT_NIMBLE_ENABLED + depends on BT_NIMBLE_ENABLED && !SOC_ESP_NIMBLE_CONTROLLER default y if IDF_TARGET_ESP32 default n help @@ -534,6 +587,16 @@ config BT_NIMBLE_MAX_CONN_REATTEMPT help Defines maximum number of connection reattempts. +config BT_NIMBLE_HANDLE_REPEAT_PAIRING_DELETION + bool "Enable stack handling of repeat pairing" + default n + depends on BT_NIMBLE_ENABLED + help + Use this option to let stack internally handle the request for repeat pairing. + Enabling this option will delete the pairing of the device and stack will NOT post any event + to application. If this option is disabled, application will get BLE_GAP_EVENT_REPEAT_PAIRING + event. + menuconfig BT_NIMBLE_50_FEATURE_SUPPORT bool "Enable BLE 5 feature" depends on BT_NIMBLE_ENABLED && (SOC_BLE_50_SUPPORTED || !BT_CONTROLLER_ENABLED) @@ -541,111 +604,162 @@ menuconfig BT_NIMBLE_50_FEATURE_SUPPORT help Enable BLE 5 feature -config BT_NIMBLE_LL_CFG_FEAT_LE_2M_PHY - bool "Enable 2M Phy" - depends on BT_NIMBLE_50_FEATURE_SUPPORT - default y - help - Enable 2M-PHY - -config BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY - bool "Enable coded Phy" - depends on BT_NIMBLE_50_FEATURE_SUPPORT - default y - help - Enable coded-PHY - -config BT_NIMBLE_EXT_ADV - bool "Enable extended advertising" - depends on BT_NIMBLE_50_FEATURE_SUPPORT - default n - help - Enable this option to do extended advertising. Extended advertising - will be supported from BLE 5.0 onwards. +if BT_NIMBLE_50_FEATURE_SUPPORT + config BT_NIMBLE_LL_CFG_FEAT_LE_2M_PHY + bool "Enable 2M Phy" + depends on BT_NIMBLE_50_FEATURE_SUPPORT + default y + help + Enable 2M-PHY -if BT_NIMBLE_EXT_ADV - config BT_NIMBLE_MAX_EXT_ADV_INSTANCES - int "Maximum number of extended advertising instances." - range 0 4 - default 1 if BT_NIMBLE_EXT_ADV - default 0 - depends on BT_NIMBLE_EXT_ADV + config BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY + bool "Enable coded Phy" + depends on BT_NIMBLE_50_FEATURE_SUPPORT + default y help - Change this option to set maximum number of extended advertising - instances. Minimum there is always one instance of - advertising. Enter how many more advertising instances you - want. - For ESP32C2, ESP32C6 and ESP32H2, each extended advertising instance - will take about 0.5k DRAM. - - config BT_NIMBLE_EXT_ADV_MAX_SIZE - int "Maximum length of the advertising data." - range 0 1650 - default 1650 if BT_NIMBLE_EXT_ADV - default 0 - depends on BT_NIMBLE_EXT_ADV + Enable coded-PHY + + config BT_NIMBLE_EXT_ADV + bool "Enable extended advertising" + depends on BT_NIMBLE_50_FEATURE_SUPPORT + default n help - Defines the length of the extended adv data. The value should not - exceed 1650. + Enable this option to do extended advertising. Extended advertising + will be supported from BLE 5.0 onwards. - config BT_NIMBLE_ENABLE_PERIODIC_ADV - bool "Enable periodic advertisement." + if BT_NIMBLE_EXT_ADV + config BT_NIMBLE_EXT_ADV_V2 + bool "Enable support for extended adv v2" + default n + depends on BT_NIMBLE_EXT_ADV + help + Enable this option to use Extended Adv V2 command instead of V1. + + config BT_NIMBLE_MAX_EXT_ADV_INSTANCES + int "Maximum number of extended advertising instances." + range 0 4 + default 1 if BT_NIMBLE_EXT_ADV + default 0 + depends on BT_NIMBLE_EXT_ADV + help + Change this option to set maximum number of extended advertising + instances. Minimum there is always one instance of + advertising. Enter how many more advertising instances you + want. + For ESP32C2, ESP32C6 and ESP32H2, each extended advertising instance + will take about 0.5k DRAM. + + config BT_NIMBLE_EXT_ADV_MAX_SIZE + int "Maximum length of the advertising data." + range 0 1650 + default 1650 if BT_NIMBLE_EXT_ADV + default 0 + depends on BT_NIMBLE_EXT_ADV + help + Defines the length of the extended adv data. The value should not + exceed 1650. + + config BT_NIMBLE_ENABLE_PERIODIC_ADV + bool "Enable periodic advertisement." + default y + depends on BT_NIMBLE_EXT_ADV + help + Enable this option to start periodic advertisement. + + config BT_NIMBLE_PERIODIC_ADV_ENH + bool "Periodic adv enhancements(adi support)" + depends on BT_NIMBLE_ENABLE_PERIODIC_ADV && SOC_BLE_PERIODIC_ADV_ENH_SUPPORTED + help + Enable the periodic advertising enhancements + + config BT_NIMBLE_PERIODIC_ADV_SYNC_TRANSFER + bool "Enable Transfer Sync Events" + depends on BT_NIMBLE_ENABLE_PERIODIC_ADV + default y + help + This enables controller transfer periodic sync events to host + + config BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES + bool "Enable Periodic Advertisement with Response (EXPERIMENTAL)" + depends on BT_NIMBLE_ENABLE_PERIODIC_ADV + default n + help + This enables controller PAwR (Periodic Advertisement with Response). + endif + + config BT_NIMBLE_EXT_SCAN + bool "Enable extended scanning" + depends on BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ROLE_OBSERVER default y - depends on BT_NIMBLE_EXT_ADV help - Enable this option to start periodic advertisement. + Enable this option to do extended scanning. - config BT_NIMBLE_PERIODIC_ADV_SYNC_TRANSFER - bool "Enable Transfer Sync Events" - depends on BT_NIMBLE_ENABLE_PERIODIC_ADV + config BT_NIMBLE_ENABLE_PERIODIC_SYNC + bool "Enable periodic sync" default y + depends on BT_NIMBLE_EXT_SCAN help - This enables controller transfer periodic sync events to host -endif - -config BT_NIMBLE_MAX_PERIODIC_SYNCS - int "Maximum number of periodic advertising syncs" - depends on BT_NIMBLE_50_FEATURE_SUPPORT - range 0 3 if IDF_TARGET_ESP32C2 - range 0 8 - default 1 if BT_NIMBLE_ENABLE_PERIODIC_ADV - default 0 - help - Set this option to set the upper limit for number of periodic sync - connections. This should be less than maximum connections allowed by - controller. - -config BT_NIMBLE_MAX_PERIODIC_ADVERTISER_LIST - int "Maximum number of periodic advertiser list" - depends on BT_NIMBLE_50_FEATURE_SUPPORT && SOC_ESP_NIMBLE_CONTROLLER - range 1 5 - default 5 if BT_NIMBLE_50_FEATURE_SUPPORT - help - Set this option to set the upper limit for number of periodic advertiser list. + Enable this option to receive periodic advertisement. + + if BT_NIMBLE_ENABLE_PERIODIC_SYNC + config BT_NIMBLE_MAX_PERIODIC_SYNCS + int "Maximum number of periodic advertising syncs" + range 0 3 if IDF_TARGET_ESP32C2 + range 0 8 + default 1 if BT_NIMBLE_ENABLE_PERIODIC_ADV + default 0 + help + Set this option to set the upper limit for number of periodic sync + connections. This should be less than maximum connections allowed by + controller. + + config BT_NIMBLE_MAX_PERIODIC_ADVERTISER_LIST + int "Maximum number of periodic advertiser list" + depends on SOC_ESP_NIMBLE_CONTROLLER + range 1 5 + default 5 if BT_NIMBLE_50_FEATURE_SUPPORT + help + Set this option to set the upper limit for number of periodic advertiser list. + endif -config BT_NIMBLE_BLE_POWER_CONTROL - bool "Enable support for BLE Power Control" - depends on BT_NIMBLE_50_FEATURE_SUPPORT && SOC_BLE_POWER_CONTROL_SUPPORTED - default n - help - Set this option to enable the Power Control feature + config BT_NIMBLE_BLE_POWER_CONTROL + bool "Enable support for BLE Power Control" + depends on BT_NIMBLE_50_FEATURE_SUPPORT && SOC_BLE_POWER_CONTROL_SUPPORTED + default n + help + Set this option to enable the Power Control feature -config BT_NIMBLE_PERIODIC_ADV_ENH - bool "Periodic adv enhancements(adi support)" - depends on BT_NIMBLE_ENABLE_PERIODIC_ADV && BT_NIMBLE_50_FEATURE_SUPPORT && SOC_BLE_PERIODIC_ADV_ENH_SUPPORTED - help - Enable the periodic advertising enhancements + config BT_NIMBLE_AOA_AOD + bool "Direction Finding" + depends on BT_NIMBLE_50_FEATURE_SUPPORT && (BT_CONTROLLER_DISABLED || SOC_BLE_CTE_SUPPORTED) + default n + help + Enable support for Connectionless and Connection Oriented Direction Finding +endif menuconfig BT_NIMBLE_GATT_CACHING bool "Enable GATT caching" - depends on BT_NIMBLE_ENABLED && BT_NIMBLE_50_FEATURE_SUPPORT + depends on BT_NIMBLE_ENABLED select BT_NIMBLE_DYNAMIC_SERVICE help Enable GATT caching +config BT_NIMBLE_GATT_CACHING_INCLUDE_SERVICES + bool "Include services in GATT caching" + depends on BT_NIMBLE_GATT_CACHING + default n + help + Enable this option to include *included services* (e.g., services referenced by other services) + in the GATT database cache. Disabling this will skip caching of included service entries. +config BT_NIMBLE_INCL_SVC_DISCOVERY + bool "Enable Included service discovery" + default y if BT_NIMBLE_GATT_CACHING_INCLUDE_SERVICES + default n + help + Enable this option to start discovery for included service. config BT_NIMBLE_GATT_CACHING_MAX_CONNS int "Maximum connections to be cached" depends on BT_NIMBLE_GATT_CACHING - default 1 + default BT_NIMBLE_MAX_CONNECTIONS help Set this option to set the upper limit on number of connections to be cached. config BT_NIMBLE_GATT_CACHING_MAX_SVCS @@ -654,6 +768,12 @@ config BT_NIMBLE_GATT_CACHING_MAX_SVCS default 64 help Set this option to set the upper limit on number of services per connection to be cached. +config BT_NIMBLE_GATT_CACHING_MAX_INCL_SVCS + int "Maximum number of included services per connection" + depends on BT_NIMBLE_GATT_CACHING + default 64 + help + Set this option to set the upper limit on number of included services per connection to be cached. config BT_NIMBLE_GATT_CACHING_MAX_CHRS int "Maximum number of characteristics per connection" depends on BT_NIMBLE_GATT_CACHING @@ -666,14 +786,22 @@ config BT_NIMBLE_GATT_CACHING_MAX_DSCS default 64 help Set this option to set the upper limit on number of descriptors per connection to be cached. +config BT_NIMBLE_GATT_CACHING_DISABLE_AUTO + bool "Do not start discovery procedure automatically upon receiving Out of Sync" + depends on BT_NIMBLE_GATT_CACHING + default n + help + When client receives ATT out-of-sync error message, it will not automatically start the discovery procedure + to correct the invalid cache. config BT_NIMBLE_WHITELIST_SIZE int "BLE white list size" depends on BT_NIMBLE_ENABLED + range 1 31 if SOC_ESP_NIMBLE_CONTROLLER range 1 15 default 12 help - BLE list size + BLE list size config BT_NIMBLE_TEST_THROUGHPUT_TEST bool "Throughput Test Mode enable" @@ -707,8 +835,172 @@ config BT_NIMBLE_BLE_GATT_BLOB_TRANSFER This option is used when data to be sent is more than 512 bytes. For peripheral role, BT_NIMBLE_MSYS_1_BLOCK_COUNT needs to be increased according to the need. -menu "GAP Service" +menu "BLE Services" + depends on BT_NIMBLE_GATT_SERVER + + config BT_NIMBLE_PROX_SERVICE + bool "Proximity service" + default y + help + Enable Proximity Service support + + config BT_NIMBLE_ANS_SERVICE + bool "Alert Notification service" + default y + help + Enable Alert Notification Service support + + config BT_NIMBLE_CTS_SERVICE + bool "Current Time Service" + default y + help + Enable Current Time Service support + + config BT_NIMBLE_HTP_SERVICE + bool "Health Thermometer service" + default y + help + Enable Health Thermometer Service support + + config BT_NIMBLE_IPSS_SERVICE + bool "Internet Protocol Support service" + default y + help + Enable Internet Protocol Service support + + config BT_NIMBLE_TPS_SERVICE + bool "Tx Power service" + default y + help + Enable Tx Power Service support + + config BT_NIMBLE_IAS_SERVICE + bool "Immediate Alert service" + default y + help + Enable Immediate Alert Service support + + config BT_NIMBLE_LLS_SERVICE + bool "Link Loss service" + default y + help + Enable Link Loss Service support + + config BT_NIMBLE_SPS_SERVICE + bool "Serial Port service" + default y + help + Enable Serial Port Service support + + config BT_NIMBLE_HR_SERVICE + bool "Heart Rate service" + default y + help + Enable HeartRate Service support + + menuconfig BT_NIMBLE_HID_SERVICE + bool "HID service" + default n + help + Enable HID service support + + config BT_NIMBLE_SVC_HID_MAX_INSTANCES + depends on BT_NIMBLE_HID_SERVICE + int "Maximum HID service instances" + default 2 + help + Defines maximum number of HID service instances + + config BT_NIMBLE_SVC_HID_MAX_RPTS + depends on BT_NIMBLE_HID_SERVICE + int "Maximum HID Report characteristics per service instance" + default 3 + help + Defines maximum number of report characteristics per service instance + + menuconfig BT_NIMBLE_BAS_SERVICE + bool "Battery service" + default y + help + Enable Battery service support + + config BT_NIMBLE_SVC_BAS_BATTERY_LEVEL_NOTIFY + depends on BT_NIMBLE_BAS_SERVICE + bool "BAS Battery Level NOTIFY permission" + help + Enable/Disable notifications on BAS Battery Level Characteristic + + menuconfig BT_NIMBLE_DIS_SERVICE + bool "DIS service" + default y + help + Enable DIS service support + + config BT_NIMBLE_SVC_DIS_MANUFACTURER_NAME + depends on BT_NIMBLE_DIS_SERVICE + bool "Manufacturer Name" + default n + help + Enable the DIS characteristic Manufacturer Name String characteristic + + config BT_NIMBLE_SVC_DIS_SERIAL_NUMBER + depends on BT_NIMBLE_DIS_SERVICE + bool "Serial Number" + default n + help + Enable the DIS Serial Number characteristic + + config BT_NIMBLE_SVC_DIS_HARDWARE_REVISION + depends on BT_NIMBLE_DIS_SERVICE + bool "Hardware Revision" + default n + help + Enable the DIS Hardware Revision characteristic + + config BT_NIMBLE_SVC_DIS_FIRMWARE_REVISION + depends on BT_NIMBLE_DIS_SERVICE + bool "Firmware Revision" + default n + help + Enable the DIS Firmware Revision characteristic + + config BT_NIMBLE_SVC_DIS_SOFTWARE_REVISION + depends on BT_NIMBLE_DIS_SERVICE + bool "Software Revision" + default n + help + Enable the DIS Software Revision characteristic + + config BT_NIMBLE_SVC_DIS_SYSTEM_ID + depends on BT_NIMBLE_DIS_SERVICE + bool "System ID" + default n + help + Enable the DIS System ID characteristic + + config BT_NIMBLE_SVC_DIS_PNP_ID + depends on BT_NIMBLE_DIS_SERVICE + bool "PnP ID" + default n + help + Enable the DIS PnP ID characteristic + + config BT_NIMBLE_SVC_DIS_INCLUDED + depends on BT_NIMBLE_DIS_SERVICE + bool "DIS as an Included Service" + default n + help + Use DIS as an included service + + menuconfig BT_NIMBLE_GAP_SERVICE + bool "GAP Service" + default y + help + Enable GAP Service support + menu "GAP Appearance write permissions" + depends on BT_NIMBLE_GAP_SERVICE + config BT_NIMBLE_SVC_GAP_APPEAR_WRITE bool "Write" default n @@ -718,14 +1010,12 @@ menu "GAP Service" config BT_NIMBLE_SVC_GAP_APPEAR_WRITE_ENC depends on BT_NIMBLE_SVC_GAP_APPEAR_WRITE bool "Write with encryption" - default n help Enable write with encryption permission (BLE_GATT_CHR_F_WRITE_ENC) config BT_NIMBLE_SVC_GAP_APPEAR_WRITE_AUTHEN depends on BT_NIMBLE_SVC_GAP_APPEAR_WRITE bool "Write with authentication" - default n help Enable write with authentication permission (BLE_GATT_CHR_F_WRITE_AUTHEN) @@ -735,48 +1025,49 @@ menu "GAP Service" default n help Enable write with authorisation permission (BLE_GATT_CHR_F_WRITE_AUTHOR) - endmenu - config BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM - int - default 0 if !BT_NIMBLE_SVC_GAP_APPEAR_WRITE - default 8 if BT_NIMBLE_SVC_GAP_APPEAR_WRITE - - config BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ENC - int - default 0 if !BT_NIMBLE_SVC_GAP_APPEAR_WRITE_ENC - default 4096 if BT_NIMBLE_SVC_GAP_APPEAR_WRITE_ENC - - config BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHN - int - default 0 if !BT_NIMBLE_SVC_GAP_APPEAR_WRITE_AUTHEN - default 8192 if BT_NIMBLE_SVC_GAP_APPEAR_WRITE_AUTHEN - - config BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHR - int - default 0 if !BT_NIMBLE_SVC_GAP_APPEAR_WRITE_AUTHOR - default 16384 if BT_NIMBLE_SVC_GAP_APPEAR_WRITE_AUTHOR + config BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM + int + default 0 if !BT_NIMBLE_SVC_GAP_APPEAR_WRITE + default 8 if BT_NIMBLE_SVC_GAP_APPEAR_WRITE + + config BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ENC + int + default 0 if !BT_NIMBLE_SVC_GAP_APPEAR_WRITE_ENC + default 4096 if BT_NIMBLE_SVC_GAP_APPEAR_WRITE_ENC + + config BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHN + int + default 0 if !BT_NIMBLE_SVC_GAP_APPEAR_WRITE_AUTHEN + default 8192 if BT_NIMBLE_SVC_GAP_APPEAR_WRITE_AUTHEN + + config BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHR + int + default 0 if !BT_NIMBLE_SVC_GAP_APPEAR_WRITE_AUTHOR + default 16384 if BT_NIMBLE_SVC_GAP_APPEAR_WRITE_AUTHOR + endmenu choice BT_NIMBLE_SVC_GAP_CENT_ADDR_RESOLUTION prompt "GAP Characteristic - Central Address Resolution" + depends on BT_NIMBLE_GAP_SERVICE default BT_NIMBLE_SVC_GAP_CAR_CHAR_NOT_SUPP help - Weather or not Central Address Resolution characteristic is supported on - the device, and if supported, weather or not Central Address Resolution - is supported. + Weather or not Central Address Resolution characteristic is supported on + the device, and if supported, weather or not Central Address Resolution + is supported. - - Central Address Resolution characteristic not supported - - Central Address Resolution not supported - - Central Address Resolution supported + - Central Address Resolution characteristic not supported + - Central Address Resolution not supported + - Central Address Resolution supported - config BT_NIMBLE_SVC_GAP_CAR_CHAR_NOT_SUPP - bool "Characteristic not supported" + config BT_NIMBLE_SVC_GAP_CAR_CHAR_NOT_SUPP + bool "Characteristic not supported" - config BT_NIMBLE_SVC_GAP_CAR_NOT_SUPP - bool "Central Address Resolution not supported" + config BT_NIMBLE_SVC_GAP_CAR_NOT_SUPP + bool "Central Address Resolution not supported" - config BT_NIMBLE_SVC_GAP_CAR_SUPP - bool "Central Address Resolution supported" + config BT_NIMBLE_SVC_GAP_CAR_SUPP + bool "Central Address Resolution supported" endchoice config BT_NIMBLE_SVC_GAP_CENT_ADDR_RESOLUTION @@ -785,7 +1076,9 @@ menu "GAP Service" default 0 if BT_NIMBLE_SVC_GAP_CAR_NOT_SUPP default 1 if BT_NIMBLE_SVC_GAP_CAR_SUPP + menu "GAP device name write permissions" + depends on BT_NIMBLE_GAP_SERVICE config BT_NIMBLE_SVC_GAP_NAME_WRITE bool "Write" default n @@ -814,6 +1107,40 @@ menu "GAP Service" Enable write with authorisation permission (BLE_GATT_CHR_F_WRITE_AUTHOR) endmenu + menu "PPCP settings" + depends on BT_NIMBLE_GAP_SERVICE + config BT_NIMBLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL + int "PPCP Connection Interval Max (Unit: 1.25 ms)" + depends on BT_NIMBLE_ROLE_PERIPHERAL && BT_NIMBLE_GAP_SERVICE + default 0 + help + Peripheral Preferred Connection Parameter: Connection Interval maximum value + Interval Max = value * 1.25 ms + + config BT_NIMBLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL + int "PPCP Connection Interval Min (Unit: 1.25 ms)" + depends on BT_NIMBLE_ROLE_PERIPHERAL && BT_NIMBLE_GAP_SERVICE + default 0 + help + Peripheral Preferred Connection Parameter: Connection Interval minimum value + Interval Min = value * 1.25 ms + + config BT_NIMBLE_SVC_GAP_PPCP_SLAVE_LATENCY + int "PPCP Slave Latency" + depends on BT_NIMBLE_GAP_SERVICE + default 0 + help + Peripheral Preferred Connection Parameter: Slave Latency + + config BT_NIMBLE_SVC_GAP_PPCP_SUPERVISION_TMO + int "PPCP Supervision Timeout (Uint: 10 ms)" + depends on BT_NIMBLE_GAP_SERVICE + default 0 + help + Peripheral Preferred Connection Parameter: Supervision Timeout + Timeout = Value * 10 ms + endmenu + config BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM int default 0 if !BT_NIMBLE_SVC_GAP_NAME_WRITE @@ -834,58 +1161,18 @@ menu "GAP Service" default 0 if !BT_NIMBLE_SVC_GAP_NAME_WRITE_AUTHOR default 16384 if BT_NIMBLE_SVC_GAP_NAME_WRITE_AUTHOR - config BT_NIMBLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL - int "PPCP Connection Interval Max (Unit: 1.25 ms)" - depends on BT_NIMBLE_ROLE_PERIPHERAL - default 0 - help - Peripheral Preferred Connection Parameter: Connection Interval maximum value - Interval Max = value * 1.25 ms - - config BT_NIMBLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL - int "PPCP Connection Interval Min (Unit: 1.25 ms)" - depends on BT_NIMBLE_ROLE_PERIPHERAL - default 0 - help - Peripheral Preferred Connection Parameter: Connection Interval minimum value - Interval Min = value * 1.25 ms - - config BT_NIMBLE_SVC_GAP_PPCP_SLAVE_LATENCY - int "PPCP Slave Latency" - default 0 - help - Peripheral Preferred Connection Parameter: Slave Latency - - config BT_NIMBLE_SVC_GAP_PPCP_SUPERVISION_TMO - int "PPCP Supervision Timeout (Uint: 10 ms)" - default 0 - help - Peripheral Preferred Connection Parameter: Supervision Timeout - Timeout = Value * 10 ms - -endmenu - -menu "BLE Services" - menuconfig BT_NIMBLE_HID_SERVICE - bool "HID service" - depends on BT_NIMBLE_ENABLED + config BT_NIMBLE_SVC_GAP_GATT_SECURITY_LEVEL + bool "LE GATT Security Level Characteristic" default n help - Enable HID service support + Enable the LE GATT Security Level Characteristic - config BT_NIMBLE_SVC_HID_MAX_INSTANCES - depends on BT_NIMBLE_HID_SERVICE - int "Maximum HID service instances" - default 2 + config BT_NIMBLE_SVC_GAP_RPA_ONLY + bool "Resolvable Private Address Only characteristic" + default n help - Defines maximum number of HID service instances + Enable the Resolvable Private Address Only characteristic - config BT_NIMBLE_SVC_HID_MAX_RPTS - depends on BT_NIMBLE_HID_SERVICE - int "Maximum HID Report characteristics per service instance" - default 3 - help - Defines maximum number of report characteristics per service instance endmenu config BT_NIMBLE_VS_SUPPORT @@ -906,7 +1193,6 @@ config BT_NIMBLE_OPTIMIZE_MULTI_CONN config BT_NIMBLE_ENC_ADV_DATA bool "Encrypted Advertising Data" - select BT_NIMBLE_EXT_ADV help This option is used to enable encrypted advertising data. @@ -923,6 +1209,12 @@ config BT_NIMBLE_HIGH_DUTY_ADV_ITVL help This enable BLE high duty advertising interval feature +config BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN + bool "Allow Connections with scanning in progress" + depends on BT_NIMBLE_ENABLED && !(IDF_TARGET_ESP32C2) + help + This enables support for user to initiate a new connection with scan in progress + config BT_NIMBLE_HOST_QUEUE_CONG_CHECK bool "BLE queue congestion check" depends on BT_NIMBLE_ENABLED @@ -932,6 +1224,15 @@ config BT_NIMBLE_HOST_QUEUE_CONG_CHECK or application layer handling adv packets is slow, it will cause the controller memory to run out. if enabled, adv packets will be lost when host queue is congested. +config BT_NIMBLE_GATTC_PROC_PREEMPTION_PROTECT + bool "Gatt-proc preemption protect check" + depends on BT_NIMBLE_ENABLED + default n + help + When BLE and Wireless protocol/IEEE 802.15.4 operate in coexistence, BLE preemption + can disrupt the GATT context,causing the service discovery callback to not be invoked. + A temporary list is maintained to preserve the GATT context and use it in case of preemption. + menu "Host-controller Transport" config BT_NIMBLE_TRANSPORT_UART bool "Enable Uart Transport" @@ -1048,3 +1349,17 @@ menu "Host-controller Transport" help UART HCI CTS pin endmenu + +config BT_NIMBLE_EATT_CHAN_NUM + int "Maximum number of EATT channels" + default 0 + depends on BT_NIMBLE_ENABLED + help + Defines the number of channels EATT bearers can use + +config BT_NIMBLE_SUBRATE + bool "Enable Subrate Change" + default n + depends on BT_NIMBLE_ENABLED + help + Enable connection subrate change feature diff --git a/lib/bt/host/nimble/esp-hci/src/esp_nimble_hci.c b/lib/bt/host/nimble/esp-hci/src/esp_nimble_hci.c index 605b8312..59e574ec 100644 --- a/lib/bt/host/nimble/esp-hci/src/esp_nimble_hci.c +++ b/lib/bt/host/nimble/esp-hci/src/esp_nimble_hci.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,6 +21,12 @@ #include "freertos/semphr.h" #include "esp_compiler.h" #include "soc/soc_caps.h" +#include "bt_common.h" +#include "hci_log/bt_hci_log.h" + +#if CONFIG_BT_BLE_LOG_SPI_OUT_HCI_ENABLED +#include "ble_log/ble_log_spi_out.h" +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_HCI_ENABLED #define NIMBLE_VHCI_TIMEOUT_MS 2000 #define BLE_HCI_EVENT_HDR_LEN (2) @@ -61,6 +67,16 @@ void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb, ble_hci_rx_acl_hs_arg = acl_arg; } +void esp_vhci_host_send_packet_wrapper(uint8_t *data, uint16_t len) +{ +#if (BT_HCI_LOG_INCLUDED == TRUE) + bt_hci_log_record_hci_data(data[0], &data[1], len - 1); +#endif +#if (CONFIG_BT_BLE_LOG_SPI_OUT_HCI_ENABLED && !SOC_ESP_NIMBLE_CONTROLLER) + ble_log_spi_out_write_with_ts(BLE_LOG_SPI_OUT_SOURCE_HCI_DOWNSTREAM, data, len); +#endif // (CONFIG_BT_BLE_LOG_SPI_OUT_HCI_ENABLED && !SOC_ESP_NIMBLE_CONTROLLER) + esp_vhci_host_send_packet(data, len); +} int ble_hci_trans_hs_cmd_tx(uint8_t *cmd) { @@ -75,7 +91,7 @@ int ble_hci_trans_hs_cmd_tx(uint8_t *cmd) } if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) { - esp_vhci_host_send_packet(cmd, len); + esp_vhci_host_send_packet_wrapper(cmd, len); } else { rc = BLE_HS_ETIMEOUT_HCI; } @@ -112,7 +128,7 @@ int ble_hci_trans_hs_acl_tx(struct os_mbuf *om) len += OS_MBUF_PKTLEN(om); if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) { - esp_vhci_host_send_packet(data, len); + esp_vhci_host_send_packet_wrapper(data, len); } else { rc = BLE_HS_ETIMEOUT_HCI; } @@ -154,14 +170,14 @@ static void ble_hci_rx_acl(uint8_t *data, uint16_t len) m = ble_transport_alloc_acl_from_ll(); if (!m) { - ESP_LOGD(TAG,"Failed to allocate buffer, retrying "); + esp_rom_printf("Failed to allocate buffer, retrying "); /* Give some time to free buffer and try again */ vTaskDelay(1); } }while(!m); if ((rc = os_mbuf_append(m, data, len)) != 0) { - ESP_LOGE(TAG, "%s failed to os_mbuf_append; rc = %d", __func__, rc); + esp_rom_printf("%s failed to os_mbuf_append; rc = %d", __func__, rc); os_mbuf_free_chain(m); return; } @@ -181,14 +197,49 @@ static void controller_rcv_pkt_ready(void) } } +static void dummy_controller_rcv_pkt_ready(void) +{ + /* Dummy function */ +} + +void bt_record_hci_data(uint8_t *data, uint16_t len) +{ +#if (BT_HCI_LOG_INCLUDED == TRUE) + if ((data[0] == BLE_HCI_UART_H4_EVT) && (data[1] == BLE_HCI_EVCODE_LE_META) && ((data[3] == BLE_HCI_LE_SUBEV_ADV_RPT) || (data[3] == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) + || (data[3] == BLE_HCI_LE_SUBEV_EXT_ADV_RPT) || (data[3] == BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT))) { + bt_hci_log_record_hci_adv(HCI_LOG_DATA_TYPE_ADV, &data[2], len - 2); + } else { + uint8_t data_type; + if (data[0] == HCI_LOG_DATA_TYPE_ISO_DATA) { + data_type = HCI_LOG_DATA_TYPE_ISO_DATA; + } else { + data_type = ((data[0] == 2) ? HCI_LOG_DATA_TYPE_C2H_ACL : data[0]); + } + bt_hci_log_record_hci_data(data_type, &data[1], len - 1); + } +#endif // (BT_HCI_LOG_INCLUDED == TRUE) +} + +static int dummy_host_rcv_pkt(uint8_t *data, uint16_t len) +{ + /* Dummy function */ + return 0; +} + /* * @brief: BT controller callback function, to transfer data packet to the host */ static int host_rcv_pkt(uint8_t *data, uint16_t len) { +#if (CONFIG_BT_BLE_LOG_SPI_OUT_HCI_ENABLED && !SOC_ESP_NIMBLE_CONTROLLER) + ble_log_spi_out_write_with_ts(BLE_LOG_SPI_OUT_SOURCE_HCI_UPSTREAM, data, len); +#endif // (CONFIG_BT_BLE_LOG_SPI_OUT_HCI_ENABLED && !SOC_ESP_NIMBLE_CONTROLLER) + + bt_record_hci_data(data, len); + if(!ble_hs_enabled_state) { /* If host is not enabled, drop the packet */ - ESP_LOGE(TAG, "Host not enabled. Dropping the packet!"); + esp_rom_printf("Host not enabled. Dropping the packet!"); return 0; } @@ -201,7 +252,7 @@ static int host_rcv_pkt(uint8_t *data, uint16_t len) assert(totlen <= UINT8_MAX + BLE_HCI_EVENT_HDR_LEN); if (totlen > MYNEWT_VAL(BLE_TRANSPORT_EVT_SIZE)) { - ESP_LOGE(TAG, "Received HCI data length at host (%d) exceeds maximum configured HCI event buffer size (%d).", + esp_rom_printf("Received HCI data length at host (%d) exceeds maximum configured HCI event buffer size (%d).", totlen, MYNEWT_VAL(BLE_TRANSPORT_EVT_SIZE)); ble_hs_sched_reset(BLE_HS_ECONTROLLER); return 0; @@ -240,6 +291,11 @@ static const esp_vhci_host_callback_t vhci_host_cb = { .notify_host_recv = host_rcv_pkt, }; +static const esp_vhci_host_callback_t dummy_vhci_host_cb = { + .notify_host_send_available = dummy_controller_rcv_pkt_ready, + .notify_host_recv = dummy_host_rcv_pkt, +}; + extern void ble_transport_init(void); extern esp_err_t ble_buf_alloc(void); @@ -289,6 +345,8 @@ esp_err_t esp_nimble_hci_deinit(void) } ble_transport_deinit(); + esp_vhci_host_register_callback(&dummy_vhci_host_cb); + ble_buf_free(); #if MYNEWT_VAL(BLE_QUEUE_CONG_CHECK) diff --git a/lib/bt/host/nimble/nimble/.travis.yml b/lib/bt/host/nimble/nimble/.travis.yml deleted file mode 100644 index d3dd9742..00000000 --- a/lib/bt/host/nimble/nimble/.travis.yml +++ /dev/null @@ -1,156 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -language: go - -dist: bionic - -_addons: &addon_conf - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-multilib - - gcc-7-multilib - - g++-multilib - -go: - - "1.16" - -git: - depth: false - -matrix: - allow_failures: - - env: - - TEST=BUILD_PORTS - - VM_AMOUNT=1 - - TARGET_SET=1 - include: - # Style checking - - os: linux - language: python - python: - - "3.5" - addons: - apt: - packages: - - "python3-pip" - env: - - TEST=STYLE - - DEBUG=1 - - # newt build - - os: linux - addons: *addon_conf - env: - - TEST=BUILD_TARGETS - - VM_AMOUNT=4 - - TARGET_SET=1 - - os: linux - addons: *addon_conf - env: - - TEST=BUILD_TARGETS - - VM_AMOUNT=4 - - TARGET_SET=2 - - os: linux - addons: *addon_conf - env: - - TEST=BUILD_TARGETS - - VM_AMOUNT=4 - - TARGET_SET=3 - - os: linux - addons: *addon_conf - env: - - TEST=BUILD_TARGETS - - VM_AMOUNT=4 - - TARGET_SET=4 - - # newt test all (Linux) - - os: linux - addons: *addon_conf - env: - - TEST=TEST_ALL - - VM_AMOUNT=2 - - TARGET_SET=1 - - os: linux - addons: *addon_conf - env: - - TEST=TEST_ALL - - VM_AMOUNT=2 - - TARGET_SET=2 - - # ports - - os: linux - addons: *addon_conf - env: - - TEST=BUILD_PORTS - - VM_AMOUNT=1 - - TARGET_SET=1 - - - os: windows - env: - - TEST=BUILD_TARGETS_WINDOWS - - VM_AMOUNT=1 - - TARGET_SET=1 - -before_install: - - printenv - - export GOPATH=$HOME/gopath - - go version - -install: - - git clone https://github.com/JuulLabs-OSS/mynewt-travis-ci $HOME/ci - - chmod +x $HOME/ci/*.sh - - | - if [ "${TEST}" == "STYLE" ]; then - pip3 install requests - else - $HOME/ci/${TRAVIS_OS_NAME}_travis_install.sh - fi - -before_script: - - | - if [ "${TEST}" == "STYLE" ]; then - $HOME/ci/install_uncrustify.sh - else - newt version - gcc --version - if [ "${TEST}" != "TEST_ALL" ]; then arm-none-eabi-gcc --version; fi - cp -R $HOME/ci/mynewt-nimble-project.yml project.yml - mkdir -p targets - cp -R $HOME/ci/mynewt-nimble-targets targets - $HOME/ci/prepare_test.sh $VM_AMOUNT - mkdir -p repos && pushd repos/ - git clone --depth=1 https://github.com/apache/mynewt-core apache-mynewt-core - git clone --depth=1 https://github.com/JuulLabs-OSS/mcuboot mcuboot - git clone --depth=1 https://github.com/apache/mynewt-mcumgr apache-mynewt-mcumgr - popd - fi - -script: - - | - if [ "${TEST}" == "STYLE" ]; then - python3 $HOME/ci/check_style.py - else - $HOME/ci/run_test.sh - fi - -cache: - directories: - - $HOME/TOOLCHAIN - - $HOME/Library/Caches/Homebrew diff --git a/lib/bt/host/nimble/nimble/apps/blecent/src/main.c b/lib/bt/host/nimble/nimble/apps/blecent/src/main.c index f794937e..a88e9234 100644 --- a/lib/bt/host/nimble/nimble/apps/blecent/src/main.c +++ b/lib/bt/host/nimble/nimble/apps/blecent/src/main.c @@ -216,7 +216,7 @@ static void blecent_scan(void) { uint8_t own_addr_type; - struct ble_gap_disc_params disc_params; + struct ble_gap_disc_params disc_params = {0}; int rc; /* Figure out address to use while advertising (no privacy for now) */ diff --git a/lib/bt/host/nimble/nimble/apps/bttester/src/atomic.h b/lib/bt/host/nimble/nimble/apps/bttester/src/atomic.h deleted file mode 100644 index 66283e9a..00000000 --- a/lib/bt/host/nimble/nimble/apps/bttester/src/atomic.h +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/* atomic operations */ - -/* - * Copyright (c) 1997-2015, Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __ATOMIC_H__ -#define __ATOMIC_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef int atomic_t; -typedef atomic_t atomic_val_t; - -/** - * @defgroup atomic_apis Atomic Services APIs - * @ingroup kernel_apis - * @{ - */ - -/** - * @brief Atomic compare-and-set. - * - * This routine performs an atomic compare-and-set on @a target. If the current - * value of @a target equals @a old_value, @a target is set to @a new_value. - * If the current value of @a target does not equal @a old_value, @a target - * is left unchanged. - * - * @param target Address of atomic variable. - * @param old_value Original value to compare against. - * @param new_value New value to store. - * @return 1 if @a new_value is written, 0 otherwise. - */ -static inline int atomic_cas(atomic_t *target, atomic_val_t old_value, - atomic_val_t new_value) -{ - return __atomic_compare_exchange_n(target, &old_value, new_value, - 0, __ATOMIC_SEQ_CST, - __ATOMIC_SEQ_CST); -} - -/** - * - * @brief Atomic addition. - * - * This routine performs an atomic addition on @a target. - * - * @param target Address of atomic variable. - * @param value Value to add. - * - * @return Previous value of @a target. - */ -static inline atomic_val_t atomic_add(atomic_t *target, atomic_val_t value) -{ - return __atomic_fetch_add(target, value, __ATOMIC_SEQ_CST); -} - -/** - * - * @brief Atomic subtraction. - * - * This routine performs an atomic subtraction on @a target. - * - * @param target Address of atomic variable. - * @param value Value to subtract. - * - * @return Previous value of @a target. - */ - -static inline atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value) -{ - return __atomic_fetch_sub(target, value, __ATOMIC_SEQ_CST); -} - -/** - * - * @brief Atomic increment. - * - * This routine performs an atomic increment by 1 on @a target. - * - * @param target Address of atomic variable. - * - * @return Previous value of @a target. - */ - -static inline atomic_val_t atomic_inc(atomic_t *target) -{ - return atomic_add(target, 1); -} - -/** - * - * @brief Atomic decrement. - * - * This routine performs an atomic decrement by 1 on @a target. - * - * @param target Address of atomic variable. - * - * @return Previous value of @a target. - */ - -static inline atomic_val_t atomic_dec(atomic_t *target) -{ - return atomic_sub(target, 1); -} - -/** - * - * @brief Atomic get. - * - * This routine performs an atomic read on @a target. - * - * @param target Address of atomic variable. - * - * @return Value of @a target. - */ - -static inline atomic_val_t atomic_get(const atomic_t *target) -{ - return __atomic_load_n(target, __ATOMIC_SEQ_CST); -} - -/** - * - * @brief Atomic get-and-set. - * - * This routine atomically sets @a target to @a value and returns - * the previous value of @a target. - * - * @param target Address of atomic variable. - * @param value Value to write to @a target. - * - * @return Previous value of @a target. - */ - -static inline atomic_val_t atomic_set(atomic_t *target, atomic_val_t value) -{ - /* This builtin, as described by Intel, is not a traditional - * test-and-set operation, but rather an atomic exchange operation. It - * writes value into *ptr, and returns the previous contents of *ptr. - */ - return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST); -} - -/** - * - * @brief Atomic clear. - * - * This routine atomically sets @a target to zero and returns its previous - * value. (Hence, it is equivalent to atomic_set(target, 0).) - * - * @param target Address of atomic variable. - * - * @return Previous value of @a target. - */ - -static inline atomic_val_t atomic_clear(atomic_t *target) -{ - return atomic_set(target, 0); -} - -/** - * - * @brief Atomic bitwise inclusive OR. - * - * This routine atomically sets @a target to the bitwise inclusive OR of - * @a target and @a value. - * - * @param target Address of atomic variable. - * @param value Value to OR. - * - * @return Previous value of @a target. - */ - -static inline atomic_val_t atomic_or(atomic_t *target, atomic_val_t value) -{ - return __atomic_fetch_or(target, value, __ATOMIC_SEQ_CST); -} - -/** - * - * @brief Atomic bitwise exclusive OR (XOR). - * - * This routine atomically sets @a target to the bitwise exclusive OR (XOR) of - * @a target and @a value. - * - * @param target Address of atomic variable. - * @param value Value to XOR - * - * @return Previous value of @a target. - */ - -static inline atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value) -{ - return __atomic_fetch_xor(target, value, __ATOMIC_SEQ_CST); -} - -/** - * - * @brief Atomic bitwise AND. - * - * This routine atomically sets @a target to the bitwise AND of @a target - * and @a value. - * - * @param target Address of atomic variable. - * @param value Value to AND. - * - * @return Previous value of @a target. - */ - -static inline atomic_val_t atomic_and(atomic_t *target, atomic_val_t value) -{ - return __atomic_fetch_and(target, value, __ATOMIC_SEQ_CST); -} - -/** - * - * @brief Atomic bitwise NAND. - * - * This routine atomically sets @a target to the bitwise NAND of @a target - * and @a value. (This operation is equivalent to target = ~(target & value).) - * - * @param target Address of atomic variable. - * @param value Value to NAND. - * - * @return Previous value of @a target. - */ - -static inline atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value) -{ - return __atomic_fetch_nand(target, value, __ATOMIC_SEQ_CST); -} - - /** - * @brief Initialize an atomic variable. - * - * This macro can be used to initialize an atomic variable. For example, - * @code atomic_t my_var = ATOMIC_INIT(75); @endcode - * - * @param i Value to assign to atomic variable. - */ -#define ATOMIC_INIT(i) (i) - - /** - * @cond INTERNAL_HIDDEN - */ - -#define ATOMIC_BITS (sizeof(atomic_val_t) * 8) -#define ATOMIC_MASK(bit) (1 << ((bit) & (ATOMIC_BITS - 1))) -#define ATOMIC_ELEM(addr, bit) ((addr) + ((bit) / ATOMIC_BITS)) - - /** - * INTERNAL_HIDDEN @endcond - */ - - /** - * @brief Define an array of atomic variables. - * - * This macro defines an array of atomic variables containing at least - * @a num_bits bits. - * - * @note - * If used from file scope, the bits of the array are initialized to zero; - * if used from within a function, the bits are left uninitialized. - * - * @param name Name of array of atomic variables. - * @param num_bits Number of bits needed. - */ -#define ATOMIC_DEFINE(name, num_bits) \ - atomic_t name[1 + ((num_bits) - 1) / ATOMIC_BITS] - - /** - * @brief Atomically test a bit. - * - * This routine tests whether bit number @a bit of @a target is set or not. - * The target may be a single atomic variable or an array of them. - * - * @param target Address of atomic variable or array. - * @param bit Bit number (starting from 0). - * - * @return 1 if the bit was set, 0 if it wasn't. - */ - static inline int - atomic_test_bit(const atomic_t *target, int bit) - { - atomic_val_t val = atomic_get(ATOMIC_ELEM(target, bit)); - - return (1 & (val >> (bit & (ATOMIC_BITS - 1)))); - } - - /** - * @brief Atomically test and clear a bit. - * - * Atomically clear bit number @a bit of @a target and return its old value. - * The target may be a single atomic variable or an array of them. - * - * @param target Address of atomic variable or array. - * @param bit Bit number (starting from 0). - * - * @return 1 if the bit was set, 0 if it wasn't. - */ - static inline int - atomic_test_and_clear_bit(atomic_t *target, int bit) - { - atomic_val_t mask = ATOMIC_MASK(bit); - atomic_val_t old; - - old = atomic_and(ATOMIC_ELEM(target, bit), ~mask); - - return (old & mask) != 0; - } - - /** - * @brief Atomically set a bit. - * - * Atomically set bit number @a bit of @a target and return its old value. - * The target may be a single atomic variable or an array of them. - * - * @param target Address of atomic variable or array. - * @param bit Bit number (starting from 0). - * - * @return 1 if the bit was set, 0 if it wasn't. - */ - static inline int - atomic_test_and_set_bit(atomic_t *target, int bit) - { - atomic_val_t mask = ATOMIC_MASK(bit); - atomic_val_t old; - - old = atomic_or(ATOMIC_ELEM(target, bit), mask); - - return (old & mask) != 0; - } - - /** - * @brief Atomically clear a bit. - * - * Atomically clear bit number @a bit of @a target. - * The target may be a single atomic variable or an array of them. - * - * @param target Address of atomic variable or array. - * @param bit Bit number (starting from 0). - * - * @return N/A - */ - static inline void - atomic_clear_bit(atomic_t *target, int bit) - { - atomic_val_t mask = ATOMIC_MASK(bit); - - atomic_and(ATOMIC_ELEM(target, bit), ~mask); - } - - /** - * @brief Atomically set a bit. - * - * Atomically set bit number @a bit of @a target. - * The target may be a single atomic variable or an array of them. - * - * @param target Address of atomic variable or array. - * @param bit Bit number (starting from 0). - * - * @return N/A - */ - static inline void - atomic_set_bit(atomic_t *target, int bit) - { - atomic_val_t mask = ATOMIC_MASK(bit); - - atomic_or(ATOMIC_ELEM(target, bit), mask); - } - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* __ATOMIC_H__ */ diff --git a/lib/bt/host/nimble/nimble/apps/bttester/src/bttester.h b/lib/bt/host/nimble/nimble/apps/bttester/src/bttester.h deleted file mode 100644 index 641db8bd..00000000 --- a/lib/bt/host/nimble/nimble/apps/bttester/src/bttester.h +++ /dev/null @@ -1,1321 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/* bttester.h - Bluetooth tester headers */ - -/* - * Copyright (C) 2021 Codecoup - * Copyright (c) 2015-2016 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __BTTESTER_H__ -#define __BTTESTER_H__ - -#include "syscfg/syscfg.h" -#include "host/ble_gatt.h" - -#if MYNEWT_VAL(BLE_MESH) -#include "mesh/glue.h" -#else -#include "glue.h" -#endif - -#define BTP_MTU MYNEWT_VAL(BTTESTER_BTP_DATA_SIZE_MAX) -#define BTP_DATA_MAX_SIZE (BTP_MTU - sizeof(struct btp_hdr)) - -#define BTP_INDEX_NONE 0xff - -#define BTP_SERVICE_ID_CORE 0 -#define BTP_SERVICE_ID_GAP 1 -#define BTP_SERVICE_ID_GATT 2 -#define BTP_SERVICE_ID_L2CAP 3 -#define BTP_SERVICE_ID_MESH 4 -#define BTP_SERVICE_ID_GATTC 6 - -#define BTP_STATUS_SUCCESS 0x00 -#define BTP_STATUS_FAILED 0x01 -#define BTP_STATUS_UNKNOWN_CMD 0x02 -#define BTP_STATUS_NOT_READY 0x03 - -#define SYS_LOG_DBG(fmt, ...) \ - if (MYNEWT_VAL(BTTESTER_DEBUG)) { \ - console_printf("[DBG] %s: " fmt "\n", \ - __func__, ## __VA_ARGS__); \ - } -#define SYS_LOG_INF(fmt, ...) console_printf("[INF] %s: " fmt "\n", \ - __func__, ## __VA_ARGS__); -#define SYS_LOG_ERR(fmt, ...) console_printf("[WRN] %s: " fmt "\n", \ - __func__, ## __VA_ARGS__); - -#define SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG -#define SYS_LOG_DOMAIN "bttester" - -#define sys_cpu_to_le32 htole32 -#define sys_le32_to_cpu le32toh -#define sys_cpu_to_le16 htole16 - -struct btp_hdr { - uint8_t service; - uint8_t opcode; - uint8_t index; - uint16_t len; - uint8_t data[0]; -} __packed; - -#define BTP_STATUS 0x00 -struct btp_status { - uint8_t code; -} __packed; - -/* Core Service */ -#define CORE_READ_SUPPORTED_COMMANDS 0x01 -struct core_read_supported_commands_rp { - uint8_t data[0]; -} __packed; - -#define CORE_READ_SUPPORTED_SERVICES 0x02 -struct core_read_supported_services_rp { - uint8_t data[0]; -} __packed; - -#define CORE_REGISTER_SERVICE 0x03 -struct core_register_service_cmd { - uint8_t id; -} __packed; - -#define CORE_UNREGISTER_SERVICE 0x04 -struct core_unregister_service_cmd { - uint8_t id; -} __packed; - -/* events */ -#define CORE_EV_IUT_READY 0x80 - -/* GAP Service */ -/* commands */ -#define GAP_READ_SUPPORTED_COMMANDS 0x01 -struct gap_read_supported_commands_rp { - uint8_t data[0]; -} __packed; - -#define GAP_READ_CONTROLLER_INDEX_LIST 0x02 -struct gap_read_controller_index_list_rp { - uint8_t num; - uint8_t index[0]; -} __packed; - -#define GAP_SETTINGS_POWERED 0 -#define GAP_SETTINGS_CONNECTABLE 1 -#define GAP_SETTINGS_FAST_CONNECTABLE 2 -#define GAP_SETTINGS_DISCOVERABLE 3 -#define GAP_SETTINGS_BONDABLE 4 -#define GAP_SETTINGS_LINK_SEC_3 5 -#define GAP_SETTINGS_SSP 6 -#define GAP_SETTINGS_BREDR 7 -#define GAP_SETTINGS_HS 8 -#define GAP_SETTINGS_LE 9 -#define GAP_SETTINGS_ADVERTISING 10 -#define GAP_SETTINGS_SC 11 -#define GAP_SETTINGS_DEBUG_KEYS 12 -#define GAP_SETTINGS_PRIVACY 13 -#define GAP_SETTINGS_CONTROLLER_CONFIG 14 -#define GAP_SETTINGS_STATIC_ADDRESS 15 - -#define GAP_READ_CONTROLLER_INFO 0x03 -struct gap_read_controller_info_rp { - uint8_t address[6]; - uint32_t supported_settings; - uint32_t current_settings; - uint8_t cod[3]; - uint8_t name[249]; - uint8_t short_name[11]; -} __packed; - -#define GAP_RESET 0x04 -struct gap_reset_rp { - uint32_t current_settings; -} __packed; - -#define GAP_SET_POWERED 0x05 -struct gap_set_powered_cmd { - uint8_t powered; -} __packed; -struct gap_set_powered_rp { - uint32_t current_settings; -} __packed; - -#define GAP_SET_CONNECTABLE 0x06 -struct gap_set_connectable_cmd { - uint8_t connectable; -} __packed; -struct gap_set_connectable_rp { - uint32_t current_settings; -} __packed; - -#define GAP_SET_FAST_CONNECTABLE 0x07 -struct gap_set_fast_connectable_cmd { - uint8_t fast_connectable; -} __packed; -struct gap_set_fast_connectable_rp { - uint32_t current_settings; -} __packed; - -#define GAP_NON_DISCOVERABLE 0x00 -#define GAP_GENERAL_DISCOVERABLE 0x01 -#define GAP_LIMITED_DISCOVERABLE 0x02 - -#define GAP_SET_DISCOVERABLE 0x08 -struct gap_set_discoverable_cmd { - uint8_t discoverable; -} __packed; -struct gap_set_discoverable_rp { - uint32_t current_settings; -} __packed; - -#define GAP_SET_BONDABLE 0x09 -struct gap_set_bondable_cmd { - uint8_t bondable; -} __packed; -struct gap_set_bondable_rp { - uint32_t current_settings; -} __packed; - -#define GAP_START_ADVERTISING 0x0a -struct gap_start_advertising_cmd { - uint8_t adv_data_len; - uint8_t scan_rsp_len; - uint8_t adv_data[0]; - uint8_t scan_rsp[0]; -} __packed; -struct gap_start_advertising_rp { - uint32_t current_settings; -} __packed; - -#define GAP_STOP_ADVERTISING 0x0b -struct gap_stop_advertising_rp { - uint32_t current_settings; -} __packed; - -#define GAP_DISCOVERY_FLAG_LE 0x01 -#define GAP_DISCOVERY_FLAG_BREDR 0x02 -#define GAP_DISCOVERY_FLAG_LIMITED 0x04 -#define GAP_DISCOVERY_FLAG_LE_ACTIVE_SCAN 0x08 -#define GAP_DISCOVERY_FLAG_LE_OBSERVE 0x10 - -#define GAP_START_DISCOVERY 0x0c -struct gap_start_discovery_cmd { - uint8_t flags; -} __packed; - -#define GAP_STOP_DISCOVERY 0x0d - -#define GAP_CONNECT 0x0e -struct gap_connect_cmd { - uint8_t address_type; - uint8_t address[6]; -} __packed; - -#define GAP_DISCONNECT 0x0f -struct gap_disconnect_cmd { - uint8_t address_type; - uint8_t address[6]; -} __packed; - -#define GAP_IO_CAP_DISPLAY_ONLY 0 -#define GAP_IO_CAP_DISPLAY_YESNO 1 -#define GAP_IO_CAP_KEYBOARD_ONLY 2 -#define GAP_IO_CAP_NO_INPUT_OUTPUT 3 -#define GAP_IO_CAP_KEYBOARD_DISPLAY 4 - -#define GAP_SET_IO_CAP 0x10 -struct gap_set_io_cap_cmd { - uint8_t io_cap; -} __packed; - -#define GAP_PAIR 0x11 -struct gap_pair_cmd { - uint8_t address_type; - uint8_t address[6]; -} __packed; - -#define GAP_UNPAIR 0x12 -struct gap_unpair_cmd { - uint8_t address_type; - uint8_t address[6]; -} __packed; - -#define GAP_PASSKEY_ENTRY 0x13 -struct gap_passkey_entry_cmd { - uint8_t address_type; - uint8_t address[6]; - uint32_t passkey; -} __packed; - -#define GAP_PASSKEY_CONFIRM 0x14 -struct gap_passkey_confirm_cmd { - uint8_t address_type; - uint8_t address[6]; - uint8_t match; -} __packed; - -#define GAP_START_DIRECT_ADV 0x15 -struct gap_start_direct_adv_cmd { - uint8_t address_type; - uint8_t address[6]; - uint8_t high_duty; -} __packed; - -#define GAP_CONN_PARAM_UPDATE 0x16 -struct gap_conn_param_update_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t conn_itvl_min; - uint16_t conn_itvl_max; - uint16_t conn_latency; - uint16_t supervision_timeout; -} __packed; - -#define GAP_PAIRING_CONSENT_RSP 0x17 -struct gap_pairing_consent_rsp_cmd { - uint8_t address_type; - uint8_t address[6]; - uint8_t consent; -} __packed; - -#define GAP_OOB_LEGACY_SET_DATA 0x18 -struct gap_oob_legacy_set_data_cmd { - uint8_t oob_data[16]; -} __packed; - -#define GAP_OOB_SC_GET_LOCAL_DATA 0x19 -struct gap_oob_sc_get_local_data_rp { - uint8_t r[16]; - uint8_t c[16]; -} __packed; - -#define GAP_OOB_SC_SET_REMOTE_DATA 0x1a -struct gap_oob_sc_set_remote_data_cmd { - uint8_t r[16]; - uint8_t c[16]; -} __packed; - -#define GAP_SET_MITM 0x1b -struct gap_set_mitm_cmd { - uint8_t mitm; -} __packed; - -#define GAP_SET_FILTER_ACCEPT_LIST 0x1c -struct gap_set_filter_accept_list_cmd { - uint8_t list_len; - ble_addr_t addrs[]; -} __packed; -/* events */ -#define GAP_EV_NEW_SETTINGS 0x80 -struct gap_new_settings_ev { - uint32_t current_settings; -} __packed; - -#define GAP_DEVICE_FOUND_FLAG_RSSI 0x01 -#define GAP_DEVICE_FOUND_FLAG_AD 0x02 -#define GAP_DEVICE_FOUND_FLAG_SD 0x04 - -#define GAP_EV_DEVICE_FOUND 0x81 -struct gap_device_found_ev { - uint8_t address_type; - uint8_t address[6]; - int8_t rssi; - uint8_t flags; - uint16_t eir_data_len; - uint8_t eir_data[0]; -} __packed; - -#define GAP_EV_DEVICE_CONNECTED 0x82 -struct gap_device_connected_ev { - uint8_t address_type; - uint8_t address[6]; - uint16_t conn_itvl; - uint16_t conn_latency; - uint16_t supervision_timeout; -} __packed; - -#define GAP_EV_DEVICE_DISCONNECTED 0x83 -struct gap_device_disconnected_ev { - uint8_t address_type; - uint8_t address[6]; -} __packed; - -#define GAP_EV_PASSKEY_DISPLAY 0x84 -struct gap_passkey_display_ev { - uint8_t address_type; - uint8_t address[6]; - uint32_t passkey; -} __packed; - -#define GAP_EV_PASSKEY_ENTRY_REQ 0x85 -struct gap_passkey_entry_req_ev { - uint8_t address_type; - uint8_t address[6]; -} __packed; - -#define GAP_EV_PASSKEY_CONFIRM_REQ 0x86 -struct gap_passkey_confirm_req_ev { - uint8_t address_type; - uint8_t address[6]; - uint32_t passkey; -} __packed; - -#define GAP_EV_IDENTITY_RESOLVED 0x87 -struct gap_identity_resolved_ev { - uint8_t address_type; - uint8_t address[6]; - uint8_t identity_address_type; - uint8_t identity_address[6]; -} __packed; - -#define GAP_EV_CONN_PARAM_UPDATE 0x88 -struct gap_conn_param_update_ev { - uint8_t address_type; - uint8_t address[6]; - uint16_t conn_itvl; - uint16_t conn_latency; - uint16_t supervision_timeout; -} __packed; - -#define GAP_EV_SEC_LEVEL_CHANGED 0x89 -struct gap_sec_level_changed_ev { - uint8_t address_type; - uint8_t address[6]; - uint8_t level; -} __packed; - -#define GAP_EV_PAIRING_CONSENT_REQ 0x8a -struct gap_pairing_consent_req_ev { - uint8_t address_type; - uint8_t address[6]; -} __packed; - -/* GATT Service */ -/* commands */ -#define GATT_READ_SUPPORTED_COMMANDS 0x01 -struct gatt_read_supported_commands_rp { - uint8_t data[0]; -} __packed; - -#define GATT_SERVICE_PRIMARY 0x00 -#define GATT_SERVICE_SECONDARY 0x01 - -#define GATT_ADD_SERVICE 0x02 -struct gatt_add_service_cmd { - uint8_t type; - uint8_t uuid_length; - uint8_t uuid[0]; -} __packed; -struct gatt_add_service_rp { - uint16_t svc_id; -} __packed; - -#define GATT_ADD_CHARACTERISTIC 0x03 -struct gatt_add_characteristic_cmd { - uint16_t svc_id; - uint8_t properties; - uint8_t permissions; - uint8_t uuid_length; - uint8_t uuid[0]; -} __packed; -struct gatt_add_characteristic_rp { - uint16_t char_id; -} __packed; - -#define GATT_ADD_DESCRIPTOR 0x04 -struct gatt_add_descriptor_cmd { - uint16_t char_id; - uint8_t permissions; - uint8_t uuid_length; - uint8_t uuid[0]; -} __packed; -struct gatt_add_descriptor_rp { - uint16_t desc_id; -} __packed; - -#define GATT_ADD_INCLUDED_SERVICE 0x05 -struct gatt_add_included_service_cmd { - uint16_t svc_id; -} __packed; -struct gatt_add_included_service_rp { - uint16_t included_service_id; -} __packed; - -#define GATT_SET_VALUE 0x06 - struct gatt_set_value_cmd { - uint16_t attr_id; - uint16_t len; - uint8_t value[0]; -} __packed; - -#define GATT_START_SERVER 0x07 -struct gatt_start_server_rp { - uint16_t db_attr_off; - uint8_t db_attr_cnt; -} __packed; - -#define GATT_SET_ENC_KEY_SIZE 0x09 -struct gatt_set_enc_key_size_cmd { - uint16_t attr_id; - uint8_t key_size; -} __packed; - -/* Gatt Client */ -struct gatt_service { - uint16_t start_handle; - uint16_t end_handle; - uint8_t uuid_length; - uint8_t uuid[0]; -} __packed; - -struct gatt_included { - uint16_t included_handle; - struct gatt_service service; -} __packed; - -struct gatt_read_uuid_chr { - uint16_t handle; - uint8_t data[0]; -} __packed; - -struct gatt_characteristic { - uint16_t characteristic_handle; - uint16_t value_handle; - uint8_t properties; - uint8_t uuid_length; - uint8_t uuid[0]; -} __packed; - -struct gatt_descriptor { - uint16_t descriptor_handle; - uint8_t uuid_length; - uint8_t uuid[0]; -} __packed; - -#define GATT_EXCHANGE_MTU 0x0a - -#define GATT_DISC_ALL_PRIM_SVCS 0x0b -struct gatt_disc_all_prim_svcs_cmd { - uint8_t address_type; - uint8_t address[6]; -} __packed; -struct gatt_disc_all_prim_svcs_rp { - uint8_t services_count; - struct gatt_service services[0]; -} __packed; - -#define GATT_DISC_PRIM_UUID 0x0c -struct gatt_disc_prim_uuid_cmd { - uint8_t address_type; - uint8_t address[6]; - uint8_t uuid_length; - uint8_t uuid[0]; -} __packed; -struct gatt_disc_prim_uuid_rp { - uint8_t services_count; - struct gatt_service services[0]; -} __packed; - -#define GATT_FIND_INCLUDED 0x0d -struct gatt_find_included_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t start_handle; - uint16_t end_handle; -} __packed; -struct gatt_find_included_rp { - uint8_t services_count; - struct gatt_included included[0]; -} __packed; - -#define GATT_DISC_ALL_CHRC 0x0e -struct gatt_disc_all_chrc_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t start_handle; - uint16_t end_handle; -} __packed; -struct gatt_disc_chrc_rp { - uint8_t characteristics_count; - struct gatt_characteristic characteristics[0]; -} __packed; - -#define GATT_DISC_CHRC_UUID 0x0f -struct gatt_disc_chrc_uuid_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t start_handle; - uint16_t end_handle; - uint8_t uuid_length; - uint8_t uuid[0]; -} __packed; - -#define GATT_DISC_ALL_DESC 0x10 -struct gatt_disc_all_desc_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t start_handle; - uint16_t end_handle; -} __packed; -struct gatt_disc_all_desc_rp { - uint8_t descriptors_count; - struct gatt_descriptor descriptors[0]; -} __packed; - -#define GATT_READ 0x11 -struct gatt_read_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t handle; -} __packed; -struct gatt_read_rp { - uint8_t att_response; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -#define GATT_READ_UUID 0x12 -struct gatt_read_uuid_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t start_handle; - uint16_t end_handle; - uint8_t uuid_length; - uint8_t uuid[0]; -} __packed; - -#define GATT_READ_LONG 0x13 -struct gatt_read_long_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t handle; - uint16_t offset; -} __packed; - -#define GATT_READ_MULTIPLE 0x14 -struct gatt_read_multiple_cmd { - uint8_t address_type; - uint8_t address[6]; - uint8_t handles_count; - uint16_t handles[0]; -} __packed; - -#define GATT_WRITE_WITHOUT_RSP 0x15 -struct gatt_write_without_rsp_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t handle; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -#define GATT_SIGNED_WRITE_WITHOUT_RSP 0x16 -struct gatt_signed_write_without_rsp_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t handle; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -#define GATT_WRITE 0x17 -struct gatt_write_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t handle; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -#define GATT_WRITE_LONG 0x18 -struct gatt_write_long_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t handle; - uint16_t offset; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -#define GATT_RELIABLE_WRITE 0x19 -struct gatt_reliable_write_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t handle; - uint16_t offset; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -#define GATT_CFG_NOTIFY 0x1a -#define GATT_CFG_INDICATE 0x1b -struct gatt_cfg_notify_cmd { - uint8_t address_type; - uint8_t address[6]; - uint8_t enable; - uint16_t ccc_handle; -} __packed; - -#define GATT_GET_ATTRIBUTES 0x1c -struct gatt_get_attributes_cmd { - uint16_t start_handle; - uint16_t end_handle; - uint8_t type_length; - uint8_t type[0]; -} __packed; -struct gatt_get_attributes_rp { - uint8_t attrs_count; - uint8_t attrs[0]; -} __packed; -struct gatt_attr { - uint16_t handle; - uint8_t permission; - uint8_t type_length; - uint8_t type[0]; -} __packed; - -#define GATT_GET_ATTRIBUTE_VALUE 0x1d -struct gatt_get_attribute_value_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t handle; -} __packed; -struct gatt_get_attribute_value_rp { - uint8_t att_response; - uint16_t value_length; - uint8_t value[0]; -} __packed; - -#define GATT_CHANGE_DATABASE 0x1e -struct gatt_change_database { - uint16_t start_handle; - uint16_t end_handle; - uint8_t visibility; -} __packed; - -/* GATT events */ -#define GATT_EV_NOTIFICATION 0x80 -struct gatt_notification_ev { - uint8_t address_type; - uint8_t address[6]; - uint8_t type; - uint16_t handle; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -#define GATT_EV_ATTR_VALUE_CHANGED 0x81 -struct gatt_attr_value_changed_ev { - uint16_t handle; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -static inline void tester_set_bit(uint8_t *addr, unsigned int bit) -{ - uint8_t *p = addr + (bit / 8); - - *p |= BIT(bit % 8); -} - -static inline uint8_t tester_test_bit(const uint8_t *addr, unsigned int bit) -{ - const uint8_t *p = addr + (bit / 8); - - return *p & BIT(bit % 8); -} - -/* L2CAP Service */ -/* commands */ -#define L2CAP_READ_SUPPORTED_COMMANDS 0x01 -struct l2cap_read_supported_commands_rp { - uint8_t data[0]; -} __packed; - -#define L2CAP_CONNECT_OPT_ECFC 0x01 -#define L2CAP_CONNECT_OPT_HOLD_CREDIT 0x02 - -#define L2CAP_CONNECT 0x02 -struct l2cap_connect_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t psm; - uint16_t mtu; - uint8_t num; - uint8_t options; -} __packed; - -struct l2cap_connect_rp { - uint8_t num; - uint8_t chan_ids[0]; -} __packed; - -#define L2CAP_DISCONNECT 0x03 -struct l2cap_disconnect_cmd { - uint8_t chan_id; -} __packed; - -#define L2CAP_SEND_DATA 0x04 -struct l2cap_send_data_cmd { - uint8_t chan_id; - uint16_t data_len; - uint8_t data[]; -} __packed; - -#define L2CAP_TRANSPORT_BREDR 0x00 -#define L2CAP_TRANSPORT_LE 0x01 - -#define L2CAP_LISTEN 0x05 -struct l2cap_listen_cmd { - uint16_t psm; - uint8_t transport; - uint16_t mtu; - uint16_t response; -} __packed; - -#define L2CAP_ACCEPT_CONNECTION 0x06 -struct l2cap_accept_connection_cmd { - uint8_t chan_id; - uint16_t result; -} __packed; - -#define L2CAP_RECONFIGURE 0x07 -struct l2cap_reconfigure_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t mtu; - uint8_t num; - uint8_t idxs[]; -} __packed; - -#define L2CAP_CREDITS 0x08 -struct l2cap_credits_cmd { - uint8_t chan_id; -} __packed; - -/* events */ -#define L2CAP_EV_CONNECTION_REQ 0x80 -struct l2cap_connection_req_ev { - uint8_t chan_id; - uint16_t psm; - uint8_t address_type; - uint8_t address[6]; -} __packed; - -#define L2CAP_EV_CONNECTED 0x81 -struct l2cap_connected_ev { - uint8_t chan_id; - uint16_t psm; - uint16_t peer_mtu; - uint16_t peer_mps; - uint16_t our_mtu; - uint16_t our_mps; - uint8_t address_type; - uint8_t address[6]; -} __packed; - -#define L2CAP_EV_DISCONNECTED 0x82 -struct l2cap_disconnected_ev { - uint16_t result; - uint8_t chan_id; - uint16_t psm; - uint8_t address_type; - uint8_t address[6]; -} __packed; - -#define L2CAP_EV_DATA_RECEIVED 0x83 -struct l2cap_data_received_ev { - uint8_t chan_id; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -#define L2CAP_EV_RECONFIGURED 0x84 -struct l2cap_reconfigured_ev { - uint8_t chan_id; - uint16_t peer_mtu; - uint16_t peer_mps; - uint16_t our_mtu; - uint16_t our_mps; -} __packed; - -/* MESH Service */ -/* commands */ -#define MESH_READ_SUPPORTED_COMMANDS 0x01 -struct mesh_read_supported_commands_rp { - uint8_t data[0]; -} __packed; - -#define MESH_OUT_BLINK BIT(0) -#define MESH_OUT_BEEP BIT(1) -#define MESH_OUT_VIBRATE BIT(2) -#define MESH_OUT_DISPLAY_NUMBER BIT(3) -#define MESH_OUT_DISPLAY_STRING BIT(4) - -#define MESH_IN_PUSH BIT(0) -#define MESH_IN_TWIST BIT(1) -#define MESH_IN_ENTER_NUMBER BIT(2) -#define MESH_IN_ENTER_STRING BIT(3) - -#define MESH_CONFIG_PROVISIONING 0x02 -struct mesh_config_provisioning_cmd { - uint8_t uuid[16]; - uint8_t static_auth[16]; - uint8_t out_size; - uint16_t out_actions; - uint8_t in_size; - uint16_t in_actions; -} __packed; - -#define MESH_PROVISION_NODE 0x03 -struct mesh_provision_node_cmd { - uint8_t net_key[16]; - uint16_t net_key_idx; - uint8_t flags; - uint32_t iv_index; - uint32_t seq_num; - uint16_t addr; - uint8_t dev_key[16]; -} __packed; - -#define MESH_INIT 0x04 -#define MESH_RESET 0x05 -#define MESH_INPUT_NUMBER 0x06 -struct mesh_input_number_cmd { - uint32_t number; -} __packed; - -#define MESH_INPUT_STRING 0x07 -struct mesh_input_string_cmd { - uint8_t string_len; - uint8_t string[0]; -} __packed; - -#define MESH_IVU_TEST_MODE 0x08 -struct mesh_ivu_test_mode_cmd { - uint8_t enable; -} __packed; - -#define MESH_IVU_TOGGLE_STATE 0x09 - -#define MESH_NET_SEND 0x0a -struct mesh_net_send_cmd { - uint8_t ttl; - uint16_t src; - uint16_t dst; - uint8_t payload_len; - uint8_t payload[0]; -} __packed; - -#define MESH_HEALTH_GENERATE_FAULTS 0x0b -struct mesh_health_generate_faults_rp { - uint8_t test_id; - uint8_t cur_faults_count; - uint8_t reg_faults_count; - uint8_t current_faults[0]; - uint8_t registered_faults[0]; -} __packed; - -#define MESH_HEALTH_CLEAR_FAULTS 0x0c - -#define MESH_LPN 0x0d -struct mesh_lpn_set_cmd { - uint8_t enable; -} __packed; - -#define MESH_LPN_POLL 0x0e - -#define MESH_MODEL_SEND 0x0f -struct mesh_model_send_cmd { - uint16_t src; - uint16_t dst; - uint8_t payload_len; - uint8_t payload[0]; -} __packed; - -#define MESH_LPN_SUBSCRIBE 0x10 -struct mesh_lpn_subscribe_cmd { - uint16_t address; -} __packed; - -#define MESH_LPN_UNSUBSCRIBE 0x11 -struct mesh_lpn_unsubscribe_cmd { - uint16_t address; -} __packed; - -#define MESH_RPL_CLEAR 0x12 -#define MESH_PROXY_IDENTITY 0x13 - -/* events */ -#define MESH_EV_OUT_NUMBER_ACTION 0x80 -struct mesh_out_number_action_ev { - uint16_t action; - uint32_t number; -} __packed; - -#define MESH_EV_OUT_STRING_ACTION 0x81 -struct mesh_out_string_action_ev { - uint8_t string_len; - uint8_t string[0]; -} __packed; - -#define MESH_EV_IN_ACTION 0x82 -struct mesh_in_action_ev { - uint16_t action; - uint8_t size; -} __packed; - -#define MESH_EV_PROVISIONED 0x83 - -#define MESH_PROV_BEARER_PB_ADV 0x00 -#define MESH_PROV_BEARER_PB_GATT 0x01 -#define MESH_EV_PROV_LINK_OPEN 0x84 -struct mesh_prov_link_open_ev { - uint8_t bearer; -} __packed; - -#define MESH_EV_PROV_LINK_CLOSED 0x85 -struct mesh_prov_link_closed_ev { - uint8_t bearer; -} __packed; - -#define MESH_EV_NET_RECV 0x86 -struct mesh_net_recv_ev { - uint8_t ttl; - uint8_t ctl; - uint16_t src; - uint16_t dst; - uint8_t payload_len; - uint8_t payload[0]; -} __packed; - -#define MESH_EV_INVALID_BEARER 0x87 -struct mesh_invalid_bearer_ev { - uint8_t opcode; -} __packed; - -#define MESH_EV_INCOMP_TIMER_EXP 0x88 - -#define MESH_EV_LPN_ESTABLISHED 0x8b -struct mesh_lpn_established_ev { - uint16_t net_idx; - uint16_t friend_addr; - uint8_t queue_size; - uint8_t recv_win; -} __packed; - -#define MESH_EV_LPN_TERMINATED 0x8c -struct mesh_lpn_terminated_ev { - uint16_t net_idx; - uint16_t friend_addr; -} __packed; - -#define MESH_EV_LPN_POLLED 0x8d -struct mesh_lpn_polled_ev { - uint16_t net_idx; - uint16_t friend_addr; - uint8_t retry; -} __packed; - -void tester_init(void); -void tester_rsp(uint8_t service, uint8_t opcode, uint8_t index, uint8_t status); -void tester_send(uint8_t service, uint8_t opcode, uint8_t index, uint8_t *data, - size_t len); -void tester_send_buf(uint8_t service, uint8_t opcode, uint8_t index, - struct os_mbuf *buf); - -uint8_t tester_init_gap(void); -uint8_t tester_unregister_gap(void); -void tester_handle_gap(uint8_t opcode, uint8_t index, uint8_t *data, - uint16_t len); -uint8_t tester_init_gatt(void); -uint8_t tester_unregister_gatt(void); -void tester_handle_gatt(uint8_t opcode, uint8_t index, uint8_t *data, - uint16_t len); -void tester_handle_gattc(uint8_t opcode, uint8_t index, uint8_t *data, - uint16_t len); -int tester_gattc_notify_rx_ev(uint16_t conn_handle, uint16_t attr_handle, - uint8_t indication, struct os_mbuf *om); -int tester_gatt_subscribe_ev(uint16_t conn_handle, uint16_t attr_handle, uint8_t reason, - uint8_t prev_notify, uint8_t cur_notify, - uint8_t prev_indicate, uint8_t cur_indicate); - -#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) -uint8_t tester_init_l2cap(void); -uint8_t tester_unregister_l2cap(void); -void tester_handle_l2cap(uint8_t opcode, uint8_t index, uint8_t *data, - uint16_t len); -#endif - -#if MYNEWT_VAL(BLE_MESH) -uint8_t tester_init_mesh(void); -uint8_t tester_unregister_mesh(void); -void tester_handle_mesh(uint8_t opcode, uint8_t index, uint8_t *data, uint16_t len); -#endif /* MYNEWT_VAL(BLE_MESH) */ - -void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg); -int gatt_svr_init(void); - -/* GATT Client Service */ -/* commands */ -#define GATTC_READ_SUPPORTED_COMMANDS 0x01 -struct gattc_read_supported_commands_rp { - uint8_t data[0]; -} __packed; - -#define GATTC_EXCHANGE_MTU 0x02 - -#define GATTC_DISC_ALL_PRIM_SVCS 0x03 -struct gattc_disc_all_prim_svcs_cmd { - uint8_t address_type; - uint8_t address[6]; -} __packed; - -#define GATTC_DISC_PRIM_UUID 0x04 -struct gattc_disc_prim_uuid_cmd { - uint8_t address_type; - uint8_t address[6]; - uint8_t uuid_length; - uint8_t uuid[0]; -} __packed; - -#define GATTC_FIND_INCLUDED 0x05 -struct gattc_find_included_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t start_handle; - uint16_t end_handle; -} __packed; - -#define GATTC_DISC_ALL_CHRC 0x06 -struct gattc_disc_all_chrc_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t start_handle; - uint16_t end_handle; -} __packed; - -#define GATTC_DISC_CHRC_UUID 0x07 -struct gattc_disc_chrc_uuid_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t start_handle; - uint16_t end_handle; - uint8_t uuid_length; - uint8_t uuid[0]; -} __packed; - -#define GATTC_DISC_ALL_DESC 0x08 -struct gattc_disc_all_desc_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t start_handle; - uint16_t end_handle; -} __packed; - -#define GATTC_READ 0x09 -struct gattc_read_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t handle; -} __packed; - -#define GATTC_READ_UUID 0x0a -struct gattc_read_uuid_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t start_handle; - uint16_t end_handle; - uint8_t uuid_length; - uint8_t uuid[0]; -} __packed; -struct gattc_read_uuid_rp { - uint8_t address_type; - uint8_t address[6]; - uint8_t status; - uint16_t data_length; - uint8_t value_length; - uint8_t data[0]; -} __packed; - -#define GATTC_READ_LONG 0x0b -struct gattc_read_long_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t handle; - uint16_t offset; -} __packed; - -#define GATTC_READ_MULTIPLE 0x0c -struct gattc_read_multiple_cmd { - uint8_t address_type; - uint8_t address[6]; - uint8_t handles_count; - uint16_t handles[0]; -} __packed; - -#define GATTC_WRITE_WITHOUT_RSP 0x0d -struct gattc_write_without_rsp_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t handle; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -#define GATTC_SIGNED_WRITE_WITHOUT_RSP 0x0e -struct gattc_signed_write_without_rsp_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t handle; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -#define GATTC_WRITE 0x0f -struct gattc_write_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t handle; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -#define GATTC_WRITE_LONG 0x10 -struct gattc_write_long_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t handle; - uint16_t offset; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -#define GATTC_RELIABLE_WRITE 0x11 -struct gattc_reliable_write_cmd { - uint8_t address_type; - uint8_t address[6]; - uint16_t handle; - uint16_t offset; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -#define GATTC_CFG_NOTIFY 0x12 -#define GATTC_CFG_INDICATE 0x13 -struct gattc_cfg_notify_cmd { - uint8_t address_type; - uint8_t address[6]; - uint8_t enable; - uint16_t ccc_handle; -} __packed; - -/* events */ -#define GATTC_EV_MTU_EXCHANGED 0x80 -struct gattc_exchange_mtu_ev { - uint8_t address_type; - uint8_t address[6]; - uint16_t mtu; -} __packed; - -#define GATTC_DISC_ALL_PRIM_RP 0x81 -struct gattc_disc_prim_svcs_rp { - uint8_t address_type; - uint8_t address[6]; - uint8_t status; - uint8_t services_count; - uint8_t data[0]; -} __packed; - -#define GATTC_DISC_PRIM_UUID_RP 0x82 - -#define GATTC_FIND_INCLUDED_RP 0x83 -struct gattc_find_included_rp { - uint8_t address_type; - uint8_t address[6]; - uint8_t status; - uint8_t services_count; - struct gatt_included included[0]; -} __packed; - -#define GATTC_DISC_ALL_CHRC_RP 0x84 -#define GATTC_DISC_CHRC_UUID_RP 0x85 -struct gattc_disc_chrc_rp { - uint8_t address_type; - uint8_t address[6]; - uint8_t status; - uint8_t characteristics_count; - struct gatt_characteristic characteristics[0]; -} __packed; - -#define GATTC_DISC_ALL_DESC_RP 0x86 -struct gattc_disc_all_desc_rp { - uint8_t address_type; - uint8_t address[6]; - uint8_t status; - uint8_t descriptors_count; - struct gatt_descriptor descriptors[0]; -} __packed; - -#define GATTC_READ_RP 0x87 -#define GATTC_READ_UUID_RP 0x88 -#define GATTC_READ_LONG_RP 0x89 -#define GATTC_READ_MULTIPLE_RP 0x8a -struct gattc_read_rp { - uint8_t address_type; - uint8_t address[6]; - uint8_t status; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -#define GATTC_WRITE_RP 0x8b -struct gattc_write_rp { - uint8_t address_type; - uint8_t address[6]; - uint8_t status; -} __packed; -#define GATTC_WRITE_LONG_RP 0x8c -#define GATTC_RELIABLE_WRITE_RP 0x8d -#define GATTC_RELIABLE_WRITE_RP 0x8d -#define GATTC_CFG_NOTIFY_RP 0x8e -#define GATTC_CFG_INDICATE_RP 0x8f -struct subscribe_rp { - uint8_t address_type; - uint8_t address[6]; - uint8_t status; -} __packed; - -#define GATTC_EV_NOTIFICATION_RXED 0x90 -struct gattc_notification_ev { - uint8_t address_type; - uint8_t address[6]; - uint8_t type; - uint16_t handle; - uint16_t data_length; - uint8_t data[0]; -} __packed; - -#endif /* __BTTESTER_H__ */ diff --git a/lib/bt/host/nimble/nimble/apps/bttester/src/gap.c b/lib/bt/host/nimble/nimble/apps/bttester/src/gap.c deleted file mode 100644 index 74b956b9..00000000 --- a/lib/bt/host/nimble/nimble/apps/bttester/src/gap.c +++ /dev/null @@ -1,1775 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/* gap.c - Bluetooth GAP Tester */ - -/* - * Copyright (c) 2015-2016 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "host/ble_gap.h" -#include "host/util/util.h" -#include "console/console.h" - -#include "../../../nimble/host/src/ble_hs_pvcy_priv.h" -#include "../../../nimble/host/src/ble_hs_hci_priv.h" -#include "../../../nimble/host/src/ble_sm_priv.h" - -#include "bttester.h" - -#define CONTROLLER_INDEX 0 -#define CONTROLLER_NAME "btp_tester" - -#define BLE_AD_DISCOV_MASK (BLE_HS_ADV_F_DISC_LTD | BLE_HS_ADV_F_DISC_GEN) -#define ADV_BUF_LEN (sizeof(struct gap_device_found_ev) + 2 * 31) - -/* parameter values to reject in CPUP if all match the pattern */ -#define REJECT_INTERVAL_MIN 0x0C80 -#define REJECT_INTERVAL_MAX 0x0C80 -#define REJECT_LATENCY 0x0000 -#define REJECT_SUPERVISION_TIMEOUT 0x0C80 - -const uint8_t irk[16] = { - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, -}; - -static uint8_t oob[16]; -static struct ble_sm_sc_oob_data oob_data_local; -static struct ble_sm_sc_oob_data oob_data_remote; - -static uint16_t current_settings; -uint8_t own_addr_type; -static ble_addr_t peer_id_addr; -static ble_addr_t peer_ota_addr; -static bool encrypted = false; - -static struct os_callout update_params_co; -static struct gap_conn_param_update_cmd update_params; - -static struct os_callout connected_ev_co; -static struct gap_device_connected_ev connected_ev; -#define CONNECTED_EV_DELAY_MS(itvl) 8 * BLE_HCI_CONN_ITVL * itvl / 1000 -static int connection_attempts; -#if MYNEWT_VAL(BTTESTER_PRIVACY_MODE) && MYNEWT_VAL(BTTESTER_USE_NRPA) -static int64_t advertising_start; -static struct os_callout bttester_nrpa_rotate_timer; -#endif - -static const struct ble_gap_conn_params dflt_conn_params = { - .scan_itvl = 0x0010, - .scan_window = 0x0010, - .itvl_min = BLE_GAP_INITIAL_CONN_ITVL_MIN, - .itvl_max = BLE_GAP_INITIAL_CONN_ITVL_MAX, - .latency = 0, - .supervision_timeout = 0x0100, - .min_ce_len = 0x0010, - .max_ce_len = 0x0300, -}; - -static void conn_param_update(struct os_event *ev); - - -static int gap_conn_find_by_addr(const ble_addr_t *dev_addr, - struct ble_gap_conn_desc *out_desc) -{ - ble_addr_t addr = *dev_addr; - - if (memcmp(BLE_ADDR_ANY, &peer_id_addr, 6) == 0) { - return ble_gap_conn_find_by_addr(&addr, out_desc); - } - - if (BLE_ADDR_IS_RPA(&addr)) { - if(ble_addr_cmp(&peer_ota_addr, &addr) != 0) { - return -1; - } - - return ble_gap_conn_find_by_addr(&addr, out_desc); - } else { - if(ble_addr_cmp(&peer_id_addr, &addr) != 0) { - return -1; - } - - if (BLE_ADDR_IS_RPA(&peer_ota_addr)) { - /* Change addr type to ID addr */ - addr.type |= 2; - } - - return ble_gap_conn_find_by_addr(&addr, out_desc); - } -} - -static int gap_event_cb(struct ble_gap_event *event, void *arg); - -static void supported_commands(uint8_t *data, uint16_t len) -{ - uint8_t cmds[3]; - struct gap_read_supported_commands_rp *rp = (void *) &cmds; - - SYS_LOG_DBG(""); - - memset(cmds, 0, sizeof(cmds)); - - tester_set_bit(cmds, GAP_READ_SUPPORTED_COMMANDS); - tester_set_bit(cmds, GAP_READ_CONTROLLER_INDEX_LIST); - tester_set_bit(cmds, GAP_READ_CONTROLLER_INFO); - tester_set_bit(cmds, GAP_SET_CONNECTABLE); - tester_set_bit(cmds, GAP_SET_DISCOVERABLE); - tester_set_bit(cmds, GAP_SET_BONDABLE); - tester_set_bit(cmds, GAP_START_ADVERTISING); - tester_set_bit(cmds, GAP_STOP_ADVERTISING); - tester_set_bit(cmds, GAP_START_DISCOVERY); - tester_set_bit(cmds, GAP_STOP_DISCOVERY); - tester_set_bit(cmds, GAP_CONNECT); - tester_set_bit(cmds, GAP_DISCONNECT); - tester_set_bit(cmds, GAP_SET_IO_CAP); - tester_set_bit(cmds, GAP_PAIR); - tester_set_bit(cmds, GAP_UNPAIR); - tester_set_bit(cmds, GAP_PASSKEY_ENTRY); - tester_set_bit(cmds, GAP_PASSKEY_CONFIRM); - tester_set_bit(cmds, GAP_START_DIRECT_ADV); - tester_set_bit(cmds, GAP_CONN_PARAM_UPDATE); - tester_set_bit(cmds, GAP_OOB_LEGACY_SET_DATA); - tester_set_bit(cmds, GAP_OOB_SC_GET_LOCAL_DATA); - tester_set_bit(cmds, GAP_OOB_SC_SET_REMOTE_DATA); - tester_set_bit(cmds, GAP_SET_MITM); - - tester_send(BTP_SERVICE_ID_GAP, GAP_READ_SUPPORTED_COMMANDS, - CONTROLLER_INDEX, (uint8_t *) rp, sizeof(cmds)); -} - -static void controller_index_list(uint8_t *data, uint16_t len) -{ - struct gap_read_controller_index_list_rp *rp; - uint8_t buf[sizeof(*rp) + 1]; - - SYS_LOG_DBG(""); - - rp = (void *) buf; - - rp->num = 1; - rp->index[0] = CONTROLLER_INDEX; - - tester_send(BTP_SERVICE_ID_GAP, GAP_READ_CONTROLLER_INDEX_LIST, - BTP_INDEX_NONE, (uint8_t *) rp, sizeof(buf)); -} - -static void controller_info(uint8_t *data, uint16_t len) -{ - struct gap_read_controller_info_rp rp; - uint32_t supported_settings = 0; - ble_addr_t addr; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_hs_pvcy_set_our_irk(irk); - assert(rc == 0); - - memset(&rp, 0, sizeof(rp)); - - /* Make sure we have proper identity address set (public preferred) */ - rc = ble_hs_util_ensure_addr(1); - assert(rc == 0); - rc = ble_hs_id_copy_addr(BLE_ADDR_RANDOM, addr.val, NULL); - assert(rc == 0); - - if (MYNEWT_VAL(BTTESTER_PRIVACY_MODE)) { - if (MYNEWT_VAL(BTTESTER_USE_NRPA)) { - own_addr_type = BLE_OWN_ADDR_RANDOM; - rc = ble_hs_id_gen_rnd(1, &addr); - assert(rc == 0); - rc = ble_hs_id_set_rnd(addr.val); - assert(rc == 0); - } else { - own_addr_type = BLE_OWN_ADDR_RPA_RANDOM_DEFAULT; - } - current_settings |= BIT(GAP_SETTINGS_PRIVACY); - supported_settings |= BIT(GAP_SETTINGS_PRIVACY); - memcpy(rp.address, addr.val, sizeof(rp.address)); - } else { - rc = ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, rp.address, NULL); - if (rc) { - own_addr_type = BLE_OWN_ADDR_RANDOM; - memcpy(rp.address, addr.val, sizeof(rp.address)); - supported_settings |= BIT(GAP_SETTINGS_STATIC_ADDRESS); - current_settings |= BIT(GAP_SETTINGS_STATIC_ADDRESS); - } else { - own_addr_type = BLE_OWN_ADDR_PUBLIC; - } - } - - supported_settings |= BIT(GAP_SETTINGS_POWERED); - supported_settings |= BIT(GAP_SETTINGS_CONNECTABLE); - supported_settings |= BIT(GAP_SETTINGS_BONDABLE); - supported_settings |= BIT(GAP_SETTINGS_LE); - supported_settings |= BIT(GAP_SETTINGS_ADVERTISING); - supported_settings |= BIT(GAP_SETTINGS_SC); - - if (ble_hs_cfg.sm_bonding) { - current_settings |= BIT(GAP_SETTINGS_BONDABLE); - } - if (ble_hs_cfg.sm_sc) { - current_settings |= BIT(GAP_SETTINGS_SC); - } - - rp.supported_settings = sys_cpu_to_le32(supported_settings); - rp.current_settings = sys_cpu_to_le32(current_settings); - - memcpy(rp.name, CONTROLLER_NAME, sizeof(CONTROLLER_NAME)); - - tester_send(BTP_SERVICE_ID_GAP, GAP_READ_CONTROLLER_INFO, - CONTROLLER_INDEX, (uint8_t *) &rp, sizeof(rp)); -} - -static struct ble_gap_adv_params adv_params = { - .conn_mode = BLE_GAP_CONN_MODE_NON, - .disc_mode = BLE_GAP_DISC_MODE_NON, -}; - -#if MYNEWT_VAL(BTTESTER_PRIVACY_MODE) && MYNEWT_VAL(BTTESTER_USE_NRPA) -static void rotate_nrpa_cb(struct os_event *ev) -{ - int rc; - ble_addr_t addr; - int32_t duration_ms = BLE_HS_FOREVER; - int32_t remaining_time; - os_time_t remaining_ticks; - - if (adv_params.disc_mode == BLE_GAP_DISC_MODE_LTD) { - duration_ms = MYNEWT_VAL(BTTESTER_LTD_ADV_TIMEOUT); - } - - ble_gap_adv_stop(); - rc = ble_hs_id_gen_rnd(1, &addr); - assert(rc == 0); - rc = ble_hs_id_set_rnd(addr.val); - assert(rc == 0); - - ble_gap_adv_start(own_addr_type, NULL, duration_ms, - &adv_params, gap_event_cb, NULL); - - remaining_time = os_get_uptime_usec() - advertising_start; - if (remaining_time > 0) { - advertising_start = os_get_uptime_usec(); - os_time_ms_to_ticks(remaining_time, &remaining_ticks); - os_callout_reset(&bttester_nrpa_rotate_timer, - remaining_ticks); - } -} -#endif - -static void set_connectable(uint8_t *data, uint16_t len) -{ - const struct gap_set_connectable_cmd *cmd = (void *) data; - struct gap_set_connectable_rp rp; - - SYS_LOG_DBG(""); - - if (cmd->connectable) { - current_settings |= BIT(GAP_SETTINGS_CONNECTABLE); - adv_params.conn_mode = BLE_GAP_CONN_MODE_UND; - } else { - current_settings &= ~BIT(GAP_SETTINGS_CONNECTABLE); - adv_params.conn_mode = BLE_GAP_CONN_MODE_NON; - } - - rp.current_settings = sys_cpu_to_le32(current_settings); - - tester_send(BTP_SERVICE_ID_GAP, GAP_SET_CONNECTABLE, CONTROLLER_INDEX, - (uint8_t *) &rp, sizeof(rp)); -} - -static uint8_t ad_flags = BLE_HS_ADV_F_BREDR_UNSUP; - -static void set_discoverable(uint8_t *data, uint16_t len) -{ - const struct gap_set_discoverable_cmd *cmd = (void *) data; - struct gap_set_discoverable_rp rp; - - SYS_LOG_DBG(""); - - switch (cmd->discoverable) { - case GAP_NON_DISCOVERABLE: - ad_flags &= ~(BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_DISC_LTD); - adv_params.disc_mode = BLE_GAP_DISC_MODE_NON; - current_settings &= ~BIT(GAP_SETTINGS_DISCOVERABLE); - break; - case GAP_GENERAL_DISCOVERABLE: - ad_flags &= ~BLE_HS_ADV_F_DISC_LTD; - ad_flags |= BLE_HS_ADV_F_DISC_GEN; - adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN; - current_settings |= BIT(GAP_SETTINGS_DISCOVERABLE); - break; - case GAP_LIMITED_DISCOVERABLE: - ad_flags &= ~BLE_HS_ADV_F_DISC_GEN; - ad_flags |= BLE_HS_ADV_F_DISC_LTD; - adv_params.disc_mode = BLE_GAP_DISC_MODE_LTD; - current_settings |= BIT(GAP_SETTINGS_DISCOVERABLE); - break; - default: - tester_rsp(BTP_SERVICE_ID_GAP, GAP_SET_DISCOVERABLE, - CONTROLLER_INDEX, BTP_STATUS_FAILED); - return; - } - - rp.current_settings = sys_cpu_to_le32(current_settings); - - tester_send(BTP_SERVICE_ID_GAP, GAP_SET_DISCOVERABLE, CONTROLLER_INDEX, - (uint8_t *) &rp, sizeof(rp)); -} - -static void set_bondable(const uint8_t *data, uint16_t len) -{ - const struct gap_set_bondable_cmd *cmd = (void *) data; - struct gap_set_bondable_rp rp; - - SYS_LOG_DBG(""); - - ble_hs_cfg.sm_bonding = cmd->bondable; - if (ble_hs_cfg.sm_bonding) { - current_settings |= BIT(GAP_SETTINGS_BONDABLE); - } else { - current_settings &= ~BIT(GAP_SETTINGS_BONDABLE); - } - - rp.current_settings = sys_cpu_to_le32(current_settings); - - tester_send(BTP_SERVICE_ID_GAP, GAP_SET_BONDABLE, CONTROLLER_INDEX, - (uint8_t *) &rp, sizeof(rp)); -} - -static struct bt_data ad[10] = { - BT_DATA(BLE_HS_ADV_TYPE_FLAGS, &ad_flags, sizeof(ad_flags)), -}; -static struct bt_data sd[10]; - -static int set_ad(const struct bt_data *ad, size_t ad_len, - uint8_t *buf, uint8_t *buf_len) -{ - int i; - - for (i = 0; i < ad_len; i++) { - buf[(*buf_len)++] = ad[i].data_len + 1; - buf[(*buf_len)++] = ad[i].type; - - memcpy(&buf[*buf_len], ad[i].data, - ad[i].data_len); - *buf_len += ad[i].data_len; - } - - return 0; -} - -static void start_advertising(const uint8_t *data, uint16_t len) -{ - const struct gap_start_advertising_cmd *cmd = (void *) data; - struct gap_start_advertising_rp rp; - int32_t duration_ms = BLE_HS_FOREVER; - uint8_t buf[BLE_HS_ADV_MAX_SZ]; - uint8_t buf_len = 0; - uint8_t adv_len, sd_len; - int err; - - int i; - - SYS_LOG_DBG(""); - - for (i = 0, adv_len = 1; i < cmd->adv_data_len; adv_len++) { - if (adv_len >= ARRAY_SIZE(ad)) { - SYS_LOG_ERR("ad[] Out of memory"); - goto fail; - } - - ad[adv_len].type = cmd->adv_data[i++]; - ad[adv_len].data_len = cmd->adv_data[i++]; - ad[adv_len].data = &cmd->adv_data[i]; - i += ad[adv_len].data_len; - } - - for (i = 0, sd_len = 0; i < cmd->scan_rsp_len; sd_len++) { - if (sd_len >= ARRAY_SIZE(sd)) { - SYS_LOG_ERR("sd[] Out of memory"); - goto fail; - } - - sd[sd_len].type = cmd->scan_rsp[i++]; - sd[sd_len].data_len = cmd->scan_rsp[i++]; - sd[sd_len].data = &cmd->scan_rsp[i]; - i += sd[sd_len].data_len; - } - - err = set_ad(ad, adv_len, buf, &buf_len); - if (err) { - goto fail; - } - - err = ble_gap_adv_set_data(buf, buf_len); - if (err != 0) { - goto fail; - } - - if (sd_len) { - buf_len = 0; - - err = set_ad(sd, sd_len, buf, &buf_len); - if (err) { - SYS_LOG_ERR("Advertising failed: err %d", err); - goto fail; - } - - err = ble_gap_adv_rsp_set_data(buf, buf_len); - if (err != 0) { - SYS_LOG_ERR("Advertising failed: err %d", err); - goto fail; - } - } - - if (adv_params.disc_mode == BLE_GAP_DISC_MODE_LTD) { - duration_ms = MYNEWT_VAL(BTTESTER_LTD_ADV_TIMEOUT); - } - -#if MYNEWT_VAL(BTTESTER_PRIVACY_MODE) && MYNEWT_VAL(BTTESTER_USE_NRPA) - if (MYNEWT_VAL(BTTESTER_NRPA_TIMEOUT) < duration_ms / 1000) { - advertising_start = os_get_uptime_usec(); - os_callout_reset(&bttester_nrpa_rotate_timer, - OS_TICKS_PER_SEC * MYNEWT_VAL(BTTESTER_NRPA_TIMEOUT)); - } -#endif - err = ble_gap_adv_start(own_addr_type, NULL, duration_ms, - &adv_params, gap_event_cb, NULL); - if (err) { - SYS_LOG_ERR("Advertising failed: err %d", err); - goto fail; - } - - current_settings |= BIT(GAP_SETTINGS_ADVERTISING); - rp.current_settings = sys_cpu_to_le32(current_settings); - - tester_send(BTP_SERVICE_ID_GAP, GAP_START_ADVERTISING, CONTROLLER_INDEX, - (uint8_t *) &rp, sizeof(rp)); - return; -fail: - tester_rsp(BTP_SERVICE_ID_GAP, GAP_START_ADVERTISING, CONTROLLER_INDEX, - BTP_STATUS_FAILED); -} - -static void stop_advertising(const uint8_t *data, uint16_t len) -{ - struct gap_stop_advertising_rp rp; - - SYS_LOG_DBG(""); - - if (ble_gap_adv_stop() != 0) { - tester_rsp(BTP_SERVICE_ID_GAP, GAP_STOP_ADVERTISING, - CONTROLLER_INDEX, BTP_STATUS_FAILED); - return; - } - - current_settings &= ~BIT(GAP_SETTINGS_ADVERTISING); - rp.current_settings = sys_cpu_to_le32(current_settings); - - tester_send(BTP_SERVICE_ID_GAP, GAP_STOP_ADVERTISING, CONTROLLER_INDEX, - (uint8_t *) &rp, sizeof(rp)); -} - -static uint8_t get_ad_flags(const uint8_t *data, uint8_t data_len) -{ - uint8_t len, i; - - /* Parse advertisement to get flags */ - for (i = 0; i < data_len; i += len - 1) { - len = data[i++]; - if (!len) { - break; - } - - /* Check if field length is correct */ - if (len > (data_len - i) || (data_len - i) < 1) { - break; - } - - switch (data[i++]) { - case BLE_HS_ADV_TYPE_FLAGS: - return data[i]; - default: - break; - } - } - - return 0; -} - -static uint8_t discovery_flags; -static struct os_mbuf *adv_buf; - -static void store_adv(const ble_addr_t *addr, int8_t rssi, - const uint8_t *data, uint8_t len) -{ - struct gap_device_found_ev *ev; - - /* cleanup */ - net_buf_simple_init(adv_buf, 0); - - ev = net_buf_simple_add(adv_buf, sizeof(*ev)); - - memcpy(ev->address, addr->val, sizeof(ev->address)); - ev->address_type = addr->type; - ev->rssi = rssi; - ev->flags = GAP_DEVICE_FOUND_FLAG_AD | GAP_DEVICE_FOUND_FLAG_RSSI; - ev->eir_data_len = len; - memcpy(net_buf_simple_add(adv_buf, len), data, len); -} - -static void device_found(ble_addr_t *addr, int8_t rssi, uint8_t evtype, - const uint8_t *data, uint8_t len) -{ - struct gap_device_found_ev *ev; - ble_addr_t a; - - /* if General/Limited Discovery - parse Advertising data to get flags */ - if (!(discovery_flags & GAP_DISCOVERY_FLAG_LE_OBSERVE) && - (evtype != BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP)) { - uint8_t flags = get_ad_flags(data, len); - - /* ignore non-discoverable devices */ - if (!(flags & BLE_AD_DISCOV_MASK)) { - SYS_LOG_DBG("Non discoverable, skipping"); - return; - } - - /* if Limited Discovery - ignore general discoverable devices */ - if ((discovery_flags & GAP_DISCOVERY_FLAG_LIMITED) && - !(flags & BLE_HS_ADV_F_DISC_LTD)) { - SYS_LOG_DBG("General discoverable, skipping"); - return; - } - } - - /* attach Scan Response data */ - if (evtype == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP) { - /* skip if there is no pending advertisement */ - if (!adv_buf->om_len) { - SYS_LOG_INF("No pending advertisement, skipping"); - return; - } - - ev = (void *) adv_buf->om_data; - a.type = ev->address_type; - memcpy(a.val, ev->address, sizeof(a.val)); - - /* - * in general, the Scan Response comes right after the - * Advertisement, but if not if send stored event and ignore - * this one - */ - if (ble_addr_cmp(addr, &a)) { - SYS_LOG_INF("Address does not match, skipping"); - goto done; - } - - ev->eir_data_len += len; - ev->flags |= GAP_DEVICE_FOUND_FLAG_SD; - - memcpy(net_buf_simple_add(adv_buf, len), data, len); - - goto done; - } - - /* - * if there is another pending advertisement, send it and store the - * current one - */ - if (adv_buf->om_len) { - tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_FOUND, - CONTROLLER_INDEX, adv_buf->om_data, - adv_buf->om_len); - } - - store_adv(addr, rssi, data, len); - - /* if Active Scan and scannable event - wait for Scan Response */ - if ((discovery_flags & GAP_DISCOVERY_FLAG_LE_ACTIVE_SCAN) && - (evtype == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND || - evtype == BLE_HCI_ADV_RPT_EVTYPE_SCAN_IND)) { - SYS_LOG_DBG("Waiting for scan response"); - return; - } -done: - tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_FOUND, - CONTROLLER_INDEX, adv_buf->om_data, adv_buf->om_len); -} - -static int discovery_cb(struct ble_gap_event *event, void *arg) -{ - if (event->type == BLE_GAP_EVENT_DISC) { - device_found(&event->disc.addr, event->disc.rssi, - event->disc.event_type, event->disc.data, - event->disc.length_data); - } - - return 0; -} - -static void start_discovery(const uint8_t *data, uint16_t len) -{ - const struct gap_start_discovery_cmd *cmd = (void *) data; - struct ble_gap_disc_params params = {0}; - uint8_t status; - - SYS_LOG_DBG(""); - - /* only LE scan is supported */ - if (cmd->flags & GAP_DISCOVERY_FLAG_BREDR) { - status = BTP_STATUS_FAILED; - goto reply; - } - - params.passive = (cmd->flags & GAP_DISCOVERY_FLAG_LE_ACTIVE_SCAN) == 0; - params.limited = (cmd->flags & GAP_DISCOVERY_FLAG_LIMITED) > 0; - params.filter_duplicates = 1; - - if (ble_gap_disc(own_addr_type, BLE_HS_FOREVER, - ¶ms, discovery_cb, NULL) != 0) { - status = BTP_STATUS_FAILED; - goto reply; - } - - net_buf_simple_init(adv_buf, 0); - discovery_flags = cmd->flags; - - status = BTP_STATUS_SUCCESS; -reply: - tester_rsp(BTP_SERVICE_ID_GAP, GAP_START_DISCOVERY, CONTROLLER_INDEX, - status); -} - -static void stop_discovery(const uint8_t *data, uint16_t len) -{ - uint8_t status = BTP_STATUS_SUCCESS; - - SYS_LOG_DBG(""); - - if (ble_gap_disc_cancel() != 0) { - status = BTP_STATUS_FAILED; - } - - tester_rsp(BTP_SERVICE_ID_GAP, GAP_STOP_DISCOVERY, CONTROLLER_INDEX, - status); -} - - -/* Bluetooth Core Spec v5.1 | Section 10.7.1 - * If a privacy-enabled Peripheral, that has a stored bond, - * receives a resolvable private address, the Host may resolve - * the resolvable private address [...] - * If the resolution is successful, the Host may accept the connection. - * If the resolution procedure fails, then the Host shall disconnect - * with the error code "Authentication failure" [...] - */ -static void periph_privacy(struct ble_gap_conn_desc desc) -{ -#if !MYNEWT_VAL(BTTESTER_PRIVACY_MODE) - return; -#endif - int count; - - SYS_LOG_DBG(""); - - ble_store_util_count(BLE_STORE_OBJ_TYPE_PEER_SEC, &count); - if (count > 0 && BLE_ADDR_IS_RPA(&desc.peer_id_addr)) { - SYS_LOG_DBG("Authentication failure, disconnecting"); - ble_gap_terminate(desc.conn_handle, BLE_ERR_AUTH_FAIL); - } -} - -static void device_connected_ev_send(struct os_event *ev) -{ - struct ble_gap_conn_desc desc; - int rc; - - SYS_LOG_DBG(""); - - rc = gap_conn_find_by_addr((ble_addr_t *)&connected_ev, &desc); - if (rc) { - tester_rsp(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_CONNECTED, - CONTROLLER_INDEX, BTP_STATUS_FAILED); - return; - } - - tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_CONNECTED, - CONTROLLER_INDEX, (uint8_t *) &connected_ev, - sizeof(connected_ev)); - - periph_privacy(desc); -} - -static void le_connected(uint16_t conn_handle, int status) -{ - struct ble_gap_conn_desc desc; - ble_addr_t *addr; - int rc; - - SYS_LOG_DBG(""); - - if (status != 0) { - return; - } - - rc = ble_gap_conn_find(conn_handle, &desc); - if (rc) { - return; - } - - peer_id_addr = desc.peer_id_addr; - peer_ota_addr = desc.peer_ota_addr; - - addr = &desc.peer_id_addr; - - memcpy(connected_ev.address, addr->val, sizeof(connected_ev.address)); - connected_ev.address_type = addr->type; - connected_ev.conn_itvl = desc.conn_itvl; - connected_ev.conn_latency = desc.conn_latency; - connected_ev.supervision_timeout = desc.supervision_timeout; - -#if MYNEWT_VAL(BTTESTER_CONN_RETRY) - os_callout_reset(&connected_ev_co, - os_time_ms_to_ticks32( - CONNECTED_EV_DELAY_MS(desc.conn_itvl))); -#else - tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_CONNECTED, - CONTROLLER_INDEX, (uint8_t *) &connected_ev, - sizeof(connected_ev)); -#endif -} - -static void le_disconnected(struct ble_gap_conn_desc *conn, int reason) -{ - struct gap_device_disconnected_ev ev; - ble_addr_t *addr = &conn->peer_ota_addr; - - SYS_LOG_DBG(""); - -#if MYNEWT_VAL(BTTESTER_CONN_RETRY) - int rc; - - if ((reason == BLE_HS_HCI_ERR(BLE_ERR_CONN_ESTABLISHMENT)) && - os_callout_queued(&connected_ev_co)) { - if (connection_attempts < MYNEWT_VAL(BTTESTER_CONN_RETRY)) { - os_callout_stop(&connected_ev_co); - - /* try connecting again */ - rc = ble_gap_connect(own_addr_type, addr, 0, - &dflt_conn_params, gap_event_cb, - NULL); - - if (rc == 0) { - connection_attempts++; - return; - } - } - } else if (os_callout_queued(&connected_ev_co)) { - os_callout_stop(&connected_ev_co); - return; - } -#endif - - connection_attempts = 0; - memset(&connected_ev, 0, sizeof(connected_ev)); - - memcpy(ev.address, addr->val, sizeof(ev.address)); - ev.address_type = addr->type; - - tester_send(BTP_SERVICE_ID_GAP, GAP_EV_DEVICE_DISCONNECTED, - CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); -} - -static void auth_passkey_oob(uint16_t conn_handle) -{ - struct ble_gap_conn_desc desc; - struct ble_sm_io pk; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find(conn_handle, &desc); - if (rc) { - return; - } - - memcpy(pk.oob, oob, sizeof(oob)); - pk.action = BLE_SM_IOACT_OOB; - - rc = ble_sm_inject_io(conn_handle, &pk); - assert(rc == 0); -} - -static void auth_passkey_display(uint16_t conn_handle, unsigned int passkey) -{ - struct ble_gap_conn_desc desc; - struct gap_passkey_display_ev ev; - ble_addr_t *addr; - struct ble_sm_io pk; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find(conn_handle, &desc); - if (rc) { - return; - } - - rc = ble_hs_hci_util_rand(&pk.passkey, sizeof(pk.passkey)); - assert(rc == 0); - /* Max value is 999999 */ - pk.passkey %= 1000000; - pk.action = BLE_SM_IOACT_DISP; - - rc = ble_sm_inject_io(conn_handle, &pk); - assert(rc == 0); - - addr = &desc.peer_ota_addr; - - memcpy(ev.address, addr->val, sizeof(ev.address)); - ev.address_type = addr->type; - ev.passkey = sys_cpu_to_le32(pk.passkey); - - tester_send(BTP_SERVICE_ID_GAP, GAP_EV_PASSKEY_DISPLAY, - CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); -} - -static void auth_passkey_entry(uint16_t conn_handle) -{ - struct ble_gap_conn_desc desc; - struct gap_passkey_entry_req_ev ev; - ble_addr_t *addr; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find(conn_handle, &desc); - if (rc) { - return; - } - - addr = &desc.peer_ota_addr; - - memcpy(ev.address, addr->val, sizeof(ev.address)); - ev.address_type = addr->type; - - tester_send(BTP_SERVICE_ID_GAP, GAP_EV_PASSKEY_ENTRY_REQ, - CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); -} - -static void auth_passkey_numcmp(uint16_t conn_handle, unsigned int passkey) -{ - struct ble_gap_conn_desc desc; - struct gap_passkey_confirm_req_ev ev; - ble_addr_t *addr; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find(conn_handle, &desc); - if (rc) { - return; - } - - addr = &desc.peer_ota_addr; - - memcpy(ev.address, addr->val, sizeof(ev.address)); - ev.address_type = addr->type; - ev.passkey = sys_cpu_to_le32(passkey); - - tester_send(BTP_SERVICE_ID_GAP, GAP_EV_PASSKEY_CONFIRM_REQ, - CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); -} - -static void auth_passkey_oob_sc(uint16_t conn_handle) -{ - int rc; - struct ble_sm_io pk; - - SYS_LOG_DBG(""); - - memset(&pk, 0, sizeof(pk)); - - pk.oob_sc_data.local = &oob_data_local; - - if (ble_hs_cfg.sm_oob_data_flag) { - pk.oob_sc_data.remote = &oob_data_remote; - } - - pk.action = BLE_SM_IOACT_OOB_SC; - rc = ble_sm_inject_io(conn_handle, &pk); - if (rc != 0) { - console_printf("error providing oob; rc=%d\n", rc); - } -} - -static void le_passkey_action(uint16_t conn_handle, - struct ble_gap_passkey_params *params) -{ - SYS_LOG_DBG(""); - - switch (params->action) { - case BLE_SM_IOACT_NONE: - break; - case BLE_SM_IOACT_OOB: - auth_passkey_oob(conn_handle); - break; - case BLE_SM_IOACT_INPUT: - auth_passkey_entry(conn_handle); - break; - case BLE_SM_IOACT_DISP: - auth_passkey_display(conn_handle, params->numcmp); - break; - case BLE_SM_IOACT_NUMCMP: - auth_passkey_numcmp(conn_handle, params->numcmp); - break; - case BLE_SM_IOACT_OOB_SC: - auth_passkey_oob_sc(conn_handle); - break; - default: - assert(0); - } -} - -static void le_identity_resolved(uint16_t conn_handle) -{ - struct ble_gap_conn_desc desc; - struct gap_identity_resolved_ev ev; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find(conn_handle, &desc); - if (rc) { - return; - } - - peer_id_addr = desc.peer_id_addr; - peer_ota_addr = desc.peer_ota_addr; - - ev.address_type = desc.peer_ota_addr.type; - memcpy(ev.address, desc.peer_ota_addr.val, sizeof(ev.address)); - - ev.identity_address_type = desc.peer_id_addr.type; - memcpy(ev.identity_address, desc.peer_id_addr.val, - sizeof(ev.identity_address)); - - tester_send(BTP_SERVICE_ID_GAP, GAP_EV_IDENTITY_RESOLVED, - CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); -} - -static void le_conn_param_update(struct ble_gap_conn_desc *desc) -{ - struct gap_conn_param_update_ev ev; - - SYS_LOG_DBG(""); - - ev.address_type = desc->peer_ota_addr.type; - memcpy(ev.address, desc->peer_ota_addr.val, sizeof(ev.address)); - - ev.conn_itvl = desc->conn_itvl; - ev.conn_latency = desc->conn_latency; - ev.supervision_timeout = desc->supervision_timeout; - - tester_send(BTP_SERVICE_ID_GAP, GAP_EV_CONN_PARAM_UPDATE, - CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); -} - -static void le_encryption_changed(struct ble_gap_conn_desc *desc) -{ - struct gap_sec_level_changed_ev ev; - - SYS_LOG_DBG(""); - - encrypted = (bool) desc->sec_state.encrypted; - - ev.address_type = desc->peer_ota_addr.type; - memcpy(ev.address, desc->peer_ota_addr.val, sizeof(ev.address)); - ev.level = 0; - - if (desc->sec_state.encrypted) { - if (desc->sec_state.authenticated) { - if (desc->sec_state.key_size == 16) { - ev.level = 3; - } else { - ev.level = 2; - } - } else { - ev.level = 1; - } - } - - tester_send(BTP_SERVICE_ID_GAP, GAP_EV_SEC_LEVEL_CHANGED, - CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); -} - -static void print_bytes(const uint8_t *bytes, int len) -{ - int i; - - for (i = 0; i < len; i++) { - console_printf("%s0x%02x", i != 0 ? ":" : "", bytes[i]); - } -} - -static void print_mbuf(const struct os_mbuf *om) -{ - int colon; - - colon = 0; - while (om != NULL) { - if (colon) { - console_printf(":"); - } else { - colon = 1; - } - print_bytes(om->om_data, om->om_len); - om = SLIST_NEXT(om, om_next); - } -} - -static void print_addr(const void *addr) -{ - const uint8_t *u8p; - - u8p = addr; - console_printf("%02x:%02x:%02x:%02x:%02x:%02x", - u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]); -} - -static void print_conn_desc(const struct ble_gap_conn_desc *desc) -{ - console_printf("handle=%d our_ota_addr_type=%d our_ota_addr=", - desc->conn_handle, desc->our_ota_addr.type); - print_addr(desc->our_ota_addr.val); - console_printf(" our_id_addr_type=%d our_id_addr=", - desc->our_id_addr.type); - print_addr(desc->our_id_addr.val); - console_printf(" peer_ota_addr_type=%d peer_ota_addr=", - desc->peer_ota_addr.type); - print_addr(desc->peer_ota_addr.val); - console_printf(" peer_id_addr_type=%d peer_id_addr=", - desc->peer_id_addr.type); - print_addr(desc->peer_id_addr.val); - console_printf(" conn_itvl=%d conn_latency=%d supervision_timeout=%d " - "key_sz=%d encrypted=%d authenticated=%d bonded=%d\n", - desc->conn_itvl, desc->conn_latency, - desc->supervision_timeout, - desc->sec_state.key_size, - desc->sec_state.encrypted, - desc->sec_state.authenticated, - desc->sec_state.bonded); -} - -static void adv_complete(void) -{ - struct gap_new_settings_ev ev; - - current_settings &= ~BIT(GAP_SETTINGS_ADVERTISING); - ev.current_settings = sys_cpu_to_le32(current_settings); - - tester_send(BTP_SERVICE_ID_GAP, GAP_EV_NEW_SETTINGS, CONTROLLER_INDEX, - (uint8_t *) &ev, sizeof(ev)); -} - -static int gap_event_cb(struct ble_gap_event *event, void *arg) -{ - struct ble_gap_conn_desc desc; - int rc; - - switch (event->type) { - case BLE_GAP_EVENT_ADV_COMPLETE: - console_printf("advertising complete; reason=%d\n", - event->adv_complete.reason); - break; - case BLE_GAP_EVENT_CONNECT: - console_printf("connection %s; status=%d ", - event->connect.status == 0 ? "established" : "failed", - event->connect.status); - if (event->connect.status == 0) { - rc = ble_gap_conn_find(event->connect.conn_handle, &desc); - assert(rc == 0); - print_conn_desc(&desc); - } - - if (desc.role == BLE_GAP_ROLE_SLAVE) { - adv_complete(); - } - - le_connected(event->connect.conn_handle, - event->connect.status); - break; - case BLE_GAP_EVENT_DISCONNECT: - console_printf("disconnect; reason=%d ", event->disconnect.reason); - print_conn_desc(&event->disconnect.conn); - le_disconnected(&event->disconnect.conn, - event->disconnect.reason); - break; - case BLE_GAP_EVENT_ENC_CHANGE: - console_printf("encryption change event; status=%d ", event->enc_change.status); - rc = ble_gap_conn_find(event->enc_change.conn_handle, &desc); - assert(rc == 0); - print_conn_desc(&desc); - le_encryption_changed(&desc); - break; - case BLE_GAP_EVENT_PASSKEY_ACTION: - console_printf("passkey action event; action=%d", - event->passkey.params.action); - if (event->passkey.params.action == BLE_SM_IOACT_NUMCMP) { - console_printf(" numcmp=%lu", - (unsigned long)event->passkey.params.numcmp); - } - console_printf("\n"); - le_passkey_action(event->passkey.conn_handle, - &event->passkey.params); - break; - case BLE_GAP_EVENT_IDENTITY_RESOLVED: - console_printf("identity resolved "); - rc = ble_gap_conn_find(event->identity_resolved.conn_handle, &desc); - assert(rc == 0); - print_conn_desc(&desc); - le_identity_resolved(event->identity_resolved.conn_handle); - break; - case BLE_GAP_EVENT_NOTIFY_RX: - console_printf("notification rx event; attr_handle=%d indication=%d " - "len=%d data=", - event->notify_rx.attr_handle, - event->notify_rx.indication, - OS_MBUF_PKTLEN(event->notify_rx.om)); - - print_mbuf(event->notify_rx.om); - console_printf("\n"); - tester_gattc_notify_rx_ev(event->notify_rx.conn_handle, - event->notify_rx.attr_handle, - event->notify_rx.indication, - event->notify_rx.om); - break; - case BLE_GAP_EVENT_SUBSCRIBE: - console_printf("subscribe event; conn_handle=%d attr_handle=%d " - "reason=%d prevn=%d curn=%d previ=%d curi=%d\n", - event->subscribe.conn_handle, - event->subscribe.attr_handle, - event->subscribe.reason, - event->subscribe.prev_notify, - event->subscribe.cur_notify, - event->subscribe.prev_indicate, - event->subscribe.cur_indicate); - tester_gatt_subscribe_ev(event->subscribe.conn_handle, - event->subscribe.attr_handle, - event->subscribe.reason, - event->subscribe.prev_notify, - event->subscribe.cur_notify, - event->subscribe.prev_indicate, - event->subscribe.cur_indicate); - break; - case BLE_GAP_EVENT_REPEAT_PAIRING: - console_printf("repeat pairing event; conn_handle=%d " - "cur_key_sz=%d cur_auth=%d cur_sc=%d " - "new_key_sz=%d new_auth=%d new_sc=%d " - "new_bonding=%d\n", - event->repeat_pairing.conn_handle, - event->repeat_pairing.cur_key_size, - event->repeat_pairing.cur_authenticated, - event->repeat_pairing.cur_sc, - event->repeat_pairing.new_key_size, - event->repeat_pairing.new_authenticated, - event->repeat_pairing.new_sc, - event->repeat_pairing.new_bonding); - rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc); - assert(rc == 0); - rc = ble_store_util_delete_peer(&desc.peer_id_addr); - assert(rc == 0); - return BLE_GAP_REPEAT_PAIRING_RETRY; - case BLE_GAP_EVENT_CONN_UPDATE: - console_printf("connection update event; status=%d ", - event->conn_update.status); - rc = ble_gap_conn_find(event->conn_update.conn_handle, &desc); - assert(rc == 0); - print_conn_desc(&desc); - le_conn_param_update(&desc); - break; - case BLE_GAP_EVENT_CONN_UPDATE_REQ: - console_printf("connection update request event; " - "conn_handle=%d itvl_min=%d itvl_max=%d " - "latency=%d supervision_timoeut=%d " - "min_ce_len=%d max_ce_len=%d\n", - event->conn_update_req.conn_handle, - event->conn_update_req.peer_params->itvl_min, - event->conn_update_req.peer_params->itvl_max, - event->conn_update_req.peer_params->latency, - event->conn_update_req.peer_params->supervision_timeout, - event->conn_update_req.peer_params->min_ce_len, - event->conn_update_req.peer_params->max_ce_len); - - *event->conn_update_req.self_params = - *event->conn_update_req.peer_params; - break; - case BLE_GAP_EVENT_L2CAP_UPDATE_REQ: - console_printf("connection update request event; " - "conn_handle=%d itvl_min=%d itvl_max=%d " - "latency=%d supervision_timoeut=%d " - "min_ce_len=%d max_ce_len=%d\n", - event->conn_update_req.conn_handle, - event->conn_update_req.peer_params->itvl_min, - event->conn_update_req.peer_params->itvl_max, - event->conn_update_req.peer_params->latency, - event->conn_update_req.peer_params->supervision_timeout, - event->conn_update_req.peer_params->min_ce_len, - event->conn_update_req.peer_params->max_ce_len); - if (event->conn_update_req.peer_params->itvl_min == REJECT_INTERVAL_MIN && - event->conn_update_req.peer_params->itvl_max == REJECT_INTERVAL_MAX && - event->conn_update_req.peer_params->latency == REJECT_LATENCY && - event->conn_update_req.peer_params->supervision_timeout == REJECT_SUPERVISION_TIMEOUT) { - return EINVAL; - } - - default: - break; - } - - return 0; -} - -static void connect(const uint8_t *data, uint16_t len) -{ - uint8_t status = BTP_STATUS_SUCCESS; - ble_addr_t *addr = (ble_addr_t *) data; - - SYS_LOG_DBG(""); - - if (ble_addr_cmp(BLE_ADDR_ANY, addr) == 0) { - addr = NULL; - } - - if (ble_gap_connect(own_addr_type, addr, 0, - &dflt_conn_params, gap_event_cb, NULL)) { - status = BTP_STATUS_FAILED; - } - - tester_rsp(BTP_SERVICE_ID_GAP, GAP_CONNECT, CONTROLLER_INDEX, status); -} - -static void disconnect(const uint8_t *data, uint16_t len) -{ - struct ble_gap_conn_desc desc; - uint8_t status; - int rc; - - SYS_LOG_DBG(""); - - rc = gap_conn_find_by_addr((ble_addr_t *)data, &desc); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - if (ble_gap_terminate(desc.conn_handle, BLE_ERR_REM_USER_CONN_TERM)) { - status = BTP_STATUS_FAILED; - } else { - status = BTP_STATUS_SUCCESS; - } - -rsp: - tester_rsp(BTP_SERVICE_ID_GAP, GAP_DISCONNECT, CONTROLLER_INDEX, - status); -} - -static void set_io_cap(const uint8_t *data, uint16_t len) -{ - const struct gap_set_io_cap_cmd *cmd = (void *) data; - uint8_t status; - - SYS_LOG_DBG(""); - - switch (cmd->io_cap) { - case GAP_IO_CAP_DISPLAY_ONLY: - ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_DISP_ONLY; - ble_hs_cfg.sm_mitm = 1; - break; - case GAP_IO_CAP_KEYBOARD_DISPLAY: - ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_KEYBOARD_DISP; - ble_hs_cfg.sm_mitm = 1; - break; - case GAP_IO_CAP_NO_INPUT_OUTPUT: - ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_NO_IO; - ble_hs_cfg.sm_mitm = 0; - break; - case GAP_IO_CAP_KEYBOARD_ONLY: - ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_KEYBOARD_ONLY; - ble_hs_cfg.sm_mitm = 1; - break; - case GAP_IO_CAP_DISPLAY_YESNO: - ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_DISP_YES_NO; - ble_hs_cfg.sm_mitm = 1; - break; - default: - status = BTP_STATUS_FAILED; - goto rsp; - } - - status = BTP_STATUS_SUCCESS; - -rsp: - tester_rsp(BTP_SERVICE_ID_GAP, GAP_SET_IO_CAP, CONTROLLER_INDEX, - status); -} - -static void pair(const uint8_t *data, uint16_t len) -{ - struct ble_gap_conn_desc desc; - uint8_t status; - int rc; - - SYS_LOG_DBG(""); - - rc = gap_conn_find_by_addr((ble_addr_t *)data, &desc); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - if (ble_gap_security_initiate(desc.conn_handle)) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - status = BTP_STATUS_SUCCESS; - -rsp: - tester_rsp(BTP_SERVICE_ID_GAP, GAP_PAIR, CONTROLLER_INDEX, status); -} - -static void unpair(const uint8_t *data, uint16_t len) -{ - uint8_t status; - int err; - - SYS_LOG_DBG(""); - - err = ble_gap_unpair((ble_addr_t *) data); - status = (uint8_t) (err != 0 ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS); - tester_rsp(BTP_SERVICE_ID_GAP, GAP_UNPAIR, CONTROLLER_INDEX, status); -} - -static void passkey_entry(const uint8_t *data, uint16_t len) -{ - const struct gap_passkey_entry_cmd *cmd = (void *) data; - struct ble_gap_conn_desc desc; - struct ble_sm_io pk; - uint8_t status; - int rc; - - SYS_LOG_DBG(""); - - rc = gap_conn_find_by_addr((ble_addr_t *)data, &desc); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - pk.action = BLE_SM_IOACT_INPUT; - pk.passkey = sys_le32_to_cpu(cmd->passkey); - - rc = ble_sm_inject_io(desc.conn_handle, &pk); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - status = BTP_STATUS_SUCCESS; - -rsp: - tester_rsp(BTP_SERVICE_ID_GAP, GAP_PASSKEY_ENTRY, CONTROLLER_INDEX, - status); -} - -static void passkey_confirm(const uint8_t *data, uint16_t len) -{ - const struct gap_passkey_confirm_cmd *cmd = (void *) data; - struct ble_gap_conn_desc desc; - struct ble_sm_io pk; - uint8_t status; - int rc; - - SYS_LOG_DBG(""); - - rc = gap_conn_find_by_addr((ble_addr_t *)data, &desc); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - pk.action = BLE_SM_IOACT_NUMCMP; - pk.numcmp_accept = cmd->match; - - rc = ble_sm_inject_io(desc.conn_handle, &pk); - if (rc) { - console_printf("sm inject io failed"); - status = BTP_STATUS_FAILED; - goto rsp; - } - - status = BTP_STATUS_SUCCESS; - -rsp: - tester_rsp(BTP_SERVICE_ID_GAP, GAP_PASSKEY_CONFIRM, CONTROLLER_INDEX, - status); -} - -static void start_direct_adv(const uint8_t *data, uint16_t len) -{ - const struct gap_start_direct_adv_cmd *cmd = (void *) data; - struct gap_start_advertising_rp rp; - static struct ble_gap_adv_params adv_params = { - .conn_mode = BLE_GAP_CONN_MODE_DIR, - }; - int err; - - SYS_LOG_DBG(""); - - adv_params.high_duty_cycle = cmd->high_duty; - - err = ble_gap_adv_start(own_addr_type, (ble_addr_t *)data, - BLE_HS_FOREVER, &adv_params, - gap_event_cb, NULL); - if (err) { - SYS_LOG_ERR("Advertising failed: err %d", err); - goto fail; - } - - current_settings |= BIT(GAP_SETTINGS_ADVERTISING); - rp.current_settings = sys_cpu_to_le32(current_settings); - - tester_send(BTP_SERVICE_ID_GAP, GAP_START_DIRECT_ADV, CONTROLLER_INDEX, - (uint8_t *) &rp, sizeof(rp)); - return; -fail: - tester_rsp(BTP_SERVICE_ID_GAP, GAP_START_DIRECT_ADV, CONTROLLER_INDEX, - BTP_STATUS_FAILED); -} - -static void conn_param_update_cb(uint16_t conn_handle, int status, void *arg) -{ - console_printf("conn param update complete; conn_handle=%d status=%d\n", - conn_handle, status); -} - -static int conn_param_update_slave(uint16_t conn_handle, - const struct gap_conn_param_update_cmd *cmd) -{ - int rc; - struct ble_l2cap_sig_update_params params; - - params.itvl_min = cmd->conn_itvl_min; - params.itvl_max = cmd->conn_itvl_max; - params.slave_latency = cmd->conn_latency; - params.timeout_multiplier = cmd->supervision_timeout; - - rc = ble_l2cap_sig_update(conn_handle, ¶ms, - conn_param_update_cb, NULL); - if (rc) { - SYS_LOG_ERR("Failed to send update params: rc=%d", rc); - } - - return 0; -} - -static int conn_param_update_master(uint16_t conn_handle, - const struct gap_conn_param_update_cmd *cmd) -{ - int rc; - struct ble_gap_upd_params params; - - params.itvl_min = cmd->conn_itvl_min; - params.itvl_max = cmd->conn_itvl_max; - params.latency = cmd->conn_latency; - params.supervision_timeout = cmd->supervision_timeout; - params.min_ce_len = 0; - params.max_ce_len = 0; - rc = ble_gap_update_params(conn_handle, ¶ms); - if (rc) { - SYS_LOG_ERR("Failed to send update params: rc=%d", rc); - } - - return rc; -} - -static void conn_param_update(struct os_event *ev) -{ - struct ble_gap_conn_desc desc; - int rc; - - SYS_LOG_DBG(""); - - rc = gap_conn_find_by_addr((ble_addr_t *)&update_params, &desc); - if (rc) { - goto rsp; - } - - if ((desc.conn_itvl >= update_params.conn_itvl_min) && - (desc.conn_itvl <= update_params.conn_itvl_max) && - (desc.conn_latency == update_params.conn_latency) && - (desc.supervision_timeout == update_params.supervision_timeout)) { - goto rsp; - } - - if (desc.role == BLE_GAP_ROLE_MASTER) { - rc = conn_param_update_master(desc.conn_handle, &update_params); - } else { - rc = conn_param_update_slave(desc.conn_handle, &update_params); - } - - if (rc == 0) { - return; - } - -rsp: - SYS_LOG_ERR("Conn param update fail; rc=%d", rc); -} - -static void conn_param_update_async(const uint8_t *data, uint16_t len) -{ - const struct gap_conn_param_update_cmd *cmd = (void *) data; - update_params = *cmd; - - os_callout_reset(&update_params_co, 0); - - tester_rsp(BTP_SERVICE_ID_GAP, GAP_CONN_PARAM_UPDATE, CONTROLLER_INDEX, - BTP_STATUS_SUCCESS); -} - -static void oob_legacy_set_data(const uint8_t *data, uint16_t len) -{ - const struct gap_oob_legacy_set_data_cmd *cmd = (void *) data; - - ble_hs_cfg.sm_oob_data_flag = 1; - memcpy(oob, cmd->oob_data, sizeof(oob)); - - tester_rsp(BTP_SERVICE_ID_GAP, GAP_OOB_LEGACY_SET_DATA, - CONTROLLER_INDEX, BTP_STATUS_SUCCESS); -} - -static void oob_sc_get_local_data(const uint8_t *data, uint16_t len) -{ - struct gap_oob_sc_get_local_data_rp rp; - - memcpy(rp.r, oob_data_local.r, 16); - memcpy(rp.c, oob_data_local.c, 16); - - tester_send(BTP_SERVICE_ID_GAP, GAP_OOB_SC_GET_LOCAL_DATA, - CONTROLLER_INDEX, (uint8_t *) &rp, sizeof(rp)); -} - -static void oob_sc_set_remote_data(const uint8_t *data, uint16_t len) -{ - const struct gap_oob_sc_set_remote_data_cmd *cmd = (void *) data; - - ble_hs_cfg.sm_oob_data_flag = 1; - memcpy(oob_data_remote.r, cmd->r, 16); - memcpy(oob_data_remote.c, cmd->c, 16); - - tester_rsp(BTP_SERVICE_ID_GAP, GAP_OOB_SC_SET_REMOTE_DATA, - CONTROLLER_INDEX, BTP_STATUS_SUCCESS); -} - -static void set_mitm(const uint8_t *data, uint16_t len) -{ - const struct gap_set_mitm_cmd *cmd = (void *) data; - - ble_hs_cfg.sm_mitm = cmd->mitm; - - tester_rsp(BTP_SERVICE_ID_GAP, GAP_SET_MITM, - CONTROLLER_INDEX, BTP_STATUS_SUCCESS); -} - -static void set_filter_accept_list(const uint8_t *data, uint16_t len) -{ - uint8_t status = BTP_STATUS_SUCCESS; - struct gap_set_filter_accept_list_cmd *tmp = - (struct gap_set_filter_accept_list_cmd *) data; - - SYS_LOG_DBG(""); - - /* - * Check if the nb of bytes received matches the len of addrs list. - * Then set the filter accept list. - */ - if (((len - sizeof(tmp->list_len))/sizeof(ble_addr_t) != - tmp->list_len) || ble_gap_wl_set(tmp->addrs, tmp->list_len)) { - status = BTP_STATUS_FAILED; - } - - tester_rsp(BTP_SERVICE_ID_GAP, GAP_SET_FILTER_ACCEPT_LIST, - CONTROLLER_INDEX, status); -} - -void tester_handle_gap(uint8_t opcode, uint8_t index, uint8_t *data, - uint16_t len) -{ - switch (opcode) { - case GAP_READ_SUPPORTED_COMMANDS: - case GAP_READ_CONTROLLER_INDEX_LIST: - if (index != BTP_INDEX_NONE){ - tester_rsp(BTP_SERVICE_ID_GAP, opcode, index, - BTP_STATUS_FAILED); - return; - } - break; - default: - if (index != CONTROLLER_INDEX){ - tester_rsp(BTP_SERVICE_ID_GAP, opcode, index, - BTP_STATUS_FAILED); - return; - } - break; - } - - switch (opcode) { - case GAP_READ_SUPPORTED_COMMANDS: - supported_commands(data, len); - return; - case GAP_READ_CONTROLLER_INDEX_LIST: - controller_index_list(data, len); - return; - case GAP_READ_CONTROLLER_INFO: - controller_info(data, len); - return; - case GAP_SET_CONNECTABLE: - set_connectable(data, len); - return; - case GAP_SET_DISCOVERABLE: - set_discoverable(data, len); - return; - case GAP_SET_BONDABLE: - set_bondable(data, len); - return; - case GAP_START_ADVERTISING: - start_advertising(data, len); - return; - case GAP_STOP_ADVERTISING: - stop_advertising(data, len); - return; - case GAP_START_DISCOVERY: - start_discovery(data, len); - return; - case GAP_STOP_DISCOVERY: - stop_discovery(data, len); - return; - case GAP_CONNECT: - connect(data, len); - return; - case GAP_DISCONNECT: - disconnect(data, len); - return; - case GAP_SET_IO_CAP: - set_io_cap(data, len); - return; - case GAP_PAIR: - pair(data, len); - return; - case GAP_UNPAIR: - unpair(data, len); - return; - case GAP_PASSKEY_ENTRY: - passkey_entry(data, len); - return; - case GAP_PASSKEY_CONFIRM: - passkey_confirm(data, len); - return; - case GAP_START_DIRECT_ADV: - start_direct_adv(data, len); - return; - case GAP_CONN_PARAM_UPDATE: - conn_param_update_async(data, len); - return; - case GAP_OOB_LEGACY_SET_DATA: - oob_legacy_set_data(data, len); - return; - case GAP_OOB_SC_GET_LOCAL_DATA: - oob_sc_get_local_data(data, len); - return; - case GAP_OOB_SC_SET_REMOTE_DATA: - oob_sc_set_remote_data(data, len); - return; - case GAP_SET_MITM: - set_mitm(data, len); - return; - case GAP_SET_FILTER_ACCEPT_LIST: - set_filter_accept_list(data, len); - return; - default: - tester_rsp(BTP_SERVICE_ID_GAP, opcode, index, - BTP_STATUS_UNKNOWN_CMD); - return; - } -} - -static void tester_init_gap_cb(int err) -{ - if (err) { - tester_rsp(BTP_SERVICE_ID_CORE, CORE_REGISTER_SERVICE, - BTP_INDEX_NONE, BTP_STATUS_FAILED); - return; - } - - current_settings = 0; - current_settings |= BIT(GAP_SETTINGS_POWERED); - current_settings |= BIT(GAP_SETTINGS_LE); - - os_callout_init(&update_params_co, os_eventq_dflt_get(), - conn_param_update, NULL); - - os_callout_init(&connected_ev_co, os_eventq_dflt_get(), - device_connected_ev_send, NULL); - - tester_rsp(BTP_SERVICE_ID_CORE, CORE_REGISTER_SERVICE, BTP_INDEX_NONE, - BTP_STATUS_SUCCESS); -} - -uint8_t tester_init_gap(void) -{ -#if MYNEWT_VAL(BLE_SM_SC) - int rc; - - rc = ble_sm_sc_oob_generate_data(&oob_data_local); - if (rc) { - console_printf("Error: generating oob data; reason=%d\n", rc); - return BTP_STATUS_FAILED; - } -#endif -#if MYNEWT_VAL(BTTESTER_PRIVACY_MODE) && MYNEWT_VAL(BTTESTER_USE_NRPA) - os_callout_init(&bttester_nrpa_rotate_timer, os_eventq_dflt_get(), - rotate_nrpa_cb, NULL); -#endif - adv_buf = NET_BUF_SIMPLE(ADV_BUF_LEN); - - tester_init_gap_cb(BTP_STATUS_SUCCESS); - return BTP_STATUS_SUCCESS; -} - -uint8_t tester_unregister_gap(void) -{ - return BTP_STATUS_SUCCESS; -} diff --git a/lib/bt/host/nimble/nimble/apps/bttester/src/gatt_cl.c b/lib/bt/host/nimble/nimble/apps/bttester/src/gatt_cl.c deleted file mode 100644 index c551bb17..00000000 --- a/lib/bt/host/nimble/nimble/apps/bttester/src/gatt_cl.c +++ /dev/null @@ -1,1483 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include -#include - -#include "host/ble_gap.h" -#include "host/ble_gatt.h" -#include "console/console.h" -#include "services/gatt/ble_svc_gatt.h" -#include "../../../nimble/host/src/ble_att_priv.h" -#include "../../../nimble/host/src/ble_gatt_priv.h" - -#include "bttester.h" - -#define CONTROLLER_INDEX 0 -#define MAX_BUFFER_SIZE 2048 - -/* Convert UUID from BTP command to bt_uuid */ -static uint8_t btp2bt_uuid(const uint8_t *uuid, uint8_t len, - ble_uuid_any_t *bt_uuid) -{ - uint16_t le16; - - switch (len) { - case 0x02: /* UUID 16 */ - bt_uuid->u.type = BLE_UUID_TYPE_16; - memcpy(&le16, uuid, sizeof(le16)); - BLE_UUID16(bt_uuid)->value = sys_le16_to_cpu(le16); - break; - case 0x10: /* UUID 128*/ - bt_uuid->u.type = BLE_UUID_TYPE_128; - memcpy(BLE_UUID128(bt_uuid)->value, uuid, 16); - break; - default: - return BTP_STATUS_FAILED; - } - return BTP_STATUS_SUCCESS; -} - -/* - * gatt_buf - cache used by a gatt client (to cache data read/discovered) - * and gatt server (to store attribute user_data). - * It is not intended to be used by client and server at the same time. - */ -static struct { - uint16_t len; - uint8_t buf[MAX_BUFFER_SIZE]; - uint16_t cnt; -} gatt_buf; -static struct bt_gatt_subscribe_params { - uint16_t ccc_handle; - uint16_t value; - uint16_t value_handle; -} subscribe_params; - -static void *gatt_buf_add(const void *data, size_t len) -{ - void *ptr = gatt_buf.buf + gatt_buf.len; - - if ((len + gatt_buf.len) > MAX_BUFFER_SIZE) { - return NULL; - } - - if (data) { - memcpy(ptr, data, len); - } else { - (void) memset(ptr, 0, len); - } - - gatt_buf.len += len; - - SYS_LOG_DBG("%d/%d used", gatt_buf.len, MAX_BUFFER_SIZE); - - return ptr; -} - -static void *gatt_buf_reserve(size_t len) -{ - return gatt_buf_add(NULL, len); -} - -static void gatt_buf_clear(void) -{ - (void) memset(&gatt_buf, 0, sizeof(gatt_buf)); -} - -static void discover_destroy(void) -{ - gatt_buf_clear(); -} - -static void read_destroy() -{ - gatt_buf_clear(); -} - -static int tester_mtu_exchanged_ev(uint16_t conn_handle, - const struct ble_gatt_error *error, - uint16_t mtu, void *arg) -{ - struct gattc_exchange_mtu_ev *ev; - struct ble_gap_conn_desc conn; - struct os_mbuf *buf = os_msys_get(0, 0); - const ble_addr_t *addr; - - SYS_LOG_DBG(""); - - if (ble_gap_conn_find(conn_handle, &conn)) { - goto fail; - } - - net_buf_simple_init(buf, 0); - ev = net_buf_simple_add(buf, sizeof(*ev)); - - addr = &conn.peer_ota_addr; - - ev->address_type = addr->type; - memcpy(ev->address, addr->val, sizeof(ev->address)); - - ev->mtu = mtu; - - tester_send_buf(BTP_SERVICE_ID_GATTC, GATTC_EV_MTU_EXCHANGED, - CONTROLLER_INDEX, buf); -fail: - os_mbuf_free_chain(buf); - return 0; -} - -static void exchange_mtu(uint8_t *data, uint16_t len) -{ - struct ble_gap_conn_desc conn; - uint8_t status = BTP_STATUS_SUCCESS; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - if (ble_gattc_exchange_mtu(conn.conn_handle, tester_mtu_exchanged_ev, NULL)) { - status = BTP_STATUS_FAILED; - goto rsp; - } - -rsp: - tester_rsp(BTP_SERVICE_ID_GATTC, GATTC_EXCHANGE_MTU, - CONTROLLER_INDEX, status); -} - -static int disc_prim_svcs_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - const struct ble_gatt_svc *gatt_svc, void *arg) -{ - struct gattc_disc_prim_svcs_rp *rp; - struct ble_gap_conn_desc conn; - struct gatt_service *service; - const ble_uuid_any_t *uuid; - const ble_addr_t *addr; - uint8_t uuid_length; - struct os_mbuf *buf = os_msys_get(0, 0); - uint8_t opcode = (uint8_t) (int) arg; - uint8_t err = (uint8_t) error->status; - int rc = 0; - - SYS_LOG_DBG(""); - - if (ble_gap_conn_find(conn_handle, &conn)) { - goto free; - } - - net_buf_simple_init(buf, 0); - rp = net_buf_simple_add(buf, sizeof(*rp)); - - addr = &conn.peer_ota_addr; - - rp->address_type = addr->type; - memcpy(rp->address, addr->val, sizeof(rp->address)); - - rp->status = err; - if (error->status != 0 && error->status != BLE_HS_EDONE) { - rp->services_count = 0; - tester_send_buf(BTP_SERVICE_ID_GATTC, opcode, - CONTROLLER_INDEX, buf); - discover_destroy(); - goto free; - } - - if (error->status == BLE_HS_EDONE) { - rp->status = 0; - rp->services_count = gatt_buf.cnt; - os_mbuf_append(buf, gatt_buf.buf, gatt_buf.len); - tester_send_buf(BTP_SERVICE_ID_GATTC, opcode, - CONTROLLER_INDEX, buf); - discover_destroy(); - goto free; - } - - uuid = &gatt_svc->uuid; - uuid_length = (uint8_t) (uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16); - - service = gatt_buf_reserve(sizeof(*service) + uuid_length); - if (!service) { - discover_destroy(); - rc = BLE_HS_ENOMEM; - goto free; - } - - service->start_handle = sys_cpu_to_le16(gatt_svc->start_handle); - service->end_handle = sys_cpu_to_le16(gatt_svc->end_handle); - service->uuid_length = uuid_length; - - if (uuid->u.type == BLE_UUID_TYPE_16) { - uint16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value); - memcpy(service->uuid, &u16, uuid_length); - } else { - memcpy(service->uuid, BLE_UUID128(uuid)->value, - uuid_length); - } - - gatt_buf.cnt++; - -free: - os_mbuf_free_chain(buf); - return rc; -} - -static void disc_all_prim_svcs(uint8_t *data, uint16_t len) -{ - struct ble_gap_conn_desc conn; - uint8_t status = BTP_STATUS_SUCCESS; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - if (ble_gattc_disc_all_svcs(conn.conn_handle, disc_prim_svcs_cb, - (void *) GATTC_DISC_ALL_PRIM_RP)) { - discover_destroy(); - status = BTP_STATUS_FAILED; - goto rsp; - } - -rsp: - tester_rsp(BTP_SERVICE_ID_GATTC, GATTC_DISC_ALL_PRIM_SVCS, - CONTROLLER_INDEX, status); -} - -static void disc_prim_uuid(uint8_t *data, uint16_t len) -{ - const struct gattc_disc_prim_uuid_cmd *cmd = (void *) data; - struct ble_gap_conn_desc conn; - ble_uuid_any_t uuid; - uint8_t status = BTP_STATUS_SUCCESS; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - if (btp2bt_uuid(cmd->uuid, cmd->uuid_length, &uuid)) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - if (ble_gattc_disc_svc_by_uuid(conn.conn_handle, - &uuid.u, disc_prim_svcs_cb, - (void *) GATTC_DISC_PRIM_UUID_RP)) { - discover_destroy(); - status = BTP_STATUS_FAILED; - goto rsp; - } - -rsp: - tester_rsp(BTP_SERVICE_ID_GATTC, GATTC_DISC_PRIM_UUID, CONTROLLER_INDEX, - status); -} - -static int find_included_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - const struct ble_gatt_svc *gatt_svc, void *arg) -{ - struct gattc_find_included_rp *rp; - struct gatt_included *included; - const ble_uuid_any_t *uuid; - int service_handle = (int) arg; - uint8_t uuid_length; - uint8_t err = (uint8_t) error->status; - struct os_mbuf *buf = os_msys_get(0, 0); - const ble_addr_t *addr; - struct ble_gap_conn_desc conn; - int rc = 0; - - SYS_LOG_DBG(""); - - if (ble_gap_conn_find(conn_handle, &conn)) { - rc = BLE_HS_EINVAL; - goto free; - } - - net_buf_simple_init(buf, 0); - rp = net_buf_simple_add(buf, sizeof(*rp)); - - addr = &conn.peer_ota_addr; - - rp->address_type = addr->type; - memcpy(rp->address, addr->val, sizeof(rp->address)); - - rp->status = err; - - SYS_LOG_DBG(""); - if (error->status != 0 && error->status != BLE_HS_EDONE) { - rp->services_count = 0; - tester_send_buf(BTP_SERVICE_ID_GATTC, GATTC_FIND_INCLUDED_RP, - CONTROLLER_INDEX, buf); - discover_destroy(); - goto free; - } - - if (error->status == BLE_HS_EDONE) { - rp->status = 0; - rp->services_count = gatt_buf.cnt; - os_mbuf_append(buf, gatt_buf.buf, gatt_buf.len); - tester_send_buf(BTP_SERVICE_ID_GATTC, GATTC_FIND_INCLUDED_RP, - CONTROLLER_INDEX, buf); - discover_destroy(); - goto free; - } - - uuid = &gatt_svc->uuid; - uuid_length = (uint8_t) (uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16); - - included = gatt_buf_reserve(sizeof(*included) + uuid_length); - if (!included) { - discover_destroy(); - rc = BLE_HS_ENOMEM; - goto free; - } - - included->included_handle = sys_cpu_to_le16(service_handle + 1 + - rp->services_count); - included->service.start_handle = sys_cpu_to_le16(gatt_svc->start_handle); - included->service.end_handle = sys_cpu_to_le16(gatt_svc->end_handle); - included->service.uuid_length = uuid_length; - - if (uuid->u.type == BLE_UUID_TYPE_16) { - uint16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value); - memcpy(included->service.uuid, &u16, uuid_length); - } else { - memcpy(included->service.uuid, BLE_UUID128(uuid)->value, - uuid_length); - } - - gatt_buf.cnt++; - -free: - os_mbuf_free_chain(buf); - return rc; -} - -static void find_included(uint8_t *data, uint16_t len) -{ - const struct gattc_find_included_cmd *cmd = (void *) data; - struct ble_gap_conn_desc conn; - uint16_t start_handle, end_handle; - int service_handle_arg; - uint8_t status = BTP_STATUS_SUCCESS; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - start_handle = sys_le16_to_cpu(cmd->start_handle); - end_handle = sys_le16_to_cpu(cmd->end_handle); - service_handle_arg = start_handle; - - if (ble_gattc_find_inc_svcs(conn.conn_handle, start_handle, end_handle, - find_included_cb, - (void *) service_handle_arg)) { - discover_destroy(); - status = BTP_STATUS_FAILED; - goto rsp; - } - -rsp: - tester_rsp(BTP_SERVICE_ID_GATTC, GATTC_FIND_INCLUDED, CONTROLLER_INDEX, - status); -} - -static int disc_chrc_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - const struct ble_gatt_chr *gatt_chr, void *arg) -{ - struct gattc_disc_chrc_rp *rp; - struct gatt_characteristic *chrc; - const ble_uuid_any_t *uuid; - uint8_t uuid_length; - uint8_t opcode = (uint8_t) (int) arg; - uint8_t err = (uint8_t) error->status; - struct os_mbuf *buf = os_msys_get(0, 0); - const ble_addr_t *addr; - struct ble_gap_conn_desc conn; - int rc = 0; - - SYS_LOG_DBG(""); - if (ble_gap_conn_find(conn_handle, &conn)) { - goto free; - } - - net_buf_simple_init(buf, 0); - rp = net_buf_simple_add(buf, sizeof(*rp)); - - addr = &conn.peer_ota_addr; - - rp->address_type = addr->type; - memcpy(rp->address, addr->val, sizeof(rp->address)); - - rp->status = err; - - if (ble_gap_conn_find(conn_handle, &conn)) { - rc = BLE_HS_EINVAL; - goto free; - } - - if (error->status != 0 && error->status != BLE_HS_EDONE) { - rp->characteristics_count = 0; - tester_send_buf(BTP_SERVICE_ID_GATTC, opcode, - CONTROLLER_INDEX, buf); - discover_destroy(); - goto free; - } - - if (error->status == BLE_HS_EDONE) { - rp->status = 0; - rp->characteristics_count = gatt_buf.cnt; - os_mbuf_append(buf, gatt_buf.buf, gatt_buf.len); - tester_send_buf(BTP_SERVICE_ID_GATTC, opcode, - CONTROLLER_INDEX, buf); - discover_destroy(); - goto free; - } - - uuid = &gatt_chr->uuid; - uuid_length = (uint8_t) (uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16); - - chrc = gatt_buf_reserve(sizeof(*chrc) + uuid_length); - if (!chrc) { - discover_destroy(); - rc = BLE_HS_ENOMEM; - goto free; - } - - chrc->characteristic_handle = sys_cpu_to_le16(gatt_chr->def_handle); - chrc->properties = gatt_chr->properties; - chrc->value_handle = sys_cpu_to_le16(gatt_chr->val_handle); - chrc->uuid_length = uuid_length; - - if (uuid->u.type == BLE_UUID_TYPE_16) { - uint16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value); - memcpy(chrc->uuid, &u16, uuid_length); - } else { - memcpy(chrc->uuid, BLE_UUID128(uuid)->value, - uuid_length); - } - - gatt_buf.cnt++; -free: - os_mbuf_free_chain(buf); - return rc; -} - -static void disc_all_chrc(uint8_t *data, uint16_t len) -{ - const struct gattc_disc_all_chrc_cmd *cmd = (void *) data; - struct ble_gap_conn_desc conn; - uint16_t start_handle, end_handle; - uint8_t status = BTP_STATUS_SUCCESS; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - SYS_LOG_DBG("Conn find rsped"); - status = BTP_STATUS_FAILED; - goto rsp; - } - - start_handle = sys_le16_to_cpu(cmd->start_handle); - end_handle = sys_le16_to_cpu(cmd->end_handle); - - rc = ble_gattc_disc_all_chrs(conn.conn_handle, start_handle, end_handle, - disc_chrc_cb, (void *) GATTC_DISC_ALL_CHRC_RP); - if (rc) { - discover_destroy(); - status = BTP_STATUS_FAILED; - goto rsp; - } - -rsp: - tester_rsp(BTP_SERVICE_ID_GATTC, GATTC_DISC_ALL_CHRC, CONTROLLER_INDEX, - status); -} - -static void disc_chrc_uuid(uint8_t *data, uint16_t len) -{ - const struct gattc_disc_chrc_uuid_cmd *cmd = (void *) data; - struct ble_gap_conn_desc conn; - uint16_t start_handle, end_handle; - ble_uuid_any_t uuid; - uint8_t status = BTP_STATUS_SUCCESS; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - if (btp2bt_uuid(cmd->uuid, cmd->uuid_length, &uuid)) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - start_handle = sys_le16_to_cpu(cmd->start_handle); - end_handle = sys_le16_to_cpu(cmd->end_handle); - - rc = ble_gattc_disc_chrs_by_uuid(conn.conn_handle, start_handle, - end_handle, &uuid.u, disc_chrc_cb, - (void *) GATTC_DISC_CHRC_UUID_RP); - if (rc) { - discover_destroy(); - status = BTP_STATUS_FAILED; - goto rsp; - } - -rsp: - tester_rsp(BTP_SERVICE_ID_GATTC, GATTC_DISC_CHRC_UUID, CONTROLLER_INDEX, - status); -} - -static int disc_all_desc_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - uint16_t chr_val_handle, - const struct ble_gatt_dsc *gatt_dsc, - void *arg) -{ - struct gattc_disc_all_desc_rp *rp; - struct gatt_descriptor *dsc; - const ble_uuid_any_t *uuid; - uint8_t uuid_length; - uint8_t err = (uint8_t) error->status; - struct os_mbuf *buf = os_msys_get(0, 0); - const ble_addr_t *addr; - struct ble_gap_conn_desc conn; - int rc = 0; - - SYS_LOG_DBG(""); - - if (ble_gap_conn_find(conn_handle, &conn)) { - rc = BLE_HS_EINVAL; - goto free; - } - - net_buf_simple_init(buf, 0); - rp = net_buf_simple_add(buf, sizeof(*rp)); - - addr = &conn.peer_ota_addr; - - rp->address_type = addr->type; - memcpy(rp->address, addr->val, sizeof(rp->address)); - - rp->status = err; - - if (error->status != 0 && error->status != BLE_HS_EDONE) { - rp->descriptors_count = 0; - tester_send_buf(BTP_SERVICE_ID_GATTC, GATTC_DISC_ALL_DESC_RP, - CONTROLLER_INDEX, buf); - discover_destroy(); - goto free; - } - - if (error->status == BLE_HS_EDONE) { - rp->status = 0; - rp->descriptors_count = gatt_buf.cnt; - os_mbuf_append(buf, gatt_buf.buf, gatt_buf.len); - tester_send_buf(BTP_SERVICE_ID_GATTC, GATTC_DISC_ALL_DESC_RP, - CONTROLLER_INDEX, buf); - discover_destroy(); - goto free; - } - - uuid = &gatt_dsc->uuid; - uuid_length = (uint8_t) (uuid->u.type == BLE_UUID_TYPE_16 ? 2 : 16); - - dsc = gatt_buf_reserve(sizeof(*dsc) + uuid_length); - if (!dsc) { - discover_destroy(); - rc = BLE_HS_ENOMEM; - goto free; - } - - dsc->descriptor_handle = sys_cpu_to_le16(gatt_dsc->handle); - dsc->uuid_length = uuid_length; - - if (uuid->u.type == BLE_UUID_TYPE_16) { - uint16_t u16 = sys_cpu_to_le16(BLE_UUID16(uuid)->value); - memcpy(dsc->uuid, &u16, uuid_length); - } else { - memcpy(dsc->uuid, BLE_UUID128(uuid)->value, uuid_length); - } - - gatt_buf.cnt++; - -free: - os_mbuf_free_chain(buf); - return rc; -} - -static void disc_all_desc(uint8_t *data, uint16_t len) -{ - const struct gattc_disc_all_desc_cmd *cmd = (void *) data; - struct ble_gap_conn_desc conn; - uint16_t start_handle, end_handle; - uint8_t status = BTP_STATUS_SUCCESS; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - start_handle = sys_le16_to_cpu(cmd->start_handle) - 1; - end_handle = sys_le16_to_cpu(cmd->end_handle); - - rc = ble_gattc_disc_all_dscs(conn.conn_handle, start_handle, end_handle, - disc_all_desc_cb, (void *) GATTC_DISC_ALL_DESC); - - SYS_LOG_DBG("rc=%d", rc); - - if (rc) { - discover_destroy(); - status = BTP_STATUS_FAILED; - goto rsp; - } - -rsp: - tester_rsp(BTP_SERVICE_ID_GATTC, GATTC_DISC_ALL_DESC, CONTROLLER_INDEX, - status); -} - -static int read_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - struct ble_gatt_attr *attr, - void *arg) -{ - struct gattc_read_rp *rp; - uint8_t opcode = (uint8_t) (int) arg; - struct os_mbuf *buf = os_msys_get(0, 0); - const ble_addr_t *addr; - struct ble_gap_conn_desc conn; - int rc = 0; - - if (ble_gap_conn_find(conn_handle, &conn)) { - rc = BLE_HS_EINVAL; - goto free; - } - - net_buf_simple_init(buf, 0); - rp = net_buf_simple_add(buf, sizeof(*rp)); - - addr = &conn.peer_ota_addr; - - rp->address_type = addr->type; - memcpy(rp->address, addr->val, sizeof(rp->address)); - - SYS_LOG_DBG("status=%d", error->status); - - if (error->status != 0 && error->status != BLE_HS_EDONE) { - rp->status = (uint8_t) BLE_HS_ATT_ERR(error->status); - rp->data_length = 0; - tester_send_buf(BTP_SERVICE_ID_GATTC, opcode, - CONTROLLER_INDEX, buf); - read_destroy(); - goto free; - } - - if (!gatt_buf_add(attr->om->om_data, attr->om->om_len)) { - read_destroy(); - rc = BLE_HS_ENOMEM; - goto free; - } - - rp->status = 0; - rp->data_length = attr->om->om_len; - os_mbuf_appendfrom(buf, attr->om, 0, os_mbuf_len(attr->om)); - tester_send_buf(BTP_SERVICE_ID_GATTC, opcode, - CONTROLLER_INDEX, buf); - read_destroy(); -free: - os_mbuf_free_chain(buf); - return rc; -} - -static void read(uint8_t *data, uint16_t len) -{ - const struct gattc_read_cmd *cmd = (void *) data; - struct ble_gap_conn_desc conn; - uint8_t status = BTP_STATUS_SUCCESS; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - /* Clear buffer */ - read_destroy(); - - if (ble_gattc_read(conn.conn_handle, sys_le16_to_cpu(cmd->handle), - read_cb, (void *) GATTC_READ_RP)) { - read_destroy(); - status = BTP_STATUS_FAILED; - goto rsp; - } - -rsp: - tester_rsp(BTP_SERVICE_ID_GATTC, GATTC_READ, CONTROLLER_INDEX, - status); -} - -static int read_uuid_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - struct ble_gatt_attr *attr, - void *arg) -{ - struct gattc_read_uuid_rp *rp; - struct gatt_read_uuid_chr *chr; - uint8_t opcode = (uint8_t) (int) arg; - uint8_t err = (uint8_t) error->status; - struct os_mbuf *buf = os_msys_get(0, 0); - const ble_addr_t *addr; - struct ble_gap_conn_desc conn; - int rc = 0; - static uint16_t attr_len; - - SYS_LOG_DBG("status=%d", error->status); - - if (ble_gap_conn_find(conn_handle, &conn)) { - rc = BLE_HS_EINVAL; - goto free; - } - - net_buf_simple_init(buf, 0); - rp = net_buf_simple_add(buf, sizeof(*rp)); - - addr = &conn.peer_ota_addr; - - rp->address_type = addr->type; - memcpy(rp->address, addr->val, sizeof(rp->address)); - - rp->status = err; - - if (error->status != 0 && error->status != BLE_HS_EDONE) { - rp->data_length = 0; - tester_send_buf(BTP_SERVICE_ID_GATTC, opcode, - CONTROLLER_INDEX, buf); - read_destroy(); - goto free; - } - - if (error->status == BLE_HS_EDONE) { - rp->data_length = gatt_buf.len; - rp->value_length = attr_len; - rp->status = 0; - os_mbuf_append(buf, gatt_buf.buf+1, gatt_buf.len-1); - tester_send_buf(BTP_SERVICE_ID_GATTC, opcode, - CONTROLLER_INDEX, buf); - read_destroy(); - goto free; - } - - if (error->status == 0) { - attr_len = attr->om->om_len; - } - - if (gatt_buf_add(attr->om->om_data, attr->om->om_len) == NULL) { - read_destroy(); - rc = BLE_HS_ENOMEM; - goto free; - } - - chr = gatt_buf_reserve(sizeof(*chr) + attr->om->om_len); - if (!chr) { - read_destroy(); - rc = BLE_HS_ENOMEM; - goto free; - } - - chr->handle = sys_cpu_to_be16(attr->handle); - memcpy(chr->data, attr->om->om_data, attr->om->om_len); - -free: - os_mbuf_free_chain(buf); - return rc; -} - -static void read_uuid(uint8_t *data, uint16_t len) -{ - const struct gattc_read_uuid_cmd *cmd = (void *) data; - struct ble_gap_conn_desc conn; - ble_uuid_any_t uuid; - uint8_t status = BTP_STATUS_SUCCESS; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - if (btp2bt_uuid(cmd->uuid, cmd->uuid_length, &uuid)) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - /* Clear buffer */ - read_destroy(); - - if (ble_gattc_read_by_uuid(conn.conn_handle, - sys_le16_to_cpu(cmd->start_handle), - sys_le16_to_cpu(cmd->end_handle), &uuid.u, - read_uuid_cb, (void *) GATTC_READ_UUID_RP)) { - read_destroy(); - status = BTP_STATUS_FAILED; - } - -rsp: - tester_rsp(BTP_SERVICE_ID_GATTC, GATTC_READ_UUID, CONTROLLER_INDEX, - status); -} - -static int read_long_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - struct ble_gatt_attr *attr, - void *arg) -{ - struct gattc_read_rp *rp;; - uint8_t opcode = (uint8_t) (int) arg; - uint8_t err = (uint8_t) error->status; - struct os_mbuf *buf = os_msys_get(0, 0); - const ble_addr_t *addr; - struct ble_gap_conn_desc conn; - int rc = 0; - - SYS_LOG_DBG("status=%d", error->status); - - if (ble_gap_conn_find(conn_handle, &conn)) { - rc = BLE_HS_EINVAL; - goto free; - } - - net_buf_simple_init(buf, 0); - rp = net_buf_simple_add(buf, sizeof(*rp)); - - addr = &conn.peer_ota_addr; - - rp->address_type = addr->type; - memcpy(rp->address, addr->val, sizeof(rp->address)); - - rp->status = err; - - if (error->status != 0 && error->status != BLE_HS_EDONE) { - rp->data_length = 0; - tester_send_buf(BTP_SERVICE_ID_GATTC, opcode, - CONTROLLER_INDEX, buf); - read_destroy(); - goto free; - } - - if (error->status == BLE_HS_EDONE) { - rp->status = 0; - rp->data_length = gatt_buf.len; - os_mbuf_append(buf, gatt_buf.buf, gatt_buf.len); - tester_send_buf(BTP_SERVICE_ID_GATTC, opcode, - CONTROLLER_INDEX, buf); - read_destroy(); - goto free; - } - - if (gatt_buf_add(attr->om->om_data, attr->om->om_len) == NULL) { - read_destroy(); - rc = BLE_HS_ENOMEM; - goto free; - } - - rp->data_length += attr->om->om_len; - -free: - os_mbuf_free_chain(buf); - return rc; -} - -static void read_long(uint8_t *data, uint16_t len) -{ - const struct gattc_read_long_cmd *cmd = (void *) data; - struct ble_gap_conn_desc conn; - uint8_t status = BTP_STATUS_SUCCESS; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - /* Clear buffer */ - read_destroy(); - - if (ble_gattc_read_long(conn.conn_handle, - sys_le16_to_cpu(cmd->handle), - sys_le16_to_cpu(cmd->offset), - read_long_cb, (void *) GATTC_READ_LONG_RP)) { - read_destroy(); - status = BTP_STATUS_FAILED; - } - -rsp: - tester_rsp(BTP_SERVICE_ID_GATTC, GATTC_READ_LONG, CONTROLLER_INDEX, - status); -} - -static void read_multiple(uint8_t *data, uint16_t len) -{ - const struct gattc_read_multiple_cmd *cmd = (void *) data; - uint16_t handles[cmd->handles_count]; - struct ble_gap_conn_desc conn; - uint8_t status = BTP_STATUS_SUCCESS; - int rc, i; - - SYS_LOG_DBG(""); - - for (i = 0; i < ARRAY_SIZE(handles); i++) { - handles[i] = sys_le16_to_cpu(cmd->handles[i]); - } - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - /* Clear buffer */ - read_destroy(); - - if (ble_gattc_read_mult(conn.conn_handle, handles, - cmd->handles_count, read_cb, (void *) GATTC_READ_MULTIPLE_RP)) { - read_destroy(); - status = BTP_STATUS_FAILED; - } - -rsp: - tester_rsp(BTP_SERVICE_ID_GATTC, GATTC_READ_MULTIPLE, CONTROLLER_INDEX, - status); -} - -static void write_without_rsp(uint8_t *data, uint16_t len, uint8_t op, bool sign) -{ - const struct gattc_write_without_rsp_cmd *cmd = (void *) data; - struct ble_gap_conn_desc conn; - uint8_t status = BTP_STATUS_SUCCESS; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - if (ble_gattc_write_no_rsp_flat(conn.conn_handle, - sys_le16_to_cpu(cmd->handle), cmd->data, - sys_le16_to_cpu(cmd->data_length))) { - status = BTP_STATUS_FAILED; - } - -rsp: - tester_rsp(BTP_SERVICE_ID_GATTC, op, CONTROLLER_INDEX, status); -} - -static int write_cb(uint16_t conn_handle, const struct ble_gatt_error *error, - struct ble_gatt_attr *attr, - void *arg) -{ - struct gattc_write_rp *rp; - uint8_t err = (uint8_t) error->status; - uint8_t opcode = (uint8_t) (int) arg; - struct os_mbuf *buf = os_msys_get(0, 0); - const ble_addr_t *addr; - struct ble_gap_conn_desc conn; - int rc = 0; - - SYS_LOG_DBG(""); - - if (ble_gap_conn_find(conn_handle, &conn)) { - rc = BLE_HS_EINVAL; - goto free; - } - - net_buf_simple_init(buf, 0); - rp = net_buf_simple_add(buf, sizeof(*rp)); - - addr = &conn.peer_ota_addr; - - rp->address_type = addr->type; - memcpy(rp->address, addr->val, sizeof(rp->address)); - - rp->status = err; - tester_send_buf(BTP_SERVICE_ID_GATTC, opcode, - CONTROLLER_INDEX, buf); -free: - os_mbuf_free_chain(buf); - return rc; -} - -static void write(uint8_t *data, uint16_t len) -{ - const struct gattc_write_cmd *cmd = (void *) data; - struct ble_gap_conn_desc conn; - uint8_t status = BTP_STATUS_SUCCESS; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - if (ble_gattc_write_flat(conn.conn_handle, sys_le16_to_cpu(cmd->handle), - cmd->data, sys_le16_to_cpu(cmd->data_length), - write_cb, (void *) GATTC_WRITE_RP)) { - status = BTP_STATUS_FAILED; - } - -rsp: - tester_rsp(BTP_SERVICE_ID_GATTC, GATTC_WRITE, CONTROLLER_INDEX, - status); -} - -static void write_long(uint8_t *data, uint16_t len) -{ - const struct gattc_write_long_cmd *cmd = (void *) data; - struct ble_gap_conn_desc conn; - struct os_mbuf *om = NULL; - uint8_t status = BTP_STATUS_SUCCESS; - int rc = 0; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - goto fail; - } - - om = ble_hs_mbuf_from_flat(cmd->data, sys_le16_to_cpu(cmd->data_length)); - if (!om) { - SYS_LOG_ERR("Insufficient resources"); - status = BTP_STATUS_FAILED; - goto fail; - } - - rc = ble_gattc_write_long(conn.conn_handle, - sys_le16_to_cpu(cmd->handle), - sys_le16_to_cpu(cmd->offset), - om, write_cb, - (void *) GATTC_WRITE_LONG_RP); - if (rc) { - status = BTP_STATUS_FAILED; - } else { - goto rsp; - } - -fail: - SYS_LOG_ERR("Failed to send Write Long request, rc=%d", rc); - os_mbuf_free_chain(om); -rsp: - tester_rsp(BTP_SERVICE_ID_GATTC, GATTC_WRITE_LONG, CONTROLLER_INDEX, - status); -} - -static int reliable_write_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - struct ble_gatt_attr *attrs, - uint8_t num_attrs, - void *arg) -{ - struct gattc_write_rp *rp; - uint8_t err = (uint8_t) error->status; - struct os_mbuf *buf = os_msys_get(0, 0); - const ble_addr_t *addr; - struct ble_gap_conn_desc conn; - int rc = 0; - - SYS_LOG_DBG(""); - - if (ble_gap_conn_find(conn_handle, &conn)) { - rc = BLE_HS_EINVAL; - goto free; - } - - net_buf_simple_init(buf, 0); - rp = net_buf_simple_add(buf, sizeof(*rp)); - - addr = &conn.peer_ota_addr; - - rp->address_type = addr->type; - memcpy(rp->address, addr->val, sizeof(rp->address)); - - rp->status = err; - tester_send_buf(BTP_SERVICE_ID_GATTC, GATTC_RELIABLE_WRITE_RP, - CONTROLLER_INDEX, buf); -free: - os_mbuf_free_chain(buf); - return rc; -} - -static void reliable_write(uint8_t *data, uint16_t len) -{ - const struct gattc_reliable_write_cmd *cmd = (void *) data; - struct ble_gap_conn_desc conn; - struct ble_gatt_attr attr; - struct os_mbuf *om = NULL; - uint8_t status = BTP_STATUS_SUCCESS; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - status = BTP_STATUS_FAILED; - goto fail; - } - - om = ble_hs_mbuf_from_flat(cmd->data, sys_le16_to_cpu(cmd->data_length)); - /* This is required, because Nimble checks if - * the data is longer than offset - */ - if (os_mbuf_extend(om, sys_le16_to_cpu(cmd->offset) + 1) == NULL) { - status = BTP_STATUS_FAILED; - goto fail; - } - - attr.handle = sys_le16_to_cpu(cmd->handle); - attr.offset = sys_le16_to_cpu(cmd->offset); - attr.om = om; - - if (ble_gattc_write_reliable(conn.conn_handle, &attr, 1, - reliable_write_cb, NULL)) { - status = BTP_STATUS_FAILED; - goto fail; - } else { - goto rsp; - } - -fail: - os_mbuf_free_chain(om); -rsp: - tester_rsp(BTP_SERVICE_ID_GATTC, GATTC_WRITE_LONG, CONTROLLER_INDEX, - status); -} - -static int subscribe_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - struct ble_gatt_attr *attrs, - void *arg) -{ - struct subscribe_rp *rp; - uint8_t err = (uint8_t) error->status; - uint8_t opcode = (uint8_t) (int) arg; - struct os_mbuf *buf = os_msys_get(0, 0); - const ble_addr_t *addr; - struct ble_gap_conn_desc conn; - int rc = 0; - - SYS_LOG_DBG(""); - - if (ble_gap_conn_find(conn_handle, &conn)) { - rc = BLE_HS_EINVAL; - goto free; - } - - net_buf_simple_init(buf, 0); - rp = net_buf_simple_add(buf, sizeof(*rp)); - - addr = &conn.peer_ota_addr; - - rp->address_type = addr->type; - memcpy(rp->address, addr->val, sizeof(rp->address)); - - rp->status = err; - tester_send_buf(BTP_SERVICE_ID_GATTC, opcode, - CONTROLLER_INDEX, buf); -free: - os_mbuf_free_chain(buf); - return rc; -} - -static int enable_subscription(uint16_t conn_handle, uint16_t ccc_handle, - uint16_t value) -{ - uint32_t opcode; - - SYS_LOG_DBG(""); - - opcode = (uint32_t) (value == 0x0001 ? GATTC_CFG_NOTIFY_RP : GATTC_CFG_INDICATE_RP); - - if (ble_gattc_write_flat(conn_handle, ccc_handle, - &value, sizeof(value), subscribe_cb, (void *) opcode)) { - return -EINVAL; - } - - subscribe_params.ccc_handle = value; - - return 0; -} - -static int disable_subscription(uint16_t conn_handle, uint16_t ccc_handle) -{ - uint16_t value = 0x00; - uint32_t opcode; - - SYS_LOG_DBG(""); - - opcode = (uint32_t) (value == 0x0001 ? GATTC_CFG_NOTIFY_RP : GATTC_CFG_INDICATE_RP); - - /* Fail if CCC handle doesn't match */ - if (ccc_handle != subscribe_params.ccc_handle) { - SYS_LOG_ERR("CCC handle doesn't match"); - return -EINVAL; - } - - if (ble_gattc_write_flat(conn_handle, ccc_handle, - &value, sizeof(value), subscribe_cb, (void *) opcode)) { - return -EINVAL; - } - - subscribe_params.ccc_handle = 0; - return 0; -} - -static void config_subscription(uint8_t *data, uint16_t len, uint8_t op) -{ - const struct gattc_cfg_notify_cmd *cmd = (void *) data; - struct ble_gap_conn_desc conn; - uint16_t ccc_handle = sys_le16_to_cpu(cmd->ccc_handle); - uint8_t status = BTP_STATUS_SUCCESS; - int rc; - - SYS_LOG_DBG(""); - - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); - if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - if (cmd->enable) { - uint16_t value; - - if (op == GATTC_CFG_NOTIFY) { - value = 0x0001; - } else { - value = 0x0002; - } - - if (enable_subscription(conn.conn_handle, - ccc_handle, value) != 0) { - status = BTP_STATUS_FAILED; - goto rsp; - } - } else { - if (disable_subscription(conn.conn_handle, ccc_handle) < 0) { - status = BTP_STATUS_FAILED; - } else { - status = BTP_STATUS_SUCCESS; - } - } - -rsp: - SYS_LOG_DBG("Config subscription (op %u) status %u", op, status); - - tester_rsp(BTP_SERVICE_ID_GATTC, op, CONTROLLER_INDEX, status); -} - -int tester_gattc_notify_rx_ev(uint16_t conn_handle, uint16_t attr_handle, - uint8_t indication, struct os_mbuf *om) -{ - struct gattc_notification_ev *ev; - struct ble_gap_conn_desc conn; - struct os_mbuf *buf = os_msys_get(0, 0); - const ble_addr_t *addr; - - SYS_LOG_DBG(""); - - if (!subscribe_params.ccc_handle) { - goto fail; - } - - if (ble_gap_conn_find(conn_handle, &conn)) { - goto fail; - } - - net_buf_simple_init(buf, 0); - ev = net_buf_simple_add(buf, sizeof(*ev)); - - addr = &conn.peer_ota_addr; - - ev->address_type = addr->type; - memcpy(ev->address, addr->val, sizeof(ev->address)); - ev->type = (uint8_t) (indication ? 0x02 : 0x01); - ev->handle = sys_cpu_to_le16(attr_handle); - ev->data_length = sys_cpu_to_le16(os_mbuf_len(om)); - os_mbuf_appendfrom(buf, om, 0, os_mbuf_len(om)); - - tester_send_buf(BTP_SERVICE_ID_GATTC, GATTC_EV_NOTIFICATION_RXED, - CONTROLLER_INDEX, buf); - -fail: - os_mbuf_free_chain(buf); - return 0; -} - -static void supported_commands(uint8_t *data, uint16_t len) -{ - uint8_t cmds[3]; - struct gatt_read_supported_commands_rp *rp = (void *) cmds; - - SYS_LOG_DBG(""); - - memset(cmds, 0, sizeof(cmds)); - - tester_set_bit(cmds, GATTC_READ_SUPPORTED_COMMANDS); - tester_set_bit(cmds, GATTC_EXCHANGE_MTU); - tester_set_bit(cmds, GATTC_DISC_ALL_PRIM_SVCS); - tester_set_bit(cmds, GATTC_DISC_PRIM_UUID); - tester_set_bit(cmds, GATTC_FIND_INCLUDED); - tester_set_bit(cmds, GATTC_DISC_ALL_CHRC); - tester_set_bit(cmds, GATTC_DISC_CHRC_UUID); - tester_set_bit(cmds, GATTC_DISC_ALL_DESC); - tester_set_bit(cmds, GATTC_READ); - tester_set_bit(cmds, GATTC_READ_UUID); - tester_set_bit(cmds, GATTC_READ_LONG); - tester_set_bit(cmds, GATTC_READ_MULTIPLE); - tester_set_bit(cmds, GATTC_WRITE_WITHOUT_RSP); -#if 0 - tester_set_bit(cmds, GATTC_SIGNED_WRITE_WITHOUT_RSP); -#endif - tester_set_bit(cmds, GATTC_WRITE); - tester_set_bit(cmds, GATTC_WRITE_LONG); - tester_set_bit(cmds, GATTC_RELIABLE_WRITE); - tester_set_bit(cmds, GATTC_CFG_NOTIFY); - tester_set_bit(cmds, GATTC_CFG_INDICATE); - - tester_send(BTP_SERVICE_ID_GATTC, GATTC_READ_SUPPORTED_COMMANDS, - CONTROLLER_INDEX, (uint8_t *) rp, sizeof(cmds)); -} - -void tester_handle_gattc(uint8_t opcode, uint8_t index, uint8_t *data, - uint16_t len) -{ - switch (opcode) { - case GATTC_READ_SUPPORTED_COMMANDS: - supported_commands(data, len); - return; - case GATTC_EXCHANGE_MTU: - exchange_mtu(data, len); - return; - case GATTC_DISC_ALL_PRIM_SVCS: - disc_all_prim_svcs(data, len); - return; - case GATTC_DISC_PRIM_UUID: - disc_prim_uuid(data, len); - return; - case GATTC_FIND_INCLUDED: - find_included(data, len); - return; - case GATTC_DISC_ALL_CHRC: - disc_all_chrc(data, len); - return; - case GATTC_DISC_CHRC_UUID: - disc_chrc_uuid(data, len); - return; - case GATTC_DISC_ALL_DESC: - disc_all_desc(data, len); - return; - case GATTC_READ: - read(data, len); - return; - case GATTC_READ_UUID: - read_uuid(data, len); - return; - case GATTC_READ_LONG: - read_long(data, len); - return; - case GATTC_READ_MULTIPLE: - read_multiple(data, len); - return; - case GATTC_WRITE_WITHOUT_RSP: - write_without_rsp(data, len, opcode, false); - return; -#if 0 - case GATTC_SIGNED_WRITE_WITHOUT_RSP: - write_without_rsp(data, len, opcode, true); - return; -#endif - case GATTC_WRITE: - write(data, len); - return; - case GATTC_WRITE_LONG: - write_long(data, len); - return; - case GATTC_RELIABLE_WRITE: - reliable_write(data, len); - return; - case GATTC_CFG_NOTIFY: - case GATTC_CFG_INDICATE: - config_subscription(data, len, opcode); - return; - default: - tester_rsp(BTP_SERVICE_ID_GATTC, opcode, index, - BTP_STATUS_UNKNOWN_CMD); - return; - } -} \ No newline at end of file diff --git a/lib/bt/host/nimble/nimble/apps/bttester/src/glue.c b/lib/bt/host/nimble/nimble/apps/bttester/src/glue.c deleted file mode 100644 index 3e606062..00000000 --- a/lib/bt/host/nimble/nimble/apps/bttester/src/glue.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "syscfg/syscfg.h" - -#if !MYNEWT_VAL(BLE_MESH) -#include -#include -#include "os/os.h" -#include "os/os_mbuf.h" -#include "glue.h" - - -#define ASSERT_NOT_CHAIN(om) assert(SLIST_NEXT(om, om_next) == NULL) - -const char *bt_hex(const void *buf, size_t len) -{ - static const char hex[] = "0123456789abcdef"; - static char hexbufs[4][137]; - static uint8_t curbuf; - const uint8_t *b = buf; - char *str; - int i; - - str = hexbufs[curbuf++]; - curbuf %= ARRAY_SIZE(hexbufs); - - len = min(len, (sizeof(hexbufs[0]) - 1) / 2); - - for (i = 0; i < len; i++) { - str[i * 2] = hex[b[i] >> 4]; - str[i * 2 + 1] = hex[b[i] & 0xf]; - } - - str[i * 2] = '\0'; - - return str; -} - -struct os_mbuf * NET_BUF_SIMPLE(uint16_t size) -{ - struct os_mbuf *buf; - - buf = os_msys_get(size, 0); - assert(buf); - - return buf; -} - -/* This is by purpose */ -void net_buf_simple_init(struct os_mbuf *buf, - size_t reserve_head) -{ - /* This is called in Zephyr after init. - * Note in Mynewt case we don't care abour reserved head*/ - buf->om_data = &buf->om_databuf[buf->om_pkthdr_len] + reserve_head; - buf->om_len = 0; -} - -void -net_buf_simple_add_le16(struct os_mbuf *om, uint16_t val) -{ - val = htole16(val); - os_mbuf_append(om, &val, sizeof(val)); - ASSERT_NOT_CHAIN(om); -} - -void -net_buf_simple_add_be16(struct os_mbuf *om, uint16_t val) -{ - val = htobe16(val); - os_mbuf_append(om, &val, sizeof(val)); - ASSERT_NOT_CHAIN(om); -} - -void -net_buf_simple_add_be32(struct os_mbuf *om, uint32_t val) -{ - val = htobe32(val); - os_mbuf_append(om, &val, sizeof(val)); - ASSERT_NOT_CHAIN(om); -} - -void -net_buf_simple_add_u8(struct os_mbuf *om, uint8_t val) -{ - os_mbuf_append(om, &val, 1); - ASSERT_NOT_CHAIN(om); -} - -void* -net_buf_simple_add(struct os_mbuf *om, uint8_t len) -{ - void * tmp; - - tmp = os_mbuf_extend(om, len); - ASSERT_NOT_CHAIN(om); - - return tmp; -} - -uint8_t * -net_buf_simple_push(struct os_mbuf *om, uint8_t len) -{ - uint8_t headroom = om->om_data - &om->om_databuf[om->om_pkthdr_len]; - - assert(headroom >= len); - om->om_data -= len; - om->om_len += len; - - return om->om_data; -} -#endif diff --git a/lib/bt/host/nimble/nimble/apps/bttester/src/glue.h b/lib/bt/host/nimble/nimble/apps/bttester/src/glue.h deleted file mode 100644 index 65085601..00000000 --- a/lib/bt/host/nimble/nimble/apps/bttester/src/glue.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef __GLUE_H__ -#define __GLUE_H__ - -#include "os/endian.h" - -#define uint8_t uint8_t -#define int8_t int8_t -#define uint16_t uint16_t -#define uint32_t uint32_t -#define int32_t int32_t - -#ifndef BIT -#define BIT(n) (1UL << (n)) -#endif - -#define __packed __attribute__((__packed__)) - -#define sys_le16_to_cpu le16toh - -struct bt_data { - uint8_t type; - uint8_t data_len; - const uint8_t *data; -}; - -#define BT_DATA(_type, _data, _data_len) \ - { \ - .type = (_type), \ - .data_len = (_data_len), \ - .data = (const uint8_t *)(_data), \ - } - -struct os_mbuf * NET_BUF_SIMPLE(uint16_t size); -void net_buf_simple_init(struct os_mbuf *buf, size_t reserve_head); -void net_buf_simple_add_le16(struct os_mbuf *om, uint16_t val); -void net_buf_simple_add_u8(struct os_mbuf *om, uint8_t val); -void *net_buf_simple_add(struct os_mbuf *om, uint8_t len); -uint8_t *net_buf_simple_push(struct os_mbuf *om, uint8_t len); - -#define net_buf_simple_add_mem(a,b,c) os_mbuf_append(a,b,c) - -const char *bt_hex(const void *buf, size_t len); - -#endif /* __GLUE_H__ */ diff --git a/lib/bt/host/nimble/nimble/apps/bttester/src/l2cap.c b/lib/bt/host/nimble/nimble/apps/bttester/src/l2cap.c deleted file mode 100644 index 7890e7cc..00000000 --- a/lib/bt/host/nimble/nimble/apps/bttester/src/l2cap.c +++ /dev/null @@ -1,765 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/* l2cap.c - Bluetooth L2CAP Tester */ - -/* - * Copyright (c) 2016 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" - -#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) - -#include "console/console.h" -#include "host/ble_gap.h" -#include "host/ble_l2cap.h" - -#include "../../../nimble/host/src/ble_l2cap_priv.h" - -#include "bttester.h" - -#define CONTROLLER_INDEX 0 -#define CHANNELS MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) -#define TESTER_COC_MTU MYNEWT_VAL(BTTESTER_L2CAP_COC_MTU) -#define TESTER_COC_BUF_COUNT (3 * MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)) - -static os_membuf_t tester_sdu_coc_mem[ - OS_MEMPOOL_SIZE(TESTER_COC_BUF_COUNT, TESTER_COC_MTU) -]; - -struct os_mbuf_pool sdu_os_mbuf_pool; -static struct os_mempool sdu_coc_mbuf_mempool; -static bool hold_credit = false; - -static struct channel { - uint8_t chan_id; /* Internal number that identifies L2CAP channel. */ - uint8_t state; - struct ble_l2cap_chan *chan; -} channels[CHANNELS]; - -static uint8_t recv_cb_buf[TESTER_COC_MTU + sizeof(struct l2cap_data_received_ev)]; - -static struct channel *get_free_channel(void) -{ - uint8_t i; - struct channel *chan; - - for (i = 0; i < CHANNELS; i++) { - if (channels[i].state) { - continue; - } - - chan = &channels[i]; - chan->chan_id = i; - - return chan; - } - - return NULL; -} - -struct channel *find_channel(struct ble_l2cap_chan *chan) -{ - int i; - - for (i = 0; i < CHANNELS; ++i) { - if (channels[i].chan == chan) { - return &channels[i]; - } - } - - return NULL; -} - -struct channel *get_channel(uint8_t chan_id) -{ - if (chan_id >= CHANNELS) { - return NULL; - } - - return &channels[chan_id]; -} - -static void -tester_l2cap_coc_recv(struct ble_l2cap_chan *chan, struct os_mbuf *sdu) -{ - SYS_LOG_DBG("LE CoC SDU received, chan: 0x%08lx, data len %d", - (uint32_t) chan, OS_MBUF_PKTLEN(sdu)); - - os_mbuf_free_chain(sdu); - if (!hold_credit) { - sdu = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); - assert(sdu != NULL); - - - ble_l2cap_recv_ready(chan, sdu); - } -} - -static void recv_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan, - struct os_mbuf *buf, void *arg) -{ - struct l2cap_data_received_ev *ev = (void *) recv_cb_buf; - struct channel *channel = find_channel(chan); - assert(channel != NULL); - - ev->chan_id = channel->chan_id; - ev->data_length = OS_MBUF_PKTLEN(buf); - - if (ev->data_length > TESTER_COC_MTU) { - SYS_LOG_ERR("Too large sdu received, truncating data"); - ev->data_length = TESTER_COC_MTU; - } - os_mbuf_copydata(buf, 0, ev->data_length, ev->data); - - tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_DATA_RECEIVED, - CONTROLLER_INDEX, recv_cb_buf, sizeof(*ev) + ev->data_length); - - tester_l2cap_coc_recv(chan, buf); -} - -static void unstalled_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan, - int status, void *arg) -{ - if (status) { - tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_SEND_DATA, - CONTROLLER_INDEX, BTP_STATUS_FAILED); - } else { - tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_SEND_DATA, - CONTROLLER_INDEX, BTP_STATUS_SUCCESS); - } -} - -static void reconfigured_ev(uint16_t conn_handle, struct ble_l2cap_chan *chan, - struct ble_l2cap_chan_info *chan_info, - int status) -{ - struct l2cap_reconfigured_ev ev; - struct channel *channel; - - if (status != 0) { - return; - } - - channel = find_channel(chan); - assert(channel != NULL); - - ev.chan_id = channel->chan_id; - ev.peer_mtu = chan_info->peer_coc_mtu; - ev.peer_mps = chan_info->peer_l2cap_mtu; - ev.our_mtu = chan_info->our_coc_mtu; - ev.our_mps = chan_info->our_l2cap_mtu; - - tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_RECONFIGURED, - CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); -} - -static void connected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan, - struct ble_l2cap_chan_info *chan_info, void *arg) -{ - struct l2cap_connected_ev ev; - struct ble_gap_conn_desc desc; - struct channel *channel = find_channel(chan); - - if (channel == NULL) { - channel = get_free_channel(); - } - - ev.chan_id = channel->chan_id; - ev.psm = chan_info->psm; - ev.peer_mtu = chan_info->peer_coc_mtu; - ev.peer_mps = chan_info->peer_l2cap_mtu; - ev.our_mtu = chan_info->our_coc_mtu; - ev.our_mps = chan_info->our_l2cap_mtu; - channel->state = 1; - channel->chan = chan; - - if (!ble_gap_conn_find(conn_handle, &desc)) { - ev.address_type = desc.peer_ota_addr.type; - memcpy(ev.address, desc.peer_ota_addr.val, - sizeof(ev.address)); - } - - tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_CONNECTED, CONTROLLER_INDEX, - (uint8_t *) &ev, sizeof(ev)); -} - -static void disconnected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan, - struct ble_l2cap_chan_info *chan_info, void *arg) -{ - struct l2cap_disconnected_ev ev; - struct ble_gap_conn_desc desc; - struct channel *channel; - - memset(&ev, 0, sizeof(struct l2cap_disconnected_ev)); - - channel = find_channel(chan); - assert(channel != NULL); - - channel->state = 0; - channel->chan = chan; - ev.chan_id = channel->chan_id; - ev.psm = chan_info->psm; - - if (!ble_gap_conn_find(conn_handle, &desc)) { - ev.address_type = desc.peer_ota_addr.type; - memcpy(ev.address, desc.peer_ota_addr.val, - sizeof(ev.address)); - } - - tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_DISCONNECTED, - CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); -} - -static int accept_cb(uint16_t conn_handle, uint16_t peer_mtu, - struct ble_l2cap_chan *chan) -{ - struct os_mbuf *sdu_rx; - - SYS_LOG_DBG("LE CoC accepting, chan: 0x%08lx, peer_mtu %d", - (uint32_t) chan, peer_mtu); - - sdu_rx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); - if (!sdu_rx) { - return BLE_HS_ENOMEM; - } - - ble_l2cap_recv_ready(chan, sdu_rx); - - return 0; -} - -static int -tester_l2cap_event(struct ble_l2cap_event *event, void *arg) -{ - struct ble_l2cap_chan_info chan_info; - int accept_response; - struct ble_gap_conn_desc conn; - - switch (event->type) { - case BLE_L2CAP_EVENT_COC_CONNECTED: - if (ble_l2cap_get_chan_info(event->connect.chan, &chan_info)) { - assert(0); - } - - if (event->connect.status) { - console_printf("LE COC error: %d\n", event->connect.status); - return 0; - } - - console_printf("LE COC connected, conn: %d, chan: 0x%08lx, " - "psm: 0x%02x, scid: 0x%04x, dcid: 0x%04x, " - "our_mps: %d, our_mtu: %d, peer_mps: %d, " - "peer_mtu: %d\n", event->connect.conn_handle, - (uint32_t) event->connect.chan, chan_info.psm, - chan_info.scid, chan_info.dcid, - chan_info.our_l2cap_mtu, chan_info.our_coc_mtu, - chan_info.peer_l2cap_mtu, chan_info.peer_coc_mtu); - - connected_cb(event->connect.conn_handle, - event->connect.chan, &chan_info, arg); - - return 0; - case BLE_L2CAP_EVENT_COC_DISCONNECTED: - if (ble_l2cap_get_chan_info(event->disconnect.chan, - &chan_info)) { - assert(0); - } - console_printf("LE CoC disconnected, chan: 0x%08lx\n", - (uint32_t) event->disconnect.chan); - - disconnected_cb(event->disconnect.conn_handle, - event->disconnect.chan, &chan_info, arg); - return 0; - case BLE_L2CAP_EVENT_COC_ACCEPT: - ble_l2cap_get_chan_info(event->accept.chan, &chan_info); - if (chan_info.psm == 0x00F2) { - /* TSPX_psm_authentication_required */ - ble_gap_conn_find(event->accept.conn_handle, &conn); - if (!conn.sec_state.authenticated) { - return BLE_HS_EAUTHEN; - } - } else if (chan_info.psm == 0x00F3) { - /* TSPX_psm_authorization_required */ - ble_gap_conn_find(event->accept.conn_handle, &conn); - if (!conn.sec_state.encrypted) { - return BLE_HS_EAUTHOR; - } - return BLE_HS_EAUTHOR; - } else if (chan_info.psm == 0x00F4) { - /* TSPX_psm_encryption_key_size_required */ - ble_gap_conn_find(event->accept.conn_handle, &conn); - if (conn.sec_state.key_size < 16) { - return BLE_HS_EENCRYPT_KEY_SZ; - } - } - - accept_response = POINTER_TO_INT(arg); - if (accept_response) { - return accept_response; - } - - console_printf("LE CoC accept, chan: 0x%08lx, handle: %u, sdu_size: %u\n", - (uint32_t) event->accept.chan, - event->accept.conn_handle, - event->accept.peer_sdu_size); - - return accept_cb(event->accept.conn_handle, - event->accept.peer_sdu_size, - event->accept.chan); - - case BLE_L2CAP_EVENT_COC_DATA_RECEIVED: - console_printf("LE CoC data received, chan: 0x%08lx, handle: %u, sdu_len: %u\n", - (uint32_t) event->receive.chan, - event->receive.conn_handle, - OS_MBUF_PKTLEN(event->receive.sdu_rx)); - - recv_cb(event->receive.conn_handle, event->receive.chan, - event->receive.sdu_rx, arg); - return 0; - case BLE_L2CAP_EVENT_COC_TX_UNSTALLED: - console_printf("LE CoC tx unstalled, chan: 0x%08lx, handle: %u, status: %d\n", - (uint32_t) event->tx_unstalled.chan, - event->tx_unstalled.conn_handle, - event->tx_unstalled.status); - - unstalled_cb(event->tx_unstalled.conn_handle, - event->tx_unstalled.chan, - event->tx_unstalled.status, arg); - return 0; - case BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED: - if (ble_l2cap_get_chan_info(event->reconfigured.chan, - &chan_info)) { - assert(0); - } - console_printf("LE CoC reconfigure completed status 0x%02x, " - "chan: 0x%08lx\n", event->reconfigured.status, - (uint32_t) event->reconfigured.chan); - - if (event->reconfigured.status == 0) { - console_printf("\t our_mps: %d our_mtu %d\n", - chan_info.our_l2cap_mtu, chan_info.our_coc_mtu); - } - - reconfigured_ev(event->reconfigured.conn_handle, - event->reconfigured.chan, - &chan_info, - event->reconfigured.status); - return 0; - case BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED: - if (ble_l2cap_get_chan_info(event->reconfigured.chan, - &chan_info)) { - assert(0); - } - console_printf("LE CoC peer reconfigured status 0x%02x, " - "chan: 0x%08lx\n", event->reconfigured.status, - (uint32_t) event->reconfigured.chan); - - if (event->reconfigured.status == 0) { - console_printf("\t peer_mps: %d peer_mtu %d\n", - chan_info.peer_l2cap_mtu, chan_info.peer_coc_mtu); - } - - reconfigured_ev(event->reconfigured.conn_handle, - event->reconfigured.chan, - &chan_info, - event->reconfigured.status); - return 0; - default: - return 0; - } -} - -static void connect(uint8_t *data, uint16_t len) -{ - const struct l2cap_connect_cmd *cmd = (void *) data; - uint8_t rp_buf[sizeof(struct l2cap_connect_rp) + cmd->num]; - struct l2cap_connect_rp *rp = (void *) rp_buf; - struct ble_gap_conn_desc desc; - struct channel *chan; - struct os_mbuf *sdu_rx[cmd->num]; - ble_addr_t *addr = (void *) data; - uint16_t mtu = htole16(cmd->mtu); - int rc; - int i, j; - bool ecfc = cmd->options & L2CAP_CONNECT_OPT_ECFC; - hold_credit = cmd->options & L2CAP_CONNECT_OPT_HOLD_CREDIT; - - SYS_LOG_DBG("connect: type: %d addr: %s", addr->type, bt_hex(addr->val, 6)); - - if (mtu == 0 || mtu > TESTER_COC_MTU) { - mtu = TESTER_COC_MTU; - } - - rc = ble_gap_conn_find_by_addr(addr, &desc); - if (rc) { - SYS_LOG_ERR("GAP conn find failed"); - goto fail; - } - - rp->num = cmd->num; - - for (i = 0; i < cmd->num; i++) { - chan = get_free_channel(); - if (!chan) { - SYS_LOG_ERR("No free channels"); - goto fail; - } - /* temporarily mark channel as used to select next one */ - chan->state = 1; - - rp->chan_ids[i] = chan->chan_id; - - sdu_rx[i] = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); - if (sdu_rx[i] == NULL) { - SYS_LOG_ERR("Failed to alloc buf"); - goto fail; - } - } - - /* mark selected channels as unused again */ - for (i = 0; i < cmd->num; i++) { - for (j = 0; j < CHANNELS; j++) { - if (rp->chan_ids[i] == channels[j].chan_id) { - channels[j].state = 0; - } - } - } - - if (cmd->num == 1 && !ecfc) { - rc = ble_l2cap_connect(desc.conn_handle, htole16(cmd->psm), - mtu, sdu_rx[0], - tester_l2cap_event, NULL); - } else if (ecfc) { - rc = ble_l2cap_enhanced_connect(desc.conn_handle, - htole16(cmd->psm), mtu, - cmd->num, sdu_rx, - tester_l2cap_event, NULL); - } else { - SYS_LOG_ERR("Invalid 'num' parameter value"); - goto fail; - } - - if (rc) { - SYS_LOG_ERR("L2CAP connect failed\n"); - goto fail; - } - - tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_CONNECT, CONTROLLER_INDEX, - (uint8_t *) rp, sizeof(rp_buf)); - - return; - -fail: - tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_CONNECT, CONTROLLER_INDEX, - BTP_STATUS_FAILED); -} - -static void disconnect(const uint8_t *data, uint16_t len) -{ - const struct l2cap_disconnect_cmd *cmd = (void *) data; - struct channel *chan; - uint8_t status; - int err; - - SYS_LOG_DBG(""); - - chan = get_channel(cmd->chan_id); - assert(chan != NULL); - - err = ble_l2cap_disconnect(chan->chan); - if (err) { - status = BTP_STATUS_FAILED; - goto rsp; - } - - status = BTP_STATUS_SUCCESS; - -rsp: - tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_DISCONNECT, CONTROLLER_INDEX, - status); -} - -static void send_data(const uint8_t *data, uint16_t len) -{ - const struct l2cap_send_data_cmd *cmd = (void *) data; - struct os_mbuf *sdu_tx = NULL; - int rc; - uint16_t data_len = sys_le16_to_cpu(cmd->data_len); - struct channel *chan = get_channel(cmd->chan_id); - - SYS_LOG_DBG("cmd->chan_id=%d", cmd->chan_id); - - if (!chan) { - SYS_LOG_ERR("Invalid channel\n"); - goto fail; - } - - /* FIXME: For now, fail if data length exceeds buffer length */ - if (data_len > TESTER_COC_MTU) { - SYS_LOG_ERR("Data length exceeds buffer length"); - goto fail; - } - - sdu_tx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); - if (sdu_tx == NULL) { - SYS_LOG_ERR("No memory in the test sdu pool\n"); - goto fail; - } - - os_mbuf_append(sdu_tx, cmd->data, data_len); - - /* ble_l2cap_send takes ownership of the sdu */ - rc = ble_l2cap_send(chan->chan, sdu_tx); - if (rc == 0 || rc == BLE_HS_ESTALLED) { - tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_SEND_DATA, CONTROLLER_INDEX, - BTP_STATUS_SUCCESS); - return; - } - - SYS_LOG_ERR("Unable to send data: %d", rc); - os_mbuf_free_chain(sdu_tx); - -fail: - tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_SEND_DATA, CONTROLLER_INDEX, - BTP_STATUS_FAILED); -} - -static int -l2cap_coc_err2hs_err(uint16_t coc_err) -{ - switch (coc_err) { - case BLE_L2CAP_COC_ERR_UNKNOWN_LE_PSM: - return BLE_HS_ENOTSUP; - case BLE_L2CAP_COC_ERR_NO_RESOURCES: - return BLE_HS_ENOMEM; - case BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHEN: - return BLE_HS_EAUTHEN; - case BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHOR: - return BLE_HS_EAUTHOR; - case BLE_L2CAP_COC_ERR_INSUFFICIENT_ENC: - return BLE_HS_EENCRYPT; - case BLE_L2CAP_COC_ERR_INSUFFICIENT_KEY_SZ: - return BLE_HS_EENCRYPT_KEY_SZ; - case BLE_L2CAP_COC_ERR_UNACCEPTABLE_PARAMETERS: - return BLE_HS_EINVAL; - default: - return 0; - } -} - -static int -l2cap_btp_listen_err2coc_err(uint16_t coc_err) -{ - switch (coc_err) { - case 0x01: - return BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHEN; - case 0x02: - return BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHOR; - case 0x03: - return BLE_L2CAP_COC_ERR_INSUFFICIENT_KEY_SZ; - case 0x04: - return BLE_L2CAP_COC_ERR_INSUFFICIENT_ENC; - default: - return 0; - } -} - -static void listen(const uint8_t *data, uint16_t len) -{ - const struct l2cap_listen_cmd *cmd = (void *) data; - uint16_t mtu = htole16(cmd->mtu); - uint16_t rsp = htole16(cmd->response); - int rc; - - SYS_LOG_DBG(""); - - if (mtu == 0 || mtu > TESTER_COC_MTU) { - mtu = TESTER_COC_MTU; - } - - rsp = l2cap_btp_listen_err2coc_err(rsp); - rsp = l2cap_coc_err2hs_err(rsp); - - /* TODO: Handle cmd->transport flag */ - rc = ble_l2cap_create_server(cmd->psm, mtu, tester_l2cap_event, - INT_TO_POINTER(rsp)); - if (rc) { - goto fail; - } - - tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_LISTEN, CONTROLLER_INDEX, - BTP_STATUS_SUCCESS); - return; - -fail: - tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_LISTEN, CONTROLLER_INDEX, - BTP_STATUS_FAILED); -} - -static void credits(uint8_t *data, uint16_t len) -{ - const struct l2cap_credits_cmd *cmd = (void *)data; - struct os_mbuf *sdu; - int rc; - - struct channel *channel = get_channel(cmd->chan_id); - if (channel == NULL) { - goto fail; - } - - sdu = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0); - if (sdu == NULL) { - os_mbuf_free_chain(sdu); - goto fail; - } - - rc = ble_l2cap_recv_ready(channel->chan, sdu); - if (rc != 0) { - goto fail; - } - tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_CREDITS, CONTROLLER_INDEX, - BTP_STATUS_SUCCESS); - return; -fail: - tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_CREDITS, CONTROLLER_INDEX, - BTP_STATUS_FAILED); -} - -static void reconfigure(const uint8_t *data, uint16_t len) -{ - const struct l2cap_reconfigure_cmd *cmd = (void *) data; - uint16_t mtu = htole16(cmd->mtu); - struct ble_gap_conn_desc desc; - ble_addr_t *addr = (void *) data; - struct ble_l2cap_chan *chans[cmd->num]; - struct channel *channel; - int rc; - int i; - - SYS_LOG_DBG(""); - - if (mtu == 0 || mtu > TESTER_COC_MTU) { - mtu = TESTER_COC_MTU; - } - - rc = ble_gap_conn_find_by_addr(addr, &desc); - if (rc) { - SYS_LOG_ERR("GAP conn find failed"); - goto fail; - } - - for (i = 0; i < cmd->num; ++i) { - channel = get_channel(cmd->idxs[i]); - if (channel == NULL) { - goto fail; - } - chans[i] = channel->chan; - } - - rc = ble_l2cap_reconfig(chans, cmd->num, mtu); - if (rc) { - goto fail; - } - - tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_RECONFIGURE, CONTROLLER_INDEX, - BTP_STATUS_SUCCESS); - return; - -fail: - tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_RECONFIGURE, CONTROLLER_INDEX, - BTP_STATUS_FAILED); -} - -static void supported_commands(uint8_t *data, uint16_t len) -{ - uint8_t cmds[1]; - struct l2cap_read_supported_commands_rp *rp = (void *) cmds; - - memset(cmds, 0, sizeof(cmds)); - - tester_set_bit(cmds, L2CAP_READ_SUPPORTED_COMMANDS); - tester_set_bit(cmds, L2CAP_CONNECT); - tester_set_bit(cmds, L2CAP_DISCONNECT); - tester_set_bit(cmds, L2CAP_LISTEN); - tester_set_bit(cmds, L2CAP_SEND_DATA); - tester_set_bit(cmds, L2CAP_RECONFIGURE); - - tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_READ_SUPPORTED_COMMANDS, - CONTROLLER_INDEX, (uint8_t *) rp, sizeof(cmds)); -} - -void tester_handle_l2cap(uint8_t opcode, uint8_t index, uint8_t *data, - uint16_t len) -{ - switch (opcode) { - case L2CAP_READ_SUPPORTED_COMMANDS: - supported_commands(data, len); - return; - case L2CAP_CONNECT: - connect(data, len); - return; - case L2CAP_DISCONNECT: - disconnect(data, len); - return; - case L2CAP_SEND_DATA: - send_data(data, len); - return; - case L2CAP_LISTEN: - listen(data, len); - return; - case L2CAP_RECONFIGURE: - reconfigure(data, len); - return; - case L2CAP_CREDITS: - credits(data, len); - return; - default: - tester_rsp(BTP_SERVICE_ID_L2CAP, opcode, index, - BTP_STATUS_UNKNOWN_CMD); - return; - } -} - -uint8_t tester_init_l2cap(void) -{ - int rc; - - /* For testing we want to support all the available channels */ - rc = os_mempool_init(&sdu_coc_mbuf_mempool, TESTER_COC_BUF_COUNT, - TESTER_COC_MTU, tester_sdu_coc_mem, - "tester_coc_sdu_pool"); - assert(rc == 0); - - rc = os_mbuf_pool_init(&sdu_os_mbuf_pool, &sdu_coc_mbuf_mempool, - TESTER_COC_MTU, TESTER_COC_BUF_COUNT); - assert(rc == 0); - - return BTP_STATUS_SUCCESS; -} - -uint8_t tester_unregister_l2cap(void) -{ - return BTP_STATUS_SUCCESS; -} - -#endif diff --git a/lib/bt/host/nimble/nimble/apps/bttester/src/mesh.c b/lib/bt/host/nimble/nimble/apps/bttester/src/mesh.c deleted file mode 100644 index 46bf7699..00000000 --- a/lib/bt/host/nimble/nimble/apps/bttester/src/mesh.c +++ /dev/null @@ -1,993 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/* mesh.c - Bluetooth Mesh Tester */ - -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "syscfg/syscfg.h" - -#if MYNEWT_VAL(BLE_MESH) - -#include - -#include "mesh/mesh.h" -#include "mesh/glue.h" -#include "mesh/testing.h" -#include "console/console.h" - -#include "bttester.h" - -extern uint8_t own_addr_type; - -#define CONTROLLER_INDEX 0 -#define CID_LOCAL 0x0002 - -/* Health server data */ -#define CUR_FAULTS_MAX 4 -#define HEALTH_TEST_ID 0x00 - -static uint8_t cur_faults[CUR_FAULTS_MAX]; -static uint8_t reg_faults[CUR_FAULTS_MAX * 2]; - -/* Provision node data */ -static uint8_t net_key[16]; -static uint16_t net_key_idx; -static uint8_t flags; -static uint32_t iv_index; -static uint16_t addr; -static uint8_t dev_key[16]; -static uint8_t input_size; - -/* Configured provisioning data */ -static uint8_t dev_uuid[16]; -static uint8_t static_auth[16]; - -/* Vendor Model data */ -#define VND_MODEL_ID_1 0x1234 - -/* Model send data */ -#define MODEL_BOUNDS_MAX 2 - -static struct model_data { - struct bt_mesh_model *model; - uint16_t addr; - uint16_t appkey_idx; -} model_bound[MODEL_BOUNDS_MAX]; - -static struct { - uint16_t local; - uint16_t dst; - uint16_t net_idx; -} net = { - .local = BT_MESH_ADDR_UNASSIGNED, - .dst = BT_MESH_ADDR_UNASSIGNED, -}; - -static void supported_commands(uint8_t *data, uint16_t len) -{ - struct os_mbuf *buf = NET_BUF_SIMPLE(BTP_DATA_MAX_SIZE); - - net_buf_simple_init(buf, 0); - - /* 1st octet */ - memset(net_buf_simple_add(buf, 1), 0, 1); - tester_set_bit(buf->om_data, MESH_READ_SUPPORTED_COMMANDS); - tester_set_bit(buf->om_data, MESH_CONFIG_PROVISIONING); - tester_set_bit(buf->om_data, MESH_PROVISION_NODE); - tester_set_bit(buf->om_data, MESH_INIT); - tester_set_bit(buf->om_data, MESH_RESET); - tester_set_bit(buf->om_data, MESH_INPUT_NUMBER); - tester_set_bit(buf->om_data, MESH_INPUT_STRING); - /* 2nd octet */ - tester_set_bit(buf->om_data, MESH_IVU_TEST_MODE); - tester_set_bit(buf->om_data, MESH_IVU_TOGGLE_STATE); - tester_set_bit(buf->om_data, MESH_NET_SEND); - tester_set_bit(buf->om_data, MESH_HEALTH_GENERATE_FAULTS); - tester_set_bit(buf->om_data, MESH_HEALTH_CLEAR_FAULTS); - tester_set_bit(buf->om_data, MESH_LPN); - tester_set_bit(buf->om_data, MESH_LPN_POLL); - tester_set_bit(buf->om_data, MESH_MODEL_SEND); - /* 3rd octet */ - memset(net_buf_simple_add(buf, 1), 0, 1); -#if MYNEWT_VAL(BLE_MESH_TESTING) - tester_set_bit(buf->om_data, MESH_LPN_SUBSCRIBE); - tester_set_bit(buf->om_data, MESH_LPN_UNSUBSCRIBE); - tester_set_bit(buf->om_data, MESH_RPL_CLEAR); -#endif /* CONFIG_BT_TESTING */ - tester_set_bit(buf->om_data, MESH_PROXY_IDENTITY); - - tester_send_buf(BTP_SERVICE_ID_MESH, MESH_READ_SUPPORTED_COMMANDS, - CONTROLLER_INDEX, buf); -} - -static void get_faults(uint8_t *faults, uint8_t faults_size, uint8_t *dst, uint8_t *count) -{ - uint8_t i, limit = *count; - - for (i = 0, *count = 0; i < faults_size && *count < limit; i++) { - if (faults[i]) { - *dst++ = faults[i]; - (*count)++; - } - } -} - -static int fault_get_cur(struct bt_mesh_model *model, uint8_t *test_id, - uint16_t *company_id, uint8_t *faults, uint8_t *fault_count) -{ - SYS_LOG_DBG(""); - - *test_id = HEALTH_TEST_ID; - *company_id = CID_LOCAL; - - get_faults(cur_faults, sizeof(cur_faults), faults, fault_count); - - return 0; -} - -static int fault_get_reg(struct bt_mesh_model *model, uint16_t company_id, - uint8_t *test_id, uint8_t *faults, uint8_t *fault_count) -{ - SYS_LOG_DBG("company_id 0x%04x", company_id); - - if (company_id != CID_LOCAL) { - return -EINVAL; - } - - *test_id = HEALTH_TEST_ID; - - get_faults(reg_faults, sizeof(reg_faults), faults, fault_count); - - return 0; -} - -static int fault_clear(struct bt_mesh_model *model, uint16_t company_id) -{ - SYS_LOG_DBG("company_id 0x%04x", company_id); - - if (company_id != CID_LOCAL) { - return -EINVAL; - } - - memset(reg_faults, 0, sizeof(reg_faults)); - - return 0; -} - -static int fault_test(struct bt_mesh_model *model, uint8_t test_id, - uint16_t company_id) -{ - SYS_LOG_DBG("test_id 0x%02x company_id 0x%04x", test_id, company_id); - - if (company_id != CID_LOCAL || test_id != HEALTH_TEST_ID) { - return -EINVAL; - } - - return 0; -} - -static const struct bt_mesh_health_srv_cb health_srv_cb = { - .fault_get_cur = fault_get_cur, - .fault_get_reg = fault_get_reg, - .fault_clear = fault_clear, - .fault_test = fault_test, -}; - -static struct bt_mesh_health_srv health_srv = { - .cb = &health_srv_cb, -}; - -static struct bt_mesh_model_pub health_pub; - -static void -health_pub_init(void) -{ - health_pub.msg = BT_MESH_HEALTH_FAULT_MSG(CUR_FAULTS_MAX); -} - -static struct bt_mesh_cfg_cli cfg_cli = { -}; - -void show_faults(uint8_t test_id, uint16_t cid, uint8_t *faults, size_t fault_count) -{ - size_t i; - - if (!fault_count) { - SYS_LOG_DBG("Health Test ID 0x%02x Company ID 0x%04x: " - "no faults", test_id, cid); - return; - } - - SYS_LOG_DBG("Health Test ID 0x%02x Company ID 0x%04x Fault Count %zu: ", - test_id, cid, fault_count); - - for (i = 0; i < fault_count; i++) { - SYS_LOG_DBG("0x%02x", faults[i]); - } -} - -static void health_current_status(struct bt_mesh_health_cli *cli, uint16_t addr, - uint8_t test_id, uint16_t cid, uint8_t *faults, - size_t fault_count) -{ - SYS_LOG_DBG("Health Current Status from 0x%04x", addr); - show_faults(test_id, cid, faults, fault_count); -} - -static struct bt_mesh_health_cli health_cli = { - .current_status = health_current_status, -}; - -static struct bt_mesh_model root_models[] = { - BT_MESH_MODEL_CFG_SRV, - BT_MESH_MODEL_CFG_CLI(&cfg_cli), - BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), - BT_MESH_MODEL_HEALTH_CLI(&health_cli), -}; - -static struct bt_mesh_model vnd_models[] = { - BT_MESH_MODEL_VND(CID_LOCAL, VND_MODEL_ID_1, BT_MESH_MODEL_NO_OPS, NULL, - NULL), -}; - -static struct bt_mesh_elem elements[] = { - BT_MESH_ELEM(0, root_models, vnd_models), -}; - -static void link_open(bt_mesh_prov_bearer_t bearer) -{ - struct mesh_prov_link_open_ev ev; - - SYS_LOG_DBG("bearer 0x%02x", bearer); - - switch (bearer) { - case BT_MESH_PROV_ADV: - ev.bearer = MESH_PROV_BEARER_PB_ADV; - break; - case BT_MESH_PROV_GATT: - ev.bearer = MESH_PROV_BEARER_PB_GATT; - break; - default: - SYS_LOG_ERR("Invalid bearer"); - - return; - } - - tester_send(BTP_SERVICE_ID_MESH, MESH_EV_PROV_LINK_OPEN, - CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); -} - -static void link_close(bt_mesh_prov_bearer_t bearer) -{ - struct mesh_prov_link_closed_ev ev; - - SYS_LOG_DBG("bearer 0x%02x", bearer); - - switch (bearer) { - case BT_MESH_PROV_ADV: - ev.bearer = MESH_PROV_BEARER_PB_ADV; - break; - case BT_MESH_PROV_GATT: - ev.bearer = MESH_PROV_BEARER_PB_GATT; - break; - default: - SYS_LOG_ERR("Invalid bearer"); - - return; - } - - tester_send(BTP_SERVICE_ID_MESH, MESH_EV_PROV_LINK_CLOSED, - CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); -} - -static int output_number(bt_mesh_output_action_t action, uint32_t number) -{ - struct mesh_out_number_action_ev ev; - - SYS_LOG_DBG("action 0x%04x number 0x%08lx", action, number); - - ev.action = sys_cpu_to_le16(action); - ev.number = sys_cpu_to_le32(number); - - tester_send(BTP_SERVICE_ID_MESH, MESH_EV_OUT_NUMBER_ACTION, - CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); - - return 0; -} - -static int output_string(const char *str) -{ - struct mesh_out_string_action_ev *ev; - struct os_mbuf *buf = NET_BUF_SIMPLE(BTP_DATA_MAX_SIZE); - - SYS_LOG_DBG("str %s", str); - - net_buf_simple_init(buf, 0); - - ev = net_buf_simple_add(buf, sizeof(*ev)); - ev->string_len = strlen(str); - - net_buf_simple_add_mem(buf, str, ev->string_len); - - tester_send_buf(BTP_SERVICE_ID_MESH, MESH_EV_OUT_STRING_ACTION, - CONTROLLER_INDEX, buf); - - os_mbuf_free_chain(buf); - return 0; -} - -static int input(bt_mesh_input_action_t action, uint8_t size) -{ - struct mesh_in_action_ev ev; - - SYS_LOG_DBG("action 0x%04x number 0x%02x", action, size); - - input_size = size; - - ev.action = sys_cpu_to_le16(action); - ev.size = size; - - tester_send(BTP_SERVICE_ID_MESH, MESH_EV_IN_ACTION, CONTROLLER_INDEX, - (uint8_t *) &ev, sizeof(ev)); - - return 0; -} - -static uint8_t vnd_app_key[16]; -static uint16_t vnd_app_key_idx = 0x000f; - -static void prov_complete(uint16_t net_idx, uint16_t addr) -{ - SYS_LOG_DBG("net_idx 0x%04x addr 0x%04x", net_idx, addr); - - net.net_idx = net_idx, - net.local = addr; - net.dst = addr; - - tester_send(BTP_SERVICE_ID_MESH, MESH_EV_PROVISIONED, CONTROLLER_INDEX, - NULL, 0); -} - -static void prov_reset(void) -{ - SYS_LOG_DBG(""); - - bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT); -} - -static const struct bt_mesh_comp comp = { - .cid = CID_LOCAL, - .elem = elements, - .elem_count = ARRAY_SIZE(elements), -}; - -static struct bt_mesh_prov prov = { - .uuid = dev_uuid, - .static_val = static_auth, - .static_val_len = sizeof(static_auth), - .output_number = output_number, - .output_string = output_string, - .input = input, - .link_open = link_open, - .link_close = link_close, - .complete = prov_complete, - .reset = prov_reset, -}; - -static void config_prov(uint8_t *data, uint16_t len) -{ - const struct mesh_config_provisioning_cmd *cmd = (void *) data; - - SYS_LOG_DBG(""); - - memcpy(dev_uuid, cmd->uuid, sizeof(dev_uuid)); - memcpy(static_auth, cmd->static_auth, sizeof(static_auth)); - - prov.output_size = cmd->out_size; - prov.output_actions = sys_le16_to_cpu(cmd->out_actions); - prov.input_size = cmd->in_size; - prov.input_actions = sys_le16_to_cpu(cmd->in_actions); - - tester_rsp(BTP_SERVICE_ID_MESH, MESH_CONFIG_PROVISIONING, - CONTROLLER_INDEX, BTP_STATUS_SUCCESS); -} - -static void provision_node(uint8_t *data, uint16_t len) -{ - const struct mesh_provision_node_cmd *cmd = (void *) data; - - SYS_LOG_DBG(""); - - memcpy(dev_key, cmd->dev_key, sizeof(dev_key)); - memcpy(net_key, cmd->net_key, sizeof(net_key)); - - addr = sys_le16_to_cpu(cmd->addr); - flags = cmd->flags; - iv_index = sys_le32_to_cpu(cmd->iv_index); - net_key_idx = sys_le16_to_cpu(cmd->net_key_idx); - - tester_rsp(BTP_SERVICE_ID_MESH, MESH_PROVISION_NODE, - CONTROLLER_INDEX, BTP_STATUS_SUCCESS); -} - -static void init(uint8_t *data, uint16_t len) -{ - uint8_t status = BTP_STATUS_SUCCESS; - int err; - - SYS_LOG_DBG(""); - - err = bt_mesh_init(own_addr_type, &prov, &comp); - if (err) { - status = BTP_STATUS_FAILED; - - goto rsp; - } - - if (addr) { - err = bt_mesh_provision(net_key, net_key_idx, flags, iv_index, - addr, dev_key); - if (err) { - status = BTP_STATUS_FAILED; - } - } else { - err = bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT); - if (err) { - status = BTP_STATUS_FAILED; - } - } - -rsp: - tester_rsp(BTP_SERVICE_ID_MESH, MESH_INIT, CONTROLLER_INDEX, - status); -} - -static void reset(uint8_t *data, uint16_t len) -{ - SYS_LOG_DBG(""); - - bt_mesh_reset(); - - tester_rsp(BTP_SERVICE_ID_MESH, MESH_RESET, CONTROLLER_INDEX, - BTP_STATUS_SUCCESS); -} - -static void input_number(uint8_t *data, uint16_t len) -{ - const struct mesh_input_number_cmd *cmd = (void *) data; - uint8_t status = BTP_STATUS_SUCCESS; - uint32_t number; - int err; - - number = sys_le32_to_cpu(cmd->number); - - SYS_LOG_DBG("number 0x%04lx", number); - - err = bt_mesh_input_number(number); - if (err) { - status = BTP_STATUS_FAILED; - } - - tester_rsp(BTP_SERVICE_ID_MESH, MESH_INPUT_NUMBER, CONTROLLER_INDEX, - status); -} - -static void input_string(uint8_t *data, uint16_t len) -{ - const struct mesh_input_string_cmd *cmd = (void *) data; - uint8_t status = BTP_STATUS_SUCCESS; - uint8_t str_auth[16]; - int err; - - SYS_LOG_DBG(""); - - if (cmd->string_len > sizeof(str_auth)) { - SYS_LOG_ERR("Too long input (%u chars required)", input_size); - status = BTP_STATUS_FAILED; - goto rsp; - } else if (cmd->string_len < input_size) { - SYS_LOG_ERR("Too short input (%u chars required)", input_size); - status = BTP_STATUS_FAILED; - goto rsp; - } - - strncpy((char *)str_auth, (char *)cmd->string, cmd->string_len); - - err = bt_mesh_input_string((char *)str_auth); - if (err) { - status = BTP_STATUS_FAILED; - } - -rsp: - tester_rsp(BTP_SERVICE_ID_MESH, MESH_INPUT_STRING, CONTROLLER_INDEX, - status); -} - -static void ivu_test_mode(uint8_t *data, uint16_t len) -{ - const struct mesh_ivu_test_mode_cmd *cmd = (void *) data; - - SYS_LOG_DBG("enable 0x%02x", cmd->enable); - - bt_mesh_iv_update_test(cmd->enable ? true : false); - - tester_rsp(BTP_SERVICE_ID_MESH, MESH_IVU_TEST_MODE, CONTROLLER_INDEX, - BTP_STATUS_SUCCESS); -} - -static void ivu_toggle_state(uint8_t *data, uint16_t len) -{ - bool result; - - SYS_LOG_DBG(""); - - result = bt_mesh_iv_update(); - if (!result) { - SYS_LOG_ERR("Failed to toggle the IV Update state"); - } - - tester_rsp(BTP_SERVICE_ID_MESH, MESH_IVU_TOGGLE_STATE, CONTROLLER_INDEX, - result ? BTP_STATUS_SUCCESS : BTP_STATUS_FAILED); -} - -static void lpn(uint8_t *data, uint16_t len) -{ - struct mesh_lpn_set_cmd *cmd = (void *) data; - bool enable; - int err; - - SYS_LOG_DBG("enable 0x%02x", cmd->enable); - - enable = cmd->enable ? true : false; - err = bt_mesh_lpn_set(enable); - if (err) { - SYS_LOG_ERR("Failed to toggle LPN (err %d)", err); - } - - tester_rsp(BTP_SERVICE_ID_MESH, MESH_LPN, CONTROLLER_INDEX, - err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS); -} - -static void lpn_poll(uint8_t *data, uint16_t len) -{ - int err; - - SYS_LOG_DBG(""); - - err = bt_mesh_lpn_poll(); - if (err) { - SYS_LOG_ERR("Failed to send poll msg (err %d)", err); - } - - tester_rsp(BTP_SERVICE_ID_MESH, MESH_LPN_POLL, CONTROLLER_INDEX, - err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS); -} - -static void net_send(uint8_t *data, uint16_t len) -{ - struct mesh_net_send_cmd *cmd = (void *) data; - struct os_mbuf *msg = NET_BUF_SIMPLE(UINT8_MAX); - struct bt_mesh_msg_ctx ctx = { - .net_idx = net.net_idx, - .app_idx = vnd_app_key_idx, - .addr = sys_le16_to_cpu(cmd->dst), - .send_ttl = cmd->ttl, - }; - int err; - - SYS_LOG_DBG("ttl 0x%02x dst 0x%04x payload_len %d", ctx.send_ttl, - ctx.addr, cmd->payload_len); - - if (!bt_mesh_app_key_exists(vnd_app_key_idx)) { - (void)bt_mesh_app_key_add(vnd_app_key_idx, net.net_idx, - vnd_app_key); - vnd_models[0].keys[0] = vnd_app_key_idx; - } - - net_buf_simple_add_mem(msg, cmd->payload, cmd->payload_len); - - err = bt_mesh_model_send(&vnd_models[0], &ctx, msg, NULL, NULL); - if (err) { - SYS_LOG_ERR("Failed to send (err %d)", err); - } - - tester_rsp(BTP_SERVICE_ID_MESH, MESH_NET_SEND, CONTROLLER_INDEX, - err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS); - - os_mbuf_free_chain(msg); -} - -static void health_generate_faults(uint8_t *data, uint16_t len) -{ - struct mesh_health_generate_faults_rp *rp; - struct os_mbuf *buf = NET_BUF_SIMPLE(sizeof(*rp) + sizeof(cur_faults) + - sizeof(reg_faults)); - uint8_t some_faults[] = { 0x01, 0x02, 0x03, 0xff, 0x06 }; - uint8_t cur_faults_count, reg_faults_count; - - rp = net_buf_simple_add(buf, sizeof(*rp)); - - cur_faults_count = min(sizeof(cur_faults), sizeof(some_faults)); - memcpy(cur_faults, some_faults, cur_faults_count); - net_buf_simple_add_mem(buf, cur_faults, cur_faults_count); - rp->cur_faults_count = cur_faults_count; - - reg_faults_count = min(sizeof(reg_faults), sizeof(some_faults)); - memcpy(reg_faults, some_faults, reg_faults_count); - net_buf_simple_add_mem(buf, reg_faults, reg_faults_count); - rp->reg_faults_count = reg_faults_count; - - bt_mesh_fault_update(&elements[0]); - - tester_send_buf(BTP_SERVICE_ID_MESH, MESH_HEALTH_GENERATE_FAULTS, - CONTROLLER_INDEX, buf); -} - -static void health_clear_faults(uint8_t *data, uint16_t len) -{ - SYS_LOG_DBG(""); - - memset(cur_faults, 0, sizeof(cur_faults)); - memset(reg_faults, 0, sizeof(reg_faults)); - - bt_mesh_fault_update(&elements[0]); - - tester_rsp(BTP_SERVICE_ID_MESH, MESH_HEALTH_CLEAR_FAULTS, - CONTROLLER_INDEX, BTP_STATUS_SUCCESS); -} - -static void model_send(uint8_t *data, uint16_t len) -{ - struct mesh_model_send_cmd *cmd = (void *) data; - struct os_mbuf *msg = NET_BUF_SIMPLE(UINT8_MAX); - struct bt_mesh_msg_ctx ctx = { - .net_idx = net.net_idx, - .app_idx = BT_MESH_KEY_DEV, - .addr = sys_le16_to_cpu(cmd->dst), - .send_ttl = BT_MESH_TTL_DEFAULT, - }; - struct bt_mesh_model *model = NULL; - int err, i; - uint16_t src = sys_le16_to_cpu(cmd->src); - - /* Lookup source address */ - for (i = 0; i < ARRAY_SIZE(model_bound); i++) { - if (bt_mesh_model_elem(model_bound[i].model)->addr == src) { - model = model_bound[i].model; - ctx.app_idx = model_bound[i].appkey_idx; - - break; - } - } - - if (!model) { - SYS_LOG_ERR("Model not found"); - err = -EINVAL; - - goto fail; - } - - SYS_LOG_DBG("src 0x%04x dst 0x%04x model %p payload_len %d", src, - ctx.addr, model, cmd->payload_len); - - net_buf_simple_add_mem(msg, cmd->payload, cmd->payload_len); - - err = bt_mesh_model_send(model, &ctx, msg, NULL, NULL); - if (err) { - SYS_LOG_ERR("Failed to send (err %d)", err); - } - -fail: - tester_rsp(BTP_SERVICE_ID_MESH, MESH_MODEL_SEND, CONTROLLER_INDEX, - err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS); - - os_mbuf_free_chain(msg); -} - -#if MYNEWT_VAL(BLE_MESH_TESTING) -static void lpn_subscribe(uint8_t *data, uint16_t len) -{ - struct mesh_lpn_subscribe_cmd *cmd = (void *) data; - uint16_t address = sys_le16_to_cpu(cmd->address); - int err; - - SYS_LOG_DBG("address 0x%04x", address); - - err = bt_test_mesh_lpn_group_add(address); - if (err) { - SYS_LOG_ERR("Failed to subscribe (err %d)", err); - } - - tester_rsp(BTP_SERVICE_ID_MESH, MESH_LPN_SUBSCRIBE, CONTROLLER_INDEX, - err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS); -} - -static void lpn_unsubscribe(uint8_t *data, uint16_t len) -{ - struct mesh_lpn_unsubscribe_cmd *cmd = (void *) data; - uint16_t address = sys_le16_to_cpu(cmd->address); - int err; - - SYS_LOG_DBG("address 0x%04x", address); - - err = bt_test_mesh_lpn_group_remove(&address, 1); - if (err) { - SYS_LOG_ERR("Failed to unsubscribe (err %d)", err); - } - - tester_rsp(BTP_SERVICE_ID_MESH, MESH_LPN_UNSUBSCRIBE, CONTROLLER_INDEX, - err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS); -} - -static void rpl_clear(uint8_t *data, uint16_t len) -{ - int err; - - SYS_LOG_DBG(""); - - err = bt_test_mesh_rpl_clear(); - if (err) { - SYS_LOG_ERR("Failed to clear RPL (err %d)", err); - } - - tester_rsp(BTP_SERVICE_ID_MESH, MESH_RPL_CLEAR, CONTROLLER_INDEX, - err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS); -} -#endif /* MYNEWT_VAL(BLE_MESH_TESTING) */ - -static void proxy_identity_enable(uint8_t *data, uint16_t len) -{ - int err; - - SYS_LOG_DBG(""); - - err = bt_mesh_proxy_identity_enable(); - if (err) { - SYS_LOG_ERR("Failed to enable proxy identity (err %d)", err); - } - - tester_rsp(BTP_SERVICE_ID_MESH, MESH_PROXY_IDENTITY, CONTROLLER_INDEX, - err ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS); -} - -void tester_handle_mesh(uint8_t opcode, uint8_t index, uint8_t *data, uint16_t len) -{ - switch (opcode) { - case MESH_READ_SUPPORTED_COMMANDS: - supported_commands(data, len); - break; - case MESH_CONFIG_PROVISIONING: - config_prov(data, len); - break; - case MESH_PROVISION_NODE: - provision_node(data, len); - break; - case MESH_INIT: - init(data, len); - break; - case MESH_RESET: - reset(data, len); - break; - case MESH_INPUT_NUMBER: - input_number(data, len); - break; - case MESH_INPUT_STRING: - input_string(data, len); - break; - case MESH_IVU_TEST_MODE: - ivu_test_mode(data, len); - break; - case MESH_IVU_TOGGLE_STATE: - ivu_toggle_state(data, len); - break; - case MESH_LPN: - lpn(data, len); - break; - case MESH_LPN_POLL: - lpn_poll(data, len); - break; - case MESH_NET_SEND: - net_send(data, len); - break; - case MESH_HEALTH_GENERATE_FAULTS: - health_generate_faults(data, len); - break; - case MESH_HEALTH_CLEAR_FAULTS: - health_clear_faults(data, len); - break; - case MESH_MODEL_SEND: - model_send(data, len); - break; -#if MYNEWT_VAL(BLE_MESH_TESTING) - case MESH_LPN_SUBSCRIBE: - lpn_subscribe(data, len); - break; - case MESH_LPN_UNSUBSCRIBE: - lpn_unsubscribe(data, len); - break; - case MESH_RPL_CLEAR: - rpl_clear(data, len); - break; -#endif /* MYNEWT_VAL(BLE_MESH_TESTING) */ - case MESH_PROXY_IDENTITY: - proxy_identity_enable(data, len); - break; - default: - tester_rsp(BTP_SERVICE_ID_MESH, opcode, index, - BTP_STATUS_UNKNOWN_CMD); - break; - } -} - -void net_recv_ev(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst, const void *payload, - size_t payload_len) -{ - struct os_mbuf *buf = NET_BUF_SIMPLE(UINT8_MAX); - struct mesh_net_recv_ev *ev; - - SYS_LOG_DBG("ttl 0x%02x ctl 0x%02x src 0x%04x dst 0x%04x " - "payload_len %d", ttl, ctl, src, dst, payload_len); - - if (payload_len > net_buf_simple_tailroom(buf)) { - SYS_LOG_ERR("Payload size exceeds buffer size"); - - goto done; - } - - ev = net_buf_simple_add(buf, sizeof(*ev)); - ev->ttl = ttl; - ev->ctl = ctl; - ev->src = sys_cpu_to_le16(src); - ev->dst = sys_cpu_to_le16(dst); - ev->payload_len = payload_len; - net_buf_simple_add_mem(buf, payload, payload_len); - - tester_send_buf(BTP_SERVICE_ID_MESH, MESH_EV_NET_RECV, CONTROLLER_INDEX, - buf); -done: - os_mbuf_free_chain(buf); -} - -static void model_bound_cb(uint16_t addr, struct bt_mesh_model *model, - uint16_t key_idx) -{ - int i; - - SYS_LOG_DBG("remote addr 0x%04x key_idx 0x%04x model %p", - addr, key_idx, model); - - for (i = 0; i < ARRAY_SIZE(model_bound); i++) { - if (!model_bound[i].model) { - model_bound[i].model = model; - model_bound[i].addr = addr; - model_bound[i].appkey_idx = key_idx; - - return; - } - } - - SYS_LOG_ERR("model_bound is full"); -} - -static void model_unbound_cb(uint16_t addr, struct bt_mesh_model *model, - uint16_t key_idx) -{ - int i; - - SYS_LOG_DBG("remote addr 0x%04x key_idx 0x%04x model %p", - addr, key_idx, model); - - for (i = 0; i < ARRAY_SIZE(model_bound); i++) { - if (model_bound[i].model == model) { - model_bound[i].model = NULL; - model_bound[i].addr = 0x0000; - model_bound[i].appkey_idx = BT_MESH_KEY_UNUSED; - - return; - } - } - - SYS_LOG_INF("model not found"); -} - -static void invalid_bearer_cb(uint8_t opcode) -{ - struct mesh_invalid_bearer_ev ev = { - .opcode = opcode, - }; - - SYS_LOG_DBG("opcode 0x%02x", opcode); - - tester_send(BTP_SERVICE_ID_MESH, MESH_EV_INVALID_BEARER, - CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); -} - -static void incomp_timer_exp_cb(void) -{ - tester_send(BTP_SERVICE_ID_MESH, MESH_EV_INCOMP_TIMER_EXP, - CONTROLLER_INDEX, NULL, 0); -} - -static struct bt_test_cb bt_test_cb = { - .mesh_net_recv = net_recv_ev, - .mesh_model_bound = model_bound_cb, - .mesh_model_unbound = model_unbound_cb, - .mesh_prov_invalid_bearer = invalid_bearer_cb, - .mesh_trans_incomp_timer_exp = incomp_timer_exp_cb, -}; - -static void lpn_established(uint16_t friend_addr) -{ - - struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - struct mesh_lpn_established_ev ev = { lpn->sub->net_idx, friend_addr, lpn->queue_size, - lpn->recv_win }; - - SYS_LOG_DBG("Friendship (as LPN) established with " - "Friend 0x%04x Queue Size %d Receive Window %d", - friend_addr, lpn->queue_size, lpn->recv_win); - - tester_send(BTP_SERVICE_ID_MESH, MESH_EV_LPN_ESTABLISHED, - CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); -} - -static void lpn_terminated(uint16_t friend_addr) -{ - struct bt_mesh_lpn *lpn = &bt_mesh.lpn; - struct mesh_lpn_terminated_ev ev = { lpn->sub->net_idx, friend_addr }; - - SYS_LOG_DBG("Friendship (as LPN) lost with Friend " - "0x%04x", friend_addr); - - tester_send(BTP_SERVICE_ID_MESH, MESH_EV_LPN_TERMINATED, - CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev)); -} - -void lpn_cb(uint16_t friend_addr, bool established) -{ - if (established) { - lpn_established(friend_addr); - } else { - lpn_terminated(friend_addr); - } -} - -uint8_t tester_init_mesh(void) -{ - health_pub_init(); - - if (IS_ENABLED(CONFIG_BT_TESTING)) { - bt_mesh_lpn_set_cb(lpn_cb); - bt_test_cb_register(&bt_test_cb); - } - - return BTP_STATUS_SUCCESS; -} - -uint8_t tester_unregister_mesh(void) -{ - return BTP_STATUS_SUCCESS; -} - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/lib/bt/host/nimble/nimble/nimble/controller/include/controller/ble_ll_plna.h b/lib/bt/host/nimble/nimble/nimble/controller/include/controller/ble_ll_plna.h deleted file mode 100644 index c4fb65ea..00000000 --- a/lib/bt/host/nimble/nimble/nimble/controller/include/controller/ble_ll_plna.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_PLNA_ -#define H_BLE_LL_PLNA_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "syscfg/syscfg.h" - -#if MYNEWT_VAL(BLE_LL_PA) -void ble_ll_plna_pa_init(void); -void ble_ll_plna_pa_enable(void); -void ble_ll_plna_pa_disable(void); -#endif - -#if MYNEWT_VAL(BLE_LL_LNA) -void ble_ll_plna_lna_init(void); -void ble_ll_plna_lna_enable(void); -void ble_ll_plna_lna_disable(void); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_LL_PLNA_ */ diff --git a/lib/bt/host/nimble/nimble/nimble/controller/include/controller/ble_ll_test.h b/lib/bt/host/nimble/nimble/nimble/controller/include/controller/ble_ll_test.h deleted file mode 100644 index 32984c6b..00000000 --- a/lib/bt/host/nimble/nimble/nimble/controller/include/controller/ble_ll_test.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_LL_TEST_ -#define H_LL_TEST_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -int ble_ll_csa2_test_all(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/bt/host/nimble/nimble/nimble/controller/src/ble_ll_supp_cmd.c b/lib/bt/host/nimble/nimble/nimble/controller/src/ble_ll_supp_cmd.c deleted file mode 100644 index 1c408fbf..00000000 --- a/lib/bt/host/nimble/nimble/nimble/controller/src/ble_ll_supp_cmd.c +++ /dev/null @@ -1,649 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include - -#include "nimble/ble.h" -#include "nimble/nimble_opt.h" -#include "nimble/hci_common.h" -#include "controller/ble_ll.h" -#include "controller/ble_ll_hci.h" - -/* Octet 0 */ -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_DISCONNECT (1 << 5) -#else -#define BLE_SUPP_CMD_DISCONNECT (0 << 5) -#endif -#define BLE_LL_SUPP_CMD_OCTET_0 (BLE_SUPP_CMD_DISCONNECT) - -/* Octet 2*/ -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_READ_REM_VER_INFO (1 << 7) -#else -#define BLE_SUPP_CMD_READ_REM_VER_INFO (0 << 7) -#endif -#define BLE_LL_SUPP_CMD_OCTET_2 (BLE_SUPP_CMD_READ_REM_VER_INFO) - -/* Octet 5 */ -#define BLE_SUPP_CMD_SET_EVENT_MASK (1 << 6) -#define BLE_SUPP_CMD_RESET (1 << 7) -#define BLE_LL_SUPP_CMD_OCTET_5 \ -( \ - BLE_SUPP_CMD_SET_EVENT_MASK | \ - BLE_SUPP_CMD_RESET \ -) - -/* Octet 10 */ -#define BLE_SUPP_CMD_RD_TX_PWR (0 << 2) -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) -#define BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW (1 << 5) -#define BLE_SUPP_CMD_HOST_BUFFER_SIZE (1 << 6) -#define BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS (1 << 7) -#else -#define BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW (0 << 5) -#define BLE_SUPP_CMD_HOST_BUFFER_SIZE (0 << 6) -#define BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS (0 << 7) -#endif -#define BLE_LL_SUPP_CMD_OCTET_10 \ -( \ - BLE_SUPP_CMD_RD_TX_PWR | \ - BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW | \ - BLE_SUPP_CMD_HOST_BUFFER_SIZE | \ - BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS \ -) - -/* Octet 14 */ -#define BLE_SUPP_CMD_RD_LOC_VER (1 << 3) -#define BLE_SUPP_CMD_RD_LOC_SUPP_FEAT (1 << 5) -#define BLE_LL_SUPP_CMD_OCTET_14 \ -( \ - BLE_SUPP_CMD_RD_LOC_VER | \ - BLE_SUPP_CMD_RD_LOC_SUPP_FEAT \ -) - -/* Octet 15 */ -#define BLE_SUPP_CMD_RD_BD_ADDR (1 << 1) - -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_RD_RSSI (1 << 5) -#else -#define BLE_SUPP_CMD_RD_RSSI (0 << 5) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_15 \ -( \ - BLE_SUPP_CMD_RD_BD_ADDR | \ - BLE_SUPP_CMD_RD_RSSI \ -) - -/* Octet 25 */ -#define BLE_SUPP_CMD_LE_SET_EV_MASK (1 << 0) -#define BLE_SUPP_CMD_LE_RD_BUF_SIZE (1 << 1) -#define BLE_SUPP_CMD_LE_RD_LOC_FEAT (1 << 2) -#define BLE_SUPP_CMD_LE_SET_RAND_ADDR (1 << 4) -#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) -#define BLE_SUPP_CMD_LE_SET_ADV_PARAMS (1 << 5) -#define BLE_SUPP_CMD_LE_SET_ADV_TX_PWR (1 << 6) -#define BLE_SUPP_CMD_LE_SET_ADV_DATA (1 << 7) -#else -#define BLE_SUPP_CMD_LE_SET_ADV_PARAMS (0 << 5) -#define BLE_SUPP_CMD_LE_SET_ADV_TX_PWR (0 << 6) -#define BLE_SUPP_CMD_LE_SET_ADV_DATA (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_25 \ -( \ - BLE_SUPP_CMD_LE_SET_EV_MASK | \ - BLE_SUPP_CMD_LE_RD_BUF_SIZE | \ - BLE_SUPP_CMD_LE_RD_LOC_FEAT | \ - BLE_SUPP_CMD_LE_SET_RAND_ADDR | \ - BLE_SUPP_CMD_LE_SET_ADV_PARAMS | \ - BLE_SUPP_CMD_LE_SET_ADV_TX_PWR | \ - BLE_SUPP_CMD_LE_SET_ADV_DATA \ -) - -/* Octet 26 */ -#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) -#define BLE_SUPP_CMD_LE_SET_SCAN_RSP_DATA (1 << 0) -#define BLE_SUPP_CMD_LE_SET_ADV_ENABLE (1 << 1) -#else -#define BLE_SUPP_CMD_LE_SET_SCAN_RSP_DATA (0 << 0) -#define BLE_SUPP_CMD_LE_SET_ADV_ENABLE (0 << 1) -#endif -#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) -#define BLE_SUPP_CMD_LE_SET_SCAN_PARAMS (1 << 2) -#define BLE_SUPP_CMD_LE_SET_SCAN_ENABLE (1 << 3) -#else -#define BLE_SUPP_CMD_LE_SET_SCAN_PARAMS (0 << 2) -#define BLE_SUPP_CMD_LE_SET_SCAN_ENABLE (0 << 3) -#endif -#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_LE_CREATE_CONN (1 << 4) -#define BLE_SUPP_CMD_LE_CREATE_CONN_CANCEL (1 << 5) -#else -#define BLE_SUPP_CMD_LE_CREATE_CONN (0 << 4) -#define BLE_SUPP_CMD_LE_CREATE_CONN_CANCEL (0 << 5) - -#endif -#define BLE_SUPP_CMD_LE_RD_WHITELIST_SIZE (1 << 6) -#define BLE_SUPP_CMD_LE_CLR_WHITELIST (1 << 7) - -#define BLE_LL_SUPP_CMD_OCTET_26 \ -( \ - BLE_SUPP_CMD_LE_SET_SCAN_RSP_DATA | \ - BLE_SUPP_CMD_LE_SET_ADV_ENABLE | \ - BLE_SUPP_CMD_LE_SET_SCAN_PARAMS | \ - BLE_SUPP_CMD_LE_SET_SCAN_ENABLE | \ - BLE_SUPP_CMD_LE_CREATE_CONN | \ - BLE_SUPP_CMD_LE_CREATE_CONN_CANCEL | \ - BLE_SUPP_CMD_LE_RD_WHITELIST_SIZE | \ - BLE_SUPP_CMD_LE_CLR_WHITELIST \ -) - -/* Octet 27 */ -#define BLE_SUPP_CMD_LE_ADD_DEV_WHITELIST (1 << 0) -#define BLE_SUPP_CMD_LE_RMV_DEV_WHITELIST (1 << 1) -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_LE_CONN_UPDATE (1 << 2) -#else -#define BLE_SUPP_CMD_LE_CONN_UPDATE (0 << 2) -#endif -#define BLE_SUPP_CMD_LE_SET_HOST_CHAN_CLASS (1 << 3) -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_LE_RD_CHAN_MAP (1 << 4) -#define BLE_SUPP_CMD_LE_RD_REM_USED_FEAT (1 << 5) -#else -#define BLE_SUPP_CMD_LE_RD_CHAN_MAP (0 << 4) -#define BLE_SUPP_CMD_LE_RD_REM_USED_FEAT (0 << 5) -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -#define BLE_SUPP_CMD_LE_ENCRYPT (1 << 6) -#else -#define BLE_SUPP_CMD_LE_ENCRYPT (0 << 6) -#endif -#define BLE_SUPP_CMD_LE_RAND (1 << 7) - -#define BLE_LL_SUPP_CMD_OCTET_27 \ -( \ - BLE_SUPP_CMD_LE_ENCRYPT | \ - BLE_SUPP_CMD_LE_RAND | \ - BLE_SUPP_CMD_LE_ADD_DEV_WHITELIST | \ - BLE_SUPP_CMD_LE_RMV_DEV_WHITELIST | \ - BLE_SUPP_CMD_LE_CONN_UPDATE | \ - BLE_SUPP_CMD_LE_SET_HOST_CHAN_CLASS | \ - BLE_SUPP_CMD_LE_RD_CHAN_MAP | \ - BLE_SUPP_CMD_LE_RD_REM_USED_FEAT \ -) - -/* Octet 28 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_LE_START_ENCRYPT (1 << 0) -#else -#define BLE_SUPP_CMD_LE_START_ENCRYPT (0 << 0) -#endif -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) -#define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (1 << 1) -#define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (1 << 2) -#else -#define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (0 << 1) -#define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (0 << 2) -#endif -#else -#define BLE_SUPP_CMD_LE_START_ENCRYPT (0 << 0) -#define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (0 << 1) -#define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (0 << 2) -#endif -#define BLE_SUPP_CMD_LE_READ_SUPP_STATES (1 << 3) - -#if MYNEWT_VAL(BLE_LL_DTM) -#define BLE_SUPP_CMD_LE_RX_TEST (1 << 4) -#define BLE_SUPP_CMD_LE_TX_TEST (1 << 5) -#define BLE_SUPP_CMD_LE_TEST_END (1 << 6) - -#else -#define BLE_SUPP_CMD_LE_RX_TEST (0 << 4) -#define BLE_SUPP_CMD_LE_TX_TEST (0 << 5) -#define BLE_SUPP_CMD_LE_TEST_END (0 << 6) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_28 \ -( \ - BLE_SUPP_CMD_LE_START_ENCRYPT | \ - BLE_SUPP_CMD_LE_LTK_REQ_REPLY | \ - BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY | \ - BLE_SUPP_CMD_LE_READ_SUPP_STATES | \ - BLE_SUPP_CMD_LE_RX_TEST | \ - BLE_SUPP_CMD_LE_TX_TEST | \ - BLE_SUPP_CMD_LE_TEST_END \ -) - -/* Octet 33 */ -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_LE_REM_CONN_PRR (1 << 4) -#define BLE_SUPP_CMD_LE_REM_CONN_PRNR (1 << 5) -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) -#define BLE_SUPP_CMD_LE_SET_DATALEN (1 << 6) -#define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (1 << 7) -#else -#define BLE_SUPP_CMD_LE_SET_DATALEN (0 << 6) -#define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (0 << 7) -#endif -#else -#define BLE_SUPP_CMD_LE_REM_CONN_PRR (0 << 4) -#define BLE_SUPP_CMD_LE_REM_CONN_PRNR (0 << 5) -#define BLE_SUPP_CMD_LE_SET_DATALEN (0 << 6) -#define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (0 << 7) -#endif - - -#define BLE_LL_SUPP_CMD_OCTET_33 \ -( \ - BLE_SUPP_CMD_LE_REM_CONN_PRR | \ - BLE_SUPP_CMD_LE_REM_CONN_PRNR | \ - BLE_SUPP_CMD_LE_SET_DATALEN | \ - BLE_SUPP_CMD_LE_RD_SUGG_DATALEN \ -) - -/* Octet 34 */ -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) -#define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (1 << 0) -#else -#define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (0 << 0) -#endif -#else -#define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (0 << 0) -#endif -#define BLE_SUPP_CMD_LE_READ_LOCAL_P256_PK (0 << 1) -#define BLE_SUPP_CMD_LE_GENERATE_DH_KEY (0 << 2) -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -#define BLE_SUPP_CMD_LE_ADD_RESOLV_LIST (1 << 3) -#define BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST (1 << 4) -#define BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST (1 << 5) -#define BLE_SUPP_CMD_LE_RD_RESOLV_SIZE (1 << 6) -#define BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR (1 << 7) -#else -#define BLE_SUPP_CMD_LE_ADD_RESOLV_LIST (0 << 3) -#define BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST (0 << 4) -#define BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST (0 << 5) -#define BLE_SUPP_CMD_LE_RD_RESOLV_SIZE (0 << 6) -#define BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_34 \ -( \ - BLE_SUPP_CMD_LE_WR_SUGG_DATALEN | \ - BLE_SUPP_CMD_LE_READ_LOCAL_P256_PK | \ - BLE_SUPP_CMD_LE_GENERATE_DH_KEY | \ - BLE_SUPP_CMD_LE_ADD_RESOLV_LIST | \ - BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST | \ - BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST | \ - BLE_SUPP_CMD_LE_RD_RESOLV_SIZE | \ - BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR \ -) - -/* Octet 35 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -#define BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR (1 << 0) -#define BLE_SUPP_CMD_LE_SET_ADDR_RES_EN (1 << 1) -#define BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO (1 << 2) -#else -#define BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR (0 << 0) -#define BLE_SUPP_CMD_LE_SET_ADDR_RES_EN (0 << 1) -#define BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO (0 << 2) -#endif -#define BLE_SUPP_CMD_LE_RD_MAX_DATALEN (1 << 3) -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_LE_READ_PHY (1 << 4) -#define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (1 << 5) -#define BLE_SUPP_CMD_LE_SET_PHY (1 << 6) -#else -#define BLE_SUPP_CMD_LE_READ_PHY (0 << 4) -#define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (0 << 5) -#define BLE_SUPP_CMD_LE_SET_PHY (0 << 6) -#endif -#else -#define BLE_SUPP_CMD_LE_READ_PHY (0 << 4) -#define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (0 << 5) -#define BLE_SUPP_CMD_LE_SET_PHY (0 << 6) -#endif - -#if MYNEWT_VAL(BLE_LL_DTM) -#define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST (1 << 7) -#else -#define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_35 \ -( \ - BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR | \ - BLE_SUPP_CMD_LE_SET_ADDR_RES_EN | \ - BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO | \ - BLE_SUPP_CMD_LE_RD_MAX_DATALEN | \ - BLE_SUPP_CMD_LE_READ_PHY | \ - BLE_SUPP_CMD_LE_SET_DEFAULT_PHY | \ - BLE_SUPP_CMD_LE_SET_PHY | \ - BLE_SUPP_CMD_LE_ENHANCED_RX_TEST \ -) - -/* Octet 36 */ -#if MYNEWT_VAL(BLE_LL_DTM) -#define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST (1 << 0) -#else -#define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST (0 << 0) -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) -#define BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR (1 << 1) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM (1 << 2) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA (1 << 3) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP (1 << 4) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE (1 << 5) -#define BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN (1 << 6) -#define BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS (1 << 7) -#else -#define BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR (0 << 1) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM (0 << 2) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA (0 << 3) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP (0 << 4) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE (0 << 5) -#define BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN (0 << 6) -#define BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_36 \ -( \ - BLE_SUPP_CMD_LE_ENHANCED_TX_TEST | \ - BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR | \ - BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM | \ - BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA | \ - BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP | \ - BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE | \ - BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN | \ - BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS \ -) - -/* Octet 37 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) -#define BLE_SUPP_CMD_LE_REMOVE_ADVS (1 << 0) -#define BLE_SUPP_CMD_LE_CLEAR_ADVS (1 << 1) -#else -#define BLE_SUPP_CMD_LE_REMOVE_ADVS (0 << 0) -#define BLE_SUPP_CMD_LE_CLEAR_ADVS (0 << 1) -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) -#define BLE_SUPP_CMD_LE_SET_PADV_PARAM (1 << 2) -#define BLE_SUPP_CMD_LE_SET_PADV_DATA (1 << 3) -#define BLE_SUPP_CMD_LE_SET_PADV_ENABLE (1 << 4) -#else -#define BLE_SUPP_CMD_LE_SET_PADV_PARAM (0 << 2) -#define BLE_SUPP_CMD_LE_SET_PADV_DATA (0 << 3) -#define BLE_SUPP_CMD_LE_SET_PADV_ENABLE (0 << 4) -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (1 << 5) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (1 << 6) -#else -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (0 << 5) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (0 << 6) -#endif -#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (1 << 7) -#else -#define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (0 << 7) -#endif -#else -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (0 << 5) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (0 << 6) -#define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_37 \ -( \ - BLE_SUPP_CMD_LE_REMOVE_ADVS | \ - BLE_SUPP_CMD_LE_CLEAR_ADVS | \ - BLE_SUPP_CMD_LE_SET_PADV_PARAM | \ - BLE_SUPP_CMD_LE_SET_PADV_DATA | \ - BLE_SUPP_CMD_LE_SET_PADV_ENABLE | \ - BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM | \ - BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE | \ - BLE_SUPP_CMD_LE_EXT_CREATE_CONN \ -) - -/* Octet 38 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) -#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC (1 << 0) -#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C (1 << 1) -#define BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC (1 << 2) -#define BLE_SUPP_CMD_LE_ADD_PADV_LIST (1 << 3) -#define BLE_SUPP_CMD_LE_REMOVE_PADV_LIST (1 << 4) -#define BLE_SUPP_CMD_LE_CLEAR_PADV_LIST (1 << 5) -#define BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE (1 << 6) -#else -#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC (0 << 0) -#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C (0 << 1) -#define BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC (0 << 2) -#define BLE_SUPP_CMD_LE_ADD_PADV_LIST (0 << 3) -#define BLE_SUPP_CMD_LE_REMOVE_PADV_LIST (0 << 4) -#define BLE_SUPP_CMD_LE_CLEAR_PADV_LIST (0 << 5) -#define BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE (0 << 6) -#endif -#define BLE_SUPP_CMD_LE_RD_TX_POWER (1 << 7) - -#define BLE_LL_SUPP_CMD_OCTET_38 \ -( \ - BLE_SUPP_CMD_LE_PADV_CREATE_SYNC | \ - BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C | \ - BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC | \ - BLE_SUPP_CMD_LE_ADD_PADV_LIST | \ - BLE_SUPP_CMD_LE_REMOVE_PADV_LIST | \ - BLE_SUPP_CMD_LE_CLEAR_PADV_LIST | \ - BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE | \ - BLE_SUPP_CMD_LE_RD_TX_POWER \ -) - -/* Octet 39 */ -#define BLE_SUPP_CMD_LE_RD_RF_PATH_COMP (1 << 0) -#define BLE_SUPP_CMD_LE_WR_RF_PATH_COMP (1 << 1) -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -#define BLE_SUPP_CMD_LE_SET_PRIVACY_MODE (1 << 2) -#else -#define BLE_SUPP_CMD_LE_SET_PRIVACY_MODE (0 << 2) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_39 \ -( \ - BLE_SUPP_CMD_LE_RD_RF_PATH_COMP | \ - BLE_SUPP_CMD_LE_WR_RF_PATH_COMP | \ - BLE_SUPP_CMD_LE_SET_PRIVACY_MODE \ -) - -/* Octet 40 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_VERSION) >= 51 && \ - MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) -#define BLE_SUPP_CMD_LE_PADV_RECV_ENABLE (1 << 5) -#else -#define BLE_SUPP_CMD_LE_PADV_RECV_ENABLE (0 << 5) -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER (1 << 6) -#define BLE_SUPP_CMD_LE_PADV_SET_INFO_TRANSFER (1 << 7) -#else -#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER (0 << 6) -#define BLE_SUPP_CMD_LE_PADV_SET_INFO_TRANSFER (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_40 \ -( \ - BLE_SUPP_CMD_LE_PADV_RECV_ENABLE | \ - BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER | \ - BLE_SUPP_CMD_LE_PADV_SET_INFO_TRANSFER \ -) - -/* Octet 41 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS (1 << 0) -#define BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS (1 << 1) -#else -#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS (0 << 0) -#define BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS (0 << 1) -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) -#define BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 (1 << 5) -#define BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC (1 << 6) -#define BLE_SUPP_CMD_LE_SET_CIG_PARAM (1 << 7) -#else -#define BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 (0 << 5) -#define BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC (0 << 6) -#define BLE_SUPP_CMD_LE_SET_CIG_PARAM (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_41 \ -( \ - BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS | \ - BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS | \ - BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 | \ - BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC | \ - BLE_SUPP_CMD_LE_SET_CIG_PARAM \ -) - -/* Octet 42 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) -#define BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST (1 << 0) -#define BLE_SUPP_CMD_LE_CREATE_CIS (1 << 1) -#define BLE_SUPP_CMD_LE_REMOVE_CIG (1 << 2) -#define BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ (1 << 3) -#define BLE_SUPP_CMD_LE_REJECT_CIS_REQ (1 << 4) -#define BLE_SUPP_CMD_LE_CREATE_BIG (1 << 5) -#define BLE_SUPP_CMD_LE_CREATE_BIG_TEST (1 << 6) -#define BLE_SUPP_CMD_LE_TERMINATE_BIG (1 << 7) -#else -#define BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST (0 << 0) -#define BLE_SUPP_CMD_LE_CREATE_CIS (0 << 1) -#define BLE_SUPP_CMD_LE_REMOVE_CIG (0 << 2) -#define BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ (0 << 3) -#define BLE_SUPP_CMD_LE_REJECT_CIS_REQ (0 << 4) -#define BLE_SUPP_CMD_LE_CREATE_BIG (0 << 5) -#define BLE_SUPP_CMD_LE_CREATE_BIG_TEST (0 << 6) -#define BLE_SUPP_CMD_LE_TERMINATE_BIG (0 << 7) -#endif -#define BLE_LL_SUPP_CMD_OCTET_42 \ -( \ - BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST | \ - BLE_SUPP_CMD_LE_CREATE_CIS | \ - BLE_SUPP_CMD_LE_REMOVE_CIG | \ - BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ | \ - BLE_SUPP_CMD_LE_REJECT_CIS_REQ | \ - BLE_SUPP_CMD_LE_CREATE_BIG | \ - BLE_SUPP_CMD_LE_CREATE_BIG_TEST | \ - BLE_SUPP_CMD_LE_TERMINATE_BIG \ -) - -/* Octet 43 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) -#define BLE_SUPP_CMD_LE_REQUEST_PEER_SCA (1 << 2) -#else -#define BLE_SUPP_CMD_LE_REQUEST_PEER_SCA (0 << 0) -#endif -#define BLE_LL_SUPP_CMD_OCTET_43 \ -( \ - BLE_SUPP_CMD_LE_REQUEST_PEER_SCA \ -) - -/* Octet 44 */ -#if MYNEWT_VAL(BLE_VERSION) >= 52 -#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (1 << 1) -#else -#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (0 << 1) -#endif -#define BLE_LL_SUPP_CMD_OCTET_44 \ -( \ - BLE_SUPP_CMD_LE_SET_HOST_FEATURE \ -) - -/* Octet 46 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) -#define BLE_SUPP_CMD_LE_SET_DEFAULT_SUBRATE (1 << 0) -#define BLE_SUPP_CMD_LE_SUBRATE_REQ (1 << 1) -#else -#define BLE_SUPP_CMD_LE_SET_DEFAULT_SUBRATE (0 << 0) -#define BLE_SUPP_CMD_LE_SUBRATE_REQ (0 << 1) -#endif -#define BLE_LL_SUPP_CMD_OCTET_46 \ -( \ - BLE_SUPP_CMD_LE_SET_DEFAULT_SUBRATE | \ - BLE_SUPP_CMD_LE_SUBRATE_REQ \ -) - -/* Defines the array of supported commands */ -const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN] = -{ - BLE_LL_SUPP_CMD_OCTET_0, /* Octet 0 */ - 0, - BLE_LL_SUPP_CMD_OCTET_2, /* Octet 2 */ - 0, - 0, - BLE_LL_SUPP_CMD_OCTET_5, - 0, - 0, - 0, /* Octet 8 */ - 0, - BLE_LL_SUPP_CMD_OCTET_10, - 0, - 0, - 0, - BLE_LL_SUPP_CMD_OCTET_14, - BLE_LL_SUPP_CMD_OCTET_15, - 0, /* Octet 16 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, /* Octet 24 */ - BLE_LL_SUPP_CMD_OCTET_25, - BLE_LL_SUPP_CMD_OCTET_26, - BLE_LL_SUPP_CMD_OCTET_27, - BLE_LL_SUPP_CMD_OCTET_28, - 0, - 0, - 0, - 0, /* Octet 32 */ - BLE_LL_SUPP_CMD_OCTET_33, - BLE_LL_SUPP_CMD_OCTET_34, - BLE_LL_SUPP_CMD_OCTET_35, - BLE_LL_SUPP_CMD_OCTET_36, - BLE_LL_SUPP_CMD_OCTET_37, - BLE_LL_SUPP_CMD_OCTET_38, - BLE_LL_SUPP_CMD_OCTET_39, - BLE_LL_SUPP_CMD_OCTET_40, /* Octet 40 */ - BLE_LL_SUPP_CMD_OCTET_41, - BLE_LL_SUPP_CMD_OCTET_42, - BLE_LL_SUPP_CMD_OCTET_43, - BLE_LL_SUPP_CMD_OCTET_44, - 0, - BLE_LL_SUPP_CMD_OCTET_46, -}; diff --git a/lib/bt/host/nimble/nimble/nimble/controller/test/src/ble_ll_csa2_test.h b/lib/bt/host/nimble/nimble/nimble/controller/test/src/ble_ll_csa2_test.h deleted file mode 100644 index 5bcc142b..00000000 --- a/lib/bt/host/nimble/nimble/nimble/controller/test/src/ble_ll_csa2_test.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_LL_CSA2_TEST_ -#define H_BLE_LL_CSA2_TEST_ - -#include "testutil/testutil.h" - -TEST_SUITE_DECL(ble_ll_csa2_test_suite); - -#endif diff --git a/lib/bt/host/nimble/nimble/nimble/drivers/nrf52/include/ble/xcvr.h b/lib/bt/host/nimble/nimble/nimble/drivers/nrf52/include/ble/xcvr.h deleted file mode 100644 index 757bb80f..00000000 --- a/lib/bt/host/nimble/nimble/nimble/drivers/nrf52/include/ble/xcvr.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_XCVR_ -#define H_BLE_XCVR_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define XCVR_RX_RADIO_RAMPUP_USECS (40) -#define XCVR_TX_RADIO_RAMPUP_USECS (40) - -/* - * NOTE: we have to account for the RTC output compare issue. We want it to be - * 5 ticks. - */ -#define XCVR_PROC_DELAY_USECS (153) -#define XCVR_RX_START_DELAY_USECS (XCVR_RX_RADIO_RAMPUP_USECS) -#define XCVR_TX_START_DELAY_USECS (XCVR_TX_RADIO_RAMPUP_USECS) -#define XCVR_TX_SCHED_DELAY_USECS \ - (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS) -#define XCVR_RX_SCHED_DELAY_USECS \ - (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS) - -/* - * Define HW whitelist size. This is the total possible whitelist size; - * not necessarily the size that will be used (may be smaller) - */ -#define BLE_HW_WHITE_LIST_SIZE (8) - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_XCVR_ */ diff --git a/lib/bt/host/nimble/nimble/nimble/drivers/nrf52/src/ble_hw.c b/lib/bt/host/nimble/nimble/nimble/drivers/nrf52/src/ble_hw.c deleted file mode 100644 index ef4c28b0..00000000 --- a/lib/bt/host/nimble/nimble/nimble/drivers/nrf52/src/ble_hw.c +++ /dev/null @@ -1,511 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include -#include -#include "syscfg/syscfg.h" -#include "os/os.h" -#include "ble/xcvr.h" -#include "nimble/ble.h" -#include "nimble/nimble_opt.h" -#include "nrfx.h" -#include "controller/ble_hw.h" -#if MYNEWT -#include "mcu/cmsis_nvic.h" -#else -#include "core_cm4.h" -#include -#endif -#include "os/os_trace_api.h" -#include -#include "hal/nrf_ecb.h" - -/* Total number of resolving list elements */ -#define BLE_HW_RESOLV_LIST_SIZE (16) - -/* We use this to keep track of which entries are set to valid addresses */ -static uint8_t g_ble_hw_whitelist_mask; - -/* Random number generator isr callback */ -ble_rng_isr_cb_t g_ble_rng_isr_cb; - -#if BABBLESIM -extern void tm_tick(void); -#endif - -/* If LL privacy is enabled, allocate memory for AAR */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - -/* The NRF51 supports up to 16 IRK entries */ -#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16) -#define NRF_IRK_LIST_ENTRIES (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)) -#else -#define NRF_IRK_LIST_ENTRIES (16) -#endif - -/* NOTE: each entry is 16 bytes long. */ -uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4]; - -/* Current number of IRK entries */ -uint8_t g_nrf_num_irks; - -#endif - -/* Returns public device address or -1 if not present */ -int -ble_hw_get_public_addr(ble_addr_t *addr) -{ - uint32_t addr_high; - uint32_t addr_low; - -#if MYNEWT_VAL(BLE_PHY_UBLOX_BMD345_PUBLIC_ADDR) - /* - * The BMD-345 modules are preprogrammed from the factory with a unique public - * The Bluetooth device address stored in the CUSTOMER[0] and CUSTOMER[1] - * registers of the User Information Configuration Registers (UICR). - * The Bluetooth device address consists of the IEEE Organizationally Unique - * Identifier (OUI) combined with the hexadecimal digits that are printed on - * a 2D barcode and in human-readable text on the module label.The Bluetooth - * device address is stored in little endian format. The most significant - * bytes of the CUSTOMER[1] register are 0xFF to complete the 32-bit register. - */ - - /* Copy into device address. We can do this because we know platform */ - addr_low = NRF_UICR->CUSTOMER[0]; - addr_high = NRF_UICR->CUSTOMER[1]; -#else - /* Does FICR have a public address */ - if ((NRF_FICR->DEVICEADDRTYPE & 1) != 0) { - return -1; - } - - /* Copy into device address. We can do this because we know platform */ - addr_low = NRF_FICR->DEVICEADDR[0]; - addr_high = NRF_FICR->DEVICEADDR[1]; -#endif - - memcpy(addr->val, &addr_low, 4); - memcpy(&addr->val[4], &addr_high, 2); - addr->type = BLE_ADDR_PUBLIC; - - return 0; -} - -/* Returns random static address or -1 if not present */ -int -ble_hw_get_static_addr(ble_addr_t *addr) -{ - int rc; - - if ((NRF_FICR->DEVICEADDRTYPE & 1) == 1) { - memcpy(addr->val, (void *)&NRF_FICR->DEVICEADDR[0], 4); - memcpy(&addr->val[4], (void *)&NRF_FICR->DEVICEADDR[1], 2); - addr->val[5] |= 0xc0; - addr->type = BLE_ADDR_RANDOM; - rc = 0; - } else { - rc = -1; - } - - return rc; -} - -/** - * Clear the whitelist - * - * @return int - */ -void -ble_hw_whitelist_clear(void) -{ - NRF_RADIO->DACNF = 0; - g_ble_hw_whitelist_mask = 0; -} - -/** - * Add a device to the hw whitelist - * - * @param addr - * @param addr_type - * - * @return int 0: success, BLE error code otherwise - */ -int -ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type) -{ - int i; - uint32_t mask; - - /* Find first ununsed device address match element */ - mask = 0x01; - for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) { - if ((mask & g_ble_hw_whitelist_mask) == 0) { - NRF_RADIO->DAB[i] = get_le32(addr); - NRF_RADIO->DAP[i] = get_le16(addr + 4); - if (addr_type == BLE_ADDR_RANDOM) { - NRF_RADIO->DACNF |= (mask << 8); - } - g_ble_hw_whitelist_mask |= mask; - return BLE_ERR_SUCCESS; - } - mask <<= 1; - } - - return BLE_ERR_MEM_CAPACITY; -} - -/** - * Remove a device from the hw whitelist - * - * @param addr - * @param addr_type - * - */ -void -ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type) -{ - int i; - uint8_t cfg_addr; - uint16_t dap; - uint16_t txadd; - uint32_t dab; - uint32_t mask; - - /* Find first ununsed device address match element */ - dab = get_le32(addr); - dap = get_le16(addr + 4); - txadd = NRF_RADIO->DACNF >> 8; - mask = 0x01; - for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) { - if (mask & g_ble_hw_whitelist_mask) { - if ((dab == NRF_RADIO->DAB[i]) && (dap == NRF_RADIO->DAP[i])) { - cfg_addr = txadd & mask; - if (addr_type == BLE_ADDR_RANDOM) { - if (cfg_addr != 0) { - break; - } - } else { - if (cfg_addr == 0) { - break; - } - } - } - } - mask <<= 1; - } - - if (i < BLE_HW_WHITE_LIST_SIZE) { - g_ble_hw_whitelist_mask &= ~mask; - NRF_RADIO->DACNF &= ~mask; - } -} - -/** - * Returns the size of the whitelist in HW - * - * @return int Number of devices allowed in whitelist - */ -uint8_t -ble_hw_whitelist_size(void) -{ - return BLE_HW_WHITE_LIST_SIZE; -} - -/** - * Enable the whitelisted devices - */ -void -ble_hw_whitelist_enable(void) -{ - /* Enable the configured device addresses */ - NRF_RADIO->DACNF |= g_ble_hw_whitelist_mask; -} - -/** - * Disables the whitelisted devices - */ -void -ble_hw_whitelist_disable(void) -{ - /* Disable all whitelist devices */ - NRF_RADIO->DACNF &= 0x0000ff00; -} - -/** - * Boolean function which returns true ('1') if there is a match on the - * whitelist. - * - * @return int - */ -int -ble_hw_whitelist_match(void) -{ - return (int)NRF_RADIO->EVENTS_DEVMATCH; -} - -/* Encrypt data */ -int -ble_hw_encrypt_block(struct ble_encryption_block *ecb) -{ - int rc; - uint32_t end; - uint32_t err; - - /* Stop ECB */ - nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STOPECB); - /* XXX: does task stop clear these counters? Anyway to do this quicker? */ - NRF_ECB->EVENTS_ENDECB = 0; - NRF_ECB->EVENTS_ERRORECB = 0; - NRF_ECB->ECBDATAPTR = (uint32_t)ecb; - - /* Start ECB */ - nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STARTECB); - - /* Wait till error or done */ - rc = 0; - while (1) { - end = NRF_ECB->EVENTS_ENDECB; - err = NRF_ECB->EVENTS_ERRORECB; - if (end || err) { - if (err) { - rc = -1; - } - break; - } -#if BABBLESIM - tm_tick(); -#endif - } - - return rc; -} - -/** - * Random number generator ISR. - */ -static void -ble_rng_isr(void) -{ - uint8_t rnum; - - os_trace_isr_enter(); - - /* No callback? Clear and disable interrupts */ - if (g_ble_rng_isr_cb == NULL) { - nrf_rng_int_disable(NRF_RNG, NRF_RNG_INT_VALRDY_MASK); - NRF_RNG->EVENTS_VALRDY = 0; - (void)NRF_RNG->SHORTS; - os_trace_isr_exit(); - return; - } - - /* If there is a value ready grab it */ - if (NRF_RNG->EVENTS_VALRDY) { - NRF_RNG->EVENTS_VALRDY = 0; - rnum = (uint8_t)NRF_RNG->VALUE; - (*g_ble_rng_isr_cb)(rnum); - } - - os_trace_isr_exit(); -} - -/** - * Initialize the random number generator - * - * @param cb - * @param bias - * - * @return int - */ -int -ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias) -{ - /* Set bias */ - if (bias) { - NRF_RNG->CONFIG = 1; - } else { - NRF_RNG->CONFIG = 0; - } - - /* If we were passed a function pointer we need to enable the interrupt */ - if (cb != NULL) { -#ifndef RIOT_VERSION - NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1); -#endif -#if MYNEWT - NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr); -#else - ble_npl_hw_set_isr(RNG_IRQn, ble_rng_isr); -#endif - NVIC_EnableIRQ(RNG_IRQn); - g_ble_rng_isr_cb = cb; - } - - return 0; -} - -/** - * Start the random number generator - * - * @return int - */ -int -ble_hw_rng_start(void) -{ - os_sr_t sr; - - /* No need for interrupt if there is no callback */ - OS_ENTER_CRITICAL(sr); - NRF_RNG->EVENTS_VALRDY = 0; - - if (g_ble_rng_isr_cb) { - nrf_rng_int_enable(NRF_RNG, NRF_RNG_INT_VALRDY_MASK); - } - nrf_rng_task_trigger(NRF_RNG, NRF_RNG_TASK_START); - OS_EXIT_CRITICAL(sr); - - return 0; -} - -/** - * Stop the random generator - * - * @return int - */ -int -ble_hw_rng_stop(void) -{ - os_sr_t sr; - - /* No need for interrupt if there is no callback */ - OS_ENTER_CRITICAL(sr); - nrf_rng_int_disable(NRF_RNG, NRF_RNG_INT_VALRDY_MASK); - nrf_rng_task_trigger(NRF_RNG, NRF_RNG_TASK_STOP); - NRF_RNG->EVENTS_VALRDY = 0; - OS_EXIT_CRITICAL(sr); - - return 0; -} - -/** - * Read the random number generator. - * - * @return uint8_t - */ -uint8_t -ble_hw_rng_read(void) -{ - uint8_t rnum; - - /* Wait for a sample */ - while (NRF_RNG->EVENTS_VALRDY == 0) { - } - - NRF_RNG->EVENTS_VALRDY = 0; - rnum = (uint8_t)NRF_RNG->VALUE; - - return rnum; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -/** - * Clear the resolving list - * - * @return int - */ -void -ble_hw_resolv_list_clear(void) -{ - g_nrf_num_irks = 0; -} - -/** - * Add a device to the hw resolving list - * - * @param irk Pointer to IRK to add - * - * @return int 0: success, BLE error code otherwise - */ -int -ble_hw_resolv_list_add(uint8_t *irk) -{ - uint32_t *nrf_entry; - - /* Find first ununsed device address match element */ - if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) { - return BLE_ERR_MEM_CAPACITY; - } - - /* Copy into irk list */ - nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks]; - memcpy(nrf_entry, irk, 16); - - /* Add to total */ - ++g_nrf_num_irks; - return BLE_ERR_SUCCESS; -} - -/** - * Remove a device from the hw resolving list - * - * @param index Index of IRK to remove - */ -void -ble_hw_resolv_list_rmv(int index) -{ - uint32_t *irk_entry; - - if (index < g_nrf_num_irks) { - --g_nrf_num_irks; - irk_entry = &g_nrf_irk_list[index]; - if (g_nrf_num_irks > index) { - memmove(irk_entry, irk_entry + 4, 16 * (g_nrf_num_irks - index)); - } - } -} - -/** - * Returns the size of the resolving list. NOTE: this returns the maximum - * allowable entries in the HW. Configuration options may limit this. - * - * @return int Number of devices allowed in resolving list - */ -uint8_t -ble_hw_resolv_list_size(void) -{ - return BLE_HW_RESOLV_LIST_SIZE; -} - -/** - * Called to determine if the address received was resolved. - * - * @return int Negative values indicate unresolved address; positive values - * indicate index in resolving list of resolved address. - */ -int -ble_hw_resolv_list_match(void) -{ - if (NRF_AAR->ENABLE && NRF_AAR->EVENTS_END && NRF_AAR->EVENTS_RESOLVED) { - return (int)NRF_AAR->STATUS; - } - - return -1; -} -#endif diff --git a/lib/bt/host/nimble/nimble/nimble/drivers/nrf52/src/ble_phy.c b/lib/bt/host/nimble/nimble/nimble/drivers/nrf52/src/ble_phy.c deleted file mode 100644 index dc8ba4e7..00000000 --- a/lib/bt/host/nimble/nimble/nimble/drivers/nrf52/src/ble_phy.c +++ /dev/null @@ -1,2257 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "syscfg/syscfg.h" -#include "os/os.h" -/* Keep os_cputime explicitly to enable build on non-Mynewt platforms */ -#include "os/os_cputime.h" -#include "ble/xcvr.h" -#include "nimble/ble.h" -#include "nimble/nimble_opt.h" -#include "nimble/nimble_npl.h" -#include "controller/ble_phy.h" -#include "controller/ble_phy_trace.h" -#include "controller/ble_ll.h" -#include "controller/ble_ll_plna.h" -#include "nrfx.h" -#if MYNEWT -#include "mcu/nrf52_clock.h" -#include "mcu/cmsis_nvic.h" -#include "hal/hal_gpio.h" -#else -#include "core_cm4.h" -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) -#if !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52840) && !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52811) -#error LE Coded PHY can only be enabled on nRF52811 or nRF52840 -#endif -#endif - -#if BABBLESIM -extern void tm_tick(void); -#endif - -/* - * NOTE: This code uses a couple of PPI channels so care should be taken when - * using PPI somewhere else. - * - * Pre-programmed channels: CH20, CH21, CH23, CH25, CH31 - * Regular channels: CH4, CH5 and optionally CH6, CH7, CH17, CH18, CH19 - * - CH4 = cancel wfr timer on address match - * - CH5 = disable radio on wfr timer expiry - * - CH6 = PA/LNA control (enable) - * - CH7 = PA/LNA control (disable) - * - CH17 = (optional) gpio debug for radio ramp-up - * - CH18 = (optional) gpio debug for wfr timer RX enabled - * - CH19 = (optional) gpio debug for wfr timer radio disabled - * - */ - -/* XXX: 4) Make sure RF is higher priority interrupt than schedule */ - -/* - * XXX: Maximum possible transmit time is 1 msec for a 60ppm crystal - * and 16ms for a 30ppm crystal! We need to limit PDU size based on - * crystal accuracy. Look at this in the spec. - */ - -/* XXX: private header file? */ -extern uint8_t g_nrf_num_irks; -extern uint32_t g_nrf_irk_list[]; - -/* To disable all radio interrupts */ -#define NRF_RADIO_IRQ_MASK_ALL (0x34FF) - -/* - * We configure the nrf with a 1 byte S0 field, 8 bit length field, and - * zero bit S1 field. The preamble is 8 bits long. - */ -#define NRF_LFLEN_BITS (8) -#define NRF_S0LEN (1) -#define NRF_S1LEN_BITS (0) -#define NRF_CILEN_BITS (2) -#define NRF_TERMLEN_BITS (3) - -/* Maximum length of frames */ -#define NRF_MAXLEN (255) -#define NRF_BALEN (3) /* For base address of 3 bytes */ - -/* NRF_RADIO->PCNF0 configuration values */ -#define NRF_PCNF0 (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | \ - (RADIO_PCNF0_S1INCL_Msk) | \ - (NRF_S0LEN << RADIO_PCNF0_S0LEN_Pos) | \ - (NRF_S1LEN_BITS << RADIO_PCNF0_S1LEN_Pos) -#define NRF_PCNF0_1M (NRF_PCNF0) | \ - (RADIO_PCNF0_PLEN_8bit << RADIO_PCNF0_PLEN_Pos) -#define NRF_PCNF0_2M (NRF_PCNF0) | \ - (RADIO_PCNF0_PLEN_16bit << RADIO_PCNF0_PLEN_Pos) -#define NRF_PCNF0_CODED (NRF_PCNF0) | \ - (RADIO_PCNF0_PLEN_LongRange << RADIO_PCNF0_PLEN_Pos) | \ - (NRF_CILEN_BITS << RADIO_PCNF0_CILEN_Pos) | \ - (NRF_TERMLEN_BITS << RADIO_PCNF0_TERMLEN_Pos) - -/* BLE PHY data structure */ -struct ble_phy_obj -{ - uint8_t phy_stats_initialized; - int8_t phy_txpwr_dbm; - uint8_t phy_chan; - uint8_t phy_state; - uint8_t phy_transition; - uint8_t phy_transition_late; - uint8_t phy_rx_started; - uint8_t phy_encrypted; - uint8_t phy_privacy; - uint8_t phy_tx_pyld_len; - uint8_t phy_cur_phy_mode; - uint8_t phy_tx_phy_mode; - uint8_t phy_rx_phy_mode; - uint8_t phy_bcc_offset; - int8_t rx_pwr_compensation; - uint32_t phy_aar_scratch; - uint32_t phy_access_address; - struct ble_mbuf_hdr rxhdr; - void *txend_arg; - ble_phy_tx_end_func txend_cb; - uint32_t phy_start_cputime; -}; -struct ble_phy_obj g_ble_phy_data; - -/* XXX: if 27 byte packets desired we can make this smaller */ -/* Global transmit/receive buffer */ -static uint32_t g_ble_phy_tx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; -static uint32_t g_ble_phy_rx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/* Make sure word-aligned for faster copies */ -static uint32_t g_ble_phy_enc_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; -#endif - -/* RF center frequency for each channel index (offset from 2400 MHz) */ -static const uint8_t g_ble_phy_chan_freq[BLE_PHY_NUM_CHANS] = { - 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, /* 0-9 */ - 24, 28, 30, 32, 34, 36, 38, 40, 42, 44, /* 10-19 */ - 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, /* 20-29 */ - 66, 68, 70, 72, 74, 76, 78, 2, 26, 80, /* 30-39 */ -}; - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) -/* packet start offsets (in usecs) */ -static const uint16_t g_ble_phy_mode_pkt_start_off[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 40, - [BLE_PHY_MODE_2M] = 24, - [BLE_PHY_MODE_CODED_125KBPS] = 376, - [BLE_PHY_MODE_CODED_500KBPS] = 376 -}; -#endif - -/* Various radio timings */ -/* Radio ramp-up times in usecs (fast mode) */ -#define BLE_PHY_T_TXENFAST (XCVR_TX_RADIO_RAMPUP_USECS) -#define BLE_PHY_T_RXENFAST (XCVR_RX_RADIO_RAMPUP_USECS) - -#if BABBLESIM -/* delay between EVENTS_READY and start of tx */ -static const uint8_t g_ble_phy_t_txdelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 1, - [BLE_PHY_MODE_2M] = 1, -}; -/* delay between EVENTS_END and end of txd packet */ -static const uint8_t g_ble_phy_t_txenddelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 1, - [BLE_PHY_MODE_2M] = 1, -}; -/* delay between rxd access address (w/ TERM1 for coded) and EVENTS_ADDRESS */ -static const uint8_t g_ble_phy_t_rxaddrdelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 9, - [BLE_PHY_MODE_2M] = 5, -}; -/* delay between end of rxd packet and EVENTS_END */ -static const uint8_t g_ble_phy_t_rxenddelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 9, - [BLE_PHY_MODE_2M] = 5, -}; -#else -/* delay between EVENTS_READY and start of tx */ -static const uint8_t g_ble_phy_t_txdelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 4, - [BLE_PHY_MODE_2M] = 3, - [BLE_PHY_MODE_CODED_125KBPS] = 5, - [BLE_PHY_MODE_CODED_500KBPS] = 5 -}; -/* delay between EVENTS_END and end of txd packet */ -static const uint8_t g_ble_phy_t_txenddelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 4, - [BLE_PHY_MODE_2M] = 3, - [BLE_PHY_MODE_CODED_125KBPS] = 9, - [BLE_PHY_MODE_CODED_500KBPS] = 3 -}; -/* delay between rxd access address (w/ TERM1 for coded) and EVENTS_ADDRESS */ -static const uint8_t g_ble_phy_t_rxaddrdelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 6, - [BLE_PHY_MODE_2M] = 2, - [BLE_PHY_MODE_CODED_125KBPS] = 17, - [BLE_PHY_MODE_CODED_500KBPS] = 17 -}; -/* delay between end of rxd packet and EVENTS_END */ -static const uint8_t g_ble_phy_t_rxenddelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 6, - [BLE_PHY_MODE_2M] = 2, - [BLE_PHY_MODE_CODED_125KBPS] = 27, - [BLE_PHY_MODE_CODED_500KBPS] = 22 -}; -#endif - -/* Statistics */ -STATS_SECT_START(ble_phy_stats) - STATS_SECT_ENTRY(phy_isrs) - STATS_SECT_ENTRY(tx_good) - STATS_SECT_ENTRY(tx_fail) - STATS_SECT_ENTRY(tx_late) - STATS_SECT_ENTRY(tx_bytes) - STATS_SECT_ENTRY(rx_starts) - STATS_SECT_ENTRY(rx_aborts) - STATS_SECT_ENTRY(rx_valid) - STATS_SECT_ENTRY(rx_crc_err) - STATS_SECT_ENTRY(rx_late) - STATS_SECT_ENTRY(radio_state_errs) - STATS_SECT_ENTRY(rx_hw_err) - STATS_SECT_ENTRY(tx_hw_err) -STATS_SECT_END -STATS_SECT_DECL(ble_phy_stats) ble_phy_stats; - -STATS_NAME_START(ble_phy_stats) - STATS_NAME(ble_phy_stats, phy_isrs) - STATS_NAME(ble_phy_stats, tx_good) - STATS_NAME(ble_phy_stats, tx_fail) - STATS_NAME(ble_phy_stats, tx_late) - STATS_NAME(ble_phy_stats, tx_bytes) - STATS_NAME(ble_phy_stats, rx_starts) - STATS_NAME(ble_phy_stats, rx_aborts) - STATS_NAME(ble_phy_stats, rx_valid) - STATS_NAME(ble_phy_stats, rx_crc_err) - STATS_NAME(ble_phy_stats, rx_late) - STATS_NAME(ble_phy_stats, radio_state_errs) - STATS_NAME(ble_phy_stats, rx_hw_err) - STATS_NAME(ble_phy_stats, tx_hw_err) -STATS_NAME_END(ble_phy_stats) - -/* - * NOTE: - * Tested the following to see what would happen: - * -> NVIC has radio irq enabled (interrupt # 1, mask 0x2). - * -> Set up nrf to receive. Clear ADDRESS event register. - * -> Enable ADDRESS interrupt on nrf5 by writing to INTENSET. - * -> Enable RX. - * -> Disable interrupts globally using OS_ENTER_CRITICAL(). - * -> Wait until a packet is received and the ADDRESS event occurs. - * -> Call ble_phy_disable(). - * - * At this point I wanted to see the state of the cortex NVIC. The IRQ - * pending bit was TRUE for the radio interrupt (as expected) as we never - * serviced the radio interrupt (interrupts were disabled). - * - * What was unexpected was this: without clearing the pending IRQ in the NVIC, - * when radio interrupts were re-enabled (address event bit in INTENSET set to - * 1) and the radio ADDRESS event register read 1 (it was never cleared after - * the first address event), the radio did not enter the ISR! I would have - * expected that if the following were true, an interrupt would occur: - * -> NVIC ISER bit set to TRUE - * -> NVIC ISPR bit reads TRUE, meaning interrupt is pending. - * -> Radio peripheral interrupts are enabled for some event (or events). - * -> Corresponding event register(s) in radio peripheral read 1. - * - * Not sure what the end result of all this is. We will clear the pending - * bit in the NVIC just to be sure when we disable the PHY. - */ - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - -/* - * Per nordic, the number of bytes needed for scratch is 16 + MAX_PKT_SIZE. - * However, when I used a smaller size it still overwrote the scratchpad. Until - * I figure this out I am just going to allocate 67 words so we have enough - * space for 267 bytes of scratch. I used 268 bytes since not sure if this - * needs to be aligned and burning a byte is no big deal. - */ -//#define NRF_ENC_SCRATCH_WORDS (((MYNEWT_VAL(BLE_LL_MAX_PKT_SIZE) + 16) + 3) / 4) -#define NRF_ENC_SCRATCH_WORDS (67) - -uint32_t g_nrf_encrypt_scratchpad[NRF_ENC_SCRATCH_WORDS]; - -struct nrf_ccm_data -{ - uint8_t key[16]; - uint64_t pkt_counter; - uint8_t dir_bit; - uint8_t iv[8]; -} __attribute__((packed)); - -struct nrf_ccm_data g_nrf_ccm_data; -#endif - -static int g_ble_phy_gpiote_idx; - -#if MYNEWT_VAL(BLE_LL_PA) || MYNEWT_VAL(BLE_LL_LNA) - -#define PLNA_SINGLE_GPIO \ - (!MYNEWT_VAL(BLE_LL_PA) || !MYNEWT_VAL(BLE_LL_LNA) || \ - (MYNEWT_VAL(BLE_LL_PA_GPIO) == MYNEWT_VAL(BLE_LL_LNA_GPIO))) - -#if PLNA_SINGLE_GPIO -static uint8_t plna_idx; -#else -#if MYNEWT_VAL(BLE_LL_PA) -static uint8_t plna_pa_idx; -#endif -#if MYNEWT_VAL(BLE_LL_LNA) -static uint8_t plna_lna_idx; -#endif -#endif - -#endif - -#ifndef BABBLESIM -static void -ble_phy_apply_errata_102_106_107(void) -{ - /* [102] RADIO: PAYLOAD/END events delayed or not triggered after ADDRESS - * [106] RADIO: Higher CRC error rates for some access addresses - * [107] RADIO: Immediate address match for access addresses containing MSBs 0x00 - */ - *(volatile uint32_t *)0x40001774 = ((*(volatile uint32_t *)0x40001774) & - 0xfffffffe) | 0x01000000; -} -#endif - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - -/* Packet start offset (in usecs). This is the preamble plus access address. - * For LE Coded PHY this also includes CI and TERM1. */ -uint32_t -ble_phy_mode_pdu_start_off(int phy_mode) -{ - return g_ble_phy_mode_pkt_start_off[phy_mode]; -} - -#if NRF52840_XXAA -static inline bool -ble_phy_mode_is_coded(uint8_t phy_mode) -{ - return (phy_mode == BLE_PHY_MODE_CODED_125KBPS) || - (phy_mode == BLE_PHY_MODE_CODED_500KBPS); -} - -static void -ble_phy_apply_nrf52840_errata(uint8_t new_phy_mode) -{ - bool new_coded = ble_phy_mode_is_coded(new_phy_mode); - bool cur_coded = ble_phy_mode_is_coded(g_ble_phy_data.phy_cur_phy_mode); - - /* - * Workarounds should be applied only when switching to/from LE Coded PHY - * so no need to apply them every time. - * - * nRF52840 Engineering A Errata v1.2 - * [164] RADIO: Low sensitivity in long range mode - * - * nRF52840 Rev 1 Errata - * [191] RADIO: High packet error rate in BLE Long Range mode - */ - if (new_coded == cur_coded) { - return; - } - - if (new_coded) { -#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_164) - /* [164] */ - *(volatile uint32_t *)0x4000173C |= 0x80000000; - *(volatile uint32_t *)0x4000173C = - ((*(volatile uint32_t *)0x4000173C & 0xFFFFFF00) | 0x5C); -#endif -#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_191) - /* [191] */ - *(volatile uint32_t *) 0x40001740 = - ((*((volatile uint32_t *) 0x40001740)) & 0x7FFF00FF) | - 0x80000000 | (((uint32_t)(196)) << 8); -#endif - } else { -#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_164) - /* [164] */ - *(volatile uint32_t *)0x4000173C &= ~0x80000000; -#endif -#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_191) - /* [191] */ - *(volatile uint32_t *) 0x40001740 = - ((*((volatile uint32_t *) 0x40001740)) & 0x7FFFFFFF); -#endif - } -} -#endif - -static void -ble_phy_mode_apply(uint8_t phy_mode) -{ - if (phy_mode == g_ble_phy_data.phy_cur_phy_mode) { - return; - } - -#if NRF52840_XXAA - ble_phy_apply_nrf52840_errata(phy_mode); -#endif - - switch (phy_mode) { - case BLE_PHY_MODE_1M: - NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit; - NRF_RADIO->PCNF0 = NRF_PCNF0_1M; - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - case BLE_PHY_MODE_2M: - NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_2Mbit; - NRF_RADIO->PCNF0 = NRF_PCNF0_2M; - break; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - case BLE_PHY_MODE_CODED_125KBPS: - NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_LR125Kbit; - NRF_RADIO->PCNF0 = NRF_PCNF0_CODED; - break; - case BLE_PHY_MODE_CODED_500KBPS: - NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_LR500Kbit; - NRF_RADIO->PCNF0 = NRF_PCNF0_CODED; - break; -#endif - default: - assert(0); - } - - g_ble_phy_data.phy_cur_phy_mode = phy_mode; -} - -void -ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode) -{ - g_ble_phy_data.phy_tx_phy_mode = tx_phy_mode; - g_ble_phy_data.phy_rx_phy_mode = rx_phy_mode; -} -#endif - -static void -ble_phy_plna_enable_pa(void) -{ -#if MYNEWT_VAL(BLE_LL_PA) - ble_ll_plna_pa_enable(); - -#if !PLNA_SINGLE_GPIO - NRF_PPI->CH[6].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_SET[plna_pa_idx]); - NRF_PPI->CH[7].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_CLR[plna_pa_idx]); -#endif - - NRF_PPI->CHENSET = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; -#endif -} - -static void -ble_phy_plna_enable_lna(void) -{ -#if MYNEWT_VAL(BLE_LL_LNA) - ble_ll_plna_lna_enable(); - -#if !PLNA_SINGLE_GPIO - NRF_PPI->CH[6].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_SET[plna_lna_idx]); - NRF_PPI->CH[7].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_CLR[plna_lna_idx]); -#endif - - NRF_PPI->CHENSET = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; -#endif -} - -int -ble_phy_get_cur_phy(void) -{ -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - switch (g_ble_phy_data.phy_cur_phy_mode) { - case BLE_PHY_MODE_1M: - return BLE_PHY_1M; - case BLE_PHY_MODE_2M: - return BLE_PHY_2M; - case BLE_PHY_MODE_CODED_125KBPS: - case BLE_PHY_MODE_CODED_500KBPS: - return BLE_PHY_CODED; - default: - assert(0); - return -1; - } -#else - return BLE_PHY_1M; -#endif -} - -/** - * Copies the data from the phy receive buffer into a mbuf chain. - * - * @param dptr Pointer to receive buffer - * @param rxpdu Pointer to already allocated mbuf chain - * - * NOTE: the packet header already has the total mbuf length in it. The - * lengths of the individual mbufs are not set prior to calling. - * - */ -void -ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu) -{ - uint32_t rem_len; - uint32_t copy_len; - uint32_t block_len; - uint32_t block_rem_len; - void *dst; - void *src; - struct os_mbuf * om; - - /* Better be aligned */ - assert(((uint32_t)dptr & 3) == 0); - - block_len = rxpdu->om_omp->omp_databuf_len; - rem_len = OS_MBUF_PKTHDR(rxpdu)->omp_len; - src = dptr; - - /* - * Setup for copying from first mbuf which is shorter due to packet header - * and extra leading space - */ - copy_len = block_len - rxpdu->om_pkthdr_len - 4; - om = rxpdu; - dst = om->om_data; - - while (true) { - /* - * Always copy blocks of length aligned to word size, only last mbuf - * will have remaining non-word size bytes appended. - */ - block_rem_len = copy_len; - copy_len = min(copy_len, rem_len); - copy_len &= ~3; - - dst = om->om_data; - om->om_len = copy_len; - rem_len -= copy_len; - block_rem_len -= copy_len; - -#if BABBLESIM - memcpy(dst, src, copy_len); - dst += copy_len; - src += copy_len; -#else - __asm__ volatile (".syntax unified \n" - " mov r4, %[len] \n" - " b 2f \n" - "1: ldr r3, [%[src], %[len]] \n" - " str r3, [%[dst], %[len]] \n" - "2: subs %[len], #4 \n" - " bpl 1b \n" - " adds %[src], %[src], r4 \n" - " adds %[dst], %[dst], r4 \n" - : [dst] "+r" (dst), [src] "+r" (src), - [len] "+r" (copy_len) - : - : "r3", "r4", "memory" - ); -#endif - - if ((rem_len < 4) && (block_rem_len >= rem_len)) { - break; - } - - /* Move to next mbuf */ - om = SLIST_NEXT(om, om_next); - copy_len = block_len; - } - - /* Copy remaining bytes, if any, to last mbuf */ - om->om_len += rem_len; - -#if BABBLESIM - memcpy(dst, src, rem_len); -#else - __asm__ volatile (".syntax unified \n" - " b 2f \n" - "1: ldrb r3, [%[src], %[len]] \n" - " strb r3, [%[dst], %[len]] \n" - "2: subs %[len], #1 \n" - " bpl 1b \n" - : [len] "+r" (rem_len) - : [dst] "r" (dst), [src] "r" (src) - : "r3", "memory" - ); -#endif - - /* Copy header */ - memcpy(BLE_MBUF_HDR_PTR(rxpdu), &g_ble_phy_data.rxhdr, - sizeof(struct ble_mbuf_hdr)); -} - -/** - * Called when we want to wait if the radio is in either the rx or tx - * disable states. We want to wait until that state is over before doing - * anything to the radio - */ -static void -nrf_wait_disabled(void) -{ - uint32_t state; - - state = NRF_RADIO->STATE; - if (state != RADIO_STATE_STATE_Disabled) { - if ((state == RADIO_STATE_STATE_RxDisable) || - (state == RADIO_STATE_STATE_TxDisable)) { - /* This will end within a short time (6 usecs). Just poll */ - while (NRF_RADIO->STATE == state) { - /* If this fails, something is really wrong. Should last - * no more than 6 usecs */ -#if BABBLESIM - tm_tick(); -#endif - } - } - } -} - -/** - * - * - */ -static int -ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs, bool tx) -{ - uint32_t next_cc; - uint32_t cur_cc; - uint32_t cntr; - uint32_t delta; - - /* - * We need to adjust start time to include radio ramp-up and TX pipeline - * delay (the latter only if applicable, so only for TX). - * - * Radio ramp-up time is 40 usecs and TX delay is 3 or 5 usecs depending on - * phy, thus we'll offset RTC by 2 full ticks (61 usecs) and then compensate - * using TIMER0 with 1 usec precision. - */ - - cputime -= 2; - rem_usecs += 61; - if (tx) { - rem_usecs -= BLE_PHY_T_TXENFAST; - rem_usecs -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; - } else { - rem_usecs -= BLE_PHY_T_RXENFAST; - } - - /* - * rem_usecs will be no more than 2 ticks, but if it is more than single - * tick then we should better count one more low-power tick rather than - * 30 high-power usecs. Also make sure we don't set TIMER0 CC to 0 as the - * compare won't occur. - */ - - if (rem_usecs > 30) { - cputime++; - rem_usecs -= 30; - } - - /* - * Can we set the RTC compare to start TIMER0? We can do it if: - * a) Current compare value is not N+1 or N+2 ticks from current - * counter. - * b) The value we want to set is not at least N+2 from current - * counter. - * - * NOTE: since the counter can tick 1 while we do these calculations we - * need to account for it. - */ - next_cc = cputime & 0xffffff; - cur_cc = NRF_RTC0->CC[0]; - cntr = NRF_RTC0->COUNTER; - - delta = (cur_cc - cntr) & 0xffffff; - if ((delta <= 3) && (delta != 0)) { - return -1; - } - delta = (next_cc - cntr) & 0xffffff; - if ((delta & 0x800000) || (delta < 3)) { - return -1; - } - - /* Clear and set TIMER0 to fire off at proper time */ - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CLEAR); - nrf_timer_cc_set(NRF_TIMER0, 0, rem_usecs); - NRF_TIMER0->EVENTS_COMPARE[0] = 0; - - /* Set RTC compare to start TIMER0 */ - NRF_RTC0->EVENTS_COMPARE[0] = 0; - nrf_rtc_cc_set(NRF_RTC0, 0, next_cc); - nrf_rtc_event_enable(NRF_RTC0, RTC_EVTENSET_COMPARE0_Msk); - - /* Enable PPI */ - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH31_Msk); - - /* Store the cputime at which we set the RTC */ - g_ble_phy_data.phy_start_cputime = cputime; - - return 0; -} - -static int -ble_phy_set_start_now(void) -{ - os_sr_t sr; - uint32_t now; - - OS_ENTER_CRITICAL(sr); - - /* - * Set TIMER0 to fire immediately. We can't set CC to 0 as compare will not - * occur in such case. - */ - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CLEAR); - nrf_timer_cc_set(NRF_TIMER0, 0, 1); - NRF_TIMER0->EVENTS_COMPARE[0] = 0; - - /* - * Set RTC compare to start TIMER0. We need to set it to at least N+2 ticks - * from current value to guarantee triggering compare event, but let's set - * it to N+3 to account for possible extra tick on RTC0 during these - * operations. - */ - now = os_cputime_get32(); - NRF_RTC0->EVENTS_COMPARE[0] = 0; - nrf_rtc_cc_set(NRF_RTC0, 0, now + 3); - nrf_rtc_event_enable(NRF_RTC0, RTC_EVTENSET_COMPARE0_Msk); - - /* Enable PPI */ - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH31_Msk); - /* - * Store the cputime at which we set the RTC - * - * XXX Compare event may be triggered on previous CC value (if it was set to - * less than N+2) so in rare cases actual start time may be 2 ticks earlier - * than what we expect. Since this is only used on RX, it may cause AUX scan - * to be scheduled 1 or 2 ticks too late so we'll miss it - it's acceptable - * for now. - */ - g_ble_phy_data.phy_start_cputime = now + 3; - - OS_EXIT_CRITICAL(sr); - - return 0; -} - -/** - * Function is used to set PPI so that we can time out waiting for a reception - * to occur. This happens for two reasons: we have sent a packet and we are - * waiting for a response (txrx should be set to ENABLE_TXRX) or we are - * starting a connection event and we are a slave and we are waiting for the - * master to send us a packet (txrx should be set to ENABLE_RX). - * - * NOTE: when waiting for a txrx turn-around, wfr_usecs is not used as there - * is no additional time to wait; we know when we should receive the address of - * the received frame. - * - * @param txrx Flag denoting if this wfr is a txrx turn-around or not. - * @param tx_phy_mode phy mode for last TX (only valid for TX->RX) - * @param wfr_usecs Amount of usecs to wait. - */ -void -ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) -{ - uint32_t end_time; - uint8_t phy; - - phy = g_ble_phy_data.phy_cur_phy_mode; - - if (txrx == BLE_PHY_WFR_ENABLE_TXRX) { - /* RX shall start exactly T_IFS after TX end captured in CC[2] */ - end_time = NRF_TIMER0->CC[2] + BLE_LL_IFS; - /* Adjust for delay between EVENT_END and actual TX end time */ - end_time += g_ble_phy_t_txenddelay[tx_phy_mode]; - /* Wait a bit longer due to allowed active clock accuracy */ - end_time += 2; - /* - * It's possible that we'll capture PDU start time at the end of timer - * cycle and since wfr expires at the beginning of calculated timer - * cycle it can be almost 1 usec too early. Let's compensate for this - * by waiting 1 usec more. - */ - end_time += 1; - } else { - /* - * RX shall start no later than wfr_usecs after RX enabled. - * CC[0] is the time of RXEN so adjust for radio ram-up. - * Do not add jitter since this is already covered by LL. - */ - end_time = NRF_TIMER0->CC[0] + BLE_PHY_T_RXENFAST + wfr_usecs; - } - - /* - * Note: on LE Coded EVENT_ADDRESS is fired after TERM1 is received, so - * we are actually calculating relative to start of packet payload - * which is fine. - */ - - /* Adjust for receiving access address since this triggers EVENT_ADDRESS */ - end_time += ble_phy_mode_pdu_start_off(phy); - /* Adjust for delay between actual access address RX and EVENT_ADDRESS */ - end_time += g_ble_phy_t_rxaddrdelay[phy]; - - /* wfr_secs is the time from rxen until timeout */ - nrf_timer_cc_set(NRF_TIMER0, 3, end_time); - NRF_TIMER0->EVENTS_COMPARE[3] = 0; - - /* Enable wait for response PPI */ - nrf_ppi_channels_enable(NRF_PPI, (PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk)); - - /* - * It may happen that if CPU is halted for a brief moment (e.g. during flash - * erase or write), TIMER0 already counted past CC[3] and thus wfr will not - * fire as expected. In case this happened, let's just disable PPIs for wfr - * and trigger wfr manually (i.e. disable radio). - * - * Note that the same applies to RX start time set in CC[0] but since it - * should fire earlier than wfr, fixing wfr is enough. - * - * CC[1] is only used as a reference on RX start, we do not need it here so - * it can be used to read TIMER0 counter. - */ - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE1); - if (NRF_TIMER0->CC[1] > NRF_TIMER0->CC[3]) { - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk); - nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_DISABLE); - } -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -static uint32_t -ble_phy_get_ccm_datarate(void) -{ -#if BLE_LL_BT5_PHY_SUPPORTED - switch (g_ble_phy_data.phy_cur_phy_mode) { - case BLE_PHY_MODE_1M: - return CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos; - case BLE_PHY_MODE_2M: - return CCM_MODE_DATARATE_2Mbit << CCM_MODE_DATARATE_Pos; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - case BLE_PHY_MODE_CODED_125KBPS: - return CCM_MODE_DATARATE_125Kbps << CCM_MODE_DATARATE_Pos; - case BLE_PHY_MODE_CODED_500KBPS: - return CCM_MODE_DATARATE_500Kbps << CCM_MODE_DATARATE_Pos; -#endif - } - - assert(0); - return 0; -#else - return CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos; -#endif -} -#endif - -/** - * Setup transceiver for receive. - */ -static void -ble_phy_rx_xcvr_setup(void) -{ - uint8_t *dptr; - - dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; - dptr += 3; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (g_ble_phy_data.phy_encrypted) { - NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_enc_buf[0]; - NRF_CCM->INPTR = (uint32_t)&g_ble_phy_enc_buf[0]; - NRF_CCM->OUTPTR = (uint32_t)dptr; - NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0]; - NRF_CCM->MODE = CCM_MODE_LENGTH_Msk | CCM_MODE_MODE_Decryption | - ble_phy_get_ccm_datarate(); - NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data; - NRF_CCM->SHORTS = 0; - NRF_CCM->EVENTS_ERROR = 0; - NRF_CCM->EVENTS_ENDCRYPT = 0; - nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_KSGEN); - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH25_Msk); - } else { - NRF_RADIO->PACKETPTR = (uint32_t)dptr; - } -#else - NRF_RADIO->PACKETPTR = (uint32_t)dptr; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (g_ble_phy_data.phy_privacy) { - NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Enabled; - NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; - NRF_AAR->SCRATCHPTR = (uint32_t)&g_ble_phy_data.phy_aar_scratch; - NRF_AAR->EVENTS_END = 0; - NRF_AAR->EVENTS_RESOLVED = 0; - NRF_AAR->EVENTS_NOTRESOLVED = 0; - } else { - if (g_ble_phy_data.phy_encrypted == 0) { - NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled; - } - } -#endif - - /* Turn off trigger TXEN on output compare match and AAR on bcmatch */ - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH20_Msk | PPI_CHEN_CH23_Msk); - - /* Reset the rx started flag. Used for the wait for response */ - g_ble_phy_data.phy_rx_started = 0; - g_ble_phy_data.phy_state = BLE_PHY_STATE_RX; - -#if BLE_LL_BT5_PHY_SUPPORTED - /* - * On Coded PHY there are CI and TERM1 fields before PDU starts so we need - * to take this into account when setting up BCC. - */ - if (g_ble_phy_data.phy_cur_phy_mode == BLE_PHY_MODE_CODED_125KBPS || - g_ble_phy_data.phy_cur_phy_mode == BLE_PHY_MODE_CODED_500KBPS) { - g_ble_phy_data.phy_bcc_offset = 5; - } else { - g_ble_phy_data.phy_bcc_offset = 0; - } -#else - g_ble_phy_data.phy_bcc_offset = 0; -#endif - - /* I want to know when 1st byte received (after address) */ - nrf_radio_bcc_set(NRF_RADIO, 8 + g_ble_phy_data.phy_bcc_offset); /* in bits */ - NRF_RADIO->EVENTS_ADDRESS = 0; - NRF_RADIO->EVENTS_DEVMATCH = 0; - NRF_RADIO->EVENTS_BCMATCH = 0; - NRF_RADIO->EVENTS_RSSIEND = 0; - NRF_RADIO->EVENTS_CRCOK = 0; - NRF_RADIO->SHORTS = RADIO_SHORTS_END_DISABLE_Msk | - RADIO_SHORTS_READY_START_Msk | - RADIO_SHORTS_ADDRESS_BCSTART_Msk | - RADIO_SHORTS_ADDRESS_RSSISTART_Msk | - RADIO_SHORTS_DISABLED_RSSISTOP_Msk; - - nrf_radio_int_enable(NRF_RADIO, RADIO_INTENSET_ADDRESS_Msk | - RADIO_INTENSET_DISABLED_Msk); -} - -/** - * Called from interrupt context when the transmit ends - * - */ -static void -ble_phy_tx_end_isr(void) -{ - uint8_t tx_phy_mode; - uint8_t was_encrypted; - uint8_t transition; - uint32_t rx_time; - - /* Store PHY on which we've just transmitted smth */ - tx_phy_mode = g_ble_phy_data.phy_cur_phy_mode; - - /* If this transmission was encrypted we need to remember it */ - was_encrypted = g_ble_phy_data.phy_encrypted; - (void)was_encrypted; - - /* Better be in TX state! */ - assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - /* - * XXX: not sure what to do. We had a HW error during transmission. - * For now I just count a stat but continue on like all is good. - */ - if (was_encrypted) { - if (NRF_CCM->EVENTS_ERROR) { - STATS_INC(ble_phy_stats, tx_hw_err); - NRF_CCM->EVENTS_ERROR = 0; - } - } -#endif - - /* Call transmit end callback */ - if (g_ble_phy_data.txend_cb) { - g_ble_phy_data.txend_cb(g_ble_phy_data.txend_arg); - } - - transition = g_ble_phy_data.phy_transition; - if (transition == BLE_PHY_TRANSITION_TX_RX) { - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_apply(g_ble_phy_data.phy_rx_phy_mode); -#endif - - /* Packet pointer needs to be reset. */ - ble_phy_rx_xcvr_setup(); - - ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, tx_phy_mode, 0); - - /* Schedule RX exactly T_IFS after TX end captured in CC[2] */ - rx_time = NRF_TIMER0->CC[2] + BLE_LL_IFS; - /* Adjust for delay between EVENT_END and actual TX end time */ - rx_time += g_ble_phy_t_txenddelay[tx_phy_mode]; - /* Adjust for radio ramp-up */ - rx_time -= BLE_PHY_T_RXENFAST; - /* Start listening a bit earlier due to allowed active clock accuracy */ - rx_time -= 2; - - nrf_timer_cc_set(NRF_TIMER0, 0, rx_time); - NRF_TIMER0->EVENTS_COMPARE[0] = 0; - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH21_Msk); - - ble_phy_plna_enable_lna(); - } else { - /* - * XXX: not sure we need to stop the timer here all the time. Or that - * it should be stopped here. - */ - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_STOP); - NRF_TIMER0->TASKS_SHUTDOWN = 1; - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | - PPI_CHEN_CH20_Msk | PPI_CHEN_CH31_Msk); - assert(transition == BLE_PHY_TRANSITION_NONE); - } -} - -static inline uint8_t -ble_phy_get_cur_rx_phy_mode(void) -{ - uint8_t phy; - - phy = g_ble_phy_data.phy_cur_phy_mode; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - /* - * For Coded PHY mode can be set to either codings since actual coding is - * set in packet header. However, here we need actual coding of received - * packet as this determines pipeline delays so need to figure this out - * using CI field. - */ - if ((phy == BLE_PHY_MODE_CODED_125KBPS) || - (phy == BLE_PHY_MODE_CODED_500KBPS)) { - phy = NRF_RADIO->PDUSTAT & RADIO_PDUSTAT_CISTAT_Msk ? - BLE_PHY_MODE_CODED_500KBPS : - BLE_PHY_MODE_CODED_125KBPS; - } -#endif - - return phy; -} - -static void -ble_phy_rx_end_isr(void) -{ - int rc; - uint8_t *dptr; - uint8_t crcok; - uint32_t tx_time; - struct ble_mbuf_hdr *ble_hdr; - - /* Disable automatic RXEN */ - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH21_Msk); - - /* Set RSSI and CRC status flag in header */ - ble_hdr = &g_ble_phy_data.rxhdr; - assert(NRF_RADIO->EVENTS_RSSIEND != 0); - ble_hdr->rxinfo.rssi = (-1 * NRF_RADIO->RSSISAMPLE) + - g_ble_phy_data.rx_pwr_compensation; - - dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; - dptr += 3; - - /* Count PHY crc errors and valid packets */ - crcok = NRF_RADIO->EVENTS_CRCOK; - if (!crcok) { - STATS_INC(ble_phy_stats, rx_crc_err); - } else { - STATS_INC(ble_phy_stats, rx_valid); - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (g_ble_phy_data.phy_encrypted) { - /* Only set MIC failure flag if frame is not zero length */ - if ((dptr[1] != 0) && (NRF_CCM->MICSTATUS == 0)) { - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_MIC_FAILURE; - } - - /* - * XXX: not sure how to deal with this. This should not - * be a MIC failure but we should not hand it up. I guess - * this is just some form of rx error and that is how we - * handle it? For now, just set CRC error flags - */ - if (NRF_CCM->EVENTS_ERROR) { - STATS_INC(ble_phy_stats, rx_hw_err); - ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; - } - - /* - * XXX: This is a total hack work-around for now but I dont - * know what else to do. If ENDCRYPT is not set and we are - * encrypted we need to not trust this frame and drop it. - */ - if (NRF_CCM->EVENTS_ENDCRYPT == 0) { - STATS_INC(ble_phy_stats, rx_hw_err); - ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; - } - } -#endif - } - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_apply(g_ble_phy_data.phy_tx_phy_mode); -#endif - - /* - * Let's schedule TX now and we will just cancel it after processing RXed - * packet if we don't need TX. - * - * We need this to initiate connection in case AUX_CONNECT_REQ was sent on - * LE Coded S8. In this case the time we process RXed packet is roughly the - * same as the limit when we need to have TX scheduled (i.e. TIMER0 and PPI - * armed) so we may simply miss the slot and set the timer in the past. - * - * When TX is scheduled in advance, we may event process packet a bit longer - * during radio ramp-up - this gives us extra 40 usecs which is more than - * enough. - */ - - /* Schedule TX exactly T_IFS after RX end captured in CC[2] */ - tx_time = NRF_TIMER0->CC[2] + BLE_LL_IFS; - /* Adjust for delay between actual RX end time and EVENT_END */ - tx_time -= g_ble_phy_t_rxenddelay[ble_hdr->rxinfo.phy_mode]; - /* Adjust for radio ramp-up */ - tx_time -= BLE_PHY_T_TXENFAST; - /* Adjust for delay between EVENT_READY and actual TX start time */ - tx_time -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; - - nrf_timer_cc_set(NRF_TIMER0, 0, tx_time); - NRF_TIMER0->EVENTS_COMPARE[0] = 0; - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH20_Msk); - - ble_phy_plna_enable_pa(); - - /* - * XXX: Hack warning! - * - * It may happen (during flash erase) that CPU is stopped for a moment and - * TIMER0 already counted past CC[0]. In such case we will be stuck waiting - * for TX to start since EVENTS_COMPARE[0] will not happen any time soon. - * For now let's set a flag denoting that we are late in RX-TX transition so - * ble_phy_tx() will fail - this allows everything to cleanup nicely without - * the need for extra handling in many places. - * - * Note: CC[3] is used only for wfr which we do not need here. - */ - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE3); - if (NRF_TIMER0->CC[3] > NRF_TIMER0->CC[0]) { - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH20_Msk); - g_ble_phy_data.phy_transition_late = 1; - } - - /* - * XXX: This is a horrible ugly hack to deal with the RAM S1 byte - * that is not sent over the air but is present here. Simply move the - * data pointer to deal with it. Fix this later. - */ - dptr[2] = dptr[1]; - dptr[1] = dptr[0]; - rc = ble_ll_rx_end(dptr + 1, ble_hdr); - if (rc < 0) { - ble_phy_disable(); - } -} - -static bool -ble_phy_rx_start_isr(void) -{ - int rc; - uint32_t state; - uint32_t usecs; - uint32_t pdu_usecs; - uint32_t ticks; - struct ble_mbuf_hdr *ble_hdr; - uint8_t *dptr; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - int adva_offset; -#endif - - dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; - - /* Clear events and clear interrupt */ - NRF_RADIO->EVENTS_ADDRESS = 0; - nrf_radio_int_disable(NRF_RADIO, RADIO_INTENCLR_ADDRESS_Msk); - - /* Clear wfr timer channels */ - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk); - - /* Initialize the ble mbuf header */ - ble_hdr = &g_ble_phy_data.rxhdr; - ble_hdr->rxinfo.flags = ble_ll_state_get(); - ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan; - ble_hdr->rxinfo.handle = 0; - ble_hdr->rxinfo.phy = ble_phy_get_cur_phy(); - ble_hdr->rxinfo.phy_mode = ble_phy_get_cur_rx_phy_mode(); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - ble_hdr->rxinfo.user_data = NULL; -#endif - - /* - * Calculate accurate packets start time (with remainder) - * - * We may start receiving packet somewhere during preamble in which case - * it is possible that actual transmission started before TIMER0 was - * running - need to take this into account. - */ - ble_hdr->beg_cputime = g_ble_phy_data.phy_start_cputime; - - usecs = NRF_TIMER0->CC[1]; - pdu_usecs = ble_phy_mode_pdu_start_off(ble_hdr->rxinfo.phy_mode) + - g_ble_phy_t_rxaddrdelay[ble_hdr->rxinfo.phy_mode]; - if (usecs < pdu_usecs) { - g_ble_phy_data.phy_start_cputime--; - usecs += 30; - } - usecs -= pdu_usecs; - - ticks = os_cputime_usecs_to_ticks(usecs); - usecs -= os_cputime_ticks_to_usecs(ticks); - if (usecs == 31) { - usecs = 0; - ++ticks; - } - - ble_hdr->beg_cputime += ticks; - ble_hdr->rem_usecs = usecs; - - /* XXX: I wonder if we always have the 1st byte. If we need to wait for - * rx chain delay, it could be 18 usecs from address interrupt. The - nrf52 may be able to get here early. */ - /* Wait to get 1st byte of frame */ - while (1) { - state = NRF_RADIO->STATE; - if (NRF_RADIO->EVENTS_BCMATCH != 0) { - break; - } - - /* - * If state is disabled, we should have the BCMATCH. If not, - * something is wrong! - */ - if (state == RADIO_STATE_STATE_Disabled) { - nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_IRQ_MASK_ALL); - NRF_RADIO->SHORTS = 0; - return false; - } - -#if BABBLESIM - tm_tick(); -#endif - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* - * If privacy is enabled and received PDU has TxAdd bit set (i.e. random - * address) we try to resolve address using AAR. - */ - if (g_ble_phy_data.phy_privacy && (dptr[3] & 0x40)) { - /* - * AdvA is located at 4th octet in RX buffer (after S0, length an S1 - * fields). In case of extended advertising PDU we need to add 2 more - * octets for extended header. - */ - adva_offset = (dptr[3] & 0x0f) == 0x07 ? 2 : 0; - NRF_AAR->ADDRPTR = (uint32_t)(dptr + 3 + adva_offset); - - /* Trigger AAR after last bit of AdvA is received */ - NRF_RADIO->EVENTS_BCMATCH = 0; - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH23_Msk); - nrf_radio_bcc_set(NRF_RADIO, (BLE_LL_PDU_HDR_LEN + adva_offset + - BLE_DEV_ADDR_LEN) * 8 + g_ble_phy_data.phy_bcc_offset); - } -#endif - - /* Call Link Layer receive start function */ - rc = ble_ll_rx_start(dptr + 3, - g_ble_phy_data.phy_chan, - &g_ble_phy_data.rxhdr); - if (rc >= 0) { - /* Set rx started flag and enable rx end ISR */ - g_ble_phy_data.phy_rx_started = 1; - } else { - /* Disable PHY */ - ble_phy_disable(); - STATS_INC(ble_phy_stats, rx_aborts); - } - - /* Count rx starts */ - STATS_INC(ble_phy_stats, rx_starts); - - return true; -} - -static void -ble_phy_isr(void) -{ - uint32_t irq_en; - - os_trace_isr_enter(); - - /* Read irq register to determine which interrupts are enabled */ - irq_en = NRF_RADIO->INTENSET; - - /* - * NOTE: order of checking is important! Possible, if things get delayed, - * we have both an ADDRESS and DISABLED interrupt in rx state. If we get - * an address, we disable the DISABLED interrupt. - */ - - /* We get this if we have started to receive a frame */ - if ((irq_en & RADIO_INTENCLR_ADDRESS_Msk) && NRF_RADIO->EVENTS_ADDRESS) { - /* - * wfr timer is calculated to expire at the exact time we should start - * receiving a packet (with 1 usec precision) so it is possible it will - * fire at the same time as EVENT_ADDRESS. If this happens, radio will - * be disabled while we are waiting for EVENT_BCCMATCH after 1st byte - * of payload is received and ble_phy_rx_start_isr() will fail. In this - * case we should not clear DISABLED irq mask so it will be handled as - * regular radio disabled event below. In other case radio was disabled - * on purpose and there's nothing more to handle so we can clear mask. - */ - if (ble_phy_rx_start_isr()) { - irq_en &= ~RADIO_INTENCLR_DISABLED_Msk; - } - } - - /* Handle disabled event. This is enabled for both TX and RX. On RX, we - * need to check phy_rx_started flag to make sure we actually were receiving - * a PDU, otherwise this is due to wfr. - */ - if ((irq_en & RADIO_INTENCLR_DISABLED_Msk) && NRF_RADIO->EVENTS_DISABLED) { - BLE_LL_ASSERT(NRF_RADIO->EVENTS_END || - ((g_ble_phy_data.phy_state == BLE_PHY_STATE_RX) && - !g_ble_phy_data.phy_rx_started)); - NRF_RADIO->EVENTS_END = 0; - NRF_RADIO->EVENTS_DISABLED = 0; - nrf_radio_int_disable(NRF_RADIO, RADIO_INTENCLR_DISABLED_Msk); - - switch (g_ble_phy_data.phy_state) { - case BLE_PHY_STATE_RX: -#if MYNEWT_VAL(BLE_LL_LNA) - NRF_PPI->CHENCLR = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; - ble_ll_plna_lna_disable(); -#endif - if (g_ble_phy_data.phy_rx_started) { - ble_phy_rx_end_isr(); - } else { - ble_ll_wfr_timer_exp(NULL); - } - break; - case BLE_PHY_STATE_TX: -#if MYNEWT_VAL(BLE_LL_PA) - NRF_PPI->CHENCLR = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; - ble_ll_plna_pa_disable(); -#endif - ble_phy_tx_end_isr(); - break; - default: - BLE_LL_ASSERT(0); - } - } - - g_ble_phy_data.phy_transition_late = 0; - - /* Count # of interrupts */ - STATS_INC(ble_phy_stats, phy_isrs); - - os_trace_isr_exit(); -} - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 || \ - MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 || \ - MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 || \ - MYNEWT_VAL(BLE_LL_PA) || \ - MYNEWT_VAL(BLE_LL_LNA) -static int -ble_phy_gpiote_configure(int pin) -{ - NRF_GPIO_Type *port; - - g_ble_phy_gpiote_idx--; - -#if NRF52840_XXAA - port = pin > 31 ? NRF_P1 : NRF_P0; - pin &= 0x1f; -#else - port = NRF_P0; -#endif - - /* Configure GPIO directly to avoid dependency to hal_gpio (for porting) */ - port->DIRSET = (1 << pin); - port->OUTCLR = (1 << pin); - - NRF_GPIOTE->CONFIG[g_ble_phy_gpiote_idx] = - (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | - ((pin & 0x1F) << GPIOTE_CONFIG_PSEL_Pos) | -#if NRF52840_XXAA - ((port == NRF_P1) << GPIOTE_CONFIG_PORT_Pos); -#else - 0; -#endif - - BLE_LL_ASSERT(g_ble_phy_gpiote_idx >= 0); - - return g_ble_phy_gpiote_idx; -} -#endif - -static void -ble_phy_dbg_time_setup(void) -{ - int idx __attribute__((unused)); - - /* - * We setup GPIOTE starting from last configuration index to minimize risk - * of conflict with GPIO setup via hal. It's not great solution, but since - * this is just debugging code we can live with this. - */ - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 - idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN)); - - nrf_ppi_channel_endpoint_setup(NRF_PPI, 17, (uint32_t)&(NRF_RADIO->EVENTS_READY), - (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx])); - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH17_Msk); - - /* CH[20] and PPI CH[21] are on to trigger TASKS_TXEN or TASKS_RXEN */ - nrf_ppi_fork_endpoint_setup(NRF_PPI, 20, (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx])); - nrf_ppi_fork_endpoint_setup(NRF_PPI, 21, (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx])); -#endif - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 - idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN)); - - /* CH[26] and CH[27] are always on for EVENT_ADDRESS and EVENT_END */ - nrf_ppi_fork_endpoint_setup(NRF_PPI, 26, (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx])); - nrf_ppi_fork_endpoint_setup(NRF_PPI, 27, (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx])); -#endif - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 - idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN)); - -#if NRF52840_XXAA - nrf_ppi_channel_endpoint_setup(NRF_PPI, 18, (uint32_t)&(NRF_RADIO->EVENTS_RXREADY), - (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx])); -#else - nrf_ppi_channel_endpoint_setup(NRF_PPI, 18, (uint32_t)&(NRF_RADIO->EVENTS_READY), - (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx])); -#endif - nrf_ppi_channel_endpoint_setup(NRF_PPI, 19, (uint32_t)&(NRF_RADIO->EVENTS_DISABLED), - (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx])); - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH18_Msk | PPI_CHEN_CH19_Msk); - - /* CH[4] and CH[5] are always on for wfr */ - nrf_ppi_fork_endpoint_setup(NRF_PPI, 4, (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx])); - nrf_ppi_fork_endpoint_setup(NRF_PPI, 5, (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx])); -#endif -} - -/** - * ble phy init - * - * Initialize the PHY. - * - * @return int 0: success; PHY error code otherwise - */ -int -ble_phy_init(void) -{ - int rc; - - g_ble_phy_gpiote_idx = 8; - - /* Default phy to use is 1M */ - g_ble_phy_data.phy_cur_phy_mode = BLE_PHY_MODE_1M; - g_ble_phy_data.phy_tx_phy_mode = BLE_PHY_MODE_1M; - g_ble_phy_data.phy_rx_phy_mode = BLE_PHY_MODE_1M; - - g_ble_phy_data.rx_pwr_compensation = 0; - - /* Set phy channel to an invalid channel so first set channel works */ - g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS; - - /* Toggle peripheral power to reset (just in case) */ - nrf_radio_power_set(NRF_RADIO, false); - nrf_radio_power_set(NRF_RADIO, true); - - /* Disable all interrupts */ - nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_IRQ_MASK_ALL); - - /* Set configuration registers */ - NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit; - NRF_RADIO->PCNF0 = NRF_PCNF0; - - /* XXX: should maxlen be 251 for encryption? */ - NRF_RADIO->PCNF1 = NRF_MAXLEN | - (RADIO_PCNF1_ENDIAN_Little << RADIO_PCNF1_ENDIAN_Pos) | - (NRF_BALEN << RADIO_PCNF1_BALEN_Pos) | - RADIO_PCNF1_WHITEEN_Msk; - - /* Enable radio fast ramp-up */ - NRF_RADIO->MODECNF0 |= (RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos) & - RADIO_MODECNF0_RU_Msk; - - /* Set logical address 1 for TX and RX */ - NRF_RADIO->TXADDRESS = 0; - NRF_RADIO->RXADDRESSES = (1 << 0); - - /* Configure the CRC registers */ - NRF_RADIO->CRCCNF = (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos) | RADIO_CRCCNF_LEN_Three; - - /* Configure BLE poly */ - NRF_RADIO->CRCPOLY = 0x0000065B; - - /* Configure IFS */ - NRF_RADIO->TIFS = BLE_LL_IFS; - - /* Captures tx/rx start in timer0 cc 1 and tx/rx end in timer0 cc 2 */ - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH26_Msk | PPI_CHEN_CH27_Msk); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - nrf_ccm_int_disable(NRF_CCM, 0xffffffff); - NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; - NRF_CCM->EVENTS_ERROR = 0; - memset(g_nrf_encrypt_scratchpad, 0, sizeof(g_nrf_encrypt_scratchpad)); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - g_ble_phy_data.phy_aar_scratch = 0; - NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; - nrf_aar_int_disable(NRF_AAR, 0xffffffff); - NRF_AAR->EVENTS_END = 0; - NRF_AAR->EVENTS_RESOLVED = 0; - NRF_AAR->EVENTS_NOTRESOLVED = 0; - NRF_AAR->NIRK = 0; -#endif - - /* TIMER0 setup for PHY when using RTC */ - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_STOP); - NRF_TIMER0->TASKS_SHUTDOWN = 1; - NRF_TIMER0->BITMODE = 3; /* 32-bit timer */ - NRF_TIMER0->MODE = 0; /* Timer mode */ - NRF_TIMER0->PRESCALER = 4; /* gives us 1 MHz */ - - /* - * PPI setup. - * Channel 4: Captures TIMER0 in CC[3] when EVENTS_ADDRESS occurs. Used - * to cancel the wait for response timer. - * Channel 5: TIMER0 CC[3] to TASKS_DISABLE on radio. This is the wait - * for response timer. - */ - nrf_ppi_channel_endpoint_setup(NRF_PPI, NRF_PPI_CHANNEL4, - (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS), - (uint32_t)&(NRF_TIMER0->TASKS_CAPTURE[3])); - nrf_ppi_channel_endpoint_setup(NRF_PPI, NRF_PPI_CHANNEL5, - (uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]), - (uint32_t)&(NRF_RADIO->TASKS_DISABLE)); - -#if MYNEWT_VAL(BLE_LL_PA) || MYNEWT_VAL(BLE_LL_LNA) -#if PLNA_SINGLE_GPIO - plna_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_PA_GPIO)); - NRF_PPI->CH[6].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_SET[plna_idx]); - NRF_PPI->CH[7].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_CLR[plna_idx]); -#else -#if MYNEWT_VAL(BLE_LL_PA) - plna_pa_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_PA_GPIO)); - NRF_GPIOTE->TASKS_CLR[plna_pa_idx] = 1; -#endif -#if MYNEWT_VAL(BLE_LL_LNA) - plna_lna_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_LNA_GPIO)); - NRF_GPIOTE->TASKS_CLR[plna_lna_idx] = 1; -#endif -#endif - - NRF_PPI->CH[6].EEP = (uint32_t)&(NRF_RADIO->EVENTS_READY); - NRF_PPI->CH[7].EEP = (uint32_t)&(NRF_RADIO->EVENTS_DISABLED); - NRF_PPI->CHENCLR = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; -#endif - - /* Set isr in vector table and enable interrupt */ -#ifndef RIOT_VERSION - NVIC_SetPriority(RADIO_IRQn, 0); -#endif -#if MYNEWT - NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr); -#else - ble_npl_hw_set_isr(RADIO_IRQn, ble_phy_isr); -#endif - NVIC_EnableIRQ(RADIO_IRQn); - - /* Register phy statistics */ - if (!g_ble_phy_data.phy_stats_initialized) { - rc = stats_init_and_reg(STATS_HDR(ble_phy_stats), - STATS_SIZE_INIT_PARMS(ble_phy_stats, - STATS_SIZE_32), - STATS_NAME_INIT_PARMS(ble_phy_stats), - "ble_phy"); - assert(rc == 0); - - g_ble_phy_data.phy_stats_initialized = 1; - } - - ble_phy_dbg_time_setup(); - - return 0; -} - -/** - * Puts the phy into receive mode. - * - * @return int 0: success; BLE Phy error code otherwise - */ -int -ble_phy_rx(void) -{ - /* - * Check radio state. - * - * In case radio is now disabling we'll wait for it to finish, but if for - * any reason it's just in idle state we proceed with RX as usual since - * nRF52 radio can ramp-up from idle state as well. - * - * Note that TX and RX states values are the same except for 3rd bit so we - * can make a shortcut here when checking for idle state. - */ - nrf_wait_disabled(); - if ((NRF_RADIO->STATE != RADIO_STATE_STATE_Disabled) && - ((NRF_RADIO->STATE & 0x07) != RADIO_STATE_STATE_RxIdle)) { - ble_phy_disable(); - STATS_INC(ble_phy_stats, radio_state_errs); - return BLE_PHY_ERR_RADIO_STATE; - } - - /* Make sure all interrupts are disabled */ - nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_IRQ_MASK_ALL); - - /* Clear events prior to enabling receive */ - NRF_RADIO->EVENTS_END = 0; - NRF_RADIO->EVENTS_DISABLED = 0; - - /* Setup for rx */ - ble_phy_rx_xcvr_setup(); - - /* PPI to start radio automatically shall be set here */ - assert(NRF_PPI->CHEN & PPI_CHEN_CH21_Msk); - - return 0; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/** - * Called to enable encryption at the PHY. Note that this state will persist - * in the PHY; in other words, if you call this function you have to call - * disable so that future PHY transmits/receives will not be encrypted. - * - * @param pkt_counter - * @param iv - * @param key - * @param is_master - */ -void -ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, - uint8_t is_master) -{ - memcpy(g_nrf_ccm_data.key, key, 16); - g_nrf_ccm_data.pkt_counter = pkt_counter; - memcpy(g_nrf_ccm_data.iv, iv, 8); - g_nrf_ccm_data.dir_bit = is_master; - g_ble_phy_data.phy_encrypted = 1; - /* Enable the module (AAR cannot be on while CCM on) */ - NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled; - NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled; -} - -void -ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir) -{ - g_nrf_ccm_data.pkt_counter = pkt_counter; - g_nrf_ccm_data.dir_bit = dir; -} - -void -ble_phy_encrypt_disable(void) -{ - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH25_Msk); - nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_STOP); - NRF_CCM->EVENTS_ERROR = 0; - NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled; - - g_ble_phy_data.phy_encrypted = 0; -} -#endif - -void -ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg) -{ - /* Set transmit end callback and arg */ - g_ble_phy_data.txend_cb = txend_cb; - g_ble_phy_data.txend_arg = arg; -} - -/** - * Called to set the start time of a transmission. - * - * This function is called to set the start time when we are not going from - * rx to tx automatically. - * - * NOTE: care must be taken when calling this function. The channel should - * already be set. - * - * @param cputime This is the tick at which the 1st bit of the preamble - * should be transmitted - * @param rem_usecs This is used only when the underlying timing uses a 32.768 - * kHz crystal. It is the # of usecs from the cputime tick - * at which the first bit of the preamble should be - * transmitted. - * @return int - */ -int -ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs) -{ - int rc; - - ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_TX, cputime, rem_usecs); - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_apply(g_ble_phy_data.phy_tx_phy_mode); -#endif - - /* XXX: This should not be necessary, but paranoia is good! */ - /* Clear timer0 compare to RXEN since we are transmitting */ - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH21_Msk); - - if (ble_phy_set_start_time(cputime, rem_usecs, true) != 0) { - STATS_INC(ble_phy_stats, tx_late); - ble_phy_disable(); - rc = BLE_PHY_ERR_TX_LATE; - } else { - /* Enable PPI to automatically start TXEN */ - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH20_Msk); - rc = 0; - - ble_phy_plna_enable_pa(); - } - - return rc; -} - -/** - * Called to set the start time of a reception - * - * This function acts a bit differently than transmit. If we are late getting - * here we will still attempt to receive. - * - * NOTE: care must be taken when calling this function. The channel should - * already be set. - * - * @param cputime - * - * @return int - */ -int -ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs) -{ - bool late = false; - int rc = 0; - - ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_RX, cputime, rem_usecs); - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_apply(g_ble_phy_data.phy_rx_phy_mode); -#endif - - /* XXX: This should not be necessary, but paranoia is good! */ - /* Clear timer0 compare to TXEN since we are transmitting */ - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH20_Msk); - - if (ble_phy_set_start_time(cputime, rem_usecs, false) != 0) { - STATS_INC(ble_phy_stats, rx_late); - - /* We're late so let's just try to start RX as soon as possible */ - ble_phy_set_start_now(); - - late = true; - } - - /* Enable PPI to automatically start RXEN */ - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH21_Msk); - - ble_phy_plna_enable_lna(); - - /* Start rx */ - rc = ble_phy_rx(); - - /* - * If we enabled receiver but were late, let's return proper error code so - * caller can handle this. - */ - if (!rc && late) { - rc = BLE_PHY_ERR_RX_LATE; - } - - return rc; -} - -int -ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans) -{ - int rc; - uint8_t *dptr; - uint8_t *pktptr; - uint8_t payload_len; - uint8_t hdr_byte; - uint32_t state; - uint32_t shortcuts; - - if (g_ble_phy_data.phy_transition_late) { - ble_phy_disable(); - STATS_INC(ble_phy_stats, tx_late); - return BLE_PHY_ERR_TX_LATE; - } - - /* - * This check is to make sure that the radio is not in a state where - * it is moving to disabled state. If so, let it get there. - */ - nrf_wait_disabled(); - - /* - * XXX: Although we may not have to do this here, I clear all the PPI - * that should not be used when transmitting. Some of them are only enabled - * if encryption and/or privacy is on, but I dont care. Better to be - * paranoid, and if you are going to clear one, might as well clear them - * all. - */ - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | - PPI_CHEN_CH23_Msk | PPI_CHEN_CH25_Msk); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (g_ble_phy_data.phy_encrypted) { - dptr = (uint8_t *)&g_ble_phy_enc_buf[0]; - pktptr = (uint8_t *)&g_ble_phy_tx_buf[0]; - NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; - NRF_CCM->INPTR = (uint32_t)dptr; - NRF_CCM->OUTPTR = (uint32_t)pktptr; - NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0]; - NRF_CCM->EVENTS_ERROR = 0; - NRF_CCM->MODE = CCM_MODE_LENGTH_Msk | ble_phy_get_ccm_datarate(); - NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data; - } else { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; -#endif - dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; - pktptr = dptr; - } -#else - dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; - pktptr = dptr; -#endif - - /* Set PDU payload */ - payload_len = pducb(&dptr[3], pducb_arg, &hdr_byte); - - /* RAM representation has S0, LENGTH and S1 fields. (3 bytes) */ - dptr[0] = hdr_byte; - dptr[1] = payload_len; - dptr[2] = 0; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - /* Start key-stream generation and encryption (via short) */ - if (g_ble_phy_data.phy_encrypted) { - nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_KSGEN); - } -#endif - - NRF_RADIO->PACKETPTR = (uint32_t)pktptr; - - /* Clear the ready, end and disabled events */ - NRF_RADIO->EVENTS_READY = 0; - NRF_RADIO->EVENTS_END = 0; - NRF_RADIO->EVENTS_DISABLED = 0; - - /* Enable shortcuts for transmit start/end. */ - shortcuts = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk; - NRF_RADIO->SHORTS = shortcuts; - nrf_radio_int_enable(NRF_RADIO, RADIO_INTENSET_DISABLED_Msk); - - /* Set the PHY transition */ - g_ble_phy_data.phy_transition = end_trans; - - /* Set transmitted payload length */ - g_ble_phy_data.phy_tx_pyld_len = payload_len; - - /* If we already started transmitting, abort it! */ - state = NRF_RADIO->STATE; - if (state != RADIO_STATE_STATE_Tx) { - /* Set phy state to transmitting and count packet statistics */ - g_ble_phy_data.phy_state = BLE_PHY_STATE_TX; - STATS_INC(ble_phy_stats, tx_good); - STATS_INCN(ble_phy_stats, tx_bytes, payload_len + BLE_LL_PDU_HDR_LEN); - rc = BLE_ERR_SUCCESS; - } else { - ble_phy_disable(); - STATS_INC(ble_phy_stats, tx_late); - rc = BLE_PHY_ERR_RADIO_STATE; - } - - return rc; -} - -/** - * ble phy txpwr set - * - * Set the transmit output power (in dBm). - * - * NOTE: If the output power specified is within the BLE limits but outside - * the chip limits, we "rail" the power level so we dont exceed the min/max - * chip values. - * - * @param dbm Power output in dBm. - * - * @return int 0: success; anything else is an error - */ -int -ble_phy_txpwr_set(int dbm) -{ - /* "Rail" power level if outside supported range */ - dbm = ble_phy_txpower_round(dbm); - - NRF_RADIO->TXPOWER = dbm; - g_ble_phy_data.phy_txpwr_dbm = dbm; - - return 0; -} - -/** - * ble phy txpwr round - * - * Get the rounded transmit output power (in dBm). - * - * @param dbm Power output in dBm. - * - * @return int Rounded power in dBm - */ -int ble_phy_txpower_round(int dbm) -{ - /* TODO this should be per nRF52XXX */ - - /* "Rail" power level if outside supported range */ - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_0dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm; - } - - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm; -} - -/** - * ble phy set access addr - * - * Set access address. - * - * @param access_addr Access address - * - * @return int 0: success; PHY error code otherwise - */ -static int -ble_phy_set_access_addr(uint32_t access_addr) -{ - NRF_RADIO->BASE0 = (access_addr << 8); - NRF_RADIO->PREFIX0 = (NRF_RADIO->PREFIX0 & 0xFFFFFF00) | (access_addr >> 24); - - g_ble_phy_data.phy_access_address = access_addr; - -#ifndef BABBLESIM - ble_phy_apply_errata_102_106_107(); -#endif - return 0; -} - -/** - * ble phy txpwr get - * - * Get the transmit power. - * - * @return int The current PHY transmit power, in dBm - */ -int -ble_phy_txpwr_get(void) -{ - return g_ble_phy_data.phy_txpwr_dbm; -} - -void -ble_phy_set_rx_pwr_compensation(int8_t compensation) -{ - g_ble_phy_data.rx_pwr_compensation = compensation; -} - -/** - * ble phy setchan - * - * Sets the logical frequency of the transceiver. The input parameter is the - * BLE channel index (0 to 39, inclusive). The NRF frequency register works like - * this: logical frequency = 2400 + FREQ (MHz). - * - * Thus, to get a logical frequency of 2402 MHz, you would program the - * FREQUENCY register to 2. - * - * @param chan This is the Data Channel Index or Advertising Channel index - * - * @return int 0: success; PHY error code otherwise - */ -int -ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit) -{ - assert(chan < BLE_PHY_NUM_CHANS); - - /* Check for valid channel range */ - if (chan >= BLE_PHY_NUM_CHANS) { - return BLE_PHY_ERR_INV_PARAM; - } - - /* Set current access address */ - ble_phy_set_access_addr(access_addr); - - /* Configure crcinit */ - NRF_RADIO->CRCINIT = crcinit; - - /* Set the frequency and the data whitening initial value */ - g_ble_phy_data.phy_chan = chan; - NRF_RADIO->FREQUENCY = g_ble_phy_chan_freq[chan]; - NRF_RADIO->DATAWHITEIV = chan; - - return 0; -} - -/** - * Stop the timer used to count microseconds when using RTC for cputime - */ -static void -ble_phy_stop_usec_timer(void) -{ - nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_STOP); - NRF_TIMER0->TASKS_SHUTDOWN = 1; - nrf_rtc_event_disable(NRF_RTC0, RTC_EVTENSET_COMPARE0_Msk); -} - -/** - * ble phy disable irq and ppi - * - * This routine is to be called when reception was stopped due to either a - * wait for response timeout or a packet being received and the phy is to be - * restarted in receive mode. Generally, the disable routine is called to stop - * the phy. - */ -static void -ble_phy_disable_irq_and_ppi(void) -{ - nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_IRQ_MASK_ALL); - NRF_RADIO->SHORTS = 0; - nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_DISABLE); - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | - PPI_CHEN_CH20_Msk | PPI_CHEN_CH21_Msk | PPI_CHEN_CH23_Msk | - PPI_CHEN_CH25_Msk | PPI_CHEN_CH31_Msk); - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk); - NVIC_ClearPendingIRQ(RADIO_IRQn); - g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE; -} - -void -ble_phy_restart_rx(void) -{ - ble_phy_stop_usec_timer(); - ble_phy_disable_irq_and_ppi(); - - ble_phy_set_start_now(); - /* Enable PPI to automatically start RXEN */ - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH21_Msk); - - ble_phy_rx(); -} - -/** - * ble phy disable - * - * Disables the PHY. This should be called when an event is over. It stops - * the usec timer (if used), disables interrupts, disables the RADIO, disables - * PPI and sets state to idle. - */ -void -ble_phy_disable(void) -{ - ble_phy_trace_void(BLE_PHY_TRACE_ID_DISABLE); - - ble_phy_stop_usec_timer(); - ble_phy_disable_irq_and_ppi(); -} - -/* Gets the current access address */ -uint32_t ble_phy_access_addr_get(void) -{ - return g_ble_phy_data.phy_access_address; -} - -/** - * Return the phy state - * - * @return int The current PHY state. - */ -int -ble_phy_state_get(void) -{ - return g_ble_phy_data.phy_state; -} - -/** - * Called to see if a reception has started - * - * @return int - */ -int -ble_phy_rx_started(void) -{ - return g_ble_phy_data.phy_rx_started; -} - -/** - * Return the transceiver state - * - * @return int transceiver state. - */ -uint8_t -ble_phy_xcvr_state_get(void) -{ - uint32_t state; - state = NRF_RADIO->STATE; - return (uint8_t)state; -} - -/** - * Called to return the maximum data pdu payload length supported by the - * phy. For this chip, if encryption is enabled, the maximum payload is 27 - * bytes. - * - * @return uint8_t Maximum data channel PDU payload size supported - */ -uint8_t -ble_phy_max_data_pdu_pyld(void) -{ - return BLE_LL_DATA_PDU_MAX_PYLD; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -void -ble_phy_resolv_list_enable(void) -{ - NRF_AAR->NIRK = (uint32_t)g_nrf_num_irks; - g_ble_phy_data.phy_privacy = 1; -} - -void -ble_phy_resolv_list_disable(void) -{ - g_ble_phy_data.phy_privacy = 0; -} -#endif - -#if MYNEWT_VAL(BLE_LL_DTM) -void ble_phy_enable_dtm(void) -{ - /* When DTM is enabled we need to disable whitening as per - * Bluetooth v5.0 Vol 6. Part F. 4.1.1 - */ - NRF_RADIO->PCNF1 &= ~RADIO_PCNF1_WHITEEN_Msk; -} - -void ble_phy_disable_dtm(void) -{ - /* Enable whitening */ - NRF_RADIO->PCNF1 |= RADIO_PCNF1_WHITEEN_Msk; -} -#endif - -void -ble_phy_rfclk_enable(void) -{ -#if MYNEWT - nrf52_clock_hfxo_request(); -#else - nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTART); -#endif -} - -void -ble_phy_rfclk_disable(void) -{ -#if MYNEWT - nrf52_clock_hfxo_release(); -#else - nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTOP); -#endif -} diff --git a/lib/bt/host/nimble/nimble/nimble/drivers/nrf52/src/ble_phy_trace.c b/lib/bt/host/nimble/nimble/nimble/drivers/nrf52/src/ble_phy_trace.c deleted file mode 100644 index 93b2eb32..00000000 --- a/lib/bt/host/nimble/nimble/nimble/drivers/nrf52/src/ble_phy_trace.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include "syscfg/syscfg.h" -#include "os/os_trace_api.h" - -#if MYNEWT_VAL(BLE_PHY_SYSVIEW) - -static os_trace_module_t g_ble_phy_trace_mod; -uint32_t ble_phy_trace_off; - -static void -ble_phy_trace_module_send_desc(void) -{ - os_trace_module_desc(&g_ble_phy_trace_mod, "0 phy_set_tx cputime=%u usecs=%u"); - os_trace_module_desc(&g_ble_phy_trace_mod, "1 phy_set_rx cputime=%u usecs=%u"); - os_trace_module_desc(&g_ble_phy_trace_mod, "2 phy_disable"); -} - -void -ble_phy_trace_init(void) -{ - ble_phy_trace_off = - os_trace_module_register(&g_ble_phy_trace_mod, "ble_phy", 3, - ble_phy_trace_module_send_desc); -} -#endif diff --git a/lib/bt/host/nimble/nimble/nimble/drivers/nrf52/syscfg.yml b/lib/bt/host/nimble/nimble/nimble/drivers/nrf52/syscfg.yml deleted file mode 100644 index 3bd49708..00000000 --- a/lib/bt/host/nimble/nimble/nimble/drivers/nrf52/syscfg.yml +++ /dev/null @@ -1,72 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - BLE_PHY_SYSVIEW: - description: > - Enable SystemView tracing module for radio driver. - value: 0 - - BLE_PHY_DBG_TIME_TXRXEN_READY_PIN: - description: > - When set to proper GPIO pin number, this pin will be set - to high state when radio is enabled using PPI channels - 20 or 21 and back to low state on radio EVENTS_READY. - This can be used to measure radio ram-up time. - value: -1 - - BLE_PHY_DBG_TIME_ADDRESS_END_PIN: - description: > - When set to proper GPIO pin number, this pin will be set - to high state on radio EVENTS_ADDRESS and back to low state - on radio EVENTS_END. - This can be used to measure radio pipeline delays. - value: -1 - - BLE_PHY_DBG_TIME_WFR_PIN: - description: > - When set to proper GPIO pin number, this pin will be set - to high state on radio EVENTS_RXREADY and back to low - state when wfr timer expires. - This can be used to check if wfr is calculated properly. - value: -1 - - BLE_PHY_NRF52840_ERRATA_164: - description: > - Enable workaround for anomaly 164 found in nRF52840. - "[164] RADIO: Low selectivity in long range mode" - This shall be only enabled for: - - nRF52840 Engineering A - value: 0 - - BLE_PHY_NRF52840_ERRATA_191: - description: > - Enable workaround for anomaly 191 found in nRF52840. - "[191] RADIO: High packet error rate in BLE Long Range mode" - This shall be only enabled for: - - nRF52840 Engineering B - - nRF52840 Engineering C - - nRF52840 Rev 1 (final silicon) - value: 1 - - BLE_PHY_UBLOX_BMD345_PUBLIC_ADDR: - description: > - Ublox BMD-345 modules come with public address preprogrammed - in UICR register. If enabled public address will be read from - custom UICR instead of FICR register. - value: 0 diff --git a/lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/include/ble/xcvr.h b/lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/include/ble/xcvr.h deleted file mode 100644 index df6ef700..00000000 --- a/lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/include/ble/xcvr.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_XCVR_ -#define H_BLE_XCVR_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define XCVR_RX_RADIO_RAMPUP_USECS (40) -#define XCVR_TX_RADIO_RAMPUP_USECS (40) - -/* - * NOTE: we have to account for the RTC output compare issue. We want it to be - * 5 ticks. - */ -#define XCVR_PROC_DELAY_USECS (153) -#define XCVR_RX_START_DELAY_USECS (XCVR_RX_RADIO_RAMPUP_USECS) -#define XCVR_TX_START_DELAY_USECS (XCVR_TX_RADIO_RAMPUP_USECS) -#define XCVR_TX_SCHED_DELAY_USECS (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS) -#define XCVR_RX_SCHED_DELAY_USECS (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS) - -/* - * Define HW whitelist size. This is the total possible whitelist size; - * not necessarily the size that will be used (may be smaller) - */ -#define BLE_HW_WHITE_LIST_SIZE (8) - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_XCVR_ */ diff --git a/lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/src/ble_hw.c b/lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/src/ble_hw.c deleted file mode 100644 index 92bf0249..00000000 --- a/lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/src/ble_hw.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* Total number of resolving list elements */ -#define BLE_HW_RESOLV_LIST_SIZE (16) - -/* We use this to keep track of which entries are set to valid addresses */ -static uint8_t g_ble_hw_whitelist_mask; - -/* Random number generator isr callback */ -static ble_rng_isr_cb_t ble_rng_isr_cb; - -/* If LL privacy is enabled, allocate memory for AAR */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - -/* The NRF5340 supports up to 16 IRK entries */ -#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16) -#define NRF_IRK_LIST_ENTRIES (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)) -#else -#define NRF_IRK_LIST_ENTRIES (16) -#endif - -/* NOTE: each entry is 16 bytes long. */ -uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4]; - -/* Current number of IRK entries */ -uint8_t g_nrf_num_irks; - -#endif - -/* Returns public device address or -1 if not present */ -int -ble_hw_get_public_addr(ble_addr_t *addr) -{ - uint32_t addr_high; - uint32_t addr_low; - - /* Does FICR have a public address */ - if ((NRF_FICR_NS->DEVICEADDRTYPE & 1) != 0) { - return -1; - } - - /* Copy into device address. We can do this because we know platform */ - addr_low = NRF_FICR_NS->DEVICEADDR[0]; - addr_high = NRF_FICR_NS->DEVICEADDR[1]; - memcpy(addr->val, &addr_low, 4); - memcpy(&addr->val[4], &addr_high, 2); - addr->type = BLE_ADDR_PUBLIC; - - return 0; -} - -/* Returns random static address or -1 if not present */ -int -ble_hw_get_static_addr(ble_addr_t *addr) -{ - int rc; - - if ((NRF_FICR_NS->DEVICEADDRTYPE & 1) == 1) { - memcpy(addr->val, (void *)&NRF_FICR_NS->DEVICEADDR[0], 4); - memcpy(&addr->val[4], (void *)&NRF_FICR_NS->DEVICEADDR[1], 2); - addr->val[5] |= 0xc0; - addr->type = BLE_ADDR_RANDOM; - rc = 0; - } else { - rc = -1; - } - - return rc; -} - -/** - * Clear the whitelist - * - * @return int - */ -void -ble_hw_whitelist_clear(void) -{ - NRF_RADIO_NS->DACNF = 0; - g_ble_hw_whitelist_mask = 0; -} - -/** - * Add a device to the hw whitelist - * - * @param addr - * @param addr_type - * - * @return int 0: success, BLE error code otherwise - */ -int -ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type) -{ - int i; - uint32_t mask; - - /* Find first ununsed device address match element */ - mask = 0x01; - for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) { - if ((mask & g_ble_hw_whitelist_mask) == 0) { - NRF_RADIO_NS->DAB[i] = get_le32(addr); - NRF_RADIO_NS->DAP[i] = get_le16(addr + 4); - if (addr_type == BLE_ADDR_RANDOM) { - NRF_RADIO_NS->DACNF |= (mask << 8); - } - g_ble_hw_whitelist_mask |= mask; - return BLE_ERR_SUCCESS; - } - mask <<= 1; - } - - return BLE_ERR_MEM_CAPACITY; -} - -/** - * Remove a device from the hw whitelist - * - * @param addr - * @param addr_type - * - */ -void -ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type) -{ - int i; - uint16_t dap; - uint16_t txadd; - uint32_t dab; - uint32_t mask; - - /* Find first ununsed device address match element */ - dab = get_le32(addr); - dap = get_le16(addr + 4); - txadd = NRF_RADIO_NS->DACNF >> 8; - mask = 0x01; - for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) { - if (mask & g_ble_hw_whitelist_mask) { - if ((dab == NRF_RADIO_NS->DAB[i]) && (dap == NRF_RADIO_NS->DAP[i])) { - if (addr_type == !!(txadd & mask)) { - break; - } - } - } - mask <<= 1; - } - - if (i < BLE_HW_WHITE_LIST_SIZE) { - g_ble_hw_whitelist_mask &= ~mask; - NRF_RADIO_NS->DACNF &= ~mask; - } -} - -/** - * Returns the size of the whitelist in HW - * - * @return int Number of devices allowed in whitelist - */ -uint8_t -ble_hw_whitelist_size(void) -{ - return BLE_HW_WHITE_LIST_SIZE; -} - -/** - * Enable the whitelisted devices - */ -void -ble_hw_whitelist_enable(void) -{ - /* Enable the configured device addresses */ - NRF_RADIO_NS->DACNF |= g_ble_hw_whitelist_mask; -} - -/** - * Disables the whitelisted devices - */ -void -ble_hw_whitelist_disable(void) -{ - /* Disable all whitelist devices */ - NRF_RADIO_NS->DACNF &= 0x0000ff00; -} - -/** - * Boolean function which returns true ('1') if there is a match on the - * whitelist. - * - * @return int - */ -int -ble_hw_whitelist_match(void) -{ - return NRF_RADIO_NS->EVENTS_DEVMATCH; -} - -/* Encrypt data */ -int -ble_hw_encrypt_block(struct ble_encryption_block *ecb) -{ - int rc; - uint32_t end; - uint32_t err; - - /* Stop ECB */ - NRF_ECB_NS->TASKS_STOPECB = 1; - /* XXX: does task stop clear these counters? Anyway to do this quicker? */ - NRF_ECB_NS->EVENTS_ENDECB = 0; - NRF_ECB_NS->EVENTS_ERRORECB = 0; - NRF_ECB_NS->ECBDATAPTR = (uint32_t)ecb; - - /* Start ECB */ - NRF_ECB_NS->TASKS_STARTECB = 1; - - /* Wait till error or done */ - rc = 0; - while (1) { - end = NRF_ECB_NS->EVENTS_ENDECB; - err = NRF_ECB_NS->EVENTS_ERRORECB; - if (end || err) { - if (err) { - rc = -1; - } - break; - } - } - - return rc; -} - -/** - * Random number generator ISR. - */ -static void -ble_rng_isr(void) -{ - uint8_t rnum; - - os_trace_isr_enter(); - - /* No callback? Clear and disable interrupts */ - if (ble_rng_isr_cb == NULL) { - NRF_RNG_NS->INTENCLR = 1; - NRF_RNG_NS->EVENTS_VALRDY = 0; - (void)NRF_RNG_NS->SHORTS; - os_trace_isr_exit(); - return; - } - - /* If there is a value ready grab it */ - if (NRF_RNG_NS->EVENTS_VALRDY) { - NRF_RNG_NS->EVENTS_VALRDY = 0; - rnum = (uint8_t)NRF_RNG_NS->VALUE; - (*ble_rng_isr_cb)(rnum); - } - - os_trace_isr_exit(); -} - -/** - * Initialize the random number generator - * - * @param cb - * @param bias - * - * @return int - */ -int -ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias) -{ - /* Set bias */ - if (bias) { - NRF_RNG_NS->CONFIG = 1; - } else { - NRF_RNG_NS->CONFIG = 0; - } - - /* If we were passed a function pointer we need to enable the interrupt */ - if (cb != NULL) { -#ifndef RIOT_VERSION - NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1); -#endif -#if MYNEWT - NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr); -#else - ble_npl_hw_set_isr(RNG_IRQn, ble_rng_isr); -#endif - NVIC_EnableIRQ(RNG_IRQn); - ble_rng_isr_cb = cb; - } - - return 0; -} - -/** - * Start the random number generator - * - * @return int - */ -int -ble_hw_rng_start(void) -{ - os_sr_t sr; - - /* No need for interrupt if there is no callback */ - OS_ENTER_CRITICAL(sr); - NRF_RNG_NS->EVENTS_VALRDY = 0; - if (ble_rng_isr_cb) { - NRF_RNG_NS->INTENSET = 1; - } - NRF_RNG_NS->TASKS_START = 1; - OS_EXIT_CRITICAL(sr); - - return 0; -} - -/** - * Stop the random generator - * - * @return int - */ -int -ble_hw_rng_stop(void) -{ - os_sr_t sr; - - /* No need for interrupt if there is no callback */ - OS_ENTER_CRITICAL(sr); - NRF_RNG_NS->INTENCLR = 1; - NRF_RNG_NS->TASKS_STOP = 1; - NRF_RNG_NS->EVENTS_VALRDY = 0; - OS_EXIT_CRITICAL(sr); - - return 0; -} - -/** - * Read the random number generator. - * - * @return uint8_t - */ -uint8_t -ble_hw_rng_read(void) -{ - uint8_t rnum; - - /* Wait for a sample */ - while (NRF_RNG_NS->EVENTS_VALRDY == 0) { - } - - NRF_RNG_NS->EVENTS_VALRDY = 0; - rnum = (uint8_t)NRF_RNG_NS->VALUE; - - return rnum; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -/** - * Clear the resolving list - * - * @return int - */ -void -ble_hw_resolv_list_clear(void) -{ - g_nrf_num_irks = 0; -} - -/** - * Add a device to the hw resolving list - * - * @param irk Pointer to IRK to add - * - * @return int 0: success, BLE error code otherwise - */ -int -ble_hw_resolv_list_add(uint8_t *irk) -{ - uint32_t *nrf_entry; - - /* Find first ununsed device address match element */ - if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) { - return BLE_ERR_MEM_CAPACITY; - } - - /* Copy into irk list */ - nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks]; - memcpy(nrf_entry, irk, 16); - - /* Add to total */ - ++g_nrf_num_irks; - return BLE_ERR_SUCCESS; -} - -/** - * Remove a device from the hw resolving list - * - * @param index Index of IRK to remove - */ -void -ble_hw_resolv_list_rmv(int index) -{ - uint32_t *irk_entry; - - if (index < g_nrf_num_irks) { - --g_nrf_num_irks; - irk_entry = &g_nrf_irk_list[index]; - if (g_nrf_num_irks > index) { - memmove(irk_entry, irk_entry + 4, 16 * (g_nrf_num_irks - index)); - } - } -} - -/** - * Returns the size of the resolving list. NOTE: this returns the maximum - * allowable entries in the HW. Configuration options may limit this. - * - * @return int Number of devices allowed in resolving list - */ -uint8_t -ble_hw_resolv_list_size(void) -{ - return BLE_HW_RESOLV_LIST_SIZE; -} - -/** - * Called to determine if the address received was resolved. - * - * @return int Negative values indicate unresolved address; positive values - * indicate index in resolving list of resolved address. - */ -int -ble_hw_resolv_list_match(void) -{ - if (NRF_AAR_NS->ENABLE && NRF_AAR_NS->EVENTS_END && - NRF_AAR_NS->EVENTS_RESOLVED) { - return (int)NRF_AAR_NS->STATUS; - } - - return -1; -} -#endif diff --git a/lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/src/ble_phy.c b/lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/src/ble_phy.c deleted file mode 100644 index 9734e887..00000000 --- a/lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/src/ble_phy.c +++ /dev/null @@ -1,2038 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "controller/ble_ll_plna.h" - -#include -#include -#include -#include -#include - -#define DPPI_CH_PUB(_ch) (((DPPI_CH_ ## _ch) & 0xff) | (1 << 31)) -#define DPPI_CH_SUB(_ch) (((DPPI_CH_ ## _ch) & 0xff) | (1 << 31)) -#define DPPI_CH_UNSUB(_ch) (((DPPI_CH_ ## _ch) & 0xff) | (0 << 31)) -#define DPPI_CH_MASK(_ch) (1 << (DPPI_CH_ ## _ch)) - -/* Channels 0..5 are always used. - * Channels 6 and 7 are used for PA/LNA (optionally). - * Channels 6..8 are used for GPIO debugging (optionally). - */ - -#define DPPI_CH_TIMER0_EVENTS_COMPARE_0 0 -#define DPPI_CH_TIMER0_EVENTS_COMPARE_3 1 -#define DPPI_CH_RADIO_EVENTS_END 2 -#define DPPI_CH_RADIO_EVENTS_BCMATCH 3 -#define DPPI_CH_RADIO_EVENTS_ADDRESS 4 -#define DPPI_CH_RTC0_EVENTS_COMPARE_0 5 -#define DPPI_CH_RADIO_EVENTS_READY 6 -#define DPPI_CH_RADIO_EVENTS_DISABLED 7 -#define DPPI_CH_RADIO_EVENTS_RXREADY 8 - -#define DPPI_CH_ENABLE_ALL (DPPIC_CHEN_CH0_Msk | DPPIC_CHEN_CH1_Msk | DPPIC_CHEN_CH2_Msk | \ - DPPIC_CHEN_CH3_Msk | DPPIC_CHEN_CH4_Msk | DPPIC_CHEN_CH5_Msk) - -#define DPPI_CH_MASK_PLNA (DPPI_CH_MASK(RADIO_EVENTS_READY) | \ - DPPI_CH_MASK(RADIO_EVENTS_DISABLED)) - -extern uint8_t g_nrf_num_irks; -extern uint32_t g_nrf_irk_list[]; - -/* To disable all radio interrupts */ -#define NRF_RADIO_IRQ_MASK_ALL (0x34FF) - -/* - * We configure the nrf with a 1 byte S0 field, 8 bit length field, and - * zero bit S1 field. The preamble is 8 bits long. - */ -#define NRF_LFLEN_BITS (8) -#define NRF_S0LEN (1) -#define NRF_S1LEN_BITS (0) -#define NRF_CILEN_BITS (2) -#define NRF_TERMLEN_BITS (3) - -/* Maximum length of frames */ -#define NRF_MAXLEN (255) -#define NRF_BALEN (3) /* For base address of 3 bytes */ - -/* NRF_RADIO_NS->PCNF0 configuration values */ -#define NRF_PCNF0 (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) | \ - (RADIO_PCNF0_S1INCL_Msk) | \ - (NRF_S0LEN << RADIO_PCNF0_S0LEN_Pos) | \ - (NRF_S1LEN_BITS << RADIO_PCNF0_S1LEN_Pos) -#define NRF_PCNF0_1M (NRF_PCNF0) | \ - (RADIO_PCNF0_PLEN_8bit << RADIO_PCNF0_PLEN_Pos) -#define NRF_PCNF0_2M (NRF_PCNF0) | \ - (RADIO_PCNF0_PLEN_16bit << RADIO_PCNF0_PLEN_Pos) -#define NRF_PCNF0_CODED (NRF_PCNF0) | \ - (RADIO_PCNF0_PLEN_LongRange << RADIO_PCNF0_PLEN_Pos) | \ - (NRF_CILEN_BITS << RADIO_PCNF0_CILEN_Pos) | \ - (NRF_TERMLEN_BITS << RADIO_PCNF0_TERMLEN_Pos) - -/* BLE PHY data structure */ -struct ble_phy_obj { - uint8_t phy_stats_initialized; - int8_t phy_txpwr_dbm; - uint8_t phy_chan; - uint8_t phy_state; - uint8_t phy_transition; - uint8_t phy_transition_late; - uint8_t phy_rx_started; - uint8_t phy_encrypted; - uint8_t phy_privacy; - uint8_t phy_tx_pyld_len; - uint8_t phy_cur_phy_mode; - uint8_t phy_tx_phy_mode; - uint8_t phy_rx_phy_mode; - uint8_t phy_bcc_offset; - int8_t rx_pwr_compensation; - uint32_t phy_aar_scratch; - uint32_t phy_access_address; - struct ble_mbuf_hdr rxhdr; - void *txend_arg; - ble_phy_tx_end_func txend_cb; - uint32_t phy_start_cputime; -}; -struct ble_phy_obj g_ble_phy_data; - -/* XXX: if 27 byte packets desired we can make this smaller */ -/* Global transmit/receive buffer */ -static uint32_t g_ble_phy_tx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; -static uint32_t g_ble_phy_rx_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/* Make sure word-aligned for faster copies */ -static uint32_t g_ble_phy_enc_buf[(BLE_PHY_MAX_PDU_LEN + 3) / 4]; -#endif - -/* RF center frequency for each channel index (offset from 2400 MHz) */ -static const uint8_t g_ble_phy_chan_freq[BLE_PHY_NUM_CHANS] = { - 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, /* 0-9 */ - 24, 28, 30, 32, 34, 36, 38, 40, 42, 44, /* 10-19 */ - 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, /* 20-29 */ - 66, 68, 70, 72, 74, 76, 78, 2, 26, 80, /* 30-39 */ -}; - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) -/* packet start offsets (in usecs) */ -static const uint16_t g_ble_phy_mode_pkt_start_off[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 40, - [BLE_PHY_MODE_2M] = 24, - [BLE_PHY_MODE_CODED_125KBPS] = 376, - [BLE_PHY_MODE_CODED_500KBPS] = 376 -}; -#endif - -/* Various radio timings */ -/* Radio ramp-up times in usecs (fast mode) */ -#define BLE_PHY_T_TXENFAST (XCVR_TX_RADIO_RAMPUP_USECS) -#define BLE_PHY_T_RXENFAST (XCVR_RX_RADIO_RAMPUP_USECS) - -/* delay between EVENTS_READY and start of tx */ -static const uint8_t g_ble_phy_t_txdelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 4, - [BLE_PHY_MODE_2M] = 3, - [BLE_PHY_MODE_CODED_125KBPS] = 5, - [BLE_PHY_MODE_CODED_500KBPS] = 5 -}; -/* delay between EVENTS_END and end of txd packet */ -static const uint8_t g_ble_phy_t_txenddelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 4, - [BLE_PHY_MODE_2M] = 3, - [BLE_PHY_MODE_CODED_125KBPS] = 9, - [BLE_PHY_MODE_CODED_500KBPS] = 3 -}; -/* delay between rxd access address (w/ TERM1 for coded) and EVENTS_ADDRESS */ -static const uint8_t g_ble_phy_t_rxaddrdelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 6, - [BLE_PHY_MODE_2M] = 2, - [BLE_PHY_MODE_CODED_125KBPS] = 17, - [BLE_PHY_MODE_CODED_500KBPS] = 17 -}; -/* delay between end of rxd packet and EVENTS_END */ -static const uint8_t g_ble_phy_t_rxenddelay[BLE_PHY_NUM_MODE] = { - [BLE_PHY_MODE_1M] = 6, - [BLE_PHY_MODE_2M] = 2, - [BLE_PHY_MODE_CODED_125KBPS] = 27, - [BLE_PHY_MODE_CODED_500KBPS] = 22 -}; - -/* Statistics */ -STATS_SECT_START(ble_phy_stats) -STATS_SECT_ENTRY(phy_isrs) -STATS_SECT_ENTRY(tx_good) -STATS_SECT_ENTRY(tx_fail) -STATS_SECT_ENTRY(tx_late) -STATS_SECT_ENTRY(tx_bytes) -STATS_SECT_ENTRY(rx_starts) -STATS_SECT_ENTRY(rx_aborts) -STATS_SECT_ENTRY(rx_valid) -STATS_SECT_ENTRY(rx_crc_err) -STATS_SECT_ENTRY(rx_late) -STATS_SECT_ENTRY(radio_state_errs) -STATS_SECT_ENTRY(rx_hw_err) -STATS_SECT_ENTRY(tx_hw_err) -STATS_SECT_END -STATS_SECT_DECL(ble_phy_stats) ble_phy_stats; - -STATS_NAME_START(ble_phy_stats) -STATS_NAME(ble_phy_stats, phy_isrs) -STATS_NAME(ble_phy_stats, tx_good) -STATS_NAME(ble_phy_stats, tx_fail) -STATS_NAME(ble_phy_stats, tx_late) -STATS_NAME(ble_phy_stats, tx_bytes) -STATS_NAME(ble_phy_stats, rx_starts) -STATS_NAME(ble_phy_stats, rx_aborts) -STATS_NAME(ble_phy_stats, rx_valid) -STATS_NAME(ble_phy_stats, rx_crc_err) -STATS_NAME(ble_phy_stats, rx_late) -STATS_NAME(ble_phy_stats, radio_state_errs) -STATS_NAME(ble_phy_stats, rx_hw_err) -STATS_NAME(ble_phy_stats, tx_hw_err) -STATS_NAME_END(ble_phy_stats) - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/* - * Per nordic, the number of bytes needed for scratch is 16 + MAX_PKT_SIZE. - * However, when I used a smaller size it still overwrote the scratchpad. Until - * I figure this out I am just going to allocate 67 words so we have enough - * space for 267 bytes of scratch. I used 268 bytes since not sure if this - * needs to be aligned and burning a byte is no big deal. - * - *#define NRF_ENC_SCRATCH_WORDS (((MYNEWT_VAL(BLE_LL_MAX_PKT_SIZE) + 16) + 3) / 4) - */ -#define NRF_ENC_SCRATCH_WORDS (67) - -static uint32_t nrf_encrypt_scratchpad[NRF_ENC_SCRATCH_WORDS]; - -struct nrf_ccm_data { - uint8_t key[16]; - uint64_t pkt_counter; - uint8_t dir_bit; - uint8_t iv[8]; -} __attribute__((packed)); - -static struct nrf_ccm_data nrf_ccm_data; -#endif - -static int g_ble_phy_gpiote_idx; - -#if MYNEWT_VAL(BLE_LL_PA) || MYNEWT_VAL(BLE_LL_LNA) - -#define PLNA_SINGLE_GPIO \ - (!MYNEWT_VAL(BLE_LL_PA) || !MYNEWT_VAL(BLE_LL_LNA) || \ - (MYNEWT_VAL(BLE_LL_PA_GPIO) == MYNEWT_VAL(BLE_LL_LNA_GPIO))) - -#if PLNA_SINGLE_GPIO -static uint8_t plna_idx; -#else -#if MYNEWT_VAL(BLE_LL_PA) -static uint8_t plna_pa_idx; -#endif -#if MYNEWT_VAL(BLE_LL_LNA) -static uint8_t plna_lna_idx; -#endif -#endif - -#endif - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 -static uint8_t phy_dbg_txrxen_ready_idx; -#endif -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 -static uint8_t phy_dbg_address_end_idx; -#endif -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 -static uint8_t phy_dbg_wfr_idx; -#endif - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - -uint32_t -ble_phy_mode_pdu_start_off(int phy_mode) -{ - return g_ble_phy_mode_pkt_start_off[phy_mode]; -} - -static void -ble_phy_mode_apply(uint8_t phy_mode) -{ - if (phy_mode == g_ble_phy_data.phy_cur_phy_mode) { - return; - } - - switch (phy_mode) { - case BLE_PHY_MODE_1M: - NRF_RADIO_NS->MODE = RADIO_MODE_MODE_Ble_1Mbit; - *((volatile uint32_t *)0x41008588) = *((volatile uint32_t *)0x01FF0080); - NRF_RADIO_NS->PCNF0 = NRF_PCNF0_1M; - break; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) - case BLE_PHY_MODE_2M: - NRF_RADIO_NS->MODE = RADIO_MODE_MODE_Ble_2Mbit; - *((volatile uint32_t *)0x41008588) = *((volatile uint32_t *)0x01FF0084); - NRF_RADIO_NS->PCNF0 = NRF_PCNF0_2M; - break; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - case BLE_PHY_MODE_CODED_125KBPS: - NRF_RADIO_NS->MODE = RADIO_MODE_MODE_Ble_LR125Kbit; - *((volatile uint32_t *)0x41008588) = *((volatile uint32_t *)0x01FF0080); - NRF_RADIO_NS->PCNF0 = NRF_PCNF0_CODED; - break; - case BLE_PHY_MODE_CODED_500KBPS: - NRF_RADIO_NS->MODE = RADIO_MODE_MODE_Ble_LR500Kbit; - *((volatile uint32_t *)0x41008588) = *((volatile uint32_t *)0x01FF0080); - NRF_RADIO_NS->PCNF0 = NRF_PCNF0_CODED; - break; -#endif - default: - assert(0); - } - - g_ble_phy_data.phy_cur_phy_mode = phy_mode; -} -#endif - -void -ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode) -{ - g_ble_phy_data.phy_tx_phy_mode = tx_phy_mode; - g_ble_phy_data.phy_rx_phy_mode = rx_phy_mode; -} - -static void -ble_phy_plna_enable_pa(void) -{ -#if MYNEWT_VAL(BLE_LL_PA) - ble_ll_plna_pa_enable(); - -#if PLNA_SINGLE_GPIO - NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_idx] = DPPI_CH_SUB(RADIO_EVENTS_READY); -#else - NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_pa_idx] = DPPI_CH_SUB(RADIO_EVENTS_READY); -#endif -#endif -} - -static void -ble_phy_plna_disable_pa(void) -{ -#if MYNEWT_VAL(BLE_LL_PA) - ble_ll_plna_pa_disable(); - -#if PLNA_SINGLE_GPIO - NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY); -#else - NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_pa_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY); -#endif -#endif -} - -static void -ble_phy_plna_enable_lna(void) -{ -#if MYNEWT_VAL(BLE_LL_LNA) - ble_ll_plna_lna_enable(); - -#if PLNA_SINGLE_GPIO - NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_idx] = DPPI_CH_SUB(RADIO_EVENTS_READY); -#else - NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_lna_idx] = DPPI_CH_SUB(RADIO_EVENTS_READY); -#endif -#endif -} - -static void -ble_phy_plna_disable_lna(void) -{ -#if MYNEWT_VAL(BLE_LL_LNA) - ble_ll_plna_lna_disable(); - -#if PLNA_SINGLE_GPIO - NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY); -#else - NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_lna_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY); -#endif -#endif -} - -int -ble_phy_get_cur_phy(void) -{ -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - switch (g_ble_phy_data.phy_cur_phy_mode) { - case BLE_PHY_MODE_1M: - return BLE_PHY_1M; - case BLE_PHY_MODE_2M: - return BLE_PHY_2M; - case BLE_PHY_MODE_CODED_125KBPS: - case BLE_PHY_MODE_CODED_500KBPS: - return BLE_PHY_CODED; - default: - assert(0); - return -1; - } -#else - return BLE_PHY_1M; -#endif -} - -void -ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu) -{ - uint32_t rem_len; - uint32_t copy_len; - uint32_t block_len; - uint32_t block_rem_len; - void *dst; - void *src; - struct os_mbuf * om; - - /* Better be aligned */ - assert(((uint32_t)dptr & 3) == 0); - - block_len = rxpdu->om_omp->omp_databuf_len; - rem_len = OS_MBUF_PKTHDR(rxpdu)->omp_len; - src = dptr; - - /* - * Setup for copying from first mbuf which is shorter due to packet header - * and extra leading space - */ - copy_len = block_len - rxpdu->om_pkthdr_len - 4; - om = rxpdu; - dst = om->om_data; - - while (true) { - /* - * Always copy blocks of length aligned to word size, only last mbuf - * will have remaining non-word size bytes appended. - */ - block_rem_len = copy_len; - copy_len = min(copy_len, rem_len); - copy_len &= ~3; - - dst = om->om_data; - om->om_len = copy_len; - rem_len -= copy_len; - block_rem_len -= copy_len; - - __asm__ volatile (".syntax unified \n" - " mov r4, %[len] \n" - " b 2f \n" - "1: ldr r3, [%[src], %[len]] \n" - " str r3, [%[dst], %[len]] \n" - "2: subs %[len], #4 \n" - " bpl 1b \n" - " adds %[src], %[src], r4 \n" - " adds %[dst], %[dst], r4 \n" - : [dst] "+r" (dst), [src] "+r" (src), - [len] "+r" (copy_len) - : - : "r3", "r4", "memory" - ); - - if ((rem_len < 4) && (block_rem_len >= rem_len)) { - break; - } - - /* Move to next mbuf */ - om = SLIST_NEXT(om, om_next); - copy_len = block_len; - } - - /* Copy remaining bytes, if any, to last mbuf */ - om->om_len += rem_len; - __asm__ volatile (".syntax unified \n" - " b 2f \n" - "1: ldrb r3, [%[src], %[len]] \n" - " strb r3, [%[dst], %[len]] \n" - "2: subs %[len], #1 \n" - " bpl 1b \n" - : [len] "+r" (rem_len) - : [dst] "r" (dst), [src] "r" (src) - : "r3", "memory" - ); - - /* Copy header */ - memcpy(BLE_MBUF_HDR_PTR(rxpdu), &g_ble_phy_data.rxhdr, - sizeof(struct ble_mbuf_hdr)); -} - -/** - * Called when we want to wait if the radio is in either the rx or tx - * disable states. We want to wait until that state is over before doing - * anything to the radio - */ -static void -nrf_wait_disabled(void) -{ - uint32_t state; - - state = NRF_RADIO_NS->STATE; - if (state != RADIO_STATE_STATE_Disabled) { - if ((state == RADIO_STATE_STATE_RxDisable) || - (state == RADIO_STATE_STATE_TxDisable)) { - /* This will end within a short time (6 usecs). Just poll */ - while (NRF_RADIO_NS->STATE == state) { - /* If this fails, something is really wrong. Should last - * no more than 6 usecs - */ - } - } - } -} - -static int -ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs, bool tx) -{ - uint32_t next_cc; - uint32_t cur_cc; - uint32_t cntr; - uint32_t delta; - - /* - * We need to adjust start time to include radio ramp-up and TX pipeline - * delay (the latter only if applicable, so only for TX). - * - * Radio ramp-up time is 40 usecs and TX delay is 3 or 5 usecs depending on - * phy, thus we'll offset RTC by 2 full ticks (61 usecs) and then compensate - * using TIMER0 with 1 usec precision. - */ - - cputime -= 2; - rem_usecs += 61; - if (tx) { - rem_usecs -= BLE_PHY_T_TXENFAST; - rem_usecs -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; - } else { - rem_usecs -= BLE_PHY_T_RXENFAST; - } - - /* - * rem_usecs will be no more than 2 ticks, but if it is more than single - * tick then we should better count one more low-power tick rather than - * 30 high-power usecs. Also make sure we don't set TIMER0 CC to 0 as the - * compare won't occur. - */ - - if (rem_usecs > 30) { - cputime++; - rem_usecs -= 30; - } - - /* - * Can we set the RTC compare to start TIMER0? We can do it if: - * a) Current compare value is not N+1 or N+2 ticks from current - * counter. - * b) The value we want to set is not at least N+2 from current - * counter. - * - * NOTE: since the counter can tick 1 while we do these calculations we - * need to account for it. - */ - next_cc = cputime & 0xffffff; - cur_cc = NRF_RTC0_NS->CC[0]; - cntr = NRF_RTC0_NS->COUNTER; - - delta = (cur_cc - cntr) & 0xffffff; - if ((delta <= 3) && (delta != 0)) { - return -1; - } - delta = (next_cc - cntr) & 0xffffff; - if ((delta & 0x800000) || (delta < 3)) { - return -1; - } - - /* Clear and set TIMER0 to fire off at proper time */ - NRF_TIMER0_NS->TASKS_CLEAR = 1; - NRF_TIMER0_NS->CC[0] = rem_usecs; - NRF_TIMER0_NS->EVENTS_COMPARE[0] = 0; - - /* Set RTC compare to start TIMER0 */ - NRF_RTC0_NS->EVENTS_COMPARE[0] = 0; - NRF_RTC0_NS->CC[0] = next_cc; - NRF_RTC0_NS->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; - - /* Enable PPI */ - NRF_TIMER0_NS->SUBSCRIBE_START = DPPI_CH_SUB(RTC0_EVENTS_COMPARE_0); - - /* Store the cputime at which we set the RTC */ - g_ble_phy_data.phy_start_cputime = cputime; - - return 0; -} - -static int -ble_phy_set_start_now(void) -{ - os_sr_t sr; - uint32_t now; - - OS_ENTER_CRITICAL(sr); - - /* - * Set TIMER0 to fire immediately. We can't set CC to 0 as compare will not - * occur in such case. - */ - NRF_TIMER0_NS->TASKS_CLEAR = 1; - NRF_TIMER0_NS->CC[0] = 1; - NRF_TIMER0_NS->EVENTS_COMPARE[0] = 0; - - /* - * Set RTC compare to start TIMER0. We need to set it to at least N+2 ticks - * from current value to guarantee triggering compare event, but let's set - * it to N+3 to account for possible extra tick on RTC0 during these - * operations. - */ - now = os_cputime_get32(); - NRF_RTC0_NS->EVENTS_COMPARE[0] = 0; - NRF_RTC0_NS->CC[0] = now + 3; - NRF_RTC0_NS->EVTENSET = RTC_EVTENSET_COMPARE0_Msk; - - /* Enable PPI */ - NRF_TIMER0_NS->SUBSCRIBE_START = DPPI_CH_SUB(RTC0_EVENTS_COMPARE_0); - - /* - * Store the cputime at which we set the RTC - * - * XXX Compare event may be triggered on previous CC value (if it was set to - * less than N+2) so in rare cases actual start time may be 2 ticks earlier - * than what we expect. Since this is only used on RX, it may cause AUX scan - * to be scheduled 1 or 2 ticks too late so we'll miss it - it's acceptable - * for now. - */ - g_ble_phy_data.phy_start_cputime = now + 3; - - OS_EXIT_CRITICAL(sr); - - return 0; -} - -void -ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) -{ - uint32_t end_time; - uint8_t phy; - - phy = g_ble_phy_data.phy_cur_phy_mode; - - if (txrx == BLE_PHY_WFR_ENABLE_TXRX) { - /* RX shall start exactly T_IFS after TX end captured in CC[2] */ - end_time = NRF_TIMER0_NS->CC[2] + BLE_LL_IFS; - /* Adjust for delay between EVENT_END and actual TX end time */ - end_time += g_ble_phy_t_txenddelay[tx_phy_mode]; - /* Wait a bit longer due to allowed active clock accuracy */ - end_time += 2; - /* - * It's possible that we'll capture PDU start time at the end of timer - * cycle and since wfr expires at the beginning of calculated timer - * cycle it can be almost 1 usec too early. Let's compensate for this - * by waiting 1 usec more. - */ - end_time += 1; - } else { - /* - * RX shall start no later than wfr_usecs after RX enabled. - * CC[0] is the time of RXEN so adjust for radio ram-up. - * Do not add jitter since this is already covered by LL. - */ - end_time = NRF_TIMER0_NS->CC[0] + BLE_PHY_T_RXENFAST + wfr_usecs; - } - - /* - * Note: on LE Coded EVENT_ADDRESS is fired after TERM1 is received, so - * we are actually calculating relative to start of packet payload - * which is fine. - */ - - /* Adjust for receiving access address since this triggers EVENT_ADDRESS */ - end_time += ble_phy_mode_pdu_start_off(phy); - /* Adjust for delay between actual access address RX and EVENT_ADDRESS */ - end_time += g_ble_phy_t_rxaddrdelay[phy]; - - /* wfr_secs is the time from rxen until timeout */ - NRF_TIMER0_NS->CC[3] = end_time; - NRF_TIMER0_NS->EVENTS_COMPARE[3] = 0; - - /* Subscribe for wait for response events */ - NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS); - NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_3); - - /* - * It may happen that if CPU is halted for a brief moment (e.g. during flash - * erase or write), TIMER0 already counted past CC[3] and thus wfr will not - * fire as expected. In case this happened, let's just disable PPIs for wfr - * and trigger wfr manually (i.e. disable radio). - * - * Note that the same applies to RX start time set in CC[0] but since it - * should fire earlier than wfr, fixing wfr is enough. - * - * CC[1] is only used as a reference on RX start, we do not need it here so - * it can be used to read TIMER0 counter. - */ - NRF_TIMER0_NS->TASKS_CAPTURE[1] = 1; - if (NRF_TIMER0_NS->CC[1] > NRF_TIMER0_NS->CC[3]) { - /* Unsubscribe from wfr events */ - NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); - NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_3); - - NRF_RADIO_NS->TASKS_DISABLE = 1; - } -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -static uint32_t -ble_phy_get_ccm_datarate(void) -{ -#if BLE_LL_BT5_PHY_SUPPORTED - switch (g_ble_phy_data.phy_cur_phy_mode) { - case BLE_PHY_MODE_1M: - return CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos; - case BLE_PHY_MODE_2M: - return CCM_MODE_DATARATE_2Mbit << CCM_MODE_DATARATE_Pos; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - case BLE_PHY_MODE_CODED_125KBPS: - return CCM_MODE_DATARATE_125Kbps << CCM_MODE_DATARATE_Pos; - case BLE_PHY_MODE_CODED_500KBPS: - return CCM_MODE_DATARATE_500Kbps << CCM_MODE_DATARATE_Pos; -#endif - } - - assert(0); - return 0; -#else - return CCM_MODE_DATARATE_1Mbit << CCM_MODE_DATARATE_Pos; -#endif -} -#endif - -/** - * Setup transceiver for receive. - */ -static void -ble_phy_rx_xcvr_setup(void) -{ - uint8_t *dptr; - - dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; - dptr += 3; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (g_ble_phy_data.phy_encrypted) { - NRF_RADIO_NS->PACKETPTR = (uint32_t)&g_ble_phy_enc_buf[0]; - NRF_CCM_NS->INPTR = (uint32_t)&g_ble_phy_enc_buf[0]; - NRF_CCM_NS->OUTPTR = (uint32_t)dptr; - NRF_CCM_NS->SCRATCHPTR = (uint32_t)&nrf_encrypt_scratchpad[0]; - NRF_CCM_NS->MODE = CCM_MODE_LENGTH_Msk | CCM_MODE_MODE_Decryption | - ble_phy_get_ccm_datarate(); - NRF_CCM_NS->CNFPTR = (uint32_t)&nrf_ccm_data; - NRF_CCM_NS->SHORTS = 0; - NRF_CCM_NS->EVENTS_ERROR = 0; - NRF_CCM_NS->EVENTS_ENDCRYPT = 0; - NRF_CCM_NS->TASKS_KSGEN = 1; - - /* Subscribe to radio address event */ - NRF_CCM_NS->SUBSCRIBE_CRYPT = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS); - } else { - NRF_RADIO_NS->PACKETPTR = (uint32_t)dptr; - } -#else - NRF_RADIO_NS->PACKETPTR = (uint32_t)dptr; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - if (g_ble_phy_data.phy_privacy) { - NRF_AAR_NS->ENABLE = AAR_ENABLE_ENABLE_Enabled; - NRF_AAR_NS->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; - NRF_AAR_NS->SCRATCHPTR = (uint32_t)&g_ble_phy_data.phy_aar_scratch; - NRF_AAR_NS->EVENTS_END = 0; - NRF_AAR_NS->EVENTS_RESOLVED = 0; - NRF_AAR_NS->EVENTS_NOTRESOLVED = 0; - } else { - if (g_ble_phy_data.phy_encrypted == 0) { - NRF_AAR_NS->ENABLE = AAR_ENABLE_ENABLE_Disabled; - } - } -#endif - - /* Turn off trigger TXEN on output compare match and AAR on bcmatch */ - NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); - NRF_AAR_NS->SUBSCRIBE_START = DPPI_CH_UNSUB(RADIO_EVENTS_BCMATCH); - - /* Reset the rx started flag. Used for the wait for response */ - g_ble_phy_data.phy_rx_started = 0; - g_ble_phy_data.phy_state = BLE_PHY_STATE_RX; - -#if BLE_LL_BT5_PHY_SUPPORTED - /* - * On Coded PHY there are CI and TERM1 fields before PDU starts so we need - * to take this into account when setting up BCC. - */ - if (g_ble_phy_data.phy_cur_phy_mode == BLE_PHY_MODE_CODED_125KBPS || - g_ble_phy_data.phy_cur_phy_mode == BLE_PHY_MODE_CODED_500KBPS) { - g_ble_phy_data.phy_bcc_offset = 5; - } else { - g_ble_phy_data.phy_bcc_offset = 0; - } -#else - g_ble_phy_data.phy_bcc_offset = 0; -#endif - - /* I want to know when 1st byte received (after address) */ - NRF_RADIO_NS->BCC = 8 + g_ble_phy_data.phy_bcc_offset; /* in bits */ - NRF_RADIO_NS->EVENTS_ADDRESS = 0; - NRF_RADIO_NS->EVENTS_DEVMATCH = 0; - NRF_RADIO_NS->EVENTS_BCMATCH = 0; - NRF_RADIO_NS->EVENTS_RSSIEND = 0; - NRF_RADIO_NS->EVENTS_CRCOK = 0; - NRF_RADIO_NS->SHORTS = RADIO_SHORTS_END_DISABLE_Msk | - RADIO_SHORTS_READY_START_Msk | - RADIO_SHORTS_ADDRESS_BCSTART_Msk | - RADIO_SHORTS_ADDRESS_RSSISTART_Msk | - RADIO_SHORTS_DISABLED_RSSISTOP_Msk; - - NRF_RADIO_NS->INTENSET = RADIO_INTENSET_ADDRESS_Msk | - RADIO_INTENSET_DISABLED_Msk; -} - -/** - * Called from interrupt context when the transmit ends - * - */ -static void -ble_phy_tx_end_isr(void) -{ - uint8_t tx_phy_mode; - uint8_t was_encrypted; - uint8_t transition; - uint32_t rx_time; - - /* Store PHY on which we've just transmitted smth */ - tx_phy_mode = g_ble_phy_data.phy_cur_phy_mode; - - /* If this transmission was encrypted we need to remember it */ - was_encrypted = g_ble_phy_data.phy_encrypted; - (void)was_encrypted; - - /* Better be in TX state! */ - assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - /* - * XXX: not sure what to do. We had a HW error during transmission. - * For now I just count a stat but continue on like all is good. - */ - if (was_encrypted) { - if (NRF_CCM_NS->EVENTS_ERROR) { - STATS_INC(ble_phy_stats, tx_hw_err); - NRF_CCM_NS->EVENTS_ERROR = 0; - } - } -#endif - - /* Call transmit end callback */ - if (g_ble_phy_data.txend_cb) { - g_ble_phy_data.txend_cb(g_ble_phy_data.txend_arg); - } - - transition = g_ble_phy_data.phy_transition; - if (transition == BLE_PHY_TRANSITION_TX_RX) { - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_apply(g_ble_phy_data.phy_rx_phy_mode); -#endif - - /* Packet pointer needs to be reset. */ - ble_phy_rx_xcvr_setup(); - - ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, tx_phy_mode, 0); - - /* Schedule RX exactly T_IFS after TX end captured in CC[2] */ - rx_time = NRF_TIMER0_NS->CC[2] + BLE_LL_IFS; - /* Adjust for delay between EVENT_END and actual TX end time */ - rx_time += g_ble_phy_t_txenddelay[tx_phy_mode]; - /* Adjust for radio ramp-up */ - rx_time -= BLE_PHY_T_RXENFAST; - /* Start listening a bit earlier due to allowed active clock accuracy */ - rx_time -= 2; - - NRF_TIMER0_NS->CC[0] = rx_time; - NRF_TIMER0_NS->EVENTS_COMPARE[0] = 0; - - /* Start radio on timer */ - NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0); - - ble_phy_plna_enable_lna(); - } else { - NRF_TIMER0_NS->TASKS_STOP = 1; - NRF_TIMER0_NS->TASKS_SHUTDOWN = 1; - - NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); - NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_3); - NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); - NRF_TIMER0_NS->SUBSCRIBE_START = DPPI_CH_UNSUB(RTC0_EVENTS_COMPARE_0); - - assert(transition == BLE_PHY_TRANSITION_NONE); - } -} - -static inline uint8_t -ble_phy_get_cur_rx_phy_mode(void) -{ - uint8_t phy; - - phy = g_ble_phy_data.phy_cur_phy_mode; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - /* - * For Coded PHY mode can be set to either codings since actual coding is - * set in packet header. However, here we need actual coding of received - * packet as this determines pipeline delays so need to figure this out - * using CI field. - */ - if ((phy == BLE_PHY_MODE_CODED_125KBPS) || - (phy == BLE_PHY_MODE_CODED_500KBPS)) { - phy = NRF_RADIO_NS->PDUSTAT & RADIO_PDUSTAT_CISTAT_Msk ? - BLE_PHY_MODE_CODED_500KBPS : BLE_PHY_MODE_CODED_125KBPS; - } -#endif - - return phy; -} - -static void -ble_phy_rx_end_isr(void) -{ - int rc; - uint8_t *dptr; - uint8_t crcok; - uint32_t tx_time; - struct ble_mbuf_hdr *ble_hdr; - - /* Disable automatic RXEN */ - NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); - - /* Set RSSI and CRC status flag in header */ - ble_hdr = &g_ble_phy_data.rxhdr; - assert(NRF_RADIO_NS->EVENTS_RSSIEND != 0); - ble_hdr->rxinfo.rssi = (-1 * NRF_RADIO_NS->RSSISAMPLE) + - g_ble_phy_data.rx_pwr_compensation; - - dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; - dptr += 3; - - /* Count PHY crc errors and valid packets */ - crcok = NRF_RADIO_NS->EVENTS_CRCOK; - if (!crcok) { - STATS_INC(ble_phy_stats, rx_crc_err); - } else { - STATS_INC(ble_phy_stats, rx_valid); - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (g_ble_phy_data.phy_encrypted) { - /* Only set MIC failure flag if frame is not zero length */ - if ((dptr[1] != 0) && (NRF_CCM_NS->MICSTATUS == 0)) { - ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_MIC_FAILURE; - } - - /* - * XXX: not sure how to deal with this. This should not - * be a MIC failure but we should not hand it up. I guess - * this is just some form of rx error and that is how we - * handle it? For now, just set CRC error flags - */ - if (NRF_CCM_NS->EVENTS_ERROR) { - STATS_INC(ble_phy_stats, rx_hw_err); - ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; - } - - /* - * XXX: This is a total hack work-around for now but I dont - * know what else to do. If ENDCRYPT is not set and we are - * encrypted we need to not trust this frame and drop it. - */ - if (NRF_CCM_NS->EVENTS_ENDCRYPT == 0) { - STATS_INC(ble_phy_stats, rx_hw_err); - ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; - } - } -#endif - } - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_apply(g_ble_phy_data.phy_tx_phy_mode); -#endif - - /* - * Let's schedule TX now and we will just cancel it after processing RXed - * packet if we don't need TX. - * - * We need this to initiate connection in case AUX_CONNECT_REQ was sent on - * LE Coded S8. In this case the time we process RXed packet is roughly the - * same as the limit when we need to have TX scheduled (i.e. TIMER0 and PPI - * armed) so we may simply miss the slot and set the timer in the past. - * - * When TX is scheduled in advance, we may event process packet a bit longer - * during radio ramp-up - this gives us extra 40 usecs which is more than - * enough. - */ - - /* Schedule TX exactly T_IFS after RX end captured in CC[2] */ - tx_time = NRF_TIMER0_NS->CC[2] + BLE_LL_IFS; - /* Adjust for delay between actual RX end time and EVENT_END */ - tx_time -= g_ble_phy_t_rxenddelay[ble_hdr->rxinfo.phy_mode]; - /* Adjust for radio ramp-up */ - tx_time -= BLE_PHY_T_TXENFAST; - /* Adjust for delay between EVENT_READY and actual TX start time */ - tx_time -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; - - NRF_TIMER0_NS->CC[0] = tx_time; - NRF_TIMER0_NS->EVENTS_COMPARE[0] = 0; - - /* Enable automatic TX */ - NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0); - - ble_phy_plna_enable_pa(); - - /* - * XXX: Hack warning! - * - * It may happen (during flash erase) that CPU is stopped for a moment and - * TIMER0 already counted past CC[0]. In such case we will be stuck waiting - * for TX to start since EVENTS_COMPARE[0] will not happen any time soon. - * For now let's set a flag denoting that we are late in RX-TX transition so - * ble_phy_tx() will fail - this allows everything to cleanup nicely without - * the need for extra handling in many places. - * - * Note: CC[3] is used only for wfr which we do not need here. - */ - NRF_TIMER0_NS->TASKS_CAPTURE[3] = 1; - if (NRF_TIMER0_NS->CC[3] > NRF_TIMER0_NS->CC[0]) { - NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); - - g_ble_phy_data.phy_transition_late = 1; - } - - /* - * XXX: This is a horrible ugly hack to deal with the RAM S1 byte - * that is not sent over the air but is present here. Simply move the - * data pointer to deal with it. Fix this later. - */ - dptr[2] = dptr[1]; - dptr[1] = dptr[0]; - rc = ble_ll_rx_end(dptr + 1, ble_hdr); - if (rc < 0) { - ble_phy_disable(); - } -} - -static bool -ble_phy_rx_start_isr(void) -{ - int rc; - uint32_t state; - uint32_t usecs; - uint32_t pdu_usecs; - uint32_t ticks; - struct ble_mbuf_hdr *ble_hdr; - uint8_t *dptr; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - int adva_offset; -#endif - - dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; - - /* Clear events and clear interrupt */ - NRF_RADIO_NS->EVENTS_ADDRESS = 0; - NRF_RADIO_NS->INTENCLR = RADIO_INTENCLR_ADDRESS_Msk; - - /* Clear wfr timer channels and DISABLED interrupt */ - NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); - NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_3); - - /* Initialize the ble mbuf header */ - ble_hdr = &g_ble_phy_data.rxhdr; - ble_hdr->rxinfo.flags = ble_ll_state_get(); - ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan; - ble_hdr->rxinfo.handle = 0; - ble_hdr->rxinfo.phy = ble_phy_get_cur_phy(); - ble_hdr->rxinfo.phy_mode = ble_phy_get_cur_rx_phy_mode(); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - ble_hdr->rxinfo.user_data = NULL; -#endif - - /* - * Calculate accurate packets start time (with remainder) - * - * We may start receiving packet somewhere during preamble in which case - * it is possible that actual transmission started before TIMER0 was - * running - need to take this into account. - */ - ble_hdr->beg_cputime = g_ble_phy_data.phy_start_cputime; - - usecs = NRF_TIMER0_NS->CC[1]; - pdu_usecs = ble_phy_mode_pdu_start_off(ble_hdr->rxinfo.phy_mode) + - g_ble_phy_t_rxaddrdelay[ble_hdr->rxinfo.phy_mode]; - if (usecs < pdu_usecs) { - g_ble_phy_data.phy_start_cputime--; - usecs += 30; - } - usecs -= pdu_usecs; - - ticks = os_cputime_usecs_to_ticks(usecs); - usecs -= os_cputime_ticks_to_usecs(ticks); - if (usecs == 31) { - usecs = 0; - ++ticks; - } - - ble_hdr->beg_cputime += ticks; - ble_hdr->rem_usecs = usecs; - - /* Wait to get 1st byte of frame */ - while (1) { - state = NRF_RADIO_NS->STATE; - if (NRF_RADIO_NS->EVENTS_BCMATCH != 0) { - break; - } - - /* - * If state is disabled, we should have the BCMATCH. If not, - * something is wrong! - */ - if (state == RADIO_STATE_STATE_Disabled) { - NRF_RADIO_NS->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; - NRF_RADIO_NS->SHORTS = 0; - return false; - } - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* - * If privacy is enabled and received PDU has TxAdd bit set (i.e. random - * address) we try to resolve address using AAR. - */ - if (g_ble_phy_data.phy_privacy && (dptr[3] & 0x40)) { - /* - * AdvA is located at 4th octet in RX buffer (after S0, length an S1 - * fields). In case of extended advertising PDU we need to add 2 more - * octets for extended header. - */ - adva_offset = (dptr[3] & 0x0f) == 0x07 ? 2 : 0; - NRF_AAR_NS->ADDRPTR = (uint32_t)(dptr + 3 + adva_offset); - - /* Trigger AAR after last bit of AdvA is received */ - NRF_RADIO_NS->EVENTS_BCMATCH = 0; - NRF_AAR_NS->SUBSCRIBE_START = DPPI_CH_SUB(RADIO_EVENTS_BCMATCH); - NRF_RADIO_NS->BCC = (BLE_LL_PDU_HDR_LEN + adva_offset + BLE_DEV_ADDR_LEN) * 8 + - g_ble_phy_data.phy_bcc_offset; - } -#endif - - /* Call Link Layer receive start function */ - rc = ble_ll_rx_start(dptr + 3, - g_ble_phy_data.phy_chan, - &g_ble_phy_data.rxhdr); - if (rc >= 0) { - /* Set rx started flag and enable rx end ISR */ - g_ble_phy_data.phy_rx_started = 1; - } else { - /* Disable PHY */ - ble_phy_disable(); - STATS_INC(ble_phy_stats, rx_aborts); - } - - /* Count rx starts */ - STATS_INC(ble_phy_stats, rx_starts); - - return true; -} - -static void -ble_phy_isr(void) -{ - uint32_t irq_en; - - os_trace_isr_enter(); - - /* Read irq register to determine which interrupts are enabled */ - irq_en = NRF_RADIO_NS->INTENCLR; - - /* - * NOTE: order of checking is important! Possible, if things get delayed, - * we have both an ADDRESS and DISABLED interrupt in rx state. If we get - * an address, we disable the DISABLED interrupt. - */ - - /* We get this if we have started to receive a frame */ - if ((irq_en & RADIO_INTENCLR_ADDRESS_Msk) && NRF_RADIO_NS->EVENTS_ADDRESS) { - /* - * wfr timer is calculated to expire at the exact time we should start - * receiving a packet (with 1 usec precision) so it is possible it will - * fire at the same time as EVENT_ADDRESS. If this happens, radio will - * be disabled while we are waiting for EVENT_BCCMATCH after 1st byte - * of payload is received and ble_phy_rx_start_isr() will fail. In this - * case we should not clear DISABLED irq mask so it will be handled as - * regular radio disabled event below. In other case radio was disabled - * on purpose and there's nothing more to handle so we can clear mask. - */ - if (ble_phy_rx_start_isr()) { - irq_en &= ~RADIO_INTENCLR_DISABLED_Msk; - } - } - - /* Handle disabled event. This is enabled for both TX and RX. On RX, we - * need to check phy_rx_started flag to make sure we actually were receiving - * a PDU, otherwise this is due to wfr. - */ - if ((irq_en & RADIO_INTENCLR_DISABLED_Msk) && - NRF_RADIO_NS->EVENTS_DISABLED) { - BLE_LL_ASSERT(NRF_RADIO_NS->EVENTS_END || - ((g_ble_phy_data.phy_state == BLE_PHY_STATE_RX) && - !g_ble_phy_data.phy_rx_started)); - NRF_RADIO_NS->EVENTS_END = 0; - NRF_RADIO_NS->EVENTS_DISABLED = 0; - NRF_RADIO_NS->INTENCLR = RADIO_INTENCLR_DISABLED_Msk; - - switch (g_ble_phy_data.phy_state) { - case BLE_PHY_STATE_RX: - ble_phy_plna_disable_lna(); - if (g_ble_phy_data.phy_rx_started) { - ble_phy_rx_end_isr(); - } else { - ble_ll_wfr_timer_exp(NULL); - } - break; - case BLE_PHY_STATE_TX: - ble_phy_plna_disable_pa(); - ble_phy_tx_end_isr(); - break; - default: - BLE_LL_ASSERT(0); - } - } - - g_ble_phy_data.phy_transition_late = 0; - /* Count # of interrupts */ - STATS_INC(ble_phy_stats, phy_isrs); - - os_trace_isr_exit(); -} - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 || \ - MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 || \ - MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 || \ - MYNEWT_VAL(BLE_LL_PA) || \ - MYNEWT_VAL(BLE_LL_LNA) -static int -ble_phy_gpiote_configure(int pin) -{ - NRF_GPIO_Type *port; - - g_ble_phy_gpiote_idx--; - - port = pin > 31 ? NRF_P1_NS : NRF_P0_NS; - pin &= 0x1f; - - /* Configure GPIO directly to avoid dependency to hal_gpio (for porting) */ - port->DIRSET = (1 << pin); - port->OUTCLR = (1 << pin); - - NRF_GPIOTE_NS->CONFIG[g_ble_phy_gpiote_idx] = - (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | - ((pin & 0x1F) << GPIOTE_CONFIG_PSEL_Pos) | - ((port == NRF_P1_NS) << GPIOTE_CONFIG_PORT_Pos); - - BLE_LL_ASSERT(g_ble_phy_gpiote_idx >= 0); - - return g_ble_phy_gpiote_idx; -} -#endif - -static void -ble_phy_dbg_time_setup(void) -{ - int idx __attribute__((unused)) = 8; - - /* - * We setup GPIOTE starting from last configuration index to minimize risk - * of conflict with GPIO setup via hal. It's not great solution, but since - * this is just debugging code we can live with this. - */ - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 - idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN)); - phy_dbg_txrxen_ready_idx = idx; - - NRF_GPIOTE_NS->SUBSCRIBE_SET[idx] = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0); - NRF_GPIOTE_NS->SUBSCRIBE_CLR[idx] = DPPI_CH_SUB(RADIO_EVENTS_READY); - - /* Publish RADIO->EVENTS_READY */ - NRF_RADIO_NS->PUBLISH_READY = DPPI_CH_PUB(RADIO_EVENTS_READY); - NRF_DPPIC_NS->CHENSET = DPPI_CH_MASK(RADIO_EVENTS_READY); - -#endif - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 - idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN)); - phy_dbg_address_end_idx = idx; - - NRF_GPIOTE_NS->SUBSCRIBE_SET[idx] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS); - NRF_GPIOTE_NS->SUBSCRIBE_CLR[idx] = DPPI_CH_SUB(RADIO_EVENTS_END); -#endif - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 - idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN)); - phy_dbg_wfr_idx = idx; - - NRF_GPIOTE_NS->SUBSCRIBE_SET[idx] = DPPI_CH_SUB(RADIO_EVENTS_RXREADY); - - /* TODO figure out how (if?) to subscribe task to multiple DPPI channels - * Currently only last one is working. Also using multiple GPIOTE for same - * PIN doesn't work... - */ - NRF_GPIOTE_NS->SUBSCRIBE_CLR[idx] = DPPI_CH_SUB(RADIO_EVENTS_DISABLED); - NRF_GPIOTE_NS->SUBSCRIBE_CLR[idx] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS); - NRF_GPIOTE_NS->SUBSCRIBE_CLR[idx] = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_3); - - /* Publish RADIO->EVENTS_RXREADY */ - NRF_RADIO_NS->PUBLISH_RXREADY = DPPI_CH_PUB(RADIO_EVENTS_READY); - NRF_DPPIC_NS->CHENSET = DPPI_CH_MASK(RADIO_EVENTS_RXREADY); - - /* Publish RADIO->EVENTS_DISABLED */ - NRF_RADIO_NS->PUBLISH_DISABLED = DPPI_CH_PUB(RADIO_EVENTS_DISABLED); - NRF_DPPIC_NS->CHENSET = DPPI_CH_MASK(RADIO_EVENTS_DISABLED); -#endif -} - -int -ble_phy_init(void) -{ - int rc; - - g_ble_phy_gpiote_idx = 8; - - /* Default phy to use is 1M */ - g_ble_phy_data.phy_cur_phy_mode = BLE_PHY_MODE_1M; - g_ble_phy_data.phy_tx_phy_mode = BLE_PHY_MODE_1M; - g_ble_phy_data.phy_rx_phy_mode = BLE_PHY_MODE_1M; - - g_ble_phy_data.rx_pwr_compensation = 0; - - /* Set phy channel to an invalid channel so first set channel works */ - g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS; - - /* Toggle peripheral power to reset (just in case) */ - NRF_RADIO_NS->POWER = 0; - NRF_RADIO_NS->POWER = 1; - - /* Errata 16 - RADIO: POWER register is not functional - * Workaround: Reset all RADIO registers in firmware. - */ - NRF_RADIO_NS->SUBSCRIBE_TXEN = 0; - NRF_RADIO_NS->SUBSCRIBE_RXEN = 0; - NRF_RADIO_NS->SUBSCRIBE_DISABLE = 0; - - /* Disable all interrupts */ - NRF_RADIO_NS->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; - - /* Set configuration registers */ - NRF_RADIO_NS->MODE = RADIO_MODE_MODE_Ble_1Mbit; - NRF_RADIO_NS->PCNF0 = NRF_PCNF0; - - /* XXX: should maxlen be 251 for encryption? */ - NRF_RADIO_NS->PCNF1 = NRF_MAXLEN | - (RADIO_PCNF1_ENDIAN_Little << RADIO_PCNF1_ENDIAN_Pos) | - (NRF_BALEN << RADIO_PCNF1_BALEN_Pos) | - RADIO_PCNF1_WHITEEN_Msk; - - /* Enable radio fast ramp-up */ - NRF_RADIO_NS->MODECNF0 |= (RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos) & RADIO_MODECNF0_RU_Msk; - - /* Set logical address 1 for TX and RX */ - NRF_RADIO_NS->TXADDRESS = 0; - NRF_RADIO_NS->RXADDRESSES = (1 << 0); - - /* Configure the CRC registers */ - NRF_RADIO_NS->CRCCNF = (RADIO_CRCCNF_SKIPADDR_Skip << RADIO_CRCCNF_SKIPADDR_Pos) | RADIO_CRCCNF_LEN_Three; - - /* Configure BLE poly */ - NRF_RADIO_NS->CRCPOLY = 0x0000065B; - - /* Configure IFS */ - NRF_RADIO_NS->TIFS = BLE_LL_IFS; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - NRF_CCM_NS->INTENCLR = 0xffffffff; - NRF_CCM_NS->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; - NRF_CCM_NS->EVENTS_ERROR = 0; - memset(nrf_encrypt_scratchpad, 0, sizeof(nrf_encrypt_scratchpad)); -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - g_ble_phy_data.phy_aar_scratch = 0; - NRF_AAR_NS->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; - NRF_AAR_NS->INTENCLR = 0xffffffff; - NRF_AAR_NS->EVENTS_END = 0; - NRF_AAR_NS->EVENTS_RESOLVED = 0; - NRF_AAR_NS->EVENTS_NOTRESOLVED = 0; - NRF_AAR_NS->NIRK = 0; -#endif - - /* TIMER0 setup for PHY when using RTC */ - NRF_TIMER0_NS->TASKS_STOP = 1; - NRF_TIMER0_NS->TASKS_SHUTDOWN = 1; - NRF_TIMER0_NS->BITMODE = 3; /* 32-bit timer */ - NRF_TIMER0_NS->MODE = 0; /* Timer mode */ - NRF_TIMER0_NS->PRESCALER = 4; /* gives us 1 MHz */ - - /* Publish events */ - NRF_TIMER0_NS->PUBLISH_COMPARE[0] = DPPI_CH_PUB(TIMER0_EVENTS_COMPARE_0); - NRF_TIMER0_NS->PUBLISH_COMPARE[3] = DPPI_CH_PUB(TIMER0_EVENTS_COMPARE_3); - NRF_RADIO_NS->PUBLISH_END = DPPI_CH_PUB(RADIO_EVENTS_END); - NRF_RADIO_NS->PUBLISH_BCMATCH = DPPI_CH_PUB(RADIO_EVENTS_BCMATCH); - NRF_RADIO_NS->PUBLISH_ADDRESS = DPPI_CH_PUB(RADIO_EVENTS_ADDRESS); - NRF_RTC0_NS->PUBLISH_COMPARE[0] = DPPI_CH_PUB(RTC0_EVENTS_COMPARE_0); - - /* Enable channels we publish on */ - NRF_DPPIC_NS->CHENSET = DPPI_CH_ENABLE_ALL; - - /* Captures tx/rx start in timer0 cc 1 and tx/rx end in timer0 cc 2 */ - NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[1] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS); - NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[2] = DPPI_CH_SUB(RADIO_EVENTS_END); - -#if MYNEWT_VAL(BLE_LL_PA) || MYNEWT_VAL(BLE_LL_LNA) - /* We keep both channels enabled and CLR task subscribed all the time. It's - * enough to just (un)subscribe SET task when needed. - * TODO: figure out if this affects power consumption - */ - -#if PLNA_SINGLE_GPIO - plna_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_PA_GPIO)); - NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY); - NRF_GPIOTE_NS->SUBSCRIBE_CLR[plna_idx] = DPPI_CH_SUB(RADIO_EVENTS_DISABLED); - NRF_GPIOTE_NS->TASKS_CLR[plna_idx] = 1; -#else -#if MYNEWT_VAL(BLE_LL_PA) - plna_pa_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_PA_GPIO)); - NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_pa_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY); - NRF_GPIOTE_NS->SUBSCRIBE_CLR[plna_pa_idx] = DPPI_CH_SUB(RADIO_EVENTS_DISABLED); - NRF_GPIOTE_NS->TASKS_CLR[plna_pa_idx] = 1; -#endif -#if MYNEWT_VAL(BLE_LL_LNA) - plna_lna_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_LNA_GPIO)); - NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_lna_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY); - NRF_GPIOTE_NS->SUBSCRIBE_CLR[plna_lna_idx] = DPPI_CH_SUB(RADIO_EVENTS_DISABLED); - NRF_GPIOTE_NS->TASKS_CLR[plna_lna_idx] = 1; -#endif -#endif - - NRF_DPPIC_NS->CHENSET = DPPI_CH_MASK_PLNA; -#endif - - /* Set isr in vector table and enable interrupt */ -#ifndef RIOT_VERSION - NVIC_SetPriority(RADIO_IRQn, 0); -#endif -#if MYNEWT - NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr); -#else - ble_npl_hw_set_isr(RADIO_IRQn, ble_phy_isr); -#endif - NVIC_EnableIRQ(RADIO_IRQn); - - /* Register phy statistics */ - if (!g_ble_phy_data.phy_stats_initialized) { - rc = stats_init_and_reg(STATS_HDR(ble_phy_stats), - STATS_SIZE_INIT_PARMS(ble_phy_stats, - STATS_SIZE_32), - STATS_NAME_INIT_PARMS(ble_phy_stats), - "ble_phy"); - assert(rc == 0); - - g_ble_phy_data.phy_stats_initialized = 1; - } - - ble_phy_dbg_time_setup(); - - return 0; -} - -int -ble_phy_rx(void) -{ - /* - * Check radio state. - * - * In case radio is now disabling we'll wait for it to finish, but if for - * any reason it's just in idle state we proceed with RX as usual since - * nRF52 radio can ramp-up from idle state as well. - * - * Note that TX and RX states values are the same except for 3rd bit so we - * can make a shortcut here when checking for idle state. - */ - nrf_wait_disabled(); - if ((NRF_RADIO_NS->STATE != RADIO_STATE_STATE_Disabled) && - ((NRF_RADIO_NS->STATE & 0x07) != RADIO_STATE_STATE_RxIdle)) { - ble_phy_disable(); - STATS_INC(ble_phy_stats, radio_state_errs); - return BLE_PHY_ERR_RADIO_STATE; - } - - /* Make sure all interrupts are disabled */ - NRF_RADIO_NS->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; - - /* Clear events prior to enabling receive */ - NRF_RADIO_NS->EVENTS_END = 0; - NRF_RADIO_NS->EVENTS_DISABLED = 0; - - /* Setup for rx */ - ble_phy_rx_xcvr_setup(); - - /* task to start RX should be subscribed here */ - assert(NRF_RADIO_NS->SUBSCRIBE_RXEN & DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0)); - - return 0; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -void -ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, - uint8_t is_central) -{ - memcpy(nrf_ccm_data.key, key, 16); - nrf_ccm_data.pkt_counter = pkt_counter; - memcpy(nrf_ccm_data.iv, iv, 8); - nrf_ccm_data.dir_bit = is_central; - g_ble_phy_data.phy_encrypted = 1; - /* Enable the module (AAR cannot be on while CCM on) */ - NRF_AAR_NS->ENABLE = AAR_ENABLE_ENABLE_Disabled; - NRF_CCM_NS->ENABLE = CCM_ENABLE_ENABLE_Enabled; -} - -void -ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir) -{ - nrf_ccm_data.pkt_counter = pkt_counter; - nrf_ccm_data.dir_bit = dir; -} - -void -ble_phy_encrypt_disable(void) -{ - NRF_CCM_NS->SUBSCRIBE_CRYPT = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); - NRF_CCM_NS->TASKS_STOP = 1; - NRF_CCM_NS->EVENTS_ERROR = 0; - NRF_CCM_NS->ENABLE = CCM_ENABLE_ENABLE_Disabled; - - g_ble_phy_data.phy_encrypted = 0; -} -#endif - -void -ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg) -{ - /* Set transmit end callback and arg */ - g_ble_phy_data.txend_cb = txend_cb; - g_ble_phy_data.txend_arg = arg; -} - -int -ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs) -{ - int rc; - - ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_TX, cputime, rem_usecs); - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_apply(g_ble_phy_data.phy_tx_phy_mode); -#endif - - /* XXX: This should not be necessary, but paranoia is good! */ - /* Clear timer0 compare to RXEN since we are transmitting */ - NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); - - if (ble_phy_set_start_time(cputime, rem_usecs, true) != 0) { - STATS_INC(ble_phy_stats, tx_late); - ble_phy_disable(); - rc = BLE_PHY_ERR_TX_LATE; - } else { - /* Enable PPI to automatically start TXEN */ - NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0); - rc = 0; - - ble_phy_plna_enable_pa(); - } - return rc; -} - -int -ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs) -{ - bool late = false; - int rc = 0; - - ble_phy_trace_u32x2(BLE_PHY_TRACE_ID_START_RX, cputime, rem_usecs); - -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) - ble_phy_mode_apply(g_ble_phy_data.phy_rx_phy_mode); -#endif - - /* XXX: This should not be necessary, but paranoia is good! */ - /* Clear timer0 compare to TXEN since we are transmitting */ - NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); - - if (ble_phy_set_start_time(cputime, rem_usecs, false) != 0) { - STATS_INC(ble_phy_stats, rx_late); - - /* We're late so let's just try to start RX as soon as possible */ - ble_phy_set_start_now(); - - late = true; - } - - /* Enable PPI to automatically start RXEN */ - NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0); - - ble_phy_plna_enable_lna(); - - /* Start rx */ - rc = ble_phy_rx(); - - /* - * If we enabled receiver but were late, let's return proper error code so - * caller can handle this. - */ - if (!rc && late) { - rc = BLE_PHY_ERR_RX_LATE; - } - - return rc; -} - -int -ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans) -{ - int rc; - uint8_t *dptr; - uint8_t *pktptr; - uint8_t payload_len; - uint8_t hdr_byte; - uint32_t state; - uint32_t shortcuts; - - if (g_ble_phy_data.phy_transition_late) { - ble_phy_disable(); - STATS_INC(ble_phy_stats, tx_late); - return BLE_PHY_ERR_TX_LATE; - } - - /* - * This check is to make sure that the radio is not in a state where - * it is moving to disabled state. If so, let it get there. - */ - nrf_wait_disabled(); - - /* - * XXX: Although we may not have to do this here, I clear all the PPI - * that should not be used when transmitting. Some of them are only enabled - * if encryption and/or privacy is on, but I dont care. Better to be - * paranoid, and if you are going to clear one, might as well clear them - * all. - */ - NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); - NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_3); - NRF_AAR_NS->SUBSCRIBE_START = DPPI_CH_UNSUB(RADIO_EVENTS_BCMATCH); - NRF_CCM_NS->SUBSCRIBE_CRYPT = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (g_ble_phy_data.phy_encrypted) { - dptr = (uint8_t *)&g_ble_phy_enc_buf[0]; - pktptr = (uint8_t *)&g_ble_phy_tx_buf[0]; - NRF_CCM_NS->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; - NRF_CCM_NS->INPTR = (uint32_t)dptr; - NRF_CCM_NS->OUTPTR = (uint32_t)pktptr; - NRF_CCM_NS->SCRATCHPTR = (uint32_t)&nrf_encrypt_scratchpad[0]; - NRF_CCM_NS->EVENTS_ERROR = 0; - NRF_CCM_NS->MODE = CCM_MODE_LENGTH_Msk | ble_phy_get_ccm_datarate(); - NRF_CCM_NS->CNFPTR = (uint32_t)&nrf_ccm_data; - } else { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - NRF_AAR_NS->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; -#endif - dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; - pktptr = dptr; - } -#else - dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; - pktptr = dptr; -#endif - - /* Set PDU payload */ - payload_len = pducb(&dptr[3], pducb_arg, &hdr_byte); - - /* RAM representation has S0, LENGTH and S1 fields. (3 bytes) */ - dptr[0] = hdr_byte; - dptr[1] = payload_len; - dptr[2] = 0; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - /* Start key-stream generation and encryption (via short) */ - if (g_ble_phy_data.phy_encrypted) { - NRF_CCM_NS->TASKS_KSGEN = 1; - } -#endif - - NRF_RADIO_NS->PACKETPTR = (uint32_t)pktptr; - - /* Clear the ready, end and disabled events */ - NRF_RADIO_NS->EVENTS_READY = 0; - NRF_RADIO_NS->EVENTS_END = 0; - NRF_RADIO_NS->EVENTS_DISABLED = 0; - - /* Enable shortcuts for transmit start/end. */ - shortcuts = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk; - NRF_RADIO_NS->SHORTS = shortcuts; - NRF_RADIO_NS->INTENSET = RADIO_INTENSET_DISABLED_Msk; - - /* Set the PHY transition */ - g_ble_phy_data.phy_transition = end_trans; - - /* Set transmitted payload length */ - g_ble_phy_data.phy_tx_pyld_len = payload_len; - - /* If we already started transmitting, abort it! */ - state = NRF_RADIO_NS->STATE; - if (state != RADIO_STATE_STATE_Tx) { - /* Set phy state to transmitting and count packet statistics */ - g_ble_phy_data.phy_state = BLE_PHY_STATE_TX; - STATS_INC(ble_phy_stats, tx_good); - STATS_INCN(ble_phy_stats, tx_bytes, payload_len + BLE_LL_PDU_HDR_LEN); - rc = BLE_ERR_SUCCESS; - } else { - ble_phy_disable(); - STATS_INC(ble_phy_stats, tx_late); - rc = BLE_PHY_ERR_RADIO_STATE; - } - - return rc; -} - -int -ble_phy_txpwr_set(int dbm) -{ - /* "Rail" power level if outside supported range */ - dbm = ble_phy_txpower_round(dbm); - - NRF_RADIO_NS->TXPOWER = dbm; - g_ble_phy_data.phy_txpwr_dbm = dbm; - - return 0; -} - -int -ble_phy_txpower_round(int dbm) -{ - /* "Rail" power level if outside supported range */ - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_0dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg3dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg5dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg5dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg6dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg6dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg7dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg7dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm; - } - - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm; -} - -static int -ble_phy_set_access_addr(uint32_t access_addr) -{ - NRF_RADIO_NS->BASE0 = (access_addr << 8); - NRF_RADIO_NS->PREFIX0 = (NRF_RADIO_NS->PREFIX0 & 0xFFFFFF00) | (access_addr >> 24); - - g_ble_phy_data.phy_access_address = access_addr; - - return 0; -} - -int -ble_phy_txpwr_get(void) -{ - return g_ble_phy_data.phy_txpwr_dbm; -} - -void -ble_phy_set_rx_pwr_compensation(int8_t compensation) -{ - g_ble_phy_data.rx_pwr_compensation = compensation; -} - -int -ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit) -{ - assert(chan < BLE_PHY_NUM_CHANS); - - /* Check for valid channel range */ - if (chan >= BLE_PHY_NUM_CHANS) { - return BLE_PHY_ERR_INV_PARAM; - } - - /* Set current access address */ - ble_phy_set_access_addr(access_addr); - - /* Configure crcinit */ - NRF_RADIO_NS->CRCINIT = crcinit; - - /* Set the frequency and the data whitening initial value */ - g_ble_phy_data.phy_chan = chan; - NRF_RADIO_NS->FREQUENCY = g_ble_phy_chan_freq[chan]; - NRF_RADIO_NS->DATAWHITEIV = chan; - - return 0; -} - -/** - * Stop the timer used to count microseconds when using RTC for cputime - */ -static void -ble_phy_stop_usec_timer(void) -{ - NRF_TIMER0_NS->TASKS_STOP = 1; - NRF_TIMER0_NS->TASKS_SHUTDOWN = 1; - NRF_RTC0_NS->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk; -} - -/** - * ble phy disable irq and ppi - * - * This routine is to be called when reception was stopped due to either a - * wait for response timeout or a packet being received and the phy is to be - * restarted in receive mode. Generally, the disable routine is called to stop - * the phy. - */ -static void -ble_phy_disable_irq_and_ppi(void) -{ - NRF_RADIO_NS->INTENCLR = NRF_RADIO_IRQ_MASK_ALL; - NRF_RADIO_NS->SHORTS = 0; - NRF_RADIO_NS->TASKS_DISABLE = 1; - - NRF_TIMER0_NS->SUBSCRIBE_START = DPPI_CH_UNSUB(RTC0_EVENTS_COMPARE_0); - NRF_TIMER0_NS->SUBSCRIBE_CAPTURE[3] = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); - NRF_RADIO_NS->SUBSCRIBE_DISABLE = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_3); - NRF_RADIO_NS->SUBSCRIBE_TXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); - NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); - NRF_AAR_NS->SUBSCRIBE_START = DPPI_CH_UNSUB(RADIO_EVENTS_BCMATCH); - NRF_CCM_NS->SUBSCRIBE_CRYPT = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); - -#if PLNA_SINGLE_GPIO - NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY); -#else -#if MYNEWT_VAL(BLE_LL_PA) - NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_pa_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY); -#endif -#if MYNEWT_VAL(BLE_LL_LNA) - NRF_GPIOTE_NS->SUBSCRIBE_SET[plna_lna_idx] = DPPI_CH_UNSUB(RADIO_EVENTS_READY); -#endif -#endif - - NVIC_ClearPendingIRQ(RADIO_IRQn); - g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE; -} - -void -ble_phy_restart_rx(void) -{ - ble_phy_stop_usec_timer(); - ble_phy_disable_irq_and_ppi(); - - ble_phy_set_start_now(); - /* Enable PPI to automatically start RXEN */ - NRF_RADIO_NS->SUBSCRIBE_RXEN = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0); - - ble_phy_rx(); -} - -static void -ble_phy_dbg_clear_pins(void) -{ -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 - NRF_GPIOTE_NS->TASKS_CLR[phy_dbg_txrxen_ready_idx] = 1; -#endif -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 - NRF_GPIOTE_NS->TASKS_CLR[phy_dbg_address_end_idx] = 1; -#endif -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 - NRF_GPIOTE_NS->TASKS_CLR[phy_dbg_wfr_idx] = 1; -#endif -} - -void -ble_phy_disable(void) -{ - ble_phy_trace_void(BLE_PHY_TRACE_ID_DISABLE); - - ble_phy_stop_usec_timer(); - ble_phy_disable_irq_and_ppi(); - - ble_phy_dbg_clear_pins(); -} - -uint32_t -ble_phy_access_addr_get(void) -{ - return g_ble_phy_data.phy_access_address; -} - -int -ble_phy_state_get(void) -{ - return g_ble_phy_data.phy_state; -} - -int -ble_phy_rx_started(void) -{ - return g_ble_phy_data.phy_rx_started; -} - -uint8_t -ble_phy_xcvr_state_get(void) -{ - uint32_t state; - state = NRF_RADIO_NS->STATE; - return (uint8_t)state; -} - -uint8_t -ble_phy_max_data_pdu_pyld(void) -{ - return BLE_LL_DATA_PDU_MAX_PYLD; -} - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -void -ble_phy_resolv_list_enable(void) -{ - NRF_AAR_NS->NIRK = (uint32_t)g_nrf_num_irks; - g_ble_phy_data.phy_privacy = 1; -} - -void -ble_phy_resolv_list_disable(void) -{ - g_ble_phy_data.phy_privacy = 0; -} -#endif - -#if MYNEWT_VAL(BLE_LL_DTM) -void -ble_phy_enable_dtm(void) -{ - /* When DTM is enabled we need to disable whitening as per - * Bluetooth v5.0 Vol 6. Part F. 4.1.1 - */ - NRF_RADIO_NS->PCNF1 &= ~RADIO_PCNF1_WHITEEN_Msk; -} - -void -ble_phy_disable_dtm(void) -{ - /* Enable whitening */ - NRF_RADIO_NS->PCNF1 |= RADIO_PCNF1_WHITEEN_Msk; -} -#endif - -void -ble_phy_rfclk_enable(void) -{ -#if MYNEWT - nrf5340_net_clock_hfxo_request(); -#else - NRF_CLOCK_NS->TASKS_HFCLKSTART = 1; -#endif -} - -void -ble_phy_rfclk_disable(void) -{ -#if MYNEWT - nrf5340_net_clock_hfxo_release(); -#else - NRF_CLOCK_NS->TASKS_HFCLKSTOP = 1; -#endif -} diff --git a/lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/src/ble_phy_trace.c b/lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/src/ble_phy_trace.c deleted file mode 100644 index dad78679..00000000 --- a/lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/src/ble_phy_trace.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include -#include -#include "controller/ble_phy_trace.h" - -#if MYNEWT_VAL(BLE_PHY_SYSVIEW) - -static os_trace_module_t g_ble_phy_trace_mod; -uint32_t ble_phy_trace_off; - -static void -ble_phy_trace_module_send_desc(void) -{ - os_trace_module_desc(&g_ble_phy_trace_mod, "0 phy_set_tx cputime=%u usecs=%u"); - os_trace_module_desc(&g_ble_phy_trace_mod, "1 phy_set_rx cputime=%u usecs=%u"); - os_trace_module_desc(&g_ble_phy_trace_mod, "2 phy_disable"); -} - -void -ble_phy_trace_init(void) -{ - ble_phy_trace_off = - os_trace_module_register(&g_ble_phy_trace_mod, "ble_phy", 3, - ble_phy_trace_module_send_desc); -} -#endif diff --git a/lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/syscfg.yml b/lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/syscfg.yml deleted file mode 100644 index ed82f6d6..00000000 --- a/lib/bt/host/nimble/nimble/nimble/drivers/nrf5340/syscfg.yml +++ /dev/null @@ -1,62 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - BLE_PHY_SYSVIEW: - description: > - Enable SystemView tracing module for radio driver. - value: 0 - - BLE_PHY_DBG_TIME_TXRXEN_READY_PIN: - description: > - When set to proper GPIO pin number, this pin will be set - to high state when radio is enabled (TASKS_TXEN or TASKS_RXEN) - and back to low state on radio EVENTS_READY. - This can be used to measure radio ram-up time. - - Note: - GPIO control for selected pin needs to be assigned to Network - Core, configure IPC_NRF5340_NET_GPIO in ipc_nrf5340 driver on - Application Core. - value: -1 - - BLE_PHY_DBG_TIME_ADDRESS_END_PIN: - description: > - When set to proper GPIO pin number, this pin will be set - to high state on radio EVENTS_ADDRESS and back to low state - on radio EVENTS_END. - This can be used to measure radio pipeline delays. - - Note: - GPIO control for selected pin needs to be assigned to Network - Core, configure IPC_NRF5340_NET_GPIO in ipc_nrf5340 driver on - Application Core. - value: -1 - - BLE_PHY_DBG_TIME_WFR_PIN: - description: > - When set to proper GPIO pin number, this pin will be set - to high state on radio EVENTS_RXREADY and back to low - state when wfr timer expires. - This can be used to check if wfr is calculated properly. - - Note: - GPIO control for selected pin needs to be assigned to Network - Core, configure IPC_NRF5340_NET_GPIO in ipc_nrf5340 driver on - Application Core. - value: -1 diff --git a/lib/bt/host/nimble/nimble/nimble/drivers/plna/sky66112/pkg.yml b/lib/bt/host/nimble/nimble/nimble/drivers/plna/sky66112/pkg.yml deleted file mode 100644 index c3cb0fd3..00000000 --- a/lib/bt/host/nimble/nimble/nimble/drivers/plna/sky66112/pkg.yml +++ /dev/null @@ -1,31 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/drivers/plna/sky66112 -pkg.description: Driver for SKY66112 front-end module -pkg.author: "Apache Mynewt " -pkg.homepage: "https://mynewt.apache.org/" -pkg.apis: - - ble_ll_pa - - ble_ll_lna -pkg.deps: - - nimble/controller - -pkg.init: - sky66112_init: 999 diff --git a/lib/bt/host/nimble/nimble/nimble/drivers/plna/sky66112/src/sky66112.c b/lib/bt/host/nimble/nimble/nimble/drivers/plna/sky66112/src/sky66112.c deleted file mode 100644 index 4a849fbb..00000000 --- a/lib/bt/host/nimble/nimble/nimble/drivers/plna/sky66112/src/sky66112.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include -#include "syscfg/syscfg.h" -#include "hal/hal_gpio.h" -#include "controller/ble_ll_plna.h" - -#define NO_BYPASS \ - ((MYNEWT_VAL(SKY66112_TX_BYPASS) == 0) && \ - (MYNEWT_VAL(SKY66112_RX_BYPASS) == 0)) - -static void -sky66112_bypass(uint8_t enabled) -{ - if (NO_BYPASS) { - return; - } - - hal_gpio_write(MYNEWT_VAL(SKY66112_PIN_CPS), enabled); -} - -void -ble_ll_plna_pa_init(void) -{ - /* Nothing to do here */ -} - -void -ble_ll_plna_pa_enable(void) -{ - if (!MYNEWT_VAL(SKY66112_TX_BYPASS)) { - sky66112_bypass(0); - } -} - -void -ble_ll_plna_pa_disable(void) -{ - if (!MYNEWT_VAL(SKY66112_TX_BYPASS)) { - sky66112_bypass(1); - } -} - -void -ble_ll_plna_lna_init(void) -{ - /* Nothing to do here */ -} - -void -ble_ll_plna_lna_enable(void) -{ - if (!MYNEWT_VAL(SKY66112_RX_BYPASS)) { - sky66112_bypass(0); - } -} - -void -ble_ll_plna_lna_disable(void) -{ - if (!MYNEWT_VAL(SKY66112_RX_BYPASS)) { - sky66112_bypass(1); - } -} - -void -sky66112_init(void) -{ - int pin; - - /* Use CRX and CTX to enable sleep mode */ - pin = MYNEWT_VAL(SKY66112_PIN_CSD); - if (pin >= 0) { - hal_gpio_init_out(pin, 1); - } - - pin = MYNEWT_VAL(SKY66112_PIN_CPS); - if (NO_BYPASS) { - /* Disable bypass */ - if (pin >= 0) { - hal_gpio_init_out(pin, 0); - } - } else { - /* Enable bypass, we'll disable it when needed */ - assert(pin >= 0); - hal_gpio_init_out(pin, 1); - } - - pin = MYNEWT_VAL(SKY66112_PIN_CHL); - if (pin >= 0) { - hal_gpio_init_out(pin, MYNEWT_VAL(SKY66112_TX_HP_MODE)); - } - - /* Select ANT1 */ - pin = MYNEWT_VAL(SKY66112_PIN_SEL); - if (pin >= 0) { - hal_gpio_init_out(pin, 0); - } -} diff --git a/lib/bt/host/nimble/nimble/nimble/drivers/plna/sky66112/syscfg.yml b/lib/bt/host/nimble/nimble/nimble/drivers/plna/sky66112/syscfg.yml deleted file mode 100644 index 50434553..00000000 --- a/lib/bt/host/nimble/nimble/nimble/drivers/plna/sky66112/syscfg.yml +++ /dev/null @@ -1,66 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - SKY66112_PIN_CSD: - description: > - GPIO pin number to control CSD signal. - When set to '-1', pin state will not be changed and it should be - driven externally. - value: -1 - SKY66112_PIN_CPS: - description: > - GPIO pin number to control CPS signal. - When set to '-1', pin state will not be changed and it should be - driven externally. - value: -1 - SKY66112_PIN_CHL: - description: > - GPIO pin number to control CHL signal. - When set to '-1', pin state will not be changed and it should be - driven externally. - value: -1 - SKY66112_PIN_SEL: - description: > - GPIO pin number to control SEL signal. - When set to '-1', pin state will not be changed and it should be - driven externally. - value: -1 - SKY66112_TX_HP_MODE: - description: > - Enables high-power mode for TX. - Only valid if CHL signal is controller by driver. - value: 0 - SKY66112_TX_BYPASS: - description: > - Enables bypass for TX which effectively disables operation as PA. - Only valid if CPS signal is controller by driver. - value: 0 - SKY66112_RX_BYPASS: - description: > - Enables bypass for RX which effectively disables operation as PA. - Only valid if CPS signal is controller by driver. - value: 0 - -syscfg.vals.!BLE_LL_PA: - # Enable TX bypass by default if PA is disabled - SKY66112_TX_BYPASS: 1 - -syscfg.vals.!BLE_LL_LNA: - # Enable RX bypass by default if LNA is disabled - SKY66112_RX_BYPASS: 1 diff --git a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_att.h b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_att.h index a4665aa3..29c21393 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_att.h +++ b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_att.h @@ -189,7 +189,6 @@ struct os_mbuf; /** Execute Write Response. */ #define BLE_ATT_OP_EXEC_WRITE_RSP 0x19 - /** Read Multiple Variable Lenght Request */ #define BLE_ATT_OP_READ_MULT_VAR_REQ 0x20 @@ -205,8 +204,13 @@ struct os_mbuf; /** Indicate Response. */ #define BLE_ATT_OP_INDICATE_RSP 0x1e +/** Multiple Handle Value Length Notification Request */ +#define BLE_ATT_OP_NOTIFY_MULTI_REQ 0x23 + /** Write Command. */ #define BLE_ATT_OP_WRITE_CMD 0x52 + +/** Signed Write Command */ #define BLE_ATT_OP_SIGNED_WRITE_CMD 0xD2 /** @} */ @@ -343,6 +347,9 @@ uint16_t ble_att_preferred_mtu(void); */ int ble_att_set_preferred_mtu(uint16_t mtu); +int ble_att_set_default_bearer_using_cid(uint16_t conn_handle, uint16_t cid); +uint16_t ble_att_get_default_bearer_cid(uint16_t conn_handle); + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_ead.h b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_ead.h index 38cf1503..8d6b6082 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_ead.h +++ b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_ead.h @@ -121,8 +121,6 @@ int ble_ead_decrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], const uint8_t iv[BLE_EAD_IV_SIZE], const uint8_t *encrypted_payload, size_t encrypted_payload_size, uint8_t *payload); -int ble_ead_serialize_data(const struct enc_adv_data *input, uint8_t *output); - #endif /* ENC_ADV_DATA */ #ifdef __cplusplus diff --git a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_esp_gap.h b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_esp_gap.h index 705f29a9..c94d81eb 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_esp_gap.h +++ b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_esp_gap.h @@ -30,6 +30,21 @@ typedef enum gap_status gap_status_t; #define BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_PROV_SRV_ADV 3 #define BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_PROXY_SRV_ADV 4 +#define ESP_BLE_VENDOR_LEGACY_SCAN_REQ_EVT_MASK BIT(0) +#define ESP_BLE_VENDOR_CHAN_MAP_UPDATE_CMPL_EVT_MASK BIT(1) +#define ESP_BLE_VENDOR_TL_RUNNING_STATUS_EVT_MASK BIT(2) +#define ESP_BLE_VENDOR_SLEEP_WAKEUP_EVT_MASK BIT(3) +#define ESP_BLE_VENDOR_CONNECT_IND_REQ_EVT_MASK BIT(4) +#define ESP_BLE_VENDOR_AUX_CONNECT_RSP_EVT_MASK BIT(5) + +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) +#ifdef CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT +#define MAX_REATTEMPT_ALLOWED CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT +#else +#define MAX_REATTEMPT_ALLOWED 0 +#endif +#endif + /** * Configure LE Data Length in controller (OGF = 0x08, OCF = 0x0022). * @@ -88,6 +103,15 @@ int ble_hs_hci_util_write_sugg_def_data_len(uint16_t sugg_max_tx_octets, uint16_ */ int ble_gap_wl_tx_rmv(const ble_addr_t *addrs); +/** + * Adds the address in controller's white list. + * + * @param addrs The entry to be added in the white list. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_wl_tx_add(const ble_addr_t *addrs); + /** * Clears all addresses from controller's white list. * @@ -257,6 +281,20 @@ int ble_gap_set_chan_select(uint8_t select); int ble_gap_dev_authorization(uint16_t conn_handle, bool authorized); +/** + * Sets the vendor-specific event mask for BLE host. + * + * This function configures the vendor-specific event mask, enabling or disabling + * specific vendor-defined events from being reported by the controller. + * + * @param event_mask Bitmask representing the events to enable. + * + * @return 0 on success; + * A nonzero value indicating an error if the command fails. + */ +int +ble_hs_send_vs_event_mask(uint32_t event_mask); + void ble_gap_rx_test_evt(const void *buf, uint8_t len); void ble_gap_tx_test_evt(const void *buf, uint8_t len); void ble_gap_end_test_evt(const void *buf, uint8_t len); diff --git a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_esp_gattc_cache.h b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_esp_gattc_cache.h new file mode 100644 index 00000000..7ec9ff2e --- /dev/null +++ b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_esp_gattc_cache.h @@ -0,0 +1,255 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#ifndef H_BLE_ESP_GATTC_GET_CACHE_ +#define H_BLE_ESP_GATTC_GET_CACHE_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if MYNEWT_VAL(BLE_GATT_CACHING) +#include "../src/ble_gattc_cache_priv.h" +/** Enumerates types of GATT database attributes */ + +typedef enum { + ESP_BLE_GATT_DB_PRIMARY_SERVICE, /*!< Primary services in the GATT database */ + ESP_BLE_GATT_DB_SECONDARY_SERVICE, /*!< Secondary services in the GATT database */ + ESP_BLE_GATT_DB_INCLUDED_SERVICE, /*!< Included services in the GATT database */ + ESP_BLE_GATT_DB_CHARACTERISTIC, /*!< Characteristics in the GATT database */ + ESP_BLE_GATT_DB_DESCRIPTOR, /*!< Descriptors in the GATT database */ + ESP_BLE_GATT_DB_ALL, /*!< All attributes in the GATT database */ +} esp_ble_gatt_db_attr_type_t; + +/** @brief Represents a GATT service element. */ +typedef struct { + bool is_primary; /*!< Indicates if the service is primary. */ + uint16_t start_handle; /*!< Service start handle. */ + uint16_t end_handle; /*!< Service end handle. */ + ble_uuid_any_t uuid; /*!< Service UUID. */ +} ble_gattc_service_elem_t; + +/** @brief Represents a GATT included service element. */ +typedef struct { + uint16_t handle; /*!< handle */ + uint16_t incl_svc_s_handle; /*!< Included service start handle. */ + uint16_t incl_svc_e_handle; /*!< Included service end handle. */ + ble_uuid_any_t uuid; /*!< Included service UUID. */ +} ble_gattc_included_svc_elem_t; + +/** @brief Represents a GATT characteristic element. */ +typedef struct { + uint16_t char_handle; /*!< Characteristic value handle. */ + uint8_t properties; /*!< Characteristic properties. */ + ble_uuid_any_t uuid; /*!< Characteristic UUID. */ +} ble_gattc_char_elem_t; + +/** @brief Represents a GATT descriptor element. */ +typedef struct { + uint16_t handle; /*!< Descriptor handle. */ + ble_uuid_any_t uuid; /*!< Descriptor UUID. */ +} ble_gattc_descr_elem_t; + +/** + * Retrieve service(s) from the cached GATT database for a given connection. + * + * This function searches the local GATT cache for a service matching the given UUID. + * If `svc_uuid` is not NULL, it returns the matching service(s). + * If `svc_uuid` is NULL, it returns all cached services. + * + * @param conn_handle Connection handle of the peer device. + * @param svc_uuid UUID of the service to search for (can be NULL to fetch all services). + * @param result Output buffer to store the retrieved service(s). + * @param count Number of entries in the cache + * @param offset Index offset for paginated access (used when more services exist). + * + * @return 0 on success, error code otherwise. + */ + + +int ble_gattc_get_service(uint16_t conn_handle, + ble_uuid_t *svc_uuid, + ble_gattc_service_elem_t *result, + uint16_t *count, uint16_t offset); +/** + * Retrieve all characteristics in a specified handle range from the cached GATT database. + * + * This function fetches all characteristics between the given start and end handles, + * typically the range of a service. Characteristics are returned from the local cache. + * + * @param conn_handle Connection handle of the peer device. + * @param start_handle Start handle of the attribute range (usually the service's start handle). + * @param end_handle End handle of the attribute range (usually the service's end handle). + * @param result Output buffer to store the retrieved characteristics. + * @param count The number of characteristics to retrieve. It will be updated with the actual number of characteristics found. + * @param offset The position offset to retrieve + * + * @return 0 on success, error code otherwise. + */ + + +int ble_gattc_get_all_char(uint16_t conn_handle, + uint16_t start_handle, + uint16_t end_handle, + ble_gattc_char_elem_t *result, + uint16_t *count, uint16_t offset); +/** + * Retrieve all descriptors of a given characteristic from the cached GATT database. + * + * This function fetches all descriptors associated with the specified characteristic + * handle from the local GATT cache. + * + * @param conn_handle Connection handle of the peer device. + * @param char_handle Handle of the characteristic whose descriptors are to be fetched. + * @param result Output buffer to store the retrieved descriptors. + * @param count The number of descriptors to retrieve. It will be updated with the actual number of descriptors found. + * @param offset The position offset to retrieve + * + * @return 0 on success, error code otherwise. + */ + + + +int ble_gattc_get_all_descr(uint16_t conn_handle, + uint16_t char_handle, + ble_gattc_descr_elem_t *result, + uint16_t *count, uint16_t offset); + +/** + * Retrieve characteristics with a specific UUID from the cached GATT database. + * + * This function fetches all characteristics matching the given UUID within the specified + * handle range (typically a service's start and end handles) from the local GATT cache. + * + * @param conn_handle Connection handle of the peer device. + * @param start_handle Start handle of the attribute range. + * @param end_handle End handle of the attribute range. + * @param char_uuid UUID of the characteristic to search for. + * @param result Output buffer to store the retrieved characteristics. + * @param count The number of characteristics to retrieve. It will be updated with the actual number of characteristics found. + * + * @return 0 on success, error code otherwise. + */ + + +int ble_gattc_get_char_by_uuid(uint16_t conn_handle, + uint16_t start_handle, + uint16_t end_handle, + ble_uuid_t *char_uuid, + ble_gattc_char_elem_t *result, uint16_t *count); + +/** + * Retrieve descriptors with a specific UUID from the cached GATT database. + * + * This function searches for all descriptors that match the given descriptor UUID + * within the specified handle range and associated with the given characteristic UUID. + * + * @param conn_handle Connection handle of the peer device. + * @param start_handle Start handle of the attribute range. + * @param end_handle End handle of the attribute range. + * @param char_uuid UUID of the characteristic to which the descriptor belongs. + * @param descr_uuid UUID of the descriptor to search for. + * @param result Output buffer to store the retrieved descriptors. + * @param count The number of descriptors to retrieve. It will be updated with the actual number of descriptors found. + * + * @return 0 on success, error code otherwise. + */ + +int ble_gattc_get_descr_by_uuid(uint16_t conn_handle, + uint16_t start_handle, + uint16_t end_handle, + ble_uuid_t *char_uuid, + ble_uuid_t *descr_uuid, + ble_gattc_descr_elem_t *result, uint16_t *count); +/** + * Retrieve descriptors with a specific UUID for a given characteristic handle from the cached GATT database. + * + * This function searches the local GATT cache for descriptors matching the provided UUID + * that are associated with the specified characteristic handle. + * + * @param conn_handle Connection handle of the peer device. + * @param char_handle Handle of the characteristic whose descriptors are to be searched. + * @param descr_uuid UUID of the descriptor to search for. + * @param result Output buffer to store the retrieved descriptors. + * @param count The number of descriptors to retrieve. It will be updated with the actual number of descriptors found. + * + * @return 0 on success, error code otherwise. + */ + +int ble_gattc_get_descr_by_char_handle(uint16_t conn_handle, + uint16_t char_handle, + ble_uuid_t *descr_uuid, + ble_gattc_descr_elem_t *result, uint16_t *count); +/** + * Retrieve included services within a specified handle range from the cached GATT database. + * + * This function searches for included (referenced) services within the specified start and end handle range. + * If `incl_uuid` is not NULL, it returns only the included services that match the provided UUID. + * Otherwise, it returns all included services found in the range. + * + * @param conn_handle Connection handle of the peer device. + * @param start_handle Start handle of the attribute range. + * @param end_handle End handle of the attribute range. + * @param incl_uuid UUID of the included service to search for (can be NULL to fetch all). + * @param result Output buffer to store the retrieved included services. + * @param count The number of included services to retrieve. It will be updated with the actual number of included services found. + * + * @return 0 on success, error code otherwise. + */ +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) +int ble_gattc_get_include_service(uint16_t conn_handle, + uint16_t start_handle, + uint16_t end_handle, + ble_uuid_t *incl_uuid, + ble_gattc_included_svc_elem_t *result, uint16_t *count); +#endif + +/** + * Get the number of attributes of a given type from the cached GATT database. + * + * This function counts the number of attributes (services, characteristics, or descriptors) + * present in the local GATT cache within a specified handle range or under a specific + * characteristic, depending on the attribute type. + * + * @param conn_handle Connection handle of the peer device. + * @param type Type of attribute to count (e.g., service, characteristic, descriptor). + * @param start_handle Start handle of the range to search. + * @param end_handle End handle of the range to search. + * @param char_handle Characteristic handle (used only if type is `ESP_BLE_GATT_DB_DESCRIPTOR`). + * @param count Output pointer to store the number of attributes found. + * + * @return 0 on success, error code otherwise. + */ + +int ble_gattc_get_attr_count(uint16_t conn_handle, esp_ble_gatt_db_attr_type_t type, + uint16_t start_handle, uint16_t end_handle, + uint16_t char_handle, uint16_t *count); +/** + * Retrieve cached GATT attributes within a given handle range. + * + * This function fetches services, characteristics, and descriptors from the local + * GATT database cache between the specified start and end handles. + * + * @param conn_handle Connection handle of the peer device. + * @param start_handle Start handle of the GATT database range. + * @param end_handle End handle of the GATT database range. + * @param result Output buffer to store the retrieved GATT database elements. + * @param count The number of attribute to retrieve. It will be updated with the actual number of attributes found. + * + * @return 0 on success, error code otherwise. + */ + + +int ble_gattc_get_db(uint16_t conn_handle, + uint16_t start_handle, uint16_t end_handle, + ble_gattc_db_elem_t* result, uint16_t *count); + +#ifdef __cplusplus +} +#endif + +#endif +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_gap.h b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_gap.h index ebab72b8..d9c1bf34 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_gap.h +++ b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_gap.h @@ -161,6 +161,16 @@ struct hci_conn_update; #define BLE_GAP_EVENT_AUTHORIZE 32 #define BLE_GAP_EVENT_TEST_UPDATE 33 #define BLE_GAP_EVENT_DATA_LEN_CHG 34 +#define BLE_GAP_EVENT_CONNLESS_IQ_REPORT 35 +#define BLE_GAP_EVENT_CONN_IQ_REPORT 36 +#define BLE_GAP_EVENT_CTE_REQ_FAILED 37 + +//TODO : Deprecate the EVENT_LINK_ESTAB going ahead +#define BLE_GAP_EVENT_LINK_ESTAB 38 +#define BLE_GAP_EVENT_EATT 39 +#define BLE_GAP_EVENT_PER_SUBEV_DATA_REQ 40 +#define BLE_GAP_EVENT_PER_SUBEV_RESP 41 +#define BLE_GAP_EVENT_PERIODIC_TRANSFER_V2 42 /* DTM events */ #define BLE_GAP_DTM_TX_START_EVT 0 @@ -218,6 +228,18 @@ struct ble_gap_sec_state { unsigned authorize:1; }; +/** Read Remote Version parameters **/ +struct ble_gap_read_rem_ver_params { + /** Version of the Current LMP **/ + uint8_t version; + + /** Company Identifier **/ + uint16_t manufacturer; + + /** Revision of the LMP **/ + uint16_t subversion; +}; + /** Advertising parameters */ struct ble_gap_adv_params { /** Advertising mode. Can be one of following constants: @@ -322,6 +344,9 @@ struct ble_gap_ext_disc_params { /** If passive scan should be used */ uint8_t passive:1; + + /** If observation procedure is to be disabled. By default all advertisement reports are accepted */ + uint8_t disable_observer_mode:1; }; /** @brief Discovery parameters */ @@ -343,6 +368,9 @@ struct ble_gap_disc_params { /** If enable duplicates filtering */ uint8_t filter_duplicates:1; + + /** If observation procedure is to be disabled. By default all advertisement reports are accepted */ + uint8_t disable_observer_mode:1; }; /** @brief Connection parameters update parameters */ @@ -504,6 +532,66 @@ struct ble_gap_repeat_pairing { uint8_t new_bonding:1; }; + +#define BLE_GAP_PER_ADV_DATA_STATUS_COMPLETE 0x00 +#define BLE_GAP_PER_ADV_DATA_STATUS_INCOMPLETE 0x01 +#define BLE_GAP_PER_ADV_DATA_STATUS_TRUNCATED 0x02 +#define BLE_GAP_PER_ADV_DATA_STATUS_RX_FAILED 0xFF + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +struct ble_gap_periodic_adv_response { + /** The subevent in which the response is received */ + uint8_t subevent; + + /** Status of the subevent indication. + * + * 0 if subevent indication was transmitted. + * 1 if subevent indication was not transmitted. + * All other values RFU. + */ + + /** The adv handle of the adv */ + uint8_t adv_handle; + + uint8_t tx_status; + + /** The TX power of the response in dBm */ + int8_t tx_power; + + /** The RSSI of the response in dBm */ + int8_t rssi; + + /** The Constant Tone Extension (CTE) of the advertisement */ + uint8_t cte_type; + + /** The response slot */ + uint8_t response_slot; + + /** Data status */ + uint8_t data_status; + + /** Data length */ + uint8_t data_length; + + /** response data */ + const uint8_t *data; +}; + +struct ble_gap_periodic_adv_response_params { + /** The periodic advertsing event for which response shall be sent in */ + uint16_t request_event; + + /** The request subevent for which response shall be sent in */ + uint8_t request_subevent; + + /** The subevent the response shall be sent in */ + uint8_t response_subevent; + + /** The response slot the response shall be sent in */ + uint8_t response_slot; +}; +#endif + /** * Represents a GAP-related event. When such an event occurs, the host * notifies the application by passing an instance of this structure to an @@ -537,8 +625,63 @@ struct ble_gap_event { /** The handle of the relevant connection. */ uint16_t conn_handle; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + /* + * Adv_Handle is used to identify an advertising set. + * If the connection is established from periodic advertising with responses + * and Role is 0x00 then the Advertising_Handle parameter shall be set + * according to the periodic advertising train the connection was established from + */ + uint8_t adv_handle; + + /* + * Sync_Handle identifying the periodic advertising train + * If the connection is established from periodic advertising with responses + * and Role is 0x01, then the Sync_Handle parameter shall be set according + * to the periodic advertising train the connection was established from + */ + uint16_t sync_handle; +#endif } connect; + /** + * Represents a successful Link establishment attempt. Sometimes, in noisy environment, + * even if BLE_GAP_EVENT_CONNECT is posted, the link syncronization procedure may fail + * and link gets disconnected with reason 0x3E. Application can wait for below event to ensure + * the link syncronization is completed. Valid for the following event + * types: + * o BLE_GAP_EVENT_LINK_ESTAB + */ + + struct { + /** + * The final status of the link establishment; + * o 0: the connection was successfully established. + * o BLE host error code: the connection attempt failed for + * the specified reason. + */ + int status; + + /** The handle of the relevant connection. */ + uint16_t conn_handle; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + /* + * Adv_Handle is used to identify an advertising set. + * If the connection is established from periodic advertising with responses + * and Role is 0x00 then the Advertising_Handle parameter shall be set + * according to the periodic advertising train the connection was established from + */ + uint8_t adv_handle; + /* + * Sync_Handle identifying the periodic advertising train + * If the connection is established from periodic advertising with responses + * and Role is 0x01, then the Sync_Handle parameter shall be set according + * to the periodic advertising train the connection was established from + */ + uint16_t sync_handle; +#endif + } link_estab; + /** * Represents a terminated connection. Valid for the following event * types: @@ -921,6 +1064,18 @@ struct ble_gap_event { /** Advertiser clock accuracy */ uint8_t adv_clk_accuracy; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + /** Number of subevents. If zero, the periodic advertiser will be a broadcaster, + * without responses. + */ + uint8_t num_subevents; + /** Interval between subevents (N * 1.25 ms) */ + uint8_t subevent_interval; + /** Time between the advertising packet and the first response slot (N * 1.25 ms). */ + uint8_t response_slot_delay; + /** Time between response slots (N * 0.125 ms) */ + uint8_t response_slot_spacing; +#endif } periodic_sync; /** @@ -938,10 +1093,24 @@ struct ble_gap_event { /** Received signal strength indication in dBm (127 if unavailable) */ int8_t rssi; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + /** + * It indicates the periodic advertising event counter (paEventCounter) of + * the event that the periodic advertising packet was received in. + */ + uint16_t event_counter; + /** + * It indicates Periodic Advertising with Responses subevent in which + * the periodic advertising packet was received in. + */ + uint8_t subevent; +#endif + /** Advertising data status, can be one of following constants: * - BLE_HCI_PERIODIC_DATA_STATUS_COMPLETE * - BLE_HCI_PERIODIC_DATA_STATUS_INCOMPLETE * - BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED + * - BLE_HCI_PERIODIC_DATA_STATUS_RX_FAILED */ uint8_t data_status; @@ -1023,6 +1192,18 @@ struct ble_gap_event { /** Advertiser clock accuracy */ uint8_t adv_clk_accuracy; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + /** Number of subevents. If zero, the periodic advertiser will be a broadcaster,- + * without responses. + */ + uint8_t num_subevents; + /** Interval between subevents (N * 1.25 ms) */ + uint8_t subevent_interval; + /** Time between the advertising packet and the first response slot (N * 1.25 ms). */ + uint8_t response_slot_delay; + /** Time between response slots (N * 0.125 ms) */ + uint8_t response_slot_spacing; +#endif } periodic_transfer; #endif @@ -1167,6 +1348,30 @@ struct ble_gap_event { uint16_t supervision_tmo; } subrate_change; #endif +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + /** + * Represents a periodic advertising subevent data request + * with parameters valid for the following event types: + * o BLE_GAP_EVENT_PER_SUBEV_DATA_REQ + */ + struct { + /** Advertising handle */ + uint8_t adv_handle; + + /** Subevent start */ + uint8_t subevent_start; + + /** Number of subevents */ + uint8_t subevent_data_count; + } periodic_adv_subev_data_req; + + /** + * Represents a periodic advertising response + * with parameters valid for the following event types: + * o BLE_GAP_EVENT_PER_SUBEV_RESP + */ + struct ble_gap_periodic_adv_response periodic_adv_response; +#endif #if MYNEWT_VAL(BLE_HCI_VS) /** @@ -1206,6 +1411,31 @@ struct ble_gap_event { int out_response; } authorize; +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + /** + * EATT Event + * + * Valid for the following event types: + * o BLE_GAP_EVENT_EATT + * + */ + struct { + /* Connection Handle */ + uint16_t conn_handle; + + /** Connected Status + * + * EATT Connected: 0 + * EATT Disconnected: 1 + */ + uint8_t status; + + /* CID of the bearer */ + uint16_t cid; + + } eatt; +#endif + #if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) /** * Represents a event mentioning connection reattempt @@ -1246,7 +1476,6 @@ struct ble_gap_event { */ uint16_t num_pkt; } dtm_state; - /** * Represent an event for LE Data length change * @@ -1269,6 +1498,161 @@ struct ble_gap_event { /* Max Rx Time */ uint16_t max_rx_time; } data_len_chg; +#if MYNEWT_VAL(BLE_AOA_AOD) + /** + * Represents a AOA/AOD connectionless iq report event + * Valid for the following event types: + * o BLE_GAP_EVENT_CONNLESS_IQ_RPT + */ + struct { + /** Sync_Handle identifying the periodic advertising train. + * Range: 0x0000 to 0x0EFF + * 0x0FFF indicates Receiver Test mode. + */ + uint16_t sync_handle; + + /** The index of the channel on which the packet was received. + * Range: 0x00 to 0x27 + * Note: 0x25 to 0x27 can be used only for packets generated during test modes. + */ + uint8_t channel_index; + + /** RSSI of the packet. + * Range: -1270 to +200 (Units: 0.1 dBm). + */ + int16_t rssi; + + /** Antenna ID used for receiving the packet. */ + uint8_t rssi_antenna_id; + + /** Type of Constant Tone Extension (CTE). + * 0x00: AoA Constant Tone Extension + * 0x01: AoD Constant Tone Extension with 1 μs slots + * 0x02: AoD Constant Tone Extension with 2 μs slots + */ + uint8_t cte_type; + + /** Switching and sampling slot durations. + * 0x01: Switching and sampling slots are 1 μs each + * 0x02: Switching and sampling slots are 2 μs each + */ + uint8_t slot_durations; + + /** Status of the packet. + * 0x00: CRC was correct + * 0x01: CRC was incorrect, but Length and CTETime fields were used to determine sampling points + * 0x02: CRC was incorrect, but the Controller determined the position and length of the CTE in another way + * 0xFF: Insufficient resources to sample (Channel_Index, CTE_Type, and Slot_Durations invalid) + */ + uint8_t packet_status; + + /** Value of paEventCounter for the reported AUX_SYNC_IND PDU. */ + uint16_t periodic_event_counter; + + /** Total number of sample pairs (I and Q samples). + * 0x00: No samples provided (only permitted if Packet_Status is 0xFF) + * 0x09 to 0x52: Total number of sample pairs + */ + uint8_t sample_count; + + /** Array of I samples for the reported packet (signed integers). + * Each value represents an I sample at a specific sampling point. + * 0x80 indicates no valid sample available. + */ + int8_t *i_samples; + + /** Array of Q samples for the reported packet (signed integers). + * Each value represents a Q sample at a specific sampling point. + * 0x80 indicates no valid sample available. + */ + int8_t *q_samples; + } connless_iq_report; + + /** + * Represents a connection iq report. + * Valid for the following event types: + * o BLE_GAP_EVENT_CONN_IQ_RPT + */ + struct { + /** Connection handle identifying the connection. */ + uint16_t conn_handle; + + /** PHY used for receiving the packet. + * 0x01: LE 1M PHY + * 0x02: LE 2M PHY + */ + uint8_t rx_phy; + + /** The index of the data channel on which the packet was received. */ + uint8_t data_channel_index; + + /** RSSI of the packet. + * Range: -1270 to +200 (Units: 0.1 dBm). + */ + int16_t rssi; + + /** Antenna ID used for receiving the packet. */ + uint8_t rssi_antenna_id; + + /** Type of Constant Tone Extension (CTE). + * 0x00: AoA Constant Tone Extension + * 0x01: AoD Constant Tone Extension with 1 μs slots + * 0x02: AoD Constant Tone Extension with 2 μs slots + */ + uint8_t cte_type; + + /** Switching and sampling slot durations. + * 0x01: Switching and sampling slots are 1 μs each + * 0x02: Switching and sampling slots are 2 μs each + */ + uint8_t slot_durations; + + /** Status of the packet. + * 0x00: CRC was correct + * 0x01: CRC was incorrect, but Length and CTETime fields were used to determine sampling points + * 0x02: CRC was incorrect, but the Controller determined the position and length of the CTE in another way + * 0xFF: Insufficient resources to sample (Channel_Index, CTE_Type, and Slot_Durations invalid) + */ + uint8_t packet_status; + + /** Value of the connection event counter for the reported packet. */ + uint16_t conn_event_counter; + + /** Total number of sample pairs (I and Q samples). + * 0x00: No samples provided (only permitted if Packet_Status is 0xFF) + * 0x09 to 0x52: Total number of sample pairs + */ + uint8_t sample_count; + + /** Array of I samples for the reported packet (signed integers). + * Each value represents an I sample at a specific sampling point. + * 0x80 indicates no valid sample available. + */ + int8_t *i_samples; + + /** Array of Q samples for the reported packet (signed integers). + * Each value represents a Q sample at a specific sampling point. + * 0x80 indicates no valid sample available. + */ + int8_t *q_samples; + } conn_iq_report; + + /** + * Represents a cte req failed event + * Valid for the following event types: + * o BLE_GAP_EVENT_CTE_REQ_FAILED + */ + struct { + /** Status indicating the reason for failure. + * Refer to HCI error codes for detailed status values. + */ + uint8_t status; + + /** Connection handle identifying the connection. */ + uint16_t conn_handle; + } cte_req_fail; + +#endif }; }; @@ -1605,6 +1989,14 @@ struct ble_gap_ext_adv_params { /** Advertising Set ID */ uint8_t sid; + +#if MYNEWT_VAL(BLE_EXT_ADV_V2) + /** Primary PHY options */ + uint8_t primary_phy_opt; + + /** Secondary PHY options */ + uint8_t secondary_phy_opt; +#endif }; /** @@ -1738,6 +2130,34 @@ struct ble_gap_periodic_adv_params { * defaults */ uint16_t itvl_max; + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + /** Number of subevents + * If zero, the periodic advertiser will be a broadcaster, without responses. + */ + uint8_t num_subevents; + + /** Interval between subevents (N * 1.25 ms) + * Shall be between 7.5ms and 318.75 ms. + */ + uint8_t subevent_interval; + + /** Time between the advertising packet in a subevent and the + * first response slot (N * 1.25 ms) + * + */ + uint8_t response_slot_delay; + + /** Time between response slots (N * 0.125 ms) + * Shall be between 0.25 and 31.875 ms. + */ + uint8_t response_slot_spacing; + + /** Number of subevent response slots + * If zero, response_slot_delay and response_slot_spacing are ignored. + */ + uint8_t num_response_slots; +#endif /* PERIODIC_ADV_WITH_RESPONSES */ }; #if MYNEWT_VAL(BLE_PERIODIC_ADV_ENH) @@ -1779,8 +2199,108 @@ struct ble_gap_periodic_sync_params { created */ unsigned int filter_duplicates:1; #endif +#if MYNEWT_VAL(BLE_AOA_AOD) + /** + * Specifies the type of Constant Tone Extension (CTE) to which the receiver should not synchronize. + * This parameter determines which types of packets with specific CTE configurations are ignored during synchronization. + * + * Possible values: + * 0: Do not sync to packets with an AoA Constant Tone Extension. + * 1: Do not sync to packets with an AoD Constant Tone Extension with 1 μs slots. + * 2: Do not sync to packets with an AoD Constant Tone Extension with 2 μs slots. + * 3: Do not sync to packets with a type 3 Constant Tone Extension (currently reserved for future use). + * 4: Do not sync to packets without a Constant Tone Extension. + */ + uint8_t sync_cte_type; +#endif }; + +#if MYNEWT_VAL(BLE_AOA_AOD) +#define BLE_GAP_CTE_TYPE_AOA 0x0 +#define BLE_GAP_CTE_TYPE_AOD_1US 0x1 +#define BLE_GAP_CTE_TYPE_AOD_2US 0x2 + +#define BLE_GAP_CTE_RSP_ALLOW_AOA_MASK BLE_HCI_CTE_RSP_ALLOW_AOA_MASK +#define BLE_GAP_CTE_RSP_ALLOW_AOD_1US_MASK BLE_HCI_CTE_RSP_ALLOW_AOD_1US_MASK +#define BLE_GAP_CTE_RSP_ALLOW_AOD_2US_MASK BLE_HCI_CTE_RSP_ALLOW_AOD_2US_MASK + + +/** @brief Periodic advertising parameters */ +struct ble_gap_periodic_adv_cte_params { + /** + * Constant Tone Extension length in 8 µs units (Range: 0x02 to 0x14) + */ + uint8_t cte_length; + + /** + * Constant Tone Extension type + * 0x00 : AoA Constant Tone Extension + * 0x01 : AoD Constant Tone Extension with 1 µs slots + * 0x02 : AoD Constant Tone Extension with 2 µs slots + */ + uint8_t cte_type; + + /** + * The number of Constant Tone Extensions to transmit in each periodic + * advertising interval (Range: 0x01 to 0x10) + */ + uint8_t cte_count; + + /** + * The number of Antenna IDs in the pattern + * (Range: 0x02 to 0x4B) + */ + uint8_t switching_pattern_length; + + /** + * Antenna ID in the pattern. + * there is a pattern pointer + */ + uint8_t* antenna_ids; + +}; + +struct ble_gap_cte_sampling_params { + /** + * The sampling rate used by the Controller + * 0x01 : Switching and sampling slots are 1 μs each + * 0x02 : Switching and sampling slots are 2 μs each + */ + uint8_t slot_durations; + + /** + * The number of Antenna IDs in the pattern + * (Range: 0x02 to 0x4B) + */ + uint8_t switching_pattern_length; + + /** + * Antenna ID in the pattern. + * there is a pattern pointer + */ + uint8_t* antenna_ids; + +}; + +#endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +struct ble_gap_set_periodic_adv_subev_data_params { + /** The subevent to set data for */ + uint8_t subevent; + + /** The first response slot to listen to */ + uint8_t response_slot_start; + + /** The number of response slots to listen to */ + uint8_t response_slot_count; + + /** The data to send */ + struct os_mbuf *data; +}; +#endif + /** * Configure periodic advertising for specified advertising instance * @@ -2023,6 +2543,122 @@ int ble_gap_clear_periodic_adv_list(void); * @return 0 on success; nonzero on failure. */ int ble_gap_read_periodic_adv_list_size(uint8_t *per_adv_list_size); + + + +#if MYNEWT_VAL(BLE_AOA_AOD) + +/** + * Set connectionless Constant Tone Extension (CTE) transmission parameters. + * + * @param instance Periodic advertising instance ID. + * @param params Pointer to the CTE transmission parameters. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_set_connless_cte_transmit_params(uint8_t instance, + const struct ble_gap_periodic_adv_cte_params *params); + +/** + * Enable or disable connectionless CTE transmission. + * + * @param instance Periodic advertising instance ID. + * @param cte_enable 0x00 to disable, 0x01 to enable CTE transmission. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_set_connless_cte_transmit_enable(uint8_t instance, uint8_t cte_enable); + +/** + * Enable or disable connectionless IQ sampling for periodic advertising. + * + * @param sync_handle Sync handle identifying the periodic advertiser. + * @param sampling_enable 0x00 to disable, 0x01 to enable IQ sampling. + * @param max_sampled_ctes Maximum number of sampled CTEs. + * @param cte_sampling_params Pointer to the CTE sampling parameters. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_set_connless_iq_sampling_enable(uint16_t sync_handle, uint8_t sampling_enable, + uint8_t max_sampled_ctes, + const struct ble_gap_cte_sampling_params *cte_sampling_params); + +/** + * Set connection CTE receive parameters. + * + * @param conn_handle Connection handle. + * @param sampling_enable 0x00 to disable, 0x01 to enable CTE sampling. + * @param cte_sampling_params Pointer to the CTE sampling parameters. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_set_conn_cte_recv_param(uint16_t conn_handle, uint8_t sampling_enable, + const struct ble_gap_cte_sampling_params *cte_sampling_params); + +/** + * Set connection CTE transmission parameters. + * + * @param conn_handle Connection handle. + * @param cte_types Bitfield specifying supported CTE types. + * @param switching_pattern_len Length of the antenna switching pattern. + * @param antenna_ids Pointer to the array of antenna IDs. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_set_conn_cte_transmit_param(uint16_t conn_handle, uint8_t cte_types, + uint8_t switching_pattern_len, const uint8_t *antenna_ids); + +/** + * Enable or disable connection CTE request. + * + * @param conn_handle Connection handle. + * @param enable 0x00 to disable, 0x01 to enable CTE request. + * @param cte_request_interval Interval between CTE requests in connection interval. + * @param requested_cte_length Requested CTE length in 8 µs units. + * @param requested_cte_type Requested CTE type. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_conn_cte_req_enable(uint16_t conn_handle, uint8_t enable, uint16_t cte_request_interval, + uint8_t requested_cte_length, uint8_t requested_cte_type); + +/** + * Enable or disable connection CTE response. + * + * @param conn_handle Connection handle. + * @param enable 0x00 to disable, 0x01 to enable CTE response. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_conn_cte_rsp_enable(uint16_t conn_handle, uint8_t enable); + +/** + * Read antenna information. + * + * @param switch_sampling_rates On success, stores the supported switching and sampling rates. + * @param num_antennae On success, stores the number of antennae. + * @param max_switch_pattern_len On success, stores the maximum switching pattern length. + * @param max_cte_len On success, stores the maximum CTE length. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_read_antenna_information(uint8_t *switch_sampling_rates, uint8_t *num_antennae, + uint8_t *max_switch_pattern_len, uint8_t *max_cte_len); + +#endif // MYNEWT_VAL(BLE_AOA_AOD) + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +int +ble_gap_set_periodic_adv_subev_data(uint8_t instance, uint8_t num_subevents, + const struct ble_gap_set_periodic_adv_subev_data_params *params); + +int ble_gap_periodic_adv_set_response_data(uint16_t sync_handle, + struct ble_gap_periodic_adv_response_params *param, + struct os_mbuf *data); + +int ble_gap_periodic_adv_sync_subev(uint16_t sync_handle, uint8_t include_tx_power, + uint8_t num_subevents, uint8_t *subevents); +#endif #endif @@ -2178,6 +2814,71 @@ int ble_gap_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, const struct ble_gap_conn_params *params, ble_gap_event_fn *cb, void *cb_arg); +/** + * Initiates an Sync connect procedure for PAwR. + * + * @param own_addr_type The type of address the stack should use for + * itself during connection establishment. + * - BLE_OWN_ADDR_PUBLIC + * - BLE_OWN_ADDR_RANDOM + * - BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT + * - BLE_OWN_ADDR_RPA_RANDOM_DEFAULT + * @param advertising_handle The advertising_Handle identifying the periodic advertising train + * Range: 0x00 to 0xEF or 0xFF + * @param subevent The Subevent parameter is used to identify the subevent where a connection + request shall be initiated from a periodic advertising train. + The Advertising_Handle and Subevent parameters + shall be set to 0xFF if these + parameters are not used. + * @param peer_addr The address of the peer to connect to. + * If this parameter is NULL, the white list + * is used. + * @param duration_ms The duration of the discovery procedure. + * On expiration, the procedure ends and a + * BLE_GAP_EVENT_DISC_COMPLETE event is + * reported. Units are milliseconds. + * @param phy_mask Define on which PHYs connection attempt should + * be done + * @param phy_1m_conn_params Additional arguments specifying the + * particulars of the connect procedure. When + * BLE_GAP_LE_PHY_1M_MASK is set in phy_mask + * this parameter can be specify to null for + * default values. + * @param phy_2m_conn_params Additional arguments specifying the + * particulars of the connect procedure. When + * BLE_GAP_LE_PHY_2M_MASK is set in phy_mask + * this parameter can be specify to null for + * default values. + * @param phy_coded_conn_params Additional arguments specifying the + * particulars of the connect procedure. When + * BLE_GAP_LE_PHY_CODED_MASK is set in + * phy_mask this parameter can be specify to + * null for default values. + * @param cb The callback to associate with this connect + * procedure. When the connect procedure + * completes, the result is reported through + * this callback. If the connect procedure + * succeeds, the connection inherits this + * callback as its event-reporting mechanism. + * @param cb_arg The optional argument to pass to the callback + * function. + * + * @return 0 on success; + * BLE_HS_EALREADY if a connection attempt is + * already in progress; + * BLE_HS_EBUSY if initiating a connection is not + * possible because scanning is in progress; + * BLE_HS_EDONE if the specified peer is already + * connected; + * Other nonzero on error. + */ +int ble_gap_connect_with_synced(uint8_t own_addr_type, uint8_t advertising_handle, + uint8_t subevent, const ble_addr_t *peer_addr, + int32_t duration_ms, uint8_t phy_mask, + const struct ble_gap_conn_params *phy_1m_conn_params, + const struct ble_gap_conn_params *phy_2m_conn_params, + const struct ble_gap_conn_params *phy_coded_conn_params, + ble_gap_event_fn *cb, void *cb_arg); /** * Initiates an extended connect procedure. * @@ -2862,6 +3563,35 @@ int ble_gap_dtm_enh_tx_start(uint8_t tx_chan, uint8_t test_data_len, uint8_t pay */ int ble_gap_dtm_enh_rx_start(uint8_t rx_chan, uint8_t index, uint8_t phy); +/** + * Set Read Remote Version Information is used to retrieve the version, manufacturer, + * and subversion information of remote controller after connection established + * + * @param conn_handle Connection handle + * @param version Defines the specification version of the LE Controller + * @param manufacturer Indicates the manufacturer of the remote Controller + * @param subversion Manufacturer specific version + + * @return 0 on success; nonzero on failure +*/ + +int ble_gap_read_rem_ver_info(uint16_t conn_handle, uint8_t *version, uint16_t *manufacturer, uint16_t *subversion); + +/** + * Read local resolvable address command + * + * @param peer_addr_type Peer Identity Address type + * + * @param peer_addr Peer Identity Address + * + * @param out_addr Local Resolvable Address received from controller. + * + * @return 0 on success; nonzero on failure + */ + +int ble_gap_rd_local_resolv_addr(uint8_t peer_addr_type, const ble_addr_t *peer_addr, + uint8_t *out_addr); + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_gatt.h b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_gatt.h index c2facf29..8ad0cba5 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_gatt.h +++ b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_gatt.h @@ -28,6 +28,7 @@ */ #include +#include "nimble/ble.h" #include "host/ble_att.h" #include "host/ble_uuid.h" #include "host/ble_esp_gatt.h" @@ -188,7 +189,7 @@ struct ble_hs_cfg; #define BLE_GATT_SVC_TYPE_SECONDARY 2 /** @} */ -/** +/** * Client Presentation Format * GATT Format Types * Ref: Assigned Numbers Specification @@ -386,6 +387,16 @@ struct ble_hs_cfg; #define BLE_GATT_CHR_BT_SIG_DESC_INTERNAL 0x010F #define BLE_GATT_CHR_BT_SIG_DESC_EXTERNAL 0x0110 +/*** @server. */ +/** Represents one notification tuple in a multi notification PDU */ +struct ble_gatt_notif { + /** The attribute handle on which to notify. */ + uint16_t handle; + + /** The notification value. */ + struct os_mbuf * value; +}; + /*** @client. */ /** Represents a GATT error. */ struct ble_gatt_error { @@ -408,6 +419,22 @@ struct ble_gatt_svc { ble_uuid_any_t uuid; }; +#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)) +/** Represents a GATT Service. */ +struct ble_gatt_incl_svc { + /** The handle of the GATT include service. */ + uint16_t handle; + + /** The start handle of the GATT include service. */ + uint16_t start_handle; + + /** The end handle of the GATT include service. */ + uint16_t end_handle; + + /** The UUID of the GATT service. */ + ble_uuid_any_t uuid; +}; +#endif /** Represents a GATT attribute. */ struct ble_gatt_attr { @@ -458,6 +485,12 @@ typedef int ble_gatt_disc_svc_fn(uint16_t conn_handle, const struct ble_gatt_svc *service, void *arg); +#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)) +typedef int ble_gatt_disc_incl_svc_fn(uint16_t conn_handle, + const struct ble_gatt_error *error, + const struct ble_gatt_incl_svc *incl_svc, + void *arg); +#endif /** * The host will free the attribute mbuf automatically after the callback is * executed. The application can take ownership of the mbuf and prevent it @@ -561,10 +594,15 @@ int ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, const ble_uuid_t *uuid, * * @return 0 on success; nonzero on failure. */ +#if MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) +int ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle, + uint16_t end_handle, + ble_gatt_disc_incl_svc_fn *cb, void *cb_arg); +#else int ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, ble_gatt_disc_svc_fn *cb, void *cb_arg); - +#endif /** * Initiates GATT procedure: Discover All Characteristics of a Service. * @@ -851,6 +889,33 @@ int ble_gattc_write_reliable(uint16_t conn_handle, int ble_gatts_notify_custom(uint16_t conn_handle, uint16_t att_handle, struct os_mbuf *om); +/** + * Sends a "free-form" multiple handle variable length characteristic + * notification. This function consumes supplied mbufs regardless of the + * outcome. Notifications are sent in order of supplied entries. + * Function tries to send minimum amount of PDUs. If PDU can't contain all + * of the characteristic values, multiple notifications are sent. If only one + * handle-value pair fits into PDU, or only one characteristic remains in the + * list, regular characteristic notification is sent. + * + * If GATT client doesn't support receiving multiple handle notifications, + * this will use GATT notification for each characteristic, separately. + * + * If value of characteristic is not specified it will be read from local + * GATT database. + * + * @param conn_handle The connection over which to execute the + * procedure. + * @param chr_count Number of characteristics to notify about. + * @param tuples Handle-value pairs in form of `ble_gatt_notif` + * structures. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gatts_notify_multiple_custom(uint16_t conn_handle, + size_t chr_count, + struct ble_gatt_notif *tuples); + /** * Deprecated. Should not be used. Use ble_gatts_notify_custom instead. */ @@ -917,6 +982,8 @@ int ble_gatts_indicate(uint16_t conn_handle, uint16_t chr_val_handle); */ int ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle); +void ble_gattc_cache_conn_undisc_all(ble_addr_t peer_addr); + /** Initialize the BLE GATT client. */ int ble_gattc_init(void); @@ -1102,6 +1169,12 @@ struct ble_gatt_access_ctxt { */ const struct ble_gatt_dsc_def *dsc; }; + + /** + * An offset in case of BLE_ATT_OP_READ_BLOB_REQ. + * If the value is greater than zero it's an indication of a long attribute read. + */ + uint16_t offset; }; /** @@ -1210,7 +1283,7 @@ STAILQ_HEAD(ble_gatts_clt_cfg_list, ble_gatts_clt_cfg); * BLE_HS_ENOMEM on heap exhaustion. */ int ble_gatts_add_svcs(const struct ble_gatt_svc_def *svcs); - +void ble_gatts_free_svcs(void); #if MYNEWT_VAL(BLE_DYNAMIC_SERVICE) /** * Adds a set of services for registration. All services added @@ -1339,6 +1412,14 @@ typedef void (*ble_gatt_svc_foreach_fn)(const struct ble_gatt_svc_def *svc, */ void ble_gatts_show_local(void); +#if MYNEWT_VAL(BLE_SVC_GAP_GATT_SECURITY_LEVEL) +/** + * Calculates and returns the maximum + * Security Mode 1 Level requirement. + */ +uint8_t ble_gatts_security_mode_1_level(void); +#endif + /** * Resets the GATT server to its initial state. On success, this function * removes all supported services, characteristics, and descriptors. This diff --git a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_hs.h b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_hs.h index 4eba4b44..79718b40 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_hs.h +++ b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_hs.h @@ -315,18 +315,49 @@ struct ble_hs_cfg { */ unsigned sm_sc:1; + /** @brief Security Manager - Enable/Disable Secure Connections Only flag + * + * If set, this will enforce P-256 elliptic curve encryption algorithm + * during pairing. + * It will force the max key size to be used during pairing. + */ + unsigned sm_sc_only:1; + + /** @brief Security Manager - Security Mode 1 Level for GATT related operations + * + * Possible values are: + * 0: Default value, ignored + * 1: No security + * 2: Unauthenticated pairing with encryption + * 3. Authenticated pairing with encryption + * 4. Authenticated LE Secure Connections pairing with encryption using a 128-bit strength encryption key + */ + uint8_t sm_sec_lvl; + /** @brief Security Manager Key Press Notification flag * * Currently unsupported and should not be set. */ unsigned sm_keypress:1; + /** @brief Enable/Disable Enhanced ATT Support + * + * Primarily used to enable EATT behaviour; denotes the number of eatt + * channels. Set to 0 to disable eatt. + * + * Default value is CONFIG_BT_NIMBLE_EATT_CHAN_NUM. + */ + uint8_t eatt; + /** @brief Security Manager Local Key Distribution Mask */ uint8_t sm_our_key_dist; /** @brief Security Manager Remote Key Distribution Mask */ uint8_t sm_their_key_dist; + /** @brief Weather to use GATT caching or not for discovery operations */ + uint8_t gatt_use_cache; + /** @brief Stack reset callback * * This callback is executed when the host resets itself and the controller diff --git a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_hs_adv.h b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_hs_adv.h index 8d5e26a3..5d2ca2a6 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_hs_adv.h +++ b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_hs_adv.h @@ -22,6 +22,7 @@ #include #include "host/ble_uuid.h" +#include "syscfg/syscfg.h" #ifdef __cplusplus extern "C" { @@ -32,6 +33,8 @@ extern "C" { /** Max field payload size (account for 2-byte header). */ #define BLE_HS_ADV_MAX_FIELD_SZ (BLE_HS_ADV_MAX_SZ - 2) +#define BLE_HS_ADV_LE_SUPP_FEAT_LEN 6 + struct ble_hs_adv_field { uint8_t length; uint8_t type; @@ -113,7 +116,7 @@ struct ble_hs_adv_fields { unsigned device_addr_type; unsigned device_addr_is_present:1; - /*** 0xF1 - 32-bit service solicitation UUIDs */ + /*** 0x1f - 32-bit service solicitation UUIDs */ const ble_uuid32_t *sol_uuids32; uint8_t sol_num_uuids32; @@ -133,6 +136,21 @@ struct ble_hs_adv_fields { const uint8_t *uri; uint8_t uri_len; + /*** 0x27 - LE Supported Features. */ + /*** Core Spec v5.4 Vol. 6 Part B 4.6 */ + uint8_t le_supp_feat[BLE_HS_ADV_LE_SUPP_FEAT_LEN]; + unsigned le_supp_feat_is_present; + + /*** 0x2f - Advertising interval - long. */ + uint32_t adv_itvl_long; + unsigned adv_itvl_long_is_present:1; + +#if MYNEWT_VAL(ENC_ADV_DATA) + /*** 0x31 - Encrypted Advertising Data. */ + const uint8_t *enc_adv_data; + uint8_t enc_adv_data_len; +#endif + /*** 0xff - Manufacturer specific data. */ const uint8_t *mfg_data; uint8_t mfg_data_len; @@ -164,9 +182,12 @@ struct ble_hs_adv_fields { #define BLE_HS_ADV_TYPE_SVC_DATA_UUID32 0x20 #define BLE_HS_ADV_TYPE_SVC_DATA_UUID128 0x21 #define BLE_HS_ADV_TYPE_URI 0x24 +#define BLE_HS_ADV_TYPE_LE_SUPP_FEAT 0x27 #define BLE_HS_ADV_TYPE_MESH_PROV 0x29 #define BLE_HS_ADV_TYPE_MESH_MESSAGE 0x2a #define BLE_HS_ADV_TYPE_MESH_BEACON 0x2b +#define BLE_HS_ADV_TYPE_ADV_ITVL_LONG 0x2f +#define BLE_HS_ADV_TYPE_ENC_ADV_DATA 0x31 #define BLE_HS_ADV_TYPE_MFG_DATA 0xff #define BLE_HS_ADV_FLAGS_LEN 1 @@ -198,6 +219,8 @@ struct ble_hs_adv_fields { #define BLE_HS_ADV_ADDR_TYPE_LEN 1 +#define BLE_HS_ADV_ADV_ITVL_LONG_LEN 4 + int ble_hs_adv_set_fields_mbuf(const struct ble_hs_adv_fields *adv_fields, struct os_mbuf *om); @@ -210,6 +233,9 @@ int ble_hs_adv_parse_fields(struct ble_hs_adv_fields *adv_fields, int ble_hs_adv_parse(const uint8_t *data, uint8_t length, ble_hs_adv_parse_func_t func, void *user_data); +int ble_hs_adv_find_field(uint8_t type, const uint8_t *data, uint8_t length, + const struct ble_hs_adv_field **out); + #ifdef __cplusplus } #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_hs_pvcy.h b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_hs_pvcy.h index 0e2fefca..1769b8f7 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_hs_pvcy.h +++ b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_hs_pvcy.h @@ -69,7 +69,7 @@ void ble_hs_resolv_deinit(void); #endif int ble_hs_pvcy_set_resolve_enabled(int enable); -void ble_hs_set_rpa_timeout(uint16_t timeout); +int ble_hs_set_rpa_timeout(uint16_t timeout); #ifdef __cplusplus } diff --git a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_store.h b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_store.h index 732f4ff0..814bdcb8 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_store.h +++ b/lib/bt/host/nimble/nimble/nimble/host/include/host/ble_store.h @@ -38,6 +38,7 @@ extern "C" { #define BLE_STORE_OBJ_TYPE_PEER_ADDR 6 #define BLE_STORE_OBJ_TYPE_LOCAL_IRK 7 +#define BLE_STORE_OBJ_TYPE_CSFC 8 /** Failed to persist record; insufficient storage capacity. */ #define BLE_STORE_EVENT_OVERFLOW 1 @@ -121,6 +122,29 @@ struct ble_store_value_cccd { unsigned value_changed:1; }; +/** + * Used as a key for lookups of stored client supported features characteristic (CSFC). + * This struct corresponds to the BLE_STORE_OBJ_TYPE_CSFC store object type. + */ +struct ble_store_key_csfc { + /** + * Key by peer identity address; + */ + ble_addr_t peer_addr; + + /** Number of results to skip; 0 means retrieve the first match. */ + uint8_t idx; +}; + +/** + * Represents a stored client supported features characteristic (CSFC). + * This struct corresponds to the BLE_STORE_OBJ_TYPE_CSFC store object type. + */ +struct ble_store_value_csfc { + ble_addr_t peer_addr; + uint8_t csfc[MYNEWT_VAL(BLE_GATT_CSFC_SIZE)]; +}; + #if MYNEWT_VAL(ENC_ADV_DATA) /** * Used as a key for lookups of encrypted advertising data. This struct corresponds @@ -181,6 +205,7 @@ union ble_store_key { #endif struct ble_store_key_rpa_rec rpa_rec; struct ble_store_key_local_irk local_irk; + struct ble_store_key_csfc csfc; }; /** @@ -195,6 +220,7 @@ union ble_store_value { #endif struct ble_store_value_rpa_rec rpa_rec; struct ble_store_value_local_irk local_irk; + struct ble_store_value_csfc csfc; }; struct ble_store_status_event { @@ -361,10 +387,18 @@ int ble_store_read_cccd(const struct ble_store_key_cccd *key, int ble_store_write_cccd(const struct ble_store_value_cccd *value); int ble_store_delete_cccd(const struct ble_store_key_cccd *key); +int ble_store_read_csfc(const struct ble_store_key_csfc *key, + struct ble_store_value_csfc *out_value); +int ble_store_write_csfc(const struct ble_store_value_csfc *value); +int ble_store_delete_csfc(const struct ble_store_key_csfc *key); + void ble_store_key_from_value_sec(struct ble_store_key_sec *out_key, const struct ble_store_value_sec *value); void ble_store_key_from_value_cccd(struct ble_store_key_cccd *out_key, const struct ble_store_value_cccd *value); +void ble_store_key_from_value_csfc(struct ble_store_key_csfc *out_key, + const struct ble_store_value_csfc *value); + #if MYNEWT_VAL(ENC_ADV_DATA) int ble_store_read_ead(const struct ble_store_key_ead *key, struct ble_store_value_ead *out_value); diff --git a/lib/bt/host/nimble/nimble/nimble/host/mesh/src/adv.c b/lib/bt/host/nimble/nimble/nimble/host/mesh/src/adv.c index d6ed29f3..4b8d732e 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/mesh/src/adv.c +++ b/lib/bt/host/nimble/nimble/nimble/host/mesh/src/adv.c @@ -217,7 +217,7 @@ int bt_mesh_scan_enable(void) #if MYNEWT_VAL(BLE_EXT_ADV) struct ble_gap_ext_disc_params uncoded_params = { .itvl = MESH_SCAN_INTERVAL, .window = MESH_SCAN_WINDOW, - .passive = 1 }; + .passive = 1, .disable_observer_mode = 0}; BT_DBG(""); diff --git a/lib/bt/host/nimble/nimble/nimble/host/mesh/src/pb_adv.c b/lib/bt/host/nimble/nimble/nimble/host/mesh/src/pb_adv.c index 35a02b0d..8225c063 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/mesh/src/pb_adv.c +++ b/lib/bt/host/nimble/nimble/nimble/host/mesh/src/pb_adv.c @@ -30,6 +30,7 @@ #define START_PAYLOAD_MAX 20 #define CONT_PAYLOAD_MAX 23 +#define RX_BUFFER_MAX 65 #define START_LAST_SEG(gpc) (gpc >> 2) #define CONT_SEG_INDEX(gpc) (gpc >> 2) @@ -39,7 +40,8 @@ #define LINK_ACK 0x01 #define LINK_CLOSE 0x02 -#define XACT_SEG_DATA(_seg) (&link.rx.buf->om_data[20 + ((_seg - 1) * 23)]) +#define XACT_SEG_OFFSET(_seg) (20 + ((_seg - 1) * 23)) +#define XACT_SEG_DATA(_seg) (&link.rx.buf->om_data[XACT_SEG_OFFSET(_seg)]) #define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg))) #define XACT_ID_MAX 0x7f @@ -222,7 +224,7 @@ static void reset_adv_link(void) } link.tx.pending_ack = XACT_ID_NVAL; if (!rx_buf) { - rx_buf = NET_BUF_SIMPLE(65); + rx_buf = NET_BUF_SIMPLE(RX_BUFFER_MAX); } link.rx.buf = rx_buf; net_buf_simple_reset(link.rx.buf); @@ -386,6 +388,11 @@ static void gen_prov_cont(struct prov_rx *rx, struct os_mbuf *buf) return; } + if (XACT_SEG_OFFSET(seg) + buf->om_len > RX_BUFFER_MAX) { + BT_WARN("Rx buffer overflow. Malformed generic prov frame?"); + return; + } + memcpy(XACT_SEG_DATA(seg), buf->om_data, buf->om_len); XACT_SEG_RECV(seg); @@ -890,7 +897,7 @@ void pb_adv_init(void) k_work_init_delayable(&link.tx.retransmit, prov_retransmit); if (!rx_buf) { - rx_buf = NET_BUF_SIMPLE(65); + rx_buf = NET_BUF_SIMPLE(RX_BUFFER_MAX); } link.rx.buf = rx_buf; net_buf_simple_reset(link.rx.buf); diff --git a/lib/bt/host/nimble/nimble/nimble/host/mesh/src/prov_device.c b/lib/bt/host/nimble/nimble/nimble/host/mesh/src/prov_device.c index 01b1eac3..64b0bb30 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/mesh/src/prov_device.c +++ b/lib/bt/host/nimble/nimble/nimble/host/mesh/src/prov_device.c @@ -303,11 +303,11 @@ static void prov_dh_key_gen(void) #if !CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS if (MYNEWT_VAL(BLE_MESH_PROV_OOB_PUBLIC_KEY) && atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { - if (uECC_valid_public_key(remote_pk, &curve_secp256r1)) { + if (uECC_valid_public_key(remote_pk, uECC_secp256r1())) { BT_ERR("Public key is not valid"); } else if (uECC_shared_secret(remote_pk, bt_mesh_prov->private_key_be, bt_mesh_prov_link.dhkey, - &curve_secp256r1) != TC_CRYPTO_SUCCESS) { + uECC_secp256r1()) != TC_CRYPTO_SUCCESS) { BT_ERR("DHKey generation failed"); } else { dh_key_gen_complete(); diff --git a/lib/bt/host/nimble/nimble/nimble/host/pkg.yml b/lib/bt/host/nimble/nimble/nimble/host/pkg.yml index c069283c..cab496ca 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/pkg.yml +++ b/lib/bt/host/nimble/nimble/nimble/host/pkg.yml @@ -41,6 +41,9 @@ pkg.deps.BLE_SM_SC: pkg.deps.BLE_MESH: - nimble/host/mesh +pkg.deps.BLE_EATT_CHAN_NUM: + - nimble/host/services/gatt + pkg.req_apis: - ble_transport - console diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/ans/include/services/ans/ble_svc_ans.h b/lib/bt/host/nimble/nimble/nimble/host/services/ans/include/services/ans/ble_svc_ans.h index 435e9e11..1a5ce0a4 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/ans/include/services/ans/ble_svc_ans.h +++ b/lib/bt/host/nimble/nimble/nimble/host/services/ans/include/services/ans/ble_svc_ans.h @@ -20,6 +20,10 @@ #ifndef H_BLE_SVC_ANS_ #define H_BLE_SVC_ANS_ +#ifdef __cplusplus +extern "C" { +#endif + struct ble_hs_cfg; /* 16 Bit Alert Notification Service UUID */ @@ -81,5 +85,8 @@ int ble_svc_ans_unr_alert_add(uint8_t cat_id); void ble_svc_ans_init(void); +#ifdef __cplusplus +} #endif +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/ans/src/ble_svc_ans.c b/lib/bt/host/nimble/nimble/nimble/host/services/ans/src/ble_svc_ans.c index edaf7f3c..0b02b9a9 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/ans/src/ble_svc_ans.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/ans/src/ble_svc_ans.c @@ -26,6 +26,7 @@ #include "host/ble_gap.h" #include "services/ans/ble_svc_ans.h" +#if MYNEWT_VAL(BLE_GATTS) /* Max length of new alert info string */ #define BLE_SVC_ANS_INFO_STR_MAX_LEN 18 /* Max length of a new alert notification, max string length + 2 bytes @@ -390,8 +391,12 @@ ble_svc_ans_new_alert_notify(uint8_t cat_id, const char * info_str) memcpy(&ble_svc_ans_new_alert_val[2], info_str, info_str_len); } } +#if NIMBLE_BLE_CONNECT return ble_gatts_notify(ble_svc_ans_conn_handle, ble_svc_ans_new_alert_val_handle); +#else + return 0; +#endif } /** @@ -407,8 +412,12 @@ ble_svc_ans_unr_alert_notify(uint8_t cat_id) { ble_svc_ans_unr_alert_stat[0] = cat_id; ble_svc_ans_unr_alert_stat[1] = ble_svc_ans_unr_alert_cnt[cat_id]; +#if NIMBLE_BLE_CONNECT return ble_gatts_notify(ble_svc_ans_conn_handle, ble_svc_ans_unr_alert_val_handle); +#else + return 0; +#endif } /** @@ -462,3 +471,4 @@ ble_svc_ans_init(void) ble_svc_ans_new_alert_cat = MYNEWT_VAL(BLE_SVC_ANS_NEW_ALERT_CAT); ble_svc_ans_unr_alert_cat = MYNEWT_VAL(BLE_SVC_ANS_UNR_ALERT_CAT); } +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h b/lib/bt/host/nimble/nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h index 24b9a26c..88675b40 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h +++ b/lib/bt/host/nimble/nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h @@ -20,6 +20,10 @@ #ifndef H_BLE_SVC_BAS_ #define H_BLE_SVC_BAS_ +#ifdef __cplusplus +extern "C" { +#endif + /* 16 Bit Battery Service UUID */ #define BLE_SVC_BAS_UUID16 0x180F @@ -30,4 +34,8 @@ int ble_svc_bas_battery_level_set(uint8_t level); void ble_svc_bas_init(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/bas/src/ble_svc_bas.c b/lib/bt/host/nimble/nimble/nimble/host/services/bas/src/ble_svc_bas.c index 631519cf..468e433b 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/bas/src/ble_svc_bas.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/bas/src/ble_svc_bas.c @@ -26,6 +26,7 @@ #include "host/ble_gap.h" #include "services/bas/ble_svc_bas.h" +#if MYNEWT_VAL(BLE_GATTS) && CONFIG_BT_NIMBLE_BAS_SERVICE /* Characteristic value handles */ #if MYNEWT_VAL(BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE) > 0 static uint16_t ble_svc_bas_battery_handle; @@ -125,3 +126,4 @@ ble_svc_bas_init(void) rc = ble_gatts_add_svcs(ble_svc_bas_defs); SYSINIT_PANIC_ASSERT(rc == 0); } +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/bleuart/src/bleuart.c b/lib/bt/host/nimble/nimble/nimble/host/services/bleuart/src/bleuart.c index 866595ed..0b4f107b 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/bleuart/src/bleuart.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/bleuart/src/bleuart.c @@ -30,6 +30,7 @@ #include "console/console.h" #include "esp_nimble_mem.h" +#if MYNEWT_VAL(BLE_GATTS) /* ble uart attr read handle */ uint16_t g_bleuart_attr_read_handle; @@ -202,3 +203,4 @@ bleuart_init(void) console_buf = nimble_platform_mem_malloc(MYNEWT_VAL(BLEUART_MAX_INPUT)); SYSINIT_PANIC_ASSERT(console_buf != NULL); } +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/cte/include/services/cte/ble_svc_cte.h b/lib/bt/host/nimble/nimble/nimble/host/services/cte/include/services/cte/ble_svc_cte.h new file mode 100644 index 00000000..b32e650e --- /dev/null +++ b/lib/bt/host/nimble/nimble/nimble/host/services/cte/include/services/cte/ble_svc_cte.h @@ -0,0 +1,44 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_SVC_CTE_ +#define H_BLE_SVC_CTE_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct ble_hs_cfg; + +#define BLE_SVC_CTE_UUID16 0x184A +#define BLE_SVC_CTE_CHR_UUID16_ENABLE 0x2BAD +#define BLE_SVC_CTE_CHR_UUID16_MINIMUM_LENGTH 0x2BAE +#define BLE_SVC_CTE_CHR_UUID16_MINIMUM_TRANSMIT_COUNT 0x2BAF +#define BLE_SVC_CTE_CHR_UUID16_TRANSMIT_DURATION 0x2BB0 +#define BLE_SVC_CTE_CHR_UUID16_INTERVAL 0x2BB1 +#define BLE_SVC_CTE_CHR_UUID16_PHY 0x2BB2 + + +void ble_svc_cte_init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/cte/pkg.yml b/lib/bt/host/nimble/nimble/nimble/host/services/cte/pkg.yml new file mode 100644 index 00000000..4e656d3d --- /dev/null +++ b/lib/bt/host/nimble/nimble/nimble/host/services/cte/pkg.yml @@ -0,0 +1,34 @@ + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: nimble/host/services/cte +pkg.description: Constant Tone Extension Service +pkg.author: "GengYuchao " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - ble + - bluetooth + - cte + - nimble + +pkg.deps: + - nimble/host + +pkg.init: + ble_svc_cte_init: 'MYNEWT_VAL(BLE_SVC_CTE_SYSINIT_STAGE)' diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/cte/src/ble_svc_cte.c b/lib/bt/host/nimble/nimble/nimble/host/services/cte/src/ble_svc_cte.c new file mode 100644 index 00000000..6446fdde --- /dev/null +++ b/lib/bt/host/nimble/nimble/nimble/host/services/cte/src/ble_svc_cte.c @@ -0,0 +1,573 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include "sysinit/sysinit.h" +#include "syscfg/syscfg.h" +#include "host/ble_hs.h" +#include "host/ble_gap.h" +#include "services/cte/ble_svc_cte.h" + +/* XXX: We shouldn't be including the host's private header files. The host + * API needs to be updated with a function to query the advertising transmit + * power. + */ +#include "../src/ble_hs_hci_priv.h" + +#if MYNEWT_VAL(BLE_AOA_AOD) + +// Define the size of characteristic values +#define CTE_ENABLE_CHAR_SIZE 1 +#define CTE_MIN_LENGTH_CHAR_SIZE 1 +#define CTE_MIN_TRANSMIT_COUNT_SIZE 1 +#define CTE_TRANSMIT_DURATION_SIZE 1 +#define CTE_INTERVAL_CHAR_SIZE 2 +#define CTE_PHY_CHAR_SIZE 1 + +// Constant Tone Extension Enable characteristic value range +#define CTE_ENABLE_MIN_VALUE 0x00 +#define CTE_ENABLE_MAX_VALUE 0x03 +// Define the constant tone extension enable bit control macros +#define CTE_ENABLE_AOA_CONNECTION (1 << 0) // Bit 0: Enable AoA Constant Tone Extension on ACL connection with client +#define CTE_ENABLE_AOD_ADVERTISING (1 << 1) // Bit 1: Enable AoD Constant Tone Extension in advertising packets + +#define CTETYPE_ALLOW_AOA_CTE_RESPONSE (1 << 0) +#define CTETYPE_ALLOW_AOD_1US_CTE_RESPONSE (1 << 1) +#define CTETYPE_ALLOW_AOD_2US_CTE_RESPONSE (1 << 2) +#define CTETYPE_MASK_ALL (0x7) // mask for the first three bits + +// Advertising Constant Tone Extension Minimum Length characteristic value range +#define CTE_MIN_LEN_MIN_VALUE 2 +#define CTE_MIN_LEN_MAX_VALUE 20 + +// Advertising Constant Tone Extension Minimum Transmit Count characteristic value range +#define CTE_MIN_TX_COUNT_MIN_VALUE 1 +#define CTE_MIN_TX_COUNT_MAX_VALUE 15 + +// Advertising Constant Tone Extension Transmit Duration characteristic value range +#define CTE_TX_DURATION_MIN_VALUE 0 +#define CTE_TX_DURATION_MAX_VALUE 255 + +// Advertising Constant Tone Extension Interval characteristic value range +#define CTE_INTERVAL_MIN_VALUE 0x0006 +#define CTE_INTERVAL_MAX_VALUE 0xFFFF + +// Advertising Constant Tone Extension PHY characteristic value range +#define CTE_PHY_MIN_VALUE 0x00 +#define CTE_PHY_MAX_VALUE 0x01 + +// SERVICE Error Code +#define SERVICE_ERROR_WRITE_REQUEST_REJECTED 0xFC +#define SERVICE_ERROR_OUT_OF_RANGE 0xFF + +/* Structure to store CTE settings per connection */ +typedef struct { + uint16_t conn_handle; + uint8_t cte_enable; + uint8_t cte_min_length; + uint8_t cte_min_transmit_count; + uint8_t cte_transmit_duration; + uint16_t cte_interval; + uint8_t cte_phy; +}cte_instance_config_t; + +/* Structure to store CTE settings per client */ +static cte_instance_config_t cte_config[MYNEWT_VAL(BLE_MAX_CONNECTIONS)]; + + +/** + * @brief Constant Tone Extensio Service UUID + */ +static const ble_uuid128_t cte_svc_uuid = + BLE_UUID128_INIT(0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, + 0x00, 0x10, 0x00, 0x00, 0x4A, 0x18, 0x00, 0x00); + +static int ble_svc_cte_enable_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg); + +static int ble_svc_cte_adv_cte_min_length_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg); + +static int ble_svc_cte_adv_cte_min_transmit_count_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg); + +static int ble_svc_cte_adv_cte_transmit_duration_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg); + +static int ble_svc_cte_adv_cte_interval_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg); + +static int ble_svc_cte_adv_cte_phy_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg); +/** + * @brief Constant Tone Extensio Service definition + */ +static const struct ble_gatt_svc_def ble_svc_cte_defs[] = { + { + /*** Service: Asset Tracking Service. */ + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = BLE_UUID16_DECLARE(BLE_SVC_CTE_UUID16), + .characteristics = (struct ble_gatt_chr_def[]) { + { + /*** Characteristic: Constant Tone Extension Enable. */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_CTE_CHR_UUID16_ENABLE), + .access_cb = ble_svc_cte_enable_access, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE, + }, + { + /*** Characteristic: Advertising Constant Tone Extension Minimum Length. */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_CTE_CHR_UUID16_MINIMUM_LENGTH), + .access_cb = ble_svc_cte_adv_cte_min_length_access, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE, + }, + { + /*** Characteristic: Advertising Constant Tone Extension Minimum Transmit Count. */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_CTE_CHR_UUID16_MINIMUM_TRANSMIT_COUNT), + .access_cb = ble_svc_cte_adv_cte_min_transmit_count_access, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE, + }, + { + /*** Characteristic: Advertising Constant Tone Extension Transmit Duration. */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_CTE_CHR_UUID16_TRANSMIT_DURATION), + .access_cb = ble_svc_cte_adv_cte_transmit_duration_access, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE, + }, + { + /*** Characteristic: Advertising Constant Tone Extension Interval. */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_CTE_CHR_UUID16_INTERVAL), + .access_cb = ble_svc_cte_adv_cte_interval_access, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE, + }, + { + /*** Characteristic: Advertising Constant Tone Extension PHY. */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_CTE_CHR_UUID16_PHY), + .access_cb = ble_svc_cte_adv_cte_phy_access, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE, + }, + { + 0, /* No more characteristics in this service. */ + } + }, + }, + + { + 0, /* No more services. */ + }, +}; + +/** + * Find the CTE configuration instance for the given connection handle. + * + * @param conn_handle The connection handle to search for. + * @return A pointer to the matching CTE configuration instance, or NULL if not found. + */ +static cte_instance_config_t* cte_find_config_by_conn_handle(uint16_t conn_handle) { + for (int i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); i++) { + if (cte_config[i].conn_handle == conn_handle) { + return &cte_config[i]; + } + } + return NULL; +} + +/**@}*/ + +/** + * Handles writing a one-octet (1 byte) characteristic value in a BLE service. + * + * This function is used to validate and write a characteristic value that is + * exactly 1 byte long. It performs length checks, range validation, and then + * updates the destination buffer with the new value if all validations pass. + * + * @param om The mbuf containing the data to be written. + * @param min_value The minimum allowed value for the characteristic. + * @param max_value The maximum allowed value for the characteristic. + * @param dst A pointer to the destination buffer where the validated + * value will be stored. + * @param len A pointer to store the length of the written value (optional). + * If provided, it will be set to 1 on success. + * + * @return 0 on success; BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN if the + * length of data in the mbuf does not match the expected + * one-octet length; BLE_ATT_ERR_UNLIKELY if an unexpected + * error occurs while flattening the mbuf; SERVICE_ERROR_OUT_OF_RANGE + * if the value is outside the allowed range. + */ +static int +ble_svc_cte_one_octet_chr_write(struct os_mbuf *om, + uint32_t min_value, uint32_t max_value, + void *dst, uint16_t *len) +{ + uint16_t om_len; + uint8_t target_len = 1; + uint8_t value = 0; + int rc; + + // Get the length of the data in the mbuf + om_len = OS_MBUF_PKTLEN(om); + + // Ensure the data length matches the expected target length + if (om_len != target_len) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + + // Flatten the mbuf data into the value buffer + rc = ble_hs_mbuf_to_flat(om, &value, target_len, NULL); + if (rc != 0) { + return BLE_ATT_ERR_UNLIKELY; + } + + // Check if the value is within the allowed range + if (value < min_value || value > max_value) { + return SERVICE_ERROR_OUT_OF_RANGE; + } + + // Update the destination with the validated value + memcpy(dst, &value, target_len); + if (len != NULL) { + *len = target_len; + } + + return 0; +} + +/** + * Handles writing a two-octet (2 bytes) characteristic value in a BLE service. + * + * This function is used to validate and write a characteristic value that is + * exactly 2 bytes long. It performs length checks, range validation, and then + * updates the destination buffer with the new value if all validations pass. + * + * @param om The mbuf containing the data to be written. + * @param min_value The minimum allowed value for the characteristic. + * @param max_value The maximum allowed value for the characteristic. + * @param dst A pointer to the destination buffer where the validated + * value will be stored. + * @param len A pointer to store the length of the written value (optional). + * If provided, it will be set to 2 on success. + * + * @return 0 on success; BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN if the + * length of data in the mbuf does not match the expected + * two-octet length; BLE_ATT_ERR_UNLIKELY if an unexpected + * error occurs while flattening the mbuf; SERVICE_ERROR_OUT_OF_RANGE + * if the value is outside the allowed range. + */ +static int +ble_svc_cte_two_octet_chr_write(struct os_mbuf *om, + uint32_t min_value, uint32_t max_value, + void *dst, uint16_t *len) +{ + uint16_t om_len; + uint8_t target_len = 2; + uint16_t value = 0; + int rc; + + // Get the length of the data in the mbuf + om_len = OS_MBUF_PKTLEN(om); + + // Ensure the data length matches the expected target length + if (om_len != target_len) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + + // Flatten the mbuf data into the value buffer + rc = ble_hs_mbuf_to_flat(om, &value, target_len, NULL); + if (rc != 0) { + return BLE_ATT_ERR_UNLIKELY; + } + + // Check if the value is within the allowed range + if (value < min_value || value > max_value) { + return SERVICE_ERROR_OUT_OF_RANGE; + } + + // Update the destination with the validated value + memcpy(dst, &value, target_len); + if (len != NULL) { + *len = target_len; + } + + return 0; +} + + +/** + * @brief Access callback for Constant Tone Extensio Service cte enable + * + * This function is called when a read or write operation is performed on the Constant Tone Extensio + * characteristic. It handles the read and write requests. + * + * @param conn_handle The connection handle + * @param attr_handle The attribute handle + * @param ctxt The GATT access context + * @param arg Unused argument + * + * @return 0 on success; non-zero error code otherwise + */ +static int ble_svc_cte_enable_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) { + int rc = BLE_ATT_ERR_UNLIKELY; + + // Find the CTE configuration instance for the given connection handle + cte_instance_config_t *config = cte_find_config_by_conn_handle(conn_handle); + + // Return an error if no matching configuration instance is found + if (config == NULL) { + return BLE_ATT_ERR_UNLIKELY; + } + + switch (ctxt->op) { + case BLE_GATT_ACCESS_OP_READ_CHR: + // Handle read characteristic request + rc = os_mbuf_append(ctxt->om, &config->cte_enable, sizeof(config->cte_enable)) == 0 ? + 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + break; + + case BLE_GATT_ACCESS_OP_WRITE_CHR: + // Handle write characteristic request + rc = ble_svc_cte_one_octet_chr_write(ctxt->om, + CTE_ENABLE_MIN_VALUE, + CTE_ENABLE_MAX_VALUE, + &config->cte_enable, NULL); + + if (rc == 0) { + if((config->cte_enable & CTE_ENABLE_AOA_CONNECTION) == CTE_ENABLE_AOA_CONNECTION) { + if(ble_gap_set_conn_cte_transmit_param(conn_handle, BLE_GAP_CTE_RSP_ALLOW_AOA_MASK, 0, NULL) != 0) + { + rc = 0xFC; + break; + } + if(ble_gap_conn_cte_rsp_enable(conn_handle, true) != 0) { + rc = 0xFC; + break; + } + } + if((config->cte_enable & CTE_ENABLE_AOD_ADVERTISING) == CTE_ENABLE_AOD_ADVERTISING) { + // TODO: Add Start advertising with CTE + } + } + break; + + default: + break; + } + + return rc; +} + +static int ble_svc_cte_adv_cte_min_length_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) { + int rc = BLE_ATT_ERR_UNLIKELY; + // Find the CTE configuration instance for the given connection handle + cte_instance_config_t *config = cte_find_config_by_conn_handle(conn_handle); + + // Return an error if no matching configuration instance is found + if (config == NULL) { + return BLE_ATT_ERR_UNLIKELY; + } + + switch (ctxt->op) { + case BLE_GATT_ACCESS_OP_READ_CHR: + // Handle read characteristic request + rc = os_mbuf_append(ctxt->om, &config->cte_min_length, sizeof(config->cte_min_length)) == 0 ? + 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + break; + + case BLE_GATT_ACCESS_OP_WRITE_CHR: + // Handle write characteristic request + rc = ble_svc_cte_one_octet_chr_write(ctxt->om, + CTE_MIN_LEN_MIN_VALUE, + CTE_MIN_LEN_MAX_VALUE, + &config->cte_min_length, NULL); + + break; + + default: + break; + } + + return rc; +} + +static int ble_svc_cte_adv_cte_min_transmit_count_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) { + int rc = BLE_ATT_ERR_UNLIKELY; + // Find the CTE configuration instance for the given connection handle + cte_instance_config_t *config = cte_find_config_by_conn_handle(conn_handle); + + // Return an error if no matching configuration instance is found + if (config == NULL) { + return BLE_ATT_ERR_UNLIKELY; + } + + switch (ctxt->op) { + case BLE_GATT_ACCESS_OP_READ_CHR: + // Handle read characteristic request + rc = os_mbuf_append(ctxt->om, &config->cte_min_transmit_count, sizeof(config->cte_min_transmit_count)) == 0 ? + 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + break; + + case BLE_GATT_ACCESS_OP_WRITE_CHR: + // Handle write characteristic request + rc = ble_svc_cte_one_octet_chr_write(ctxt->om, + CTE_MIN_TX_COUNT_MIN_VALUE, + CTE_MIN_TX_COUNT_MAX_VALUE, + &config->cte_min_transmit_count, NULL); + + break; + + default: + break; + } + + return rc; +} + +static int ble_svc_cte_adv_cte_transmit_duration_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) { + int rc = BLE_ATT_ERR_UNLIKELY; + // Find the CTE configuration instance for the given connection handle + cte_instance_config_t *config = cte_find_config_by_conn_handle(conn_handle); + + // Return an error if no matching configuration instance is found + if (config == NULL) { + return BLE_ATT_ERR_UNLIKELY; + } + + switch (ctxt->op) { + case BLE_GATT_ACCESS_OP_READ_CHR: + // Handle read characteristic request + rc = os_mbuf_append(ctxt->om, &config->cte_transmit_duration, sizeof(config->cte_transmit_duration)) == 0 ? + 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + break; + + case BLE_GATT_ACCESS_OP_WRITE_CHR: + // Handle write characteristic request + rc = ble_svc_cte_one_octet_chr_write(ctxt->om, + CTE_TX_DURATION_MIN_VALUE, + CTE_TX_DURATION_MAX_VALUE, + &config->cte_transmit_duration, NULL); + + break; + + default: + break; + } + + return rc; +} + +static int ble_svc_cte_adv_cte_interval_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) { + int rc = BLE_ATT_ERR_UNLIKELY; + // Find the CTE configuration instance for the given connection handle + cte_instance_config_t *config = cte_find_config_by_conn_handle(conn_handle); + + // Return an error if no matching configuration instance is found + if (config == NULL) { + return BLE_ATT_ERR_UNLIKELY; + } + + switch (ctxt->op) { + case BLE_GATT_ACCESS_OP_READ_CHR: + // Handle read characteristic request + rc = os_mbuf_append(ctxt->om, &config->cte_interval, sizeof(config->cte_interval)) == 0 ? + 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + break; + + case BLE_GATT_ACCESS_OP_WRITE_CHR: + // Handle write characteristic request + rc = ble_svc_cte_two_octet_chr_write(ctxt->om, + CTE_INTERVAL_MIN_VALUE, + CTE_INTERVAL_MAX_VALUE, + &config->cte_interval, NULL); + + break; + + default: + break; + } + + return rc; +} + +static int ble_svc_cte_adv_cte_phy_access(uint16_t conn_handle, uint16_t attr_handle, + struct ble_gatt_access_ctxt *ctxt, void *arg) { + int rc = BLE_ATT_ERR_UNLIKELY; + // Find the CTE configuration instance for the given connection handle + cte_instance_config_t *config = cte_find_config_by_conn_handle(conn_handle); + + // Return an error if no matching configuration instance is found + if (config == NULL) { + return BLE_ATT_ERR_UNLIKELY; + } + + switch (ctxt->op) { + case BLE_GATT_ACCESS_OP_READ_CHR: + // Handle read characteristic request + rc = os_mbuf_append(ctxt->om, &config->cte_phy, sizeof(config->cte_phy)) == 0 ? + 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + break; + + case BLE_GATT_ACCESS_OP_WRITE_CHR: + // Handle write characteristic request + rc = ble_svc_cte_one_octet_chr_write(ctxt->om, + CTE_PHY_MIN_VALUE, + CTE_PHY_MAX_VALUE, + &config->cte_phy, NULL); + break; + + default: + break; + } + + return rc; +} + +static void cte_init_config(void) { + for (int i = 0; i < MYNEWT_VAL(BLE_MAX_CONNECTIONS); i++) { + cte_config[i].conn_handle = i; + cte_config[i].cte_enable = 0; + cte_config[i].cte_min_length = CTE_MIN_LEN_MIN_VALUE; + cte_config[i].cte_min_transmit_count = CTE_MIN_TX_COUNT_MIN_VALUE; + cte_config[i].cte_transmit_duration = CTE_TX_DURATION_MIN_VALUE; + cte_config[i].cte_interval = CTE_INTERVAL_MIN_VALUE; + cte_config[i].cte_phy = CTE_PHY_MIN_VALUE; + } +} + +/** + * @brief Initialize the Constant Tone Extensio Service + */ +void +ble_svc_cte_init(void) +{ + int rc; + cte_init_config(); + + rc = ble_gatts_count_cfg(ble_svc_cte_defs); + assert(rc == 0); + + rc = ble_gatts_add_svcs(ble_svc_cte_defs); + assert(rc == 0); + +} + +#endif \ No newline at end of file diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/cte/syscfg.yml b/lib/bt/host/nimble/nimble/nimble/host/services/cte/syscfg.yml new file mode 100644 index 00000000..24109fe1 --- /dev/null +++ b/lib/bt/host/nimble/nimble/nimble/host/services/cte/syscfg.yml @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +syscfg.defs: + BLE_SVC_ATP_SYSINIT_STAGE: + description: > + Sysinit stage for the asset tag BLE service. + value: 303 + diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/cts/include/services/cts/ble_svc_cts.h b/lib/bt/host/nimble/nimble/nimble/host/services/cts/include/services/cts/ble_svc_cts.h index cf62f912..57df3ecc 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/cts/include/services/cts/ble_svc_cts.h +++ b/lib/bt/host/nimble/nimble/nimble/host/services/cts/include/services/cts/ble_svc_cts.h @@ -20,6 +20,10 @@ #ifndef H_BLE_SVC_CTS_ #define H_BLE_SVC_CTS_ +#ifdef __cplusplus +extern "C" { +#endif + #define BLE_SVC_CTS_ERR_DATA_FIELD_IGNORED 0x80 /* 16 Bit Current Time Service UUID */ #define BLE_SVC_CTS_UUID16 0x1805 @@ -157,4 +161,8 @@ ble_svc_cts_init(struct ble_svc_cts_cfg cfg); void ble_svc_cts_time_updated(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/cts/src/ble_svc_cts.c b/lib/bt/host/nimble/nimble/nimble/host/services/cts/src/ble_svc_cts.c index 1c9f8c88..29119c5f 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/cts/src/ble_svc_cts.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/cts/src/ble_svc_cts.c @@ -28,7 +28,7 @@ #include "time.h" #include - +#if MYNEWT_VAL(BLE_GATTS) && CONFIG_BT_NIMBLE_CTS_SERVICE struct ble_svc_cts_cfg cts_cfg = {0}; /* characteristic values */ @@ -277,3 +277,4 @@ ble_svc_cts_init(struct ble_svc_cts_cfg cfg) rc = ble_gatts_add_svcs(ble_svc_cts_defs); SYSINIT_PANIC_ASSERT(rc == 0); } +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/dis/include/services/dis/ble_svc_dis.h b/lib/bt/host/nimble/nimble/nimble/host/services/dis/include/services/dis/ble_svc_dis.h index aa70d2e6..749c439f 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/dis/include/services/dis/ble_svc_dis.h +++ b/lib/bt/host/nimble/nimble/nimble/host/services/dis/include/services/dis/ble_svc_dis.h @@ -20,6 +20,10 @@ #ifndef H_BLE_SVC_DIS_ #define H_BLE_SVC_DIS_ +#ifdef __cplusplus +extern "C" { +#endif + /** * Example: * @@ -42,7 +46,16 @@ #define BLE_SVC_DIS_CHR_UUID16_HARDWARE_REVISION 0x2A27 #define BLE_SVC_DIS_CHR_UUID16_SOFTWARE_REVISION 0x2A28 #define BLE_SVC_DIS_CHR_UUID16_MANUFACTURER_NAME 0x2A29 +#define BLE_SVC_DIS_CHR_UUID16_IEEE_REG_CERT_LIST 0x2A2A #define BLE_SVC_DIS_CHR_UUID16_PNP_ID 0x2A50 +#define BLE_SVC_DIS_CHR_UUID16_UDI 0x2BFF + +/* One PTS Case requires DIS to be included. + * The UUID below is randomly chosen. + */ +static const ble_uuid128_t ble_svc_dis_include_uuid = + BLE_UUID128_INIT(0x2d, 0x71, 0xa2, 0x59, 0xb4, 0x58, 0xc8, 0x12, + 0x99, 0x99, 0x43, 0x95, 0x12, 0x2f, 0x46, 0xFF); /** * Structure holding data for the main characteristics @@ -81,14 +94,26 @@ struct ble_svc_dis_data { /** * System ID. * Represent the System Id of the device. + * Length: 8 Octets */ const char *system_id; /** * PNP ID. * Represent the PNP Id of the device. + * Length: 7 Octets */ const char *pnp_id; + + /** + * IEEE 11073-20601 Regulatory Certification Data List + */ + const char *ieee; + + /** + * UDI for Medical Devices + */ + const char *udi; }; /** @@ -102,6 +127,11 @@ extern struct ble_svc_dis_data ble_svc_dis_data; */ void ble_svc_dis_init(void); +/** + * Service initialisation as an included service. + */ +void ble_svc_dis_included_init(void); + const char *ble_svc_dis_model_number(void); int ble_svc_dis_model_number_set(const char *value); const char *ble_svc_dis_serial_number(void); @@ -119,4 +149,8 @@ int ble_svc_dis_system_id_set(const char *value); int ble_svc_dis_pnp_id_set(const char *value); const char *ble_svc_dis_pnp_id(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/dis/src/ble_svc_dis.c b/lib/bt/host/nimble/nimble/nimble/host/services/dis/src/ble_svc_dis.c index 9066bc8e..2abf5bf2 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/dis/src/ble_svc_dis.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/dis/src/ble_svc_dis.c @@ -23,6 +23,7 @@ #include "host/ble_hs.h" #include "services/dis/ble_svc_dis.h" +#if MYNEWT_VAL(BLE_GATTS) && CONFIG_BT_NIMBLE_DIS_SERVICE /* Device information */ struct ble_svc_dis_data ble_svc_dis_data = { .model_number = MYNEWT_VAL(BLE_SVC_DIS_MODEL_NUMBER_DEFAULT), @@ -32,6 +33,9 @@ struct ble_svc_dis_data ble_svc_dis_data = { .software_revision = MYNEWT_VAL(BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT), .manufacturer_name = MYNEWT_VAL(BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT), .system_id = MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_DEFAULT), + .pnp_id = MYNEWT_VAL(BLE_SVC_DIS_PNP_ID_DEFAULT), + .ieee = "dummy_data", + .udi = NULL, /** For now no UID fields are supported */ }; /* Access function */ @@ -109,6 +113,11 @@ static const struct ble_gatt_svc_def ble_svc_dis_defs[] = { MYNEWT_VAL(BLE_SVC_DIS_SYSTEM_ID_READ_PERM), }, { #endif + /*** Chatacteristic: IEEE 11073-20601 Regulatory Certification Data List */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_IEEE_REG_CERT_LIST), + .access_cb = ble_svc_dis_access, + .flags = BLE_GATT_CHR_F_READ, + }, { #if (MYNEWT_VAL(BLE_SVC_DIS_PNP_ID_READ_PERM) >= 0) /*** Characteristic: PNP Id */ .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_PNP_ID), @@ -117,6 +126,11 @@ static const struct ble_gatt_svc_def ble_svc_dis_defs[] = { MYNEWT_VAL(BLE_SVC_DIS_PNP_ID_READ_PERM), }, { #endif + /*** UDI for Medical Devices */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_DIS_CHR_UUID16_UDI), + .access_cb = ble_svc_dis_access, + .flags = BLE_GATT_CHR_F_READ + }, { 0, /* No more characteristics in this service */ }, } @@ -127,6 +141,15 @@ static const struct ble_gatt_svc_def ble_svc_dis_defs[] = { }, }; +const struct ble_gatt_svc_def *included_services[] = {ble_svc_dis_defs, NULL}; +const struct ble_gatt_svc_def ble_svc_dis_include_def[] = { + { + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = &ble_svc_dis_include_uuid.u, + .includes = included_services, + } +}; + /** * Simple read access callback for the device information service * characteristic. @@ -224,8 +247,22 @@ ble_svc_dis_access(uint16_t conn_handle, uint16_t attr_handle, info = MYNEWT_VAL(BLE_SVC_PNP_SYSTEM_ID_DEFAULT); } #endif + uint8_t flag = 0x01; + os_mbuf_append(ctxt->om, &flag, sizeof flag); break; #endif + case BLE_SVC_DIS_CHR_UUID16_IEEE_REG_CERT_LIST: + info = ble_svc_dis_data.ieee; + break; + + case BLE_SVC_DIS_CHR_UUID16_UDI: + info = ble_svc_dis_data.udi; + if (info == NULL) { + uint8_t flag = 0x00; + os_mbuf_append(ctxt->om, &flag, sizeof(flag)); + } + break; + default: assert(0); return BLE_ATT_ERR_UNLIKELY; @@ -344,6 +381,21 @@ ble_svc_dis_pnp_id_set(const char *value) return 0; } +void +ble_svc_dis_included_init(void) +{ + int rc; + + SYSINIT_ASSERT_ACTIVE(); + + rc = ble_gatts_count_cfg(ble_svc_dis_include_def); + SYSINIT_PANIC_ASSERT(rc == 0); + + rc = ble_gatts_add_svcs(ble_svc_dis_include_def); + SYSINIT_PANIC_ASSERT(rc == 0); +} + + /** * Initialize the DIS package. */ @@ -361,3 +413,4 @@ ble_svc_dis_init(void) rc = ble_gatts_add_svcs(ble_svc_dis_defs); SYSINIT_PANIC_ASSERT(rc == 0); } +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h b/lib/bt/host/nimble/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h index f748d649..92d305fb 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h +++ b/lib/bt/host/nimble/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h @@ -34,6 +34,8 @@ extern "C" { #define BLE_SVC_GAP_CHR_UUID16_APPEARANCE 0x2a01 #define BLE_SVC_GAP_CHR_UUID16_PERIPH_PREF_CONN_PARAMS 0x2a04 #define BLE_SVC_GAP_CHR_UUID16_CENTRAL_ADDRESS_RESOLUTION 0x2aa6 +#define BLE_SVC_GAP_CHR_UUID16_RPA_ONLY 0x2AC9 +#define BLE_SVC_GAP_CHR_UUID16_LE_GATT_SECURITY_LEVELS 0x2BF5 #if MYNEWT_VAL(ENC_ADV_DATA) #define BLE_SVC_GAP_CHR_UUID16_KEY_MATERIAL 0x2B88 @@ -57,6 +59,7 @@ int ble_svc_gap_device_key_material_set(uint8_t *session_key, uint8_t *iv); #endif void ble_svc_gap_init(void); +void ble_svc_gap_deinit(void); #ifdef __cplusplus } diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/gap/src/ble_svc_gap.c b/lib/bt/host/nimble/nimble/nimble/host/services/gap/src/ble_svc_gap.c index 2f783228..a04cf571 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/gap/src/ble_svc_gap.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/gap/src/ble_svc_gap.c @@ -25,6 +25,8 @@ #include "services/gap/ble_svc_gap.h" #include "os/endian.h" +#if MYNEWT_VAL(BLE_GATTS) + #define PPCP_ENABLED \ MYNEWT_VAL(BLE_ROLE_PERIPHERAL) && \ (MYNEWT_VAL(BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL) || \ @@ -42,6 +44,7 @@ static char ble_svc_gap_name[BLE_SVC_GAP_NAME_MAX_LEN + 1] = static uint16_t ble_svc_gap_appearance = MYNEWT_VAL(BLE_SVC_GAP_APPEARANCE); #if MYNEWT_VAL(ENC_ADV_DATA) +static uint16_t ble_svc_gap_enc_adv_data_handle; static struct key_material km = { .session_key = {0}, .iv = {0}, @@ -94,9 +97,24 @@ static const struct ble_gatt_svc_def ble_svc_gap_defs[] = { .flags = BLE_GATT_CHR_F_READ, }, { #endif +#if MYNEWT_VAL(BLE_SVC_GAP_RPA_ONLY) + /*** Characteristic: Resolvable Private Address Only. */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_GAP_CHR_UUID16_RPA_ONLY), + .access_cb = ble_svc_gap_access, + .flags = BLE_GATT_CHR_F_READ, + }, { +#endif #if MYNEWT_VAL(ENC_ADV_DATA) .uuid = BLE_UUID16_DECLARE(BLE_SVC_GAP_CHR_UUID16_KEY_MATERIAL), .access_cb = ble_svc_gap_access, + .val_handle = &ble_svc_gap_enc_adv_data_handle, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_READ_AUTHOR | BLE_GATT_CHR_F_INDICATE, + }, { +#endif +#if MYNEWT_VAL(BLE_SVC_GAP_GATT_SECURITY_LEVEL) + /*** Characteristic: LE GATT Security Levels. */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_GAP_CHR_UUID16_LE_GATT_SECURITY_LEVELS), + .access_cb = ble_svc_gap_access, .flags = BLE_GATT_CHR_F_READ, }, { #endif @@ -190,6 +208,26 @@ ble_svc_gap_appearance_write_access(struct ble_gatt_access_ctxt *ctxt) #endif } +#if MYNEWT_VAL(BLE_SVC_GAP_GATT_SECURITY_LEVEL) +static int +ble_svc_gap_security_level_read_access(uint16_t conn_handle, struct os_mbuf * om) +{ + uint8_t security_level[2]; + int rc; + + /* Currently this characteristic is only supported for + * Security Mode 1 + */ + security_level[0] = 0x01; //Mode 1 + security_level[1] = ble_gatts_security_mode_1_level(); //Mode 1 Level + + rc = os_mbuf_append(om, security_level, sizeof(security_level)); + + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; +} +#endif + + static int ble_svc_gap_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) @@ -205,6 +243,15 @@ ble_svc_gap_access(uint16_t conn_handle, uint16_t attr_handle, htole16(MYNEWT_VAL(BLE_SVC_GAP_PPCP_SLAVE_LATENCY)), htole16(MYNEWT_VAL(BLE_SVC_GAP_PPCP_SUPERVISION_TMO)) }; +#endif +#if MYNEWT_VAL(BLE_SVC_GAP_RPA_ONLY) + /* As per Core Specification 6.0, Vol 3: Host, Part C: GAP, 12.5 + * The only allowed value for the characteristic is zero. + * All other values are RFU. + * As such, the presence of the characteristic itself indicates that + * the device is RPA only + */ + uint8_t rpa_only = 0; #endif int rc; @@ -248,6 +295,13 @@ ble_svc_gap_access(uint16_t conn_handle, uint16_t attr_handle, return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; #endif +#if MYNEWT_VAL(BLE_SVC_GAP_RPA_ONLY) + case BLE_SVC_GAP_CHR_UUID16_RPA_ONLY: + assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR); + rc = os_mbuf_append(ctxt->om, &rpa_only, sizeof(rpa_only)); + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; +#endif + #if MYNEWT_VAL(ENC_ADV_DATA) case BLE_SVC_GAP_CHR_UUID16_KEY_MATERIAL: rc = os_mbuf_append(ctxt->om, &(km.session_key), sizeof(km.session_key)); @@ -256,6 +310,13 @@ ble_svc_gap_access(uint16_t conn_handle, uint16_t attr_handle, return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; #endif +#if MYNEWT_VAL(BLE_SVC_GAP_GATT_SECURITY_LEVEL) + case BLE_SVC_GAP_CHR_UUID16_LE_GATT_SECURITY_LEVELS: + assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR); + rc = ble_svc_gap_security_level_read_access(conn_handle, ctxt->om); + return rc; +#endif + default: assert(0); return BLE_ATT_ERR_UNLIKELY; @@ -311,6 +372,7 @@ ble_svc_gap_device_key_material_set(uint8_t *session_key, uint8_t *iv) { memcpy(&km.session_key, session_key, BLE_EAD_KEY_SIZE); memcpy(&km.iv, iv, BLE_EAD_IV_SIZE); + ble_gatts_chr_updated(ble_svc_gap_enc_adv_data_handle); return 0; } #endif @@ -333,3 +395,10 @@ ble_svc_gap_init(void) SYSINIT_PANIC_ASSERT(rc == 0); #endif } + +void +ble_svc_gap_deinit(void) +{ + ble_gatts_free_svcs(); +} +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h b/lib/bt/host/nimble/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h index a035f9a1..ea78fa61 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h +++ b/lib/bt/host/nimble/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h @@ -29,10 +29,16 @@ extern "C" { struct ble_hs_cfg; -#define BLE_SVC_GATT_CHR_SERVICE_CHANGED_UUID16 0x2a05 +#define BLE_SVC_GATT_CHR_SERVICE_CHANGED_UUID16 0x2a05 #define BLE_SVC_GATT_CHR_SERVER_SUPPORTED_FEAT_UUID16 0x2b3a #define BLE_SVC_GATT_CHR_CLIENT_SUPPORTED_FEAT_UUID16 0x2b29 +#define BLE_SVR_GATT_CHR_SVR_SUP_FEAT_EATT_FLAG 0x01 + +#define BLE_SVR_GATT_CHR_CLT_SUP_FEAT_ROBUST_CACHING_FLAG 0x01 +#define BLE_SVR_GATT_CHR_CLT_SUP_FEAT_EATT_FLAG 0x02 +#define BLE_SVR_GATT_CHR_CLT_SUP_FEAT_MULTI_NOTIF_FLAG 0x04 + #if MYNEWT_VAL(BLE_GATT_CACHING) #define BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16 0x2b2a @@ -45,7 +51,7 @@ uint8_t ble_svc_gatt_get_csfs(void); uint8_t ble_svc_gatt_get_local_cl_supported_feat(void); void ble_svc_gatt_changed(uint16_t start_handle, uint16_t end_handle); void ble_svc_gatt_init(void); - +void ble_svc_gatt_deinit(void); #ifdef __cplusplus } #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c b/lib/bt/host/nimble/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c index f32b7294..c76bc901 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c @@ -23,6 +23,7 @@ #include "host/ble_hs.h" #include "services/gatt/ble_svc_gatt.h" +#if MYNEWT_VAL(BLE_GATTS) #if MYNEWT_VAL(BLE_GATT_CACHING) static uint16_t ble_svc_gatt_db_hash_handle; static uint16_t ble_svc_gatt_client_supp_feature_handle; @@ -232,4 +233,27 @@ ble_svc_gatt_init(void) rc = ble_gatts_add_svcs(ble_svc_gatt_defs); SYSINIT_PANIC_ASSERT(rc == 0); + + if (MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 && ble_hs_cfg.eatt) { + ble_svc_gatt_local_srv_sup_feat |= (1 << BLE_SVC_GATT_SRV_SUP_FEAT_EATT_BIT); + } + + if (MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 && ble_hs_cfg.eatt) { + ble_svc_gatt_local_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_EATT_BIT); + } + + if (MYNEWT_VAL(BLE_ATT_SVR_NOTIFY_MULTI) > 0) { + ble_svc_gatt_local_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_MULT_NTF_BIT); + } + + if (MYNEWT_VAL(BLE_GATT_CACHING) > 0) { + ble_svc_gatt_local_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_ROBUST_CATCHING_BIT); + } +} + +void +ble_svc_gatt_deinit(void) +{ + ble_gatts_free_svcs(); } +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/hid/include/services/hid/ble_svc_hid.h b/lib/bt/host/nimble/nimble/nimble/host/services/hid/include/services/hid/ble_svc_hid.h index dcdf129c..50c6e532 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/hid/include/services/hid/ble_svc_hid.h +++ b/lib/bt/host/nimble/nimble/nimble/host/services/hid/include/services/hid/ble_svc_hid.h @@ -21,6 +21,10 @@ #ifndef H_BLE_SVC_HID_ #define H_BLE_SVC_HID_ +#ifdef __cplusplus +extern "C" { +#endif + /* 16 Bit Battery Service UUID */ #define BLE_SVC_HID_UUID16 0x1812 @@ -65,6 +69,8 @@ struct ble_svc_hid_params{ unsigned int kbd_inp_present : 1; unsigned int kbd_out_present : 1; unsigned int mouse_inp_present : 1; + unsigned int kbd_inp_write_perm:1; + unsigned int mouse_inp_write_perm:1; /* protocol mode char */ uint8_t proto_mode; uint16_t proto_mode_handle; @@ -108,5 +114,9 @@ void ble_svc_hid_init(void); int ble_svc_hid_add(struct ble_svc_hid_params params); void ble_svc_hid_reset(void); +#ifdef __cplusplus +} +#endif + #endif #endif // CONFIG_BT_NIMBLE_HID_SERVICE diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/hid/src/ble_svc_hid.c b/lib/bt/host/nimble/nimble/nimble/host/services/hid/src/ble_svc_hid.c index e091bb3d..bb5d11b6 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/hid/src/ble_svc_hid.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/hid/src/ble_svc_hid.c @@ -23,7 +23,9 @@ #include "sysinit/sysinit.h" #include "syscfg/syscfg.h" + #if MYNEWT_VAL(BLE_SVC_HID_SERVICE) +#if MYNEWT_VAL(BLE_GATTS) #include "host/ble_hs.h" #include "host/ble_gap.h" #include "services/hid/ble_svc_hid.h" @@ -180,24 +182,34 @@ void fill_boot_kbd_inp(uint8_t instance) { struct ble_gatt_chr_def *chr, demo_chr; + uint16_t write_flags; if (!hid_instances[instance].kbd_inp_present) { return; } + + write_flags = BLE_GATT_CHR_F_WRITE | +#if MYNEWT_VAL(BLE_SM_LVL) == 2 + BLE_GATT_CHR_F_WRITE_ENC | +#elif MYNEWT_VAL(BLE_SM_LVL) == 3 + BLE_GATT_CHR_F_WRITE_ENC | BLE_GATT_CHR_F_WRITE_AUTHEN +#endif + 0; + write_flags = (hid_instances[instance].kbd_inp_write_perm ? write_flags : 0); + demo_chr = (struct ble_gatt_chr_def) { /*** Report Map characteristic */ .uuid = uuid_boot_kbd_inp, .access_cb = ble_svc_hid_access, .val_handle = &hid_instances[instance].kbd_inp_handle, .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | - BLE_GATT_CHR_F_WRITE | #if MYNEWT_VAL(BLE_SM_LVL) == 2 - BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC | + BLE_GATT_CHR_F_READ_ENC | #elif MYNEWT_VAL(BLE_SM_LVL) == 3 - BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_WRITE_AUTHEN | - BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC | + BLE_GATT_CHR_F_READ_AUTHEN | + BLE_GATT_CHR_F_READ_ENC | #endif - 0, + write_flags, }; chr = ble_svc_hid_get_chr_block(); @@ -237,24 +249,34 @@ void fill_boot_mouse_inp(uint8_t instance) { struct ble_gatt_chr_def *chr, demo_chr; + uint16_t write_flags; if (!hid_instances[instance].mouse_inp_present) { return; } + + write_flags = BLE_GATT_CHR_F_WRITE | +#if MYNEWT_VAL(BLE_SM_LVL) == 2 + BLE_GATT_CHR_F_WRITE_ENC | +#elif MYNEWT_VAL(BLE_SM_LVL) == 3 + BLE_GATT_CHR_F_WRITE_ENC | BLE_GATT_CHR_F_WRITE_AUTHEN +#endif + 0; + write_flags = (hid_instances[instance].mouse_inp_write_perm ? write_flags : 0); + demo_chr = (struct ble_gatt_chr_def) { /*** Report Map characteristic */ .uuid = uuid_boot_mouse_inp, .access_cb = ble_svc_hid_access, .val_handle = &hid_instances[instance].mouse_inp_handle, .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY | - BLE_GATT_CHR_F_WRITE | #if MYNEWT_VAL(BLE_SM_LVL) == 2 - BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC | + BLE_GATT_CHR_F_READ_ENC | #elif MYNEWT_VAL(BLE_SM_LVL) == 3 - BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_WRITE_AUTHEN | - BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC | + BLE_GATT_CHR_F_READ_AUTHEN | + BLE_GATT_CHR_F_READ_ENC | #endif - 0, + write_flags, }; chr = ble_svc_hid_get_chr_block(); @@ -691,4 +713,5 @@ ble_svc_hid_init(void) rc = ble_gatts_add_svcs(ble_svc_hid_defs); SYSINIT_PANIC_ASSERT(rc == 0); } +#endif #endif // CONFIG_BT_NIMBLE_HID_SERVICE diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/hr/include/services/hr/ble_svc_hr.h b/lib/bt/host/nimble/nimble/nimble/host/services/hr/include/services/hr/ble_svc_hr.h index 9ed8b21f..2f8eaa50 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/hr/include/services/hr/ble_svc_hr.h +++ b/lib/bt/host/nimble/nimble/nimble/host/services/hr/include/services/hr/ble_svc_hr.h @@ -7,6 +7,10 @@ #ifndef H_BLE_SVC_HR_ #define H_BLE_SVC_HR_ +#ifdef __cplusplus +extern "C" { +#endif + struct ble_hs_cfg; /* 16 Bit Heart Rate Service UUID */ @@ -26,4 +30,8 @@ void ble_svc_hr_on_gap_disconnect(uint16_t conn_handle); void ble_svc_hr_init(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/hr/src/ble_svc_hr.c b/lib/bt/host/nimble/nimble/nimble/host/services/hr/src/ble_svc_hr.c index c471c9ff..6fa6c6b8 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/hr/src/ble_svc_hr.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/hr/src/ble_svc_hr.c @@ -13,6 +13,7 @@ #include "host/ble_gap.h" #include "services/hr/ble_svc_hr.h" +#if MYNEWT_VAL(BLE_GATTS) && CONFIG_BT_NIMBLE_HR_SERVICE /* Characteristic values */ static uint8_t ble_svc_hr_measurement; static uint16_t ble_svc_hr_body_sensor_loc; @@ -231,3 +232,4 @@ ble_svc_hr_init(void) ble_svc_hr_conn_handle[i] = -1; } } +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/htp/include/services/htp/ble_svc_htp.h b/lib/bt/host/nimble/nimble/nimble/host/services/htp/include/services/htp/ble_svc_htp.h index 9b7fbac9..97c40451 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/htp/include/services/htp/ble_svc_htp.h +++ b/lib/bt/host/nimble/nimble/nimble/host/services/htp/include/services/htp/ble_svc_htp.h @@ -7,6 +7,10 @@ #ifndef H_BLE_SVC_HTP_ #define H_BLE_SVC_HTP_ +#ifdef __cplusplus +extern "C" { +#endif + struct ble_hs_cfg; /* 16 Bit Health Thermometer Service UUID */ @@ -47,4 +51,8 @@ int ble_svc_htp_notify(uint16_t conn_handle, float temp, bool temp_unit); void ble_svc_htp_init(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/htp/src/ble_svc_htp.c b/lib/bt/host/nimble/nimble/nimble/host/services/htp/src/ble_svc_htp.c index 134e9803..7e1413ba 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/htp/src/ble_svc_htp.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/htp/src/ble_svc_htp.c @@ -13,6 +13,7 @@ #include "host/ble_gap.h" #include "services/htp/ble_svc_htp.h" +#if MYNEWT_VAL(BLE_GATTS) && CONFIG_BT_NIMBLE_HTP_SERVICE /* Characteristic values */ static uint16_t ble_svc_htp_temp_type; static uint16_t ble_svc_htp_temp_msr_itvl; @@ -289,3 +290,4 @@ ble_svc_htp_init(void) memset(&conn_chr_subs, 0, sizeof(conn_chr_subs)); } +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/ias/include/services/ias/ble_svc_ias.h b/lib/bt/host/nimble/nimble/nimble/host/services/ias/include/services/ias/ble_svc_ias.h index 26c18d01..3bce343b 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/ias/include/services/ias/ble_svc_ias.h +++ b/lib/bt/host/nimble/nimble/nimble/host/services/ias/include/services/ias/ble_svc_ias.h @@ -20,6 +20,10 @@ #ifndef H_BLE_IAS_TPS_ #define H_BLE_IAS_TPS_ +#ifdef __cplusplus +extern "C" { +#endif + #define BLE_SVC_IAS_UUID16 0x1802 #define BLE_SVC_IAS_CHR_UUID16_ALERT_LEVEL 0x2a06 @@ -33,6 +37,9 @@ typedef int ble_svc_ias_event_fn(uint8_t alert_level); void ble_svc_ias_set_cb(ble_svc_ias_event_fn *cb); void ble_svc_ias_init(void); +#ifdef __cplusplus +} #endif +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/ias/src/ble_svc_ias.c b/lib/bt/host/nimble/nimble/nimble/host/services/ias/src/ble_svc_ias.c index 9f5da148..f9154976 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/ias/src/ble_svc_ias.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/ias/src/ble_svc_ias.c @@ -23,6 +23,7 @@ #include "host/ble_hs.h" #include "services/ias/ble_svc_ias.h" +#if MYNEWT_VAL(BLE_GATTS) && CONFIG_BT_NIMBLE_IAS_SERVICE /* Callback function */ static ble_svc_ias_event_fn *ble_svc_ias_cb_fn; @@ -147,3 +148,4 @@ ble_svc_ias_init(void) rc = ble_gatts_add_svcs(ble_svc_ias_defs); SYSINIT_PANIC_ASSERT(rc == 0); } +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/ipss/src/ble_svc_ipss.c b/lib/bt/host/nimble/nimble/nimble/host/services/ipss/src/ble_svc_ipss.c index f42ca1e9..d883bf48 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/ipss/src/ble_svc_ipss.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/ipss/src/ble_svc_ipss.c @@ -23,6 +23,7 @@ #include "host/ble_hs.h" #include "services/ipss/ble_svc_ipss.h" +#if MYNEWT_VAL(BLE_GATTS) && CONFIG_BT_NIMBLE_IPSS_SERVICE static const struct ble_gatt_svc_def ble_svc_ipss_defs[] = { { /*** Service: GATT */ @@ -49,3 +50,4 @@ ble_svc_ipss_init(void) rc = ble_gatts_add_svcs(ble_svc_ipss_defs); SYSINIT_PANIC_ASSERT(rc == 0); } +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/lls/src/ble_svc_lls.c b/lib/bt/host/nimble/nimble/nimble/host/services/lls/src/ble_svc_lls.c index b5f7f9bd..335a7927 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/lls/src/ble_svc_lls.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/lls/src/ble_svc_lls.c @@ -23,6 +23,7 @@ #include "host/ble_hs.h" #include "services/lls/ble_svc_lls.h" +#if MYNEWT_VAL(BLE_GATTS) && CONFIG_BT_NIMBLE_LLS_SERVICE /* Callback function */ static ble_svc_lls_event_fn *ble_svc_lls_cb_fn; @@ -134,7 +135,9 @@ void ble_svc_lls_on_gap_disconnect(int reason) { if (reason == BLE_HS_HCI_ERR(BLE_ERR_CONN_SPVN_TMO)) { + if (ble_svc_lls_cb_fn != NULL) { ble_svc_lls_cb_fn(ble_svc_lls_alert_level); + } } } @@ -190,3 +193,4 @@ ble_svc_lls_init(void) rc = ble_gatts_add_svcs(ble_svc_lls_defs); SYSINIT_PANIC_ASSERT(rc == 0); } +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/prox/include/services/prox/ble_svc_prox.h b/lib/bt/host/nimble/nimble/nimble/host/services/prox/include/services/prox/ble_svc_prox.h index b34fbb95..8b1e4c62 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/prox/include/services/prox/ble_svc_prox.h +++ b/lib/bt/host/nimble/nimble/nimble/host/services/prox/include/services/prox/ble_svc_prox.h @@ -7,6 +7,10 @@ #ifndef H_BLE_SVC_PROX_ #define H_BLE_SVC_PROX_ +#ifdef __cplusplus +extern "C" { +#endif + struct ble_hs_cfg; /* 16 Bit Proximity Sensor Service UUID */ @@ -29,4 +33,8 @@ struct ble_hs_cfg; */ void ble_svc_prox_init(void); +#ifdef __cplusplus +} +#endif + #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/prox/src/ble_svc_prox.c b/lib/bt/host/nimble/nimble/nimble/host/services/prox/src/ble_svc_prox.c index c2c1df65..49c67dd5 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/prox/src/ble_svc_prox.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/prox/src/ble_svc_prox.c @@ -13,6 +13,7 @@ #include "host/ble_gap.h" #include "services/prox/ble_svc_prox.h" +#if MYNEWT_VAL(BLE_GATTS) && CONFIG_BT_NIMBLE_PROX_SERVICE /* Characteristic values */ static uint8_t ble_svc_prox_link_loss_alert; static int8_t ble_svc_prox_alert; @@ -261,3 +262,4 @@ ble_svc_prox_init(void) ble_svc_prox_alert_conn[i] = false; } } +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/sps/include/services/sps/ble_svc_sps.h b/lib/bt/host/nimble/nimble/nimble/host/services/sps/include/services/sps/ble_svc_sps.h index 72d4f4aa..5daa96ef 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/sps/include/services/sps/ble_svc_sps.h +++ b/lib/bt/host/nimble/nimble/nimble/host/services/sps/include/services/sps/ble_svc_sps.h @@ -22,11 +22,22 @@ #ifndef H_BLE_SVC_SPS_ #define H_BLE_SVC_SPS_ +#ifdef __cplusplus +extern "C" { +#endif #define BLE_SVC_SPS_UUID16 0x1813 -#define BLE_SVC_SPS_CHR_UUID16_SCAN_ITVL_WINDOW 0x2A23 +#define BLE_SVC_SPS_CHR_UUID16_SCAN_ITVL_WINDOW 0x2A4F #define BLE_SVC_SPS_CHR_UUID16_SCAN_REFRESH 0x2A31 +typedef int ble_svc_sps_event_fn(uint16_t scan_interval, uint16_t scan_window); + void ble_svc_sps_scan_refresh(void); void ble_svc_sps_init(uint16_t scan_itvl, uint16_t scan_window); +void ble_svc_sps_set_cb(ble_svc_sps_event_fn *cb); + +#ifdef __cplusplus +} +#endif + #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/sps/src/ble_svc_sps.c b/lib/bt/host/nimble/nimble/nimble/host/services/sps/src/ble_svc_sps.c index f7cbd197..c8ac0ad4 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/sps/src/ble_svc_sps.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/sps/src/ble_svc_sps.c @@ -23,12 +23,14 @@ #include "host/ble_hs.h" #include "services/sps/ble_svc_sps.h" +#if MYNEWT_VAL(BLE_GATTS) && CONFIG_BT_NIMBLE_SPS_SERVICE static uint16_t ble_scan_itvl; static uint16_t ble_scan_window; static uint8_t ble_scan_refresh; static uint16_t ble_scan_itvl_handle; static uint16_t ble_scan_refresh_handle; +static ble_svc_sps_event_fn *ble_svc_sps_cb_fn; /* Access function */ static int @@ -100,9 +102,12 @@ ble_svc_sps_access(uint16_t conn_handle, uint16_t attr_handle, case BLE_SVC_SPS_CHR_UUID16_SCAN_ITVL_WINDOW: assert(ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR); rc = ble_svc_sps_chr_write(ctxt->om, 0, sizeof(ble_scan_itvl) + sizeof(ble_scan_window), &write_val, NULL); - if(rc != 0) { + if(rc == 0) { ble_scan_itvl = (write_val & 0xffff0000) >> 16; - ble_scan_window = (write_val && 0x0000ffff); + ble_scan_window = (write_val & 0x0000ffff); + } + if (ble_svc_sps_cb_fn) { + ble_svc_sps_cb_fn(ble_scan_itvl, ble_scan_window); } return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; case BLE_SVC_SPS_CHR_UUID16_SCAN_REFRESH: @@ -118,6 +123,11 @@ ble_svc_sps_access(uint16_t conn_handle, uint16_t attr_handle, return 0; } +void +ble_svc_sps_set_cb(ble_svc_sps_event_fn *cb) +{ + ble_svc_sps_cb_fn = cb; +} /** * Initialize the SPS package. @@ -138,3 +148,4 @@ ble_svc_sps_init(uint16_t scan_itvl, uint16_t scan_window) rc = ble_gatts_add_svcs(ble_svc_sps_defs); SYSINIT_PANIC_ASSERT(rc == 0); } +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/tps/include/services/tps/ble_svc_tps.h b/lib/bt/host/nimble/nimble/nimble/host/services/tps/include/services/tps/ble_svc_tps.h index ec4cd790..446cc37c 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/tps/include/services/tps/ble_svc_tps.h +++ b/lib/bt/host/nimble/nimble/nimble/host/services/tps/include/services/tps/ble_svc_tps.h @@ -20,6 +20,10 @@ #ifndef H_BLE_SVC_TPS_ #define H_BLE_SVC_TPS_ +#ifdef __cplusplus +extern "C" { +#endif + struct ble_hs_cfg; #define BLE_SVC_TPS_UUID16 0x1804 @@ -27,5 +31,8 @@ struct ble_hs_cfg; void ble_svc_tps_init(void); +#ifdef __cplusplus +} #endif +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/services/tps/src/ble_svc_tps.c b/lib/bt/host/nimble/nimble/nimble/host/services/tps/src/ble_svc_tps.c index 9885a921..313eb7fb 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/services/tps/src/ble_svc_tps.c +++ b/lib/bt/host/nimble/nimble/nimble/host/services/tps/src/ble_svc_tps.c @@ -30,6 +30,7 @@ */ #include "../src/ble_hs_hci_priv.h" +#if MYNEWT_VAL(BLE_GATTS) && CONFIG_BT_NIMBLE_TPS_SERVICE int8_t ble_svc_tps_tx_power_level; /* Access function */ @@ -105,3 +106,4 @@ ble_svc_tps_init(void) rc = ble_gatts_add_svcs(ble_svc_tps_defs); SYSINIT_PANIC_ASSERT(rc == 0); } +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_aes_ccm.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_aes_ccm.c index 285db47e..7af09830 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_aes_ccm.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_aes_ccm.c @@ -265,14 +265,20 @@ int ble_aes_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t uint8_t *out_msg, size_t mic_size) { uint8_t mic[16]; + uint8_t key_reversed[16]; if (aad_len >= 0xff00 || mic_size > sizeof(mic)) { return BLE_HS_EINVAL; } - ble_aes_ccm_crypt(key, nonce, enc_msg, out_msg, msg_len); + /** Setting the correct endian-ness of the key */ + for (int i = 0; i < 16; i++) { + key_reversed[i] = key[15 - i]; + } + + ble_aes_ccm_crypt(key_reversed, nonce, enc_msg, out_msg, msg_len); - ble_aes_ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size); + ble_aes_ccm_auth(key_reversed, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size); /*if (memcmp(mic, enc_msg + msg_len, mic_size)) { printf("\n%s return here", __func__); @@ -286,16 +292,25 @@ int ble_aes_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t size_t msg_len, const uint8_t *aad, size_t aad_len, uint8_t *out_msg, size_t mic_size) { + /** MIC starts after encrypted message and is part of encrypted advertisement data */ uint8_t *mic = out_msg + msg_len; + uint8_t key_reversed[16]; /* Unsupported AAD size */ if (aad_len >= 0xff00 || mic_size > 16) { return BLE_HS_EINVAL; } - ble_aes_ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size); + /* Correcting the endian-ness of the key */ + for (int i = 0; i < 16; i++) { + key_reversed[i] = key[15 - i]; + } + + /** Calculating MIC */ + ble_aes_ccm_auth(key_reversed, nonce, msg, msg_len, aad, aad_len, mic, mic_size); - ble_aes_ccm_crypt(key, nonce, msg, out_msg, msg_len); + /** Encrypting advertisment */ + ble_aes_ccm_crypt(key_reversed, nonce, msg, out_msg, msg_len); return 0; } diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_att.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_att.c index 91e77080..ea008e43 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_att.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_att.c @@ -35,7 +35,7 @@ static uint16_t ble_att_preferred_mtu_val; /** Dispatch table for incoming ATT requests. Sorted by op code. */ -typedef int ble_att_rx_fn(uint16_t conn_handle, struct os_mbuf **om); +typedef int ble_att_rx_fn(uint16_t conn_handle, uint16_t cid, struct os_mbuf **om); struct ble_att_rx_dispatch_entry { uint8_t bde_op; ble_att_rx_fn *bde_fn; @@ -43,36 +43,41 @@ struct ble_att_rx_dispatch_entry { /** Dispatch table for incoming ATT commands. Must be ordered by op code. */ static const struct ble_att_rx_dispatch_entry ble_att_rx_dispatch[] = { +#if MYNEWT_VAL(BLE_GATTC) { BLE_ATT_OP_ERROR_RSP, ble_att_clt_rx_error }, - { BLE_ATT_OP_MTU_REQ, ble_att_svr_rx_mtu }, { BLE_ATT_OP_MTU_RSP, ble_att_clt_rx_mtu }, - { BLE_ATT_OP_FIND_INFO_REQ, ble_att_svr_rx_find_info }, { BLE_ATT_OP_FIND_INFO_RSP, ble_att_clt_rx_find_info }, - { BLE_ATT_OP_FIND_TYPE_VALUE_REQ, ble_att_svr_rx_find_type_value }, { BLE_ATT_OP_FIND_TYPE_VALUE_RSP, ble_att_clt_rx_find_type_value }, - { BLE_ATT_OP_READ_TYPE_REQ, ble_att_svr_rx_read_type }, { BLE_ATT_OP_READ_TYPE_RSP, ble_att_clt_rx_read_type }, - { BLE_ATT_OP_READ_REQ, ble_att_svr_rx_read }, { BLE_ATT_OP_READ_RSP, ble_att_clt_rx_read }, - { BLE_ATT_OP_READ_BLOB_REQ, ble_att_svr_rx_read_blob }, { BLE_ATT_OP_READ_BLOB_RSP, ble_att_clt_rx_read_blob }, - { BLE_ATT_OP_READ_MULT_REQ, ble_att_svr_rx_read_mult }, { BLE_ATT_OP_READ_MULT_RSP, ble_att_clt_rx_read_mult }, - { BLE_ATT_OP_READ_GROUP_TYPE_REQ, ble_att_svr_rx_read_group_type }, { BLE_ATT_OP_READ_GROUP_TYPE_RSP, ble_att_clt_rx_read_group_type }, - { BLE_ATT_OP_WRITE_REQ, ble_att_svr_rx_write }, { BLE_ATT_OP_WRITE_RSP, ble_att_clt_rx_write }, - { BLE_ATT_OP_PREP_WRITE_REQ, ble_att_svr_rx_prep_write }, { BLE_ATT_OP_PREP_WRITE_RSP, ble_att_clt_rx_prep_write }, - { BLE_ATT_OP_EXEC_WRITE_REQ, ble_att_svr_rx_exec_write }, { BLE_ATT_OP_EXEC_WRITE_RSP, ble_att_clt_rx_exec_write }, + { BLE_ATT_OP_INDICATE_RSP, ble_att_clt_rx_indicate }, + { BLE_ATT_OP_READ_MULT_VAR_RSP, ble_att_clt_rx_read_mult_var }, +#endif +#if MYNEWT_VAL(BLE_GATTS) + { BLE_ATT_OP_MTU_REQ, ble_att_svr_rx_mtu }, + { BLE_ATT_OP_FIND_INFO_REQ, ble_att_svr_rx_find_info }, + { BLE_ATT_OP_FIND_TYPE_VALUE_REQ, ble_att_svr_rx_find_type_value }, + { BLE_ATT_OP_READ_TYPE_REQ, ble_att_svr_rx_read_type }, + { BLE_ATT_OP_READ_REQ, ble_att_svr_rx_read }, + { BLE_ATT_OP_READ_BLOB_REQ, ble_att_svr_rx_read_blob }, + { BLE_ATT_OP_READ_MULT_REQ, ble_att_svr_rx_read_mult }, + { BLE_ATT_OP_READ_GROUP_TYPE_REQ, ble_att_svr_rx_read_group_type }, + { BLE_ATT_OP_WRITE_REQ, ble_att_svr_rx_write }, + { BLE_ATT_OP_PREP_WRITE_REQ, ble_att_svr_rx_prep_write }, + { BLE_ATT_OP_EXEC_WRITE_REQ, ble_att_svr_rx_exec_write }, { BLE_ATT_OP_NOTIFY_REQ, ble_att_svr_rx_notify }, { BLE_ATT_OP_INDICATE_REQ, ble_att_svr_rx_indicate }, - { BLE_ATT_OP_INDICATE_RSP, ble_att_clt_rx_indicate }, { BLE_ATT_OP_READ_MULT_VAR_REQ, ble_att_svr_rx_read_mult_var }, - { BLE_ATT_OP_READ_MULT_VAR_RSP, ble_att_clt_rx_read_mult_var }, + { BLE_ATT_OP_NOTIFY_MULTI_REQ, ble_att_svr_rx_notify_multi }, { BLE_ATT_OP_WRITE_CMD, ble_att_svr_rx_write_no_rsp }, { BLE_ATT_OP_SIGNED_WRITE_CMD, ble_att_svr_rx_signed_write }, +#endif }; #define BLE_ATT_RX_DISPATCH_SZ \ @@ -132,6 +137,8 @@ STATS_NAME_START(ble_att_stats) STATS_NAME(ble_att_stats, indicate_req_tx) STATS_NAME(ble_att_stats, indicate_rsp_rx) STATS_NAME(ble_att_stats, indicate_rsp_tx) + STATS_NAME(ble_att_stats, multi_notify_req_rx) + STATS_NAME(ble_att_stats, multi_notify_req_tx) STATS_NAME(ble_att_stats, write_cmd_rx) STATS_NAME(ble_att_stats, write_cmd_tx) STATS_NAME_END(ble_att_stats) @@ -147,23 +154,27 @@ ble_att_rx_dispatch_entry_find(uint8_t op) if (entry->bde_op == op) { return entry; } - - if (entry->bde_op > op) { - break; - } } return NULL; } int -ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn, +ble_att_conn_chan_find(uint16_t conn_handle, uint16_t cid, struct ble_hs_conn **out_conn, struct ble_l2cap_chan **out_chan) { - return ble_hs_misc_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, + return ble_hs_misc_conn_chan_find(conn_handle, cid, out_conn, out_chan); } +int +ble_att_conn_chan_find_by_psm(uint16_t conn_handle, uint16_t psm, + struct ble_hs_conn **out_conn, + struct ble_l2cap_chan **out_chan) +{ + return ble_hs_misc_conn_chan_find(conn_handle, psm, out_conn, out_chan); +} + void ble_att_inc_tx_stat(uint8_t att_op) { @@ -272,6 +283,10 @@ ble_att_inc_tx_stat(uint8_t att_op) STATS_INC(ble_att_stats, indicate_rsp_tx); break; + case BLE_ATT_OP_NOTIFY_MULTI_REQ: + STATS_INC(ble_att_stats, multi_notify_req_tx); + break; + case BLE_ATT_OP_WRITE_CMD: STATS_INC(ble_att_stats, write_cmd_tx); break; @@ -389,6 +404,10 @@ ble_att_inc_rx_stat(uint8_t att_op) STATS_INC(ble_att_stats, indicate_rsp_rx); break; + case BLE_ATT_OP_NOTIFY_MULTI_REQ: + STATS_INC(ble_att_stats, multi_notify_req_rx); + break; + case BLE_ATT_OP_WRITE_CMD: STATS_INC(ble_att_stats, write_cmd_rx); break; @@ -413,7 +432,7 @@ ble_att_truncate_to_mtu(const struct ble_l2cap_chan *att_chan, } uint16_t -ble_att_mtu(uint16_t conn_handle) +ble_att_mtu_by_cid(uint16_t conn_handle, uint16_t cid) { struct ble_l2cap_chan *chan; struct ble_hs_conn *conn; @@ -422,7 +441,7 @@ ble_att_mtu(uint16_t conn_handle) ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, cid, &conn, &chan); if (rc == 0) { mtu = ble_att_chan_mtu(chan); } else { @@ -434,6 +453,12 @@ ble_att_mtu(uint16_t conn_handle) return mtu; } +uint16_t +ble_att_mtu(uint16_t conn_handle) +{ + return ble_att_mtu_by_cid(conn_handle, BLE_L2CAP_CID_ATT); +} + void ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu) { @@ -449,6 +474,16 @@ ble_att_chan_mtu(const struct ble_l2cap_chan *chan) { uint16_t mtu; +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + if (ble_hs_cfg.eatt && chan->psm == BLE_EATT_PSM) { + /* The ATT_MTU for the Enhanced ATT bearer shall be set to the minimum of the + * MTU field values of the two devices. Reference: + * Core v5.4 Vol 3 Part G 5.3.1 ATT_MTU + */ + return min(chan->coc_tx.mtu, chan->coc_rx.mtu); + } +#endif + /* If either side has not exchanged MTU size, use the default. Otherwise, * use the lesser of the two exchanged values. */ @@ -467,35 +502,46 @@ ble_att_chan_mtu(const struct ble_l2cap_chan *chan) static void ble_att_rx_handle_unknown_request(uint8_t op, uint16_t conn_handle, - struct os_mbuf **om) + uint16_t cid, struct os_mbuf **om) { /* If this is command (bit6 is set to 1), do nothing */ if (op & 0x40) { return; } - +#if MYNEWT_VAL(BLE_GATTS) os_mbuf_adj(*om, OS_MBUF_PKTLEN(*om)); - ble_att_svr_tx_error_rsp(conn_handle, *om, op, 0, + ble_att_svr_tx_error_rsp(conn_handle, cid, *om, op, 0, BLE_ATT_ERR_REQ_NOT_SUPPORTED); +#endif *om = NULL; } +static void +ble_att_send_outstanding_after_response(uint16_t conn_handle) +{ + struct ble_hs_conn *conn; + struct ble_l2cap_chan *chan; + int rc; + + ble_hs_lock(); + rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn, + &chan); + if (rc) { + return; + } + conn->client_att_busy = false; + ble_att_tx_with_conn(conn, chan, NULL); + ble_hs_unlock(); +} + static int -ble_att_rx(struct ble_l2cap_chan *chan) +ble_att_rx_extended(uint16_t conn_handle, uint16_t cid, struct os_mbuf **om) { const struct ble_att_rx_dispatch_entry *entry; uint8_t op; - uint16_t conn_handle; - struct os_mbuf **om; int rc; - conn_handle = ble_l2cap_get_conn_handle(chan); - if (conn_handle == BLE_HS_CONN_HANDLE_NONE) { - return BLE_HS_ENOTCONN; - } - - om = &chan->rx_buf; BLE_HS_DBG_ASSERT(*om != NULL); rc = os_mbuf_copydata(*om, 0, 1, &op); @@ -503,9 +549,13 @@ ble_att_rx(struct ble_l2cap_chan *chan) return BLE_HS_EMSGSIZE; } + if (cid == BLE_L2CAP_CID_ATT && ble_att_is_response_op(op)) { + ble_att_send_outstanding_after_response(conn_handle); + } + entry = ble_att_rx_dispatch_entry_find(op); if (entry == NULL) { - ble_att_rx_handle_unknown_request(op, conn_handle, om); + ble_att_rx_handle_unknown_request(op, conn_handle, cid, om); return BLE_HS_ENOTSUP; } @@ -514,10 +564,10 @@ ble_att_rx(struct ble_l2cap_chan *chan) /* Strip L2CAP ATT header from the front of the mbuf. */ os_mbuf_adj(*om, 1); - rc = entry->bde_fn(conn_handle, om); + rc = entry->bde_fn(conn_handle, cid, om); if (rc != 0) { if (rc == BLE_HS_ENOTSUP) { - ble_att_rx_handle_unknown_request(op, conn_handle, om); + ble_att_rx_handle_unknown_request(op, conn_handle, cid, om); } return rc; } @@ -525,6 +575,19 @@ ble_att_rx(struct ble_l2cap_chan *chan) return 0; } +static int +ble_att_rx(struct ble_l2cap_chan *chan) +{ + uint16_t conn_handle; + + conn_handle = ble_l2cap_get_conn_handle(chan); + if (conn_handle == BLE_HS_CONN_HANDLE_NONE) { + return BLE_HS_ENOTCONN; + } + + return ble_att_rx_extended(conn_handle, chan->scid, &chan->rx_buf); +} + uint16_t ble_att_preferred_mtu(void) { @@ -585,6 +648,105 @@ ble_att_create_chan(uint16_t conn_handle) return chan; } +bool +ble_att_is_request_op(uint8_t opcode) +{ + switch (opcode) { + case BLE_ATT_OP_MTU_REQ: + case BLE_ATT_OP_FIND_INFO_REQ: + case BLE_ATT_OP_FIND_TYPE_VALUE_REQ: + case BLE_ATT_OP_READ_TYPE_REQ: + case BLE_ATT_OP_READ_REQ: + case BLE_ATT_OP_READ_BLOB_REQ: + case BLE_ATT_OP_READ_MULT_REQ: + case BLE_ATT_OP_READ_GROUP_TYPE_REQ: + case BLE_ATT_OP_WRITE_REQ: + case BLE_ATT_OP_PREP_WRITE_REQ: + case BLE_ATT_OP_EXEC_WRITE_REQ: + case BLE_ATT_OP_INDICATE_REQ: + case BLE_ATT_OP_READ_MULT_VAR_REQ: + return true; + } + return false; +} + +bool +ble_att_is_response_op(uint8_t opcode) +{ + switch (opcode) { + case BLE_ATT_OP_MTU_RSP: + case BLE_ATT_OP_ERROR_RSP: + case BLE_ATT_OP_FIND_INFO_RSP: + case BLE_ATT_OP_FIND_TYPE_VALUE_RSP: + case BLE_ATT_OP_READ_TYPE_RSP: + case BLE_ATT_OP_INDICATE_RSP: + case BLE_ATT_OP_READ_RSP: + case BLE_ATT_OP_READ_BLOB_RSP: + case BLE_ATT_OP_READ_MULT_RSP: + case BLE_ATT_OP_READ_GROUP_TYPE_RSP: + case BLE_ATT_OP_WRITE_RSP: + case BLE_ATT_OP_PREP_WRITE_RSP: + case BLE_ATT_OP_EXEC_WRITE_RSP: + case BLE_ATT_OP_READ_MULT_VAR_RSP: + return true; + } + + return false; +} + +bool +ble_att_is_att_pdu_op(uint8_t opcode) +{ + if (ble_att_is_request_op(opcode)) { + return true; + } + + if (ble_att_is_response_op(opcode)) { + return true; + } + + switch (opcode) { + case BLE_ATT_OP_NOTIFY_MULTI_REQ: + case BLE_ATT_OP_WRITE_CMD: + case BLE_ATT_OP_SIGNED_WRITE_CMD: + case BLE_ATT_OP_NOTIFY_REQ: + return true; + } + return false; +} + +int +ble_att_set_default_bearer_using_cid(uint16_t conn_handle, uint16_t cid) { +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + struct ble_hs_conn * conn; + + ble_hs_lock(); + conn = ble_hs_conn_find(conn_handle); + ble_hs_unlock(); + + if (conn == NULL) { + return BLE_HS_ENOTCONN; + } + conn->default_cid = cid; + return 0; +#endif + return BLE_HS_ENOTSUP; +} + +uint16_t +ble_att_get_default_bearer_cid(uint16_t conn_handle) { +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + struct ble_hs_conn * conn; + + conn = ble_hs_conn_find(conn_handle); + if (conn == NULL) { + return 0; + } + return conn->default_cid; +#endif + return 0; +} + int ble_att_init(void) { @@ -599,6 +761,8 @@ ble_att_init(void) return BLE_HS_EOS; } + ble_eatt_init(ble_att_rx_extended); + return 0; } diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_clt.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_clt.c index 2b62e27b..acdf8e8d 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_clt.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_clt.c @@ -32,12 +32,13 @@ #endif #if NIMBLE_BLE_CONNECT +#if MYNEWT_VAL(BLE_GATTC) /***************************************************************************** * $error response * *****************************************************************************/ int -ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_error(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { struct ble_att_error_rsp *rsp; int rc; @@ -49,7 +50,7 @@ ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom) rsp = (struct ble_att_error_rsp *)(*rxom)->om_data; - ble_gattc_rx_err(conn_handle, le16toh(rsp->baep_handle), + ble_gattc_rx_err(conn_handle, cid, le16toh(rsp->baep_handle), le16toh(rsp->baep_error_code)); return 0; @@ -74,7 +75,7 @@ ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu) ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, &conn, &chan); if (rc != 0) { rc = BLE_HS_ENOTCONN; } else if (chan->flags & BLE_L2CAP_CHAN_F_TXED_MTU) { @@ -95,14 +96,14 @@ ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu) req->bamc_mtu = htole16(mtu); - rc = ble_att_tx(conn_handle, txom); + rc = ble_att_tx(conn_handle, BLE_L2CAP_CID_ATT, txom); if (rc != 0) { return rc; } ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, &conn, &chan); if (rc == 0) { chan->flags |= BLE_L2CAP_CHAN_F_TXED_MTU; } @@ -113,7 +114,7 @@ ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu) } int -ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_mtu(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { struct ble_att_mtu_cmd *cmd; struct ble_l2cap_chan *chan; @@ -122,13 +123,19 @@ ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) mtu = 0; +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + if (ble_hs_cfg.eatt && cid != BLE_L2CAP_CID_ATT) { + return BLE_HS_ENOTSUP; + } +#endif + rc = ble_hs_mbuf_pullup_base(rxom, sizeof(*cmd)); if (rc == 0) { cmd = (struct ble_att_mtu_cmd *)(*rxom)->om_data; ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, NULL, &chan); + rc = ble_att_conn_chan_find(conn_handle, cid, NULL, &chan); if (rc == 0) { ble_att_set_peer_mtu(chan, le16toh(cmd->bamc_mtu)); mtu = ble_att_chan_mtu(chan); @@ -141,7 +148,7 @@ ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) } } - ble_gattc_rx_mtu(conn_handle, rc, mtu); + ble_gattc_rx_mtu(conn_handle, BLE_L2CAP_CID_ATT, rc, mtu); return rc; } @@ -150,7 +157,7 @@ ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int -ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t start_handle, +ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle) { #if !NIMBLE_BLE_ATT_CLT_FIND_INFO @@ -172,7 +179,7 @@ ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t start_handle, req->bafq_start_handle = htole16(start_handle); req->bafq_end_handle = htole16(end_handle); - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } static int @@ -227,7 +234,7 @@ ble_att_clt_parse_find_info_entry(struct os_mbuf **rxom, uint8_t rsp_format, } int -ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **om) +ble_att_clt_rx_find_info(uint16_t conn_handle, uint16_t cid, struct os_mbuf **om) { #if !NIMBLE_BLE_ATT_CLT_FIND_INFO return BLE_HS_ENOTSUP; @@ -254,14 +261,14 @@ ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **om) } /* Hand find-info entry to GATT. */ - ble_gattc_rx_find_info_idata(conn_handle, &idata); + ble_gattc_rx_find_info_idata(conn_handle, cid, &idata); } rc = 0; done: /* Notify GATT that response processing is done. */ - ble_gattc_rx_find_info_complete(conn_handle, rc); + ble_gattc_rx_find_info_complete(conn_handle, cid, rc); return rc; } @@ -274,8 +281,9 @@ done: * anyway */ int -ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t start_handle, - uint16_t end_handle, uint16_t attribute_type, +ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t cid, + uint16_t start_handle, uint16_t end_handle, + uint16_t attribute_type, const void *attribute_value, int value_len) { #if !NIMBLE_BLE_ATT_CLT_FIND_TYPE @@ -300,7 +308,7 @@ ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t start_handle, req->bavq_attr_type = htole16(attribute_type); memcpy(req->bavq_value, attribute_value, value_len); - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } static int @@ -326,7 +334,7 @@ ble_att_clt_parse_find_type_value_hinfo( } int -ble_att_clt_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_find_type_value(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_FIND_TYPE return BLE_HS_ENOTSUP; @@ -343,11 +351,11 @@ ble_att_clt_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) break; } - ble_gattc_rx_find_type_value_hinfo(conn_handle, &hinfo); + ble_gattc_rx_find_type_value_hinfo(conn_handle, cid, &hinfo); } /* Notify GATT client that the full response has been parsed. */ - ble_gattc_rx_find_type_value_complete(conn_handle, rc); + ble_gattc_rx_find_type_value_complete(conn_handle, cid, rc); return 0; } @@ -357,7 +365,7 @@ ble_att_clt_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int -ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t start_handle, +ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid) { #if !NIMBLE_BLE_ATT_CLT_READ_TYPE @@ -382,11 +390,11 @@ ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t start_handle, ble_uuid_flat(uuid, req->uuid); - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } int -ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ_TYPE return BLE_HS_ENOTSUP; @@ -428,13 +436,13 @@ ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) adata.value_len = data_len - sizeof(*data); adata.value = data->value; - ble_gattc_rx_read_type_adata(conn_handle, &adata); + ble_gattc_rx_read_type_adata(conn_handle, cid, &adata); os_mbuf_adj(*rxom, data_len); } done: /* Notify GATT that the response is done being parsed. */ - ble_gattc_rx_read_type_complete(conn_handle, rc); + ble_gattc_rx_read_type_complete(conn_handle, cid, rc); return rc; } @@ -444,7 +452,7 @@ done: *****************************************************************************/ int -ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle) +ble_att_clt_tx_read(uint16_t conn_handle, uint16_t cid, uint16_t handle) { #if !NIMBLE_BLE_ATT_CLT_READ return BLE_HS_ENOTSUP; @@ -465,7 +473,7 @@ ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle) req->barq_handle = htole16(handle); - rc = ble_att_tx(conn_handle, txom); + rc = ble_att_tx(conn_handle, cid, txom); if (rc != 0) { return rc; } @@ -474,14 +482,14 @@ ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle) } int -ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ return BLE_HS_ENOTSUP; #endif /* Pass the Attribute Value field to GATT. */ - ble_gattc_rx_read_rsp(conn_handle, 0, rxom); + ble_gattc_rx_read_rsp(conn_handle, cid, 0, rxom); return 0; } @@ -490,7 +498,7 @@ ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int -ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, uint16_t offset) +ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t offset) { #if !NIMBLE_BLE_ATT_CLT_READ_BLOB return BLE_HS_ENOTSUP; @@ -512,7 +520,7 @@ ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, uint16_t offset) req->babq_handle = htole16(handle); req->babq_offset = htole16(offset); - rc = ble_att_tx(conn_handle, txom); + rc = ble_att_tx(conn_handle, cid, txom); if (rc != 0) { return rc; } @@ -521,14 +529,14 @@ ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, uint16_t offset) } int -ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read_blob(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ_BLOB return BLE_HS_ENOTSUP; #endif /* Pass the Attribute Value field to GATT. */ - ble_gattc_rx_read_blob_rsp(conn_handle, 0, rxom); + ble_gattc_rx_read_blob_rsp(conn_handle, cid, 0, rxom); return 0; } @@ -536,8 +544,8 @@ ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom) * $read multiple * *****************************************************************************/ int -ble_att_clt_tx_read_mult(uint16_t conn_handle, const uint16_t *handles, - int num_handles, bool variable) +ble_att_clt_tx_read_mult(uint16_t conn_handle, uint16_t cid, + const uint16_t *handles, int num_handles, bool variable) { #if !NIMBLE_BLE_ATT_CLT_READ_MULT return BLE_HS_ENOTSUP; @@ -565,30 +573,30 @@ ble_att_clt_tx_read_mult(uint16_t conn_handle, const uint16_t *handles, req->handles[i] = htole16(handles[i]); } - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } int -ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read_mult(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ_MULT return BLE_HS_ENOTSUP; #endif /* Pass the Attribute Value field to GATT. */ - ble_gattc_rx_read_mult_rsp(conn_handle, 0, rxom, false); + ble_gattc_rx_read_mult_rsp(conn_handle, cid, 0, rxom, false); return 0; } int -ble_att_clt_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read_mult_var(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ_MULT_VAR return BLE_HS_ENOTSUP; #endif /* Pass the Attribute Value field to GATT. */ - ble_gattc_rx_read_mult_rsp(conn_handle, 0, rxom, true); + ble_gattc_rx_read_mult_rsp(conn_handle, cid, 0, rxom, true); return 0; } @@ -597,7 +605,7 @@ ble_att_clt_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int -ble_att_clt_tx_read_group_type(uint16_t conn_handle, +ble_att_clt_tx_read_group_type(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid) { @@ -622,7 +630,7 @@ ble_att_clt_tx_read_group_type(uint16_t conn_handle, req->bagq_end_handle = htole16(end_handle); ble_uuid_flat(uuid, req->uuid); - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } static int @@ -650,7 +658,7 @@ ble_att_clt_parse_read_group_type_adata( } int -ble_att_clt_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read_group_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE return BLE_HS_ENOTSUP; @@ -680,13 +688,13 @@ ble_att_clt_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) goto done; } - ble_gattc_rx_read_group_type_adata(conn_handle, &adata); + ble_gattc_rx_read_group_type_adata(conn_handle, cid, &adata); os_mbuf_adj(*rxom, len); } done: /* Notify GATT that the response is done being parsed. */ - ble_gattc_rx_read_group_type_complete(conn_handle, rc); + ble_gattc_rx_read_group_type_complete(conn_handle, cid, rc); return rc; } @@ -695,7 +703,7 @@ done: *****************************************************************************/ int -ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t handle, +ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t cid, uint16_t handle, struct os_mbuf *txom) { #if !NIMBLE_BLE_ATT_CLT_WRITE @@ -714,12 +722,12 @@ ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t handle, req->bawq_handle = htole16(handle); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + return ble_att_tx(conn_handle, cid, txom2); } int -ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom) +ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t cid, + uint16_t handle, struct os_mbuf *txom) { #if !NIMBLE_BLE_ATT_CLT_WRITE_NO_RSP return BLE_HS_ENOTSUP; @@ -753,24 +761,24 @@ ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t handle, cmd->handle = htole16(handle); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + return ble_att_tx(conn_handle, cid, txom2); } int -ble_att_clt_rx_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_WRITE return BLE_HS_ENOTSUP; #endif /* No payload. */ - ble_gattc_rx_write_rsp(conn_handle); + ble_gattc_rx_write_rsp(conn_handle, cid); return 0; } int -ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t handle, uint8_t *csrk, - uint32_t counter, struct os_mbuf *txom) +ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t cid, uint16_t handle, + uint8_t *csrk, uint32_t counter, struct os_mbuf *txom) { #if !NIMBLE_BLE_ATT_CLT_SIGNED_WRITE return BLE_HS_ENOTSUP; @@ -856,7 +864,7 @@ ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t handle, uint8_t * if(message != NULL) nimble_platform_mem_free(message); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + return ble_att_tx(conn_handle, cid, txom2); err: if(message != NULL) nimble_platform_mem_free(message); os_mbuf_free_chain(txom2); @@ -868,7 +876,7 @@ err: *****************************************************************************/ int -ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, +ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t offset, struct os_mbuf *txom) { #if !NIMBLE_BLE_ATT_CLT_PREP_WRITE @@ -897,7 +905,7 @@ ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, #endif if (OS_MBUF_PKTLEN(txom) > - ble_att_mtu(conn_handle) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ) { + ble_att_mtu_by_cid(conn_handle, cid) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ) { rc = BLE_HS_EINVAL; goto err; } @@ -912,7 +920,7 @@ ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, req->bapc_offset = htole16(offset); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + return ble_att_tx(conn_handle, cid, txom2); err: os_mbuf_free_chain(txom); @@ -920,7 +928,7 @@ err: } int -ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_prep_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_PREP_WRITE return BLE_HS_ENOTSUP; @@ -949,7 +957,7 @@ ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom) done: /* Notify GATT client that the full response has been parsed. */ - ble_gattc_rx_prep_write_rsp(conn_handle, rc, handle, offset, rxom); + ble_gattc_rx_prep_write_rsp(conn_handle, cid, rc, handle, offset, rxom); return rc; } @@ -958,7 +966,7 @@ done: *****************************************************************************/ int -ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags) +ble_att_clt_tx_exec_write(uint16_t conn_handle, uint16_t cid, uint8_t flags) { #if !NIMBLE_BLE_ATT_CLT_EXEC_WRITE return BLE_HS_ENOTSUP; @@ -975,7 +983,7 @@ ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags) req->baeq_flags = flags; - rc = ble_att_tx(conn_handle, txom); + rc = ble_att_tx(conn_handle, cid, txom); if (rc != 0) { return rc; } @@ -984,16 +992,18 @@ ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags) } int -ble_att_clt_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_exec_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_EXEC_WRITE return BLE_HS_ENOTSUP; #endif - ble_gattc_rx_exec_write_rsp(conn_handle, 0); + ble_gattc_rx_exec_write_rsp(conn_handle, cid, 0); return 0; } +#endif + /***************************************************************************** * $handle value notification * *****************************************************************************/ @@ -1008,6 +1018,7 @@ ble_att_clt_tx_notify(uint16_t conn_handle, uint16_t handle, struct ble_att_notify_req *req; struct os_mbuf *txom2; + uint16_t cid; int rc; if (handle == 0) { @@ -1024,7 +1035,10 @@ ble_att_clt_tx_notify(uint16_t conn_handle, uint16_t handle, req->banq_handle = htole16(handle); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + cid = ble_eatt_get_available_chan_cid(conn_handle, BLE_GATT_OP_DUMMY); + rc = ble_att_tx(conn_handle, cid, txom2); + ble_eatt_release_chan(conn_handle, BLE_GATT_OP_DUMMY); + return rc; err: os_mbuf_free_chain(txom); @@ -1036,8 +1050,8 @@ err: *****************************************************************************/ int -ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom) +ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t cid, + uint16_t handle, struct os_mbuf *txom) { #if !NIMBLE_BLE_ATT_CLT_INDICATE return BLE_HS_ENOTSUP; @@ -1061,23 +1075,55 @@ ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t handle, req->baiq_handle = htole16(handle); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + return ble_att_tx(conn_handle, cid, txom2); err: os_mbuf_free_chain(txom); return rc; } +#if MYNEWT_VAL(BLE_GATTC) int -ble_att_clt_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_indicate(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_INDICATE return BLE_HS_ENOTSUP; #endif /* No payload. */ - ble_gatts_rx_indicate_rsp(conn_handle); + ble_gatts_rx_indicate_rsp(conn_handle, cid); return 0; } +/***************************************************************************** +* $multiple handle value notification * +*****************************************************************************/ + +int +ble_att_clt_tx_notify_mult(uint16_t conn_handle, struct os_mbuf *txom) +{ +#if !NIMBLE_BLE_ATT_CLT_NOTIFY_MULT + return BLE_HS_ENOTSUP; +#endif + + struct os_mbuf *txom2; + uint16_t cid; + int rc; + + if (ble_att_cmd_get(BLE_ATT_OP_NOTIFY_MULTI_REQ, 0, &txom2) == NULL) { + return BLE_HS_ENOMEM; + } + + os_mbuf_concat(txom2, txom); + + cid = ble_eatt_get_available_chan_cid(conn_handle, BLE_GATT_OP_DUMMY); + rc = ble_att_tx(conn_handle, cid, txom2); + if (cid != BLE_L2CAP_CID_ATT) { + ble_eatt_release_chan(conn_handle, BLE_GATT_OP_DUMMY); + } + + return rc; +} + +#endif #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_cmd.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_cmd.c index 6669392f..36f7c9aa 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_cmd.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_cmd.c @@ -55,28 +55,67 @@ ble_att_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom) } int -ble_att_tx(uint16_t conn_handle, struct os_mbuf *txom) +ble_att_tx_with_conn(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan, struct os_mbuf *txom) { - struct ble_l2cap_chan *chan; - struct ble_hs_conn *conn; int rc; + struct os_mbuf_pkthdr *omp; + + if (!txom) { + if (conn->client_att_busy) { + return 0; + } + omp = STAILQ_FIRST(&conn->att_tx_q); + if (omp == NULL) { + return 0; + } + STAILQ_REMOVE_HEAD(&conn->att_tx_q, omp_next); + txom = OS_MBUF_PKTHDR_TO_MBUF(omp); + BLE_EATT_LOG_DEBUG("%s: wakeup will send %p\n", __func__, txom); + } BLE_HS_DBG_ASSERT_EVAL(txom->om_len >= 1); + + if (ble_att_is_request_op(txom->om_data[0])) { + if (conn->client_att_busy) { + BLE_EATT_LOG_DEBUG("ATT Queue %p, client busy %d\n", txom, conn->client_att_busy); + STAILQ_INSERT_TAIL(&conn->att_tx_q, OS_MBUF_PKTHDR(txom), omp_next); + return 0; + } + conn->client_att_busy = true; + } + ble_att_inc_tx_stat(txom->om_data[0]); - ble_hs_lock(); + ble_att_truncate_to_mtu(chan, txom); + rc = ble_l2cap_tx(conn, chan, txom); + assert(rc == 0); + return rc; +} + +int +ble_att_tx(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom) +{ + struct ble_l2cap_chan *chan; + struct ble_hs_conn *conn; + int rc; +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + if (ble_hs_cfg.eatt && cid != BLE_L2CAP_CID_ATT) { + return ble_eatt_tx(conn_handle, cid, txom); + } +#endif + + ble_hs_lock(); rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn, &chan); if (rc != 0) { + ble_hs_unlock(); os_mbuf_free_chain(txom); - } else { - ble_att_truncate_to_mtu(chan, txom); - rc = ble_l2cap_tx(conn, chan, txom); + return rc; } + rc = ble_att_tx_with_conn(conn, chan, txom); ble_hs_unlock(); - return rc; } diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_cmd_priv.h b/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_cmd_priv.h index 54052a98..f3090d11 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_cmd_priv.h +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_cmd_priv.h @@ -309,6 +309,20 @@ struct ble_att_exec_write_req { */ #define BLE_ATT_EXEC_WRITE_RSP_SZ 1 +/** + * | Parameter | Size (octets) | + * +-----------------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Attribute Handle Length Value Tuple List | 8 to (ATT_MTU-1) | + */ +#define BLE_ATT_NOTIFY_MULTI_REQ_BASE_SZ 9 + +struct ble_att_tuple_list { + uint16_t handle; + uint16_t value_len; + uint8_t data[0]; +} __attribute__((packed)); + /** * | Parameter | Size (octets) | * +------------------------------------+-------------------+ @@ -454,8 +468,15 @@ void ble_att_indicate_rsp_write(void *payload, int len); void *ble_att_cmd_prepare(uint8_t opcode, size_t len, struct os_mbuf *txom); void *ble_att_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom); -int ble_att_tx(uint16_t conn_handle, struct os_mbuf *txom); - +int ble_att_tx(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom); + +struct ble_l2cap_chan; +struct ble_hs_conn; +int ble_att_tx_with_conn(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan, + struct os_mbuf *txom); +bool ble_att_is_response_op(uint8_t opcode); +bool ble_att_is_request_op(uint8_t opcode); +bool ble_att_is_att_pdu_op(uint8_t opcode); #ifdef __cplusplus } #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_priv.h b/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_priv.h index 0e723de9..7494cb6e 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_priv.h +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_priv.h @@ -102,6 +102,8 @@ STATS_SECT_START(ble_att_stats) STATS_SECT_ENTRY(indicate_req_tx) STATS_SECT_ENTRY(indicate_rsp_rx) STATS_SECT_ENTRY(indicate_rsp_tx) + STATS_SECT_ENTRY(multi_notify_req_rx) + STATS_SECT_ENTRY(multi_notify_req_tx) STATS_SECT_ENTRY(write_cmd_rx) STATS_SECT_ENTRY(write_cmd_tx) STATS_SECT_END @@ -171,13 +173,15 @@ SLIST_HEAD(ble_att_clt_entry_list, ble_att_clt_entry); /*** @gen */ struct ble_l2cap_chan *ble_att_create_chan(uint16_t conn_handle); -int ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn, +int ble_att_conn_chan_find(uint16_t conn_handle, uint16_t cid, + struct ble_hs_conn **out_conn, struct ble_l2cap_chan **out_chan); void ble_att_inc_tx_stat(uint8_t att_op); void ble_att_truncate_to_mtu(const struct ble_l2cap_chan *att_chan, struct os_mbuf *txom); void ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu); uint16_t ble_att_chan_mtu(const struct ble_l2cap_chan *chan); +uint16_t ble_att_mtu_by_cid(uint16_t conn_handle, uint16_t cid); int ble_att_init(void); /*** @svr */ @@ -190,36 +194,38 @@ ble_att_svr_find_by_uuid(struct ble_att_svr_entry *start_at, const ble_uuid_t *uuid, uint16_t end_handle); uint16_t ble_att_svr_prev_handle(void); -int ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_svr_rx_mtu(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); struct ble_att_svr_entry *ble_att_svr_find_by_handle(uint16_t handle_id); int32_t ble_att_svr_ticks_until_tmo(const struct ble_att_svr_conn *svr, ble_npl_time_t now); -int ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_svr_rx_find_type_value(uint16_t conn_handle, +int ble_att_svr_rx_find_info(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_svr_rx_find_type_value(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read_type(uint16_t conn_handle, +int ble_att_svr_rx_read_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read_group_type(uint16_t conn_handle, +int ble_att_svr_rx_read_group_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read(uint16_t conn_handle, +int ble_att_svr_rx_read(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read_blob(uint16_t conn_handle, +int ble_att_svr_rx_read_blob(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read_mult_var(uint16_t conn_handle, +int ble_att_svr_rx_read_mult_var(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read_mult(uint16_t conn_handle, +int ble_att_svr_rx_read_mult(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_write(uint16_t conn_handle, +int ble_att_svr_rx_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_svr_rx_signed_write(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_svr_rx_prep_write(uint16_t conn_handle, +int ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_svr_rx_signed_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_svr_rx_prep_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_exec_write(uint16_t conn_handle, +int ble_att_svr_rx_exec_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_notify(uint16_t conn_handle, +int ble_att_svr_rx_notify(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_indicate(uint16_t conn_handle, +int ble_att_svr_rx_notify_multi(uint16_t conn_handle, uint16_t cid, + struct os_mbuf **rxom); +int ble_att_svr_rx_indicate(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); void ble_att_svr_prep_clear(struct ble_att_prep_entry_list *prep_list); int ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle, @@ -231,9 +237,12 @@ int ble_att_svr_init(void); void ble_att_svr_hide_range(uint16_t start_handle, uint16_t end_handle); void ble_att_svr_restore_range(uint16_t start_handle, uint16_t end_handle); -int ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, +int ble_att_svr_tx_error_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom, uint8_t req_op, uint16_t handle, uint8_t error_code); +#if MYNEWT_VAL(BLE_SVC_GAP_GATT_SECURITY_LEVEL) +uint8_t ble_att_svr_security_mode_1_level(void); +#endif /*** $clt */ /** An information-data entry in a find information response. */ @@ -264,52 +273,56 @@ struct ble_att_read_group_type_adata { uint8_t *value; }; -int ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_rx_error(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); int ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu); -int ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle); -int ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, +int ble_att_clt_rx_mtu(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_read(uint16_t conn_handle, uint16_t cid, uint16_t handle); +int ble_att_clt_rx_read(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t offset); -int ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_mult(uint16_t conn_handle, +int ble_att_clt_rx_read_blob(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_read_mult(uint16_t conn_handle, uint16_t cid, const uint16_t *handles, int num_handles, bool variable); -int ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t start_handle, +int ble_att_clt_rx_read_mult(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_rx_read_mult_var(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid); -int ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_group_type(uint16_t conn_handle, +int ble_att_clt_rx_read_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_read_group_type(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid128); -int ble_att_clt_rx_read_group_type(uint16_t conn_handle, +int ble_att_clt_rx_read_group_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t start_handle, +int ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle); -int ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t start_handle, +int ble_att_clt_rx_find_info(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, uint16_t attribute_type, const void *attribute_value, int value_len); -int ble_att_clt_rx_find_type_value(uint16_t conn_handle, +int ble_att_clt_rx_find_type_value(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, - uint16_t offset, struct os_mbuf *txom); -int ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags); -int ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t handle, - uint8_t * csrk, uint32_t counter, - struct os_mbuf * txom); -int ble_att_clt_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_rx_write(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t cid, + uint16_t handle, struct os_mbuf *txom); +int ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t cid, + uint16_t handle, struct os_mbuf *txom); +int ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t cid, + uint16_t handle, uint16_t offset, + struct os_mbuf *txom); +int ble_att_clt_rx_prep_write(uint16_t conn_handle, uint16_t cid, + struct os_mbuf **rxom); +int ble_att_clt_tx_exec_write(uint16_t conn_handle, uint16_t cid, + uint8_t flags); +int ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t cid, + uint16_t handle, uint8_t * csrk, + uint32_t counter, struct os_mbuf * txom); +int ble_att_clt_rx_exec_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_rx_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); int ble_att_clt_tx_notify(uint16_t conn_handle, uint16_t handle, struct os_mbuf *txom); -int ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t cid, + uint16_t handle, struct os_mbuf *txom); +int ble_att_clt_rx_indicate(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_notify_mult(uint16_t conn_handle, struct os_mbuf *txom); #ifdef __cplusplus } diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_svr.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_svr.c index f15b4b0b..517b1e2d 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_svr.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_att_svr.c @@ -28,6 +28,8 @@ #include "esp_nimble_mem.h" #if NIMBLE_BLE_CONNECT +#if MYNEWT_VAL(BLE_GATTS) + /** * ATT server - Attribute Protocol * @@ -325,7 +327,7 @@ ble_att_svr_check_perms(uint16_t conn_handle, int is_read, /* In SC Only mode all characteristics requiring security * require it on level 4 */ - if (MYNEWT_VAL(BLE_SM_SC_ONLY)) { + if (ble_hs_cfg.sm_sc_only) { if (!sec_state.authenticated || !sec_state.encrypted) { *out_att_err = BLE_ATT_ERR_INSUFFICIENT_AUTHEN; @@ -371,7 +373,9 @@ ble_att_svr_check_perms(uint16_t conn_handle, int is_read, if (author) { /* XXX: Prompt user for authorization. */ + ble_hs_lock(); conn = ble_hs_conn_find(conn_handle); + ble_hs_unlock(); if(!conn->bhc_sec_state.authorize){ rc = ble_gap_authorize_event(conn_handle, entry->ha_handle_id, is_read); if (rc == BLE_GAP_AUTHORIZE_REJECT) { @@ -623,7 +627,7 @@ ble_att_svr_write_handle(uint16_t conn_handle, uint16_t attr_handle, } int -ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, +ble_att_svr_tx_error_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom, uint8_t req_op, uint16_t handle, uint8_t error_code) { struct ble_att_error_rsp *rsp; @@ -640,7 +644,7 @@ ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, rsp->baep_handle = htole16(handle); rsp->baep_error_code = error_code; - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } /** @@ -667,13 +671,10 @@ ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, * field. */ static int -ble_att_svr_tx_rsp(uint16_t conn_handle, int hs_status, struct os_mbuf *om, +ble_att_svr_tx_rsp(uint16_t conn_handle, uint16_t cid, int hs_status, struct os_mbuf *om, uint8_t att_op, uint8_t err_status, uint16_t err_handle) { - struct ble_l2cap_chan *chan; - struct ble_hs_conn *conn; int do_tx; - int rc; if (hs_status != 0 && err_status == 0) { /* Processing failed, but err_status of 0 means don't send error. */ @@ -683,28 +684,14 @@ ble_att_svr_tx_rsp(uint16_t conn_handle, int hs_status, struct os_mbuf *om, } if (do_tx) { - ble_hs_lock(); - - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); - if (rc != 0) { - /* No longer connected. */ - hs_status = rc; - } else { - if (hs_status == 0) { - BLE_HS_DBG_ASSERT(om != NULL); - - ble_att_inc_tx_stat(om->om_data[0]); - ble_att_truncate_to_mtu(chan, om); - hs_status = ble_l2cap_tx(conn, chan, om); - om = NULL; - if (hs_status != 0) { - err_status = BLE_ATT_ERR_UNLIKELY; - } - } + if (hs_status == 0) { + hs_status = ble_att_tx(conn_handle, cid, om); + om = NULL; + if (hs_status) { + err_status = BLE_ATT_ERR_UNLIKELY; + } } - ble_hs_unlock(); - if (hs_status != 0) { STATS_INC(ble_att_stats, error_rsp_tx); @@ -715,7 +702,7 @@ ble_att_svr_tx_rsp(uint16_t conn_handle, int hs_status, struct os_mbuf *om, os_mbuf_adj(om, OS_MBUF_PKTLEN(om)); } if (om != NULL) { - ble_att_svr_tx_error_rsp(conn_handle, om, att_op, + ble_att_svr_tx_error_rsp(conn_handle, cid, om, att_op, err_handle, err_status); om = NULL; } @@ -742,7 +729,7 @@ ble_att_svr_build_mtu_rsp(uint16_t conn_handle, struct os_mbuf **rxom, txom = NULL; ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, NULL, &chan); + rc = ble_att_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, NULL, &chan); if (rc == 0) { mtu = chan->my_mtu; } @@ -774,7 +761,7 @@ done: } int -ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_mtu(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { struct ble_att_mtu_cmd *cmd; struct ble_l2cap_chan *chan; @@ -787,6 +774,10 @@ ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) txom = NULL; mtu = 0; + if (cid != BLE_L2CAP_CID_ATT) { + return BLE_HS_ENOTSUP; + } + rc = ble_att_svr_pullup_req_base(rxom, sizeof(*cmd), &att_err); if (rc != 0) { goto done; @@ -804,12 +795,12 @@ ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_MTU_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, BLE_L2CAP_CID_ATT, rc, txom, BLE_ATT_OP_MTU_REQ, att_err, 0); if (rc == 0) { ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, &conn, &chan); if (rc == 0) { ble_att_set_peer_mtu(chan, mtu); chan->flags |= BLE_L2CAP_CHAN_F_TXED_MTU; @@ -908,7 +899,7 @@ done: } static int -ble_att_svr_build_find_info_rsp(uint16_t conn_handle, +ble_att_svr_build_find_info_rsp(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, struct os_mbuf **rxom, struct os_mbuf **out_txom, @@ -937,7 +928,7 @@ ble_att_svr_build_find_info_rsp(uint16_t conn_handle, /* Write the variable length Information Data field, populating the format * field as appropriate. */ - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); rc = ble_att_svr_fill_info(start_handle, end_handle, txom, mtu, &rsp->bafp_format); if (rc != 0) { @@ -954,7 +945,7 @@ done: } int -ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_find_info(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_FIND_INFO) return BLE_HS_ENOTSUP; @@ -991,7 +982,7 @@ ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom) goto done; } - rc = ble_att_svr_build_find_info_rsp(conn_handle, + rc = ble_att_svr_build_find_info_rsp(conn_handle, cid, start_handle, end_handle, rxom, &txom, &att_err); if (rc != 0) { @@ -1002,7 +993,7 @@ ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_FIND_INFO_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_FIND_INFO_REQ, att_err, err_handle); return rc; } @@ -1217,7 +1208,7 @@ done: } static int -ble_att_svr_build_find_type_value_rsp(uint16_t conn_handle, +ble_att_svr_build_find_type_value_rsp(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, ble_uuid16_t attr_type, @@ -1244,7 +1235,7 @@ ble_att_svr_build_find_type_value_rsp(uint16_t conn_handle, } /* Write the variable length Information Data field. */ - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); rc = ble_att_svr_fill_type_value(conn_handle, start_handle, end_handle, attr_type, *rxom, txom, mtu, @@ -1261,7 +1252,7 @@ done: } int -ble_att_svr_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_find_type_value(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_FIND_TYPE) return BLE_HS_ENOTSUP; @@ -1299,7 +1290,7 @@ ble_att_svr_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) rc = BLE_HS_EBADDATA; goto done; } - rc = ble_att_svr_build_find_type_value_rsp(conn_handle, start_handle, + rc = ble_att_svr_build_find_type_value_rsp(conn_handle, cid, start_handle, end_handle, attr_type, rxom, &txom, &att_err); if (rc != 0) { @@ -1310,7 +1301,7 @@ ble_att_svr_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_FIND_TYPE_VALUE_REQ, att_err, err_handle); return rc; @@ -1323,20 +1314,38 @@ static void ble_att_svr_make_conn_aware(uint16_t conn_handle) { int i = 0; conn = ble_hs_conn_find_assert(conn_handle); - conn->bhc_gatt_svr.aware_state = true; + conn->bhc_gatt_svr.aware_state = false; + conn->bhc_gatt_svr.half_aware = 1; ble_hs_conn_addrs(conn, &addrs); for(i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { if(memcmp(ble_gatts_conn_aware_states[i].peer_id_addr, addrs.peer_id_addr.val, sizeof addrs.peer_id_addr.val)) { - ble_gatts_conn_aware_states[i].aware = true; + ble_gatts_conn_aware_states[i].aware = false; + ble_gatts_conn_aware_states[i].half_aware = 1; } } } static bool ble_att_svr_check_conn_aware(uint16_t conn_handle) { struct ble_hs_conn *conn; + struct ble_hs_conn_addrs addrs; + conn = ble_hs_conn_find_assert(conn_handle); + + if (conn->bhc_gatt_svr.half_aware == 1) { + conn->bhc_gatt_svr.half_aware = 0; + conn->bhc_gatt_svr.aware_state = true; + + ble_hs_conn_addrs(conn, &addrs); + for(int i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { + if(memcmp(ble_gatts_conn_aware_states[i].peer_id_addr, + addrs.peer_id_addr.val, sizeof addrs.peer_id_addr.val)) { + ble_gatts_conn_aware_states[i].half_aware = 0; + ble_gatts_conn_aware_states[i].aware = true; + } + } + } return conn->bhc_gatt_svr.aware_state; } @@ -1348,7 +1357,7 @@ static uint8_t * ble_att_svr_get_csfs(uint16_t conn_handle) { #endif static int -ble_att_svr_build_read_type_rsp(uint16_t conn_handle, +ble_att_svr_build_read_type_rsp(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid, struct os_mbuf **rxom, @@ -1391,7 +1400,7 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, goto done; } - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); /* Find all matching attributes, writing a record for each. */ entry = NULL; @@ -1463,7 +1472,7 @@ done: } int -ble_att_svr_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ_TYPE) return BLE_HS_ENOTSUP; @@ -1471,6 +1480,10 @@ ble_att_svr_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) struct ble_att_read_type_req *req; uint16_t start_handle, end_handle; +#if MYNEWT_VAL(BLE_GATT_CACHING) + struct ble_hs_conn *conn; + struct ble_hs_conn_addrs addrs; +#endif struct os_mbuf *txom; uint16_t err_handle; uint16_t pktlen; @@ -1517,14 +1530,39 @@ ble_att_svr_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) #if MYNEWT_VAL(BLE_GATT_CACHING) ble_hs_lock(); - ble_att_svr_make_conn_aware(conn_handle); - ble_hs_unlock(); + if (uuid.u.type == BLE_UUID_TYPE_16 && ( + uuid.u16.value == BLE_ATT_UUID_INCLUDE || + uuid.u16.value == BLE_ATT_UUID_CHARACTERISTIC || + uuid.u16.value == BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16)) { + int i = 0; - if(rc != 0) { - goto done; + conn = ble_hs_conn_find_assert(conn_handle); + conn->bhc_gatt_svr.aware_state = true; + conn->bhc_gatt_svr.half_aware = 0; + + ble_hs_conn_addrs(conn, &addrs); + for(i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { + if(memcmp(ble_gatts_conn_aware_states[i].peer_id_addr, + addrs.peer_id_addr.val, sizeof addrs.peer_id_addr.val)) { + ble_gatts_conn_aware_states[i].aware = true; + ble_gatts_conn_aware_states[i].half_aware = 0; + } + } + } else { + if((ble_att_svr_get_csfs(conn_handle)[0] & 1) + && ble_svc_gatt_csf_handle() != err_handle ) { + if (!ble_att_svr_check_conn_aware(conn_handle)) { + att_err = BLE_ATT_ERR_DB_OUT_OF_SYNC; + rc = BLE_HS_EREJECT; + ble_att_svr_make_conn_aware(conn_handle); + ble_hs_unlock(); + goto done; + } + } } + ble_hs_unlock(); #endif - rc = ble_att_svr_build_read_type_rsp(conn_handle, start_handle, end_handle, + rc = ble_att_svr_build_read_type_rsp(conn_handle, cid, start_handle, end_handle, &uuid.u, rxom, &txom, &att_err, &err_handle); if (rc != 0) { @@ -1534,13 +1572,13 @@ ble_att_svr_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_READ_TYPE_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_TYPE_REQ, att_err, err_handle); return rc; } int -ble_att_svr_rx_read(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ) return BLE_HS_ENOTSUP; @@ -1597,13 +1635,13 @@ ble_att_svr_rx_read(uint16_t conn_handle, struct os_mbuf **rxom) } done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_READ_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_REQ, att_err, err_handle); return rc; } int -ble_att_svr_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read_blob(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ_BLOB) return BLE_HS_ENOTSUP; @@ -1665,13 +1703,13 @@ ble_att_svr_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_READ_BLOB_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_BLOB_REQ, att_err, err_handle); return rc; } static int -ble_att_svr_build_read_mult_rsp(uint16_t conn_handle, +ble_att_svr_build_read_mult_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom, struct os_mbuf **out_txom, uint8_t *att_err, @@ -1682,7 +1720,7 @@ ble_att_svr_build_read_mult_rsp(uint16_t conn_handle, uint16_t mtu; int rc; - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); rc = ble_att_svr_pkt(rxom, &txom, att_err); if (rc != 0) { @@ -1732,7 +1770,7 @@ done: } int -ble_att_svr_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read_mult(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ_MULT) return BLE_HS_ENOTSUP; @@ -1763,18 +1801,18 @@ ble_att_svr_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom) ble_hs_unlock(); #endif - rc = ble_att_svr_build_read_mult_rsp(conn_handle, rxom, &txom, &att_err, + rc = ble_att_svr_build_read_mult_rsp(conn_handle, cid, rxom, &txom, &att_err, &err_handle); #if MYNEWT_VAL(BLE_GATT_CACHING) done : #endif - return ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_READ_MULT_REQ, + return ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_MULT_REQ, att_err, err_handle); } static int -ble_att_svr_build_read_mult_rsp_var(uint16_t conn_handle, +ble_att_svr_build_read_mult_rsp_var(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom, struct os_mbuf **out_txom, uint8_t *att_err, @@ -1787,7 +1825,7 @@ ble_att_svr_build_read_mult_rsp_var(uint16_t conn_handle, struct os_mbuf *tmp = NULL; int rc; - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); rc = ble_att_svr_pkt(rxom, &txom, att_err); if (rc != 0) { @@ -1856,7 +1894,7 @@ done: } int -ble_att_svr_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read_mult_var(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ_MULT) return BLE_HS_ENOTSUP; @@ -1887,13 +1925,13 @@ ble_att_svr_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom) ble_hs_unlock(); #endif - rc = ble_att_svr_build_read_mult_rsp_var(conn_handle, rxom, &txom, &att_err, + rc = ble_att_svr_build_read_mult_rsp_var(conn_handle, cid, rxom, &txom, &att_err, &err_handle); #if MYNEWT_VAL(BLE_GATT_CACHING) done: #endif - return ble_att_svr_tx_rsp(conn_handle, rc, txom, + return ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_MULT_VAR_REQ, att_err, err_handle); } @@ -1923,7 +1961,20 @@ ble_att_svr_service_uuid(struct ble_att_svr_entry *entry, return rc; } - rc = ble_uuid_init_from_buf(uuid, val, attr_len); + /** + * - For Primary/Secondary Services: attr_len is typically 2 (16-bit), 4 (32-bit), or 16 (128-bit) + * - For Included Services: + * - When UUID is 16-bit, value length = 2 (start) + 2 (end) + 2 (uuid) = 6 + * - So, attr_len == 6 implies 16-bit UUID, and the UUID is at offset 4 + */ + if (attr_len == 6) { + // Adjust attr_len to pass only UUID (last 2 bytes) to uuid init + attr_len = 2; + rc = ble_uuid_init_from_buf(uuid, val + 4, attr_len); + } else { + // For normal services (not included), UUID starts at offset 0 + rc = ble_uuid_init_from_buf(uuid, val, attr_len); + } return rc; } @@ -1962,7 +2013,7 @@ ble_att_svr_read_group_type_entry_write(struct os_mbuf *om, uint16_t mtu, * @return 0 on success; BLE_HS error code on failure. */ static int -ble_att_svr_build_read_group_type_rsp(uint16_t conn_handle, +ble_att_svr_build_read_group_type_rsp(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *group_uuid, @@ -1992,7 +2043,7 @@ ble_att_svr_build_read_group_type_rsp(uint16_t conn_handle, entry = NULL; - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); /* Just reuse the request buffer for the response. */ txom = *rxom; @@ -2134,7 +2185,7 @@ done: } int -ble_att_svr_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read_group_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ_GROUP_TYPE) return BLE_HS_ENOTSUP; @@ -2203,9 +2254,10 @@ ble_att_svr_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) goto done; } - rc = ble_att_svr_build_read_group_type_rsp(conn_handle, start_handle, - end_handle, &uuid.u, - rxom, &txom, &att_err, + rc = ble_att_svr_build_read_group_type_rsp(conn_handle, cid, + start_handle, end_handle, + &uuid.u, rxom, + &txom, &att_err, &err_handle); if (rc != 0) { goto done; @@ -2214,7 +2266,7 @@ ble_att_svr_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_GROUP_TYPE_REQ, att_err, err_handle); return rc; @@ -2249,7 +2301,7 @@ done: } int -ble_att_svr_rx_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_WRITE) return BLE_HS_ENOTSUP; @@ -2309,13 +2361,13 @@ ble_att_svr_rx_write(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_WRITE_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_WRITE_REQ, att_err, handle); return rc; } int -ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_WRITE_NO_RSP) return BLE_HS_ENOTSUP; @@ -2352,12 +2404,16 @@ ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom) } int -ble_att_svr_rx_signed_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_signed_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_SIGNED_WRITE) return BLE_HS_ENOTSUP; #endif + if (MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 && ble_hs_cfg.eatt) { + return BLE_HS_ENOTSUP; + } + struct ble_att_signed_write_cmd *req; struct ble_store_value_sec value_sec; struct ble_store_key_sec key_sec; @@ -2456,10 +2512,10 @@ ble_att_svr_rx_signed_write(uint16_t conn_handle, struct os_mbuf **rxom) goto err; } - if(message != NULL) nimble_platform_mem_free(message); + nimble_platform_mem_free(message); return 0; err: - if(message != NULL) nimble_platform_mem_free(message); + nimble_platform_mem_free(message); return rc; } @@ -2727,7 +2783,7 @@ ble_att_svr_insert_prep_entry(uint16_t conn_handle, } int -ble_att_svr_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_prep_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_QUEUED_WRITE) return BLE_HS_ENOTSUP; @@ -2817,13 +2873,13 @@ ble_att_svr_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_PREP_WRITE_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_PREP_WRITE_REQ, att_err, err_handle); return rc; } int -ble_att_svr_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_exec_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_QUEUED_WRITE) return BLE_HS_ENOTSUP; @@ -2907,13 +2963,13 @@ done: ble_att_svr_prep_clear(&prep_list); } - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_EXEC_WRITE_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_EXEC_WRITE_REQ, att_err, err_handle); return rc; } int -ble_att_svr_rx_notify(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_notify(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_NOTIFY) return BLE_HS_ENOTSUP; @@ -2942,7 +2998,7 @@ ble_att_svr_rx_notify(uint16_t conn_handle, struct os_mbuf **rxom) /* All indications shall be confirmed, but only these with required * security established shall be pass to application */ - if (MYNEWT_VAL(BLE_SM_LVL) >= 2 && !sec_state.encrypted) { + if (ble_hs_cfg.sm_sec_lvl >= 2 && !sec_state.encrypted) { return 0; } @@ -2955,6 +3011,67 @@ ble_att_svr_rx_notify(uint16_t conn_handle, struct os_mbuf **rxom) return 0; } +int +ble_att_svr_rx_notify_multi(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) +{ +#if !MYNEWT_VAL(BLE_ATT_SVR_NOTIFY_MULTI) + return BLE_HS_ENOTSUP; +#endif + + struct ble_att_tuple_list *req; + uint16_t handle; + int rc = 0; + uint16_t pkt_len; + struct os_mbuf *tmp; + uint16_t attr_len; + + pkt_len = OS_MBUF_PKTLEN(*rxom); + while (pkt_len > 0) { + rc = ble_att_svr_pullup_req_base(rxom, sizeof(struct ble_att_tuple_list), NULL); + if (rc != 0) { + return BLE_HS_ENOMEM; + } + + req = (struct ble_att_tuple_list *)(*rxom)->om_data; + + handle = le16toh(req->handle); + attr_len = le16toh(req->value_len); + + os_mbuf_adj(*rxom, 4); + + if (attr_len > BLE_ATT_ATTR_MAX_LEN) { + BLE_HS_LOG_ERROR("attr length (%d) > max (%d)", + attr_len, BLE_ATT_ATTR_MAX_LEN); + rc = BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + goto done; + } + + tmp = os_msys_get_pkthdr(attr_len, 0); + if (!tmp) { + BLE_HS_LOG_ERROR("not enough resources, aborting"); + rc = BLE_ATT_ERR_INSUFFICIENT_RES; + goto done; + } + + rc = os_mbuf_appendfrom(tmp, *rxom, 0, attr_len); + if (rc) { + BLE_HS_LOG_ERROR("not enough resources, aborting"); + rc = BLE_ATT_ERR_INSUFFICIENT_RES; + goto done; + } + + ble_gap_notify_rx_event(conn_handle, handle, tmp, 0); + + os_mbuf_adj(*rxom, attr_len); + pkt_len = OS_MBUF_PKTLEN(*rxom); + } +done: + os_mbuf_free_chain(*rxom); + *rxom = NULL; + + return rc; +} + /** * @return 0 on success; nonzero on failure. */ @@ -2988,7 +3105,7 @@ done: } int -ble_att_svr_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_indicate(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_INDICATE) return BLE_HS_ENOTSUP; @@ -3033,7 +3150,7 @@ ble_att_svr_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom) /* All indications shall be confirmed, but only these with required * security established shall be pass to application */ - if (MYNEWT_VAL(BLE_SM_LVL) >= 2 && !sec_state.encrypted) { + if (ble_hs_cfg.sm_sec_lvl >= 2 && !sec_state.encrypted) { goto done; } @@ -3046,7 +3163,7 @@ ble_att_svr_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_INDICATE_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_INDICATE_REQ, att_err, handle); return rc; } @@ -3366,4 +3483,46 @@ int ble_att_fill_database_info(uint8_t *out_data) return 0; } #endif + +#if MYNEWT_VAL(BLE_SVC_GAP_GATT_SECURITY_LEVEL) +/** + * Return the highest Security Mode 1 Level requirement. + * + * @return Maximum level requirement + */ +uint8_t +ble_att_svr_security_mode_1_level() +{ + struct ble_att_svr_entry *entry; + uint8_t highest_security_level = 0x01; //No Security + uint8_t sec_level; + uint8_t flags; + + for (entry = STAILQ_FIRST(&ble_att_svr_list); + entry != NULL; + entry = STAILQ_NEXT(entry, ha_next)) { + + flags = entry->ha_flags; + if ((flags & BLE_ATT_F_READ_AUTHEN) || (flags & BLE_ATT_F_WRITE_AUTHEN)) { + sec_level = 0x03; //Authenticated pairing with encryption + /* This is the highest currently supported value. + * Break here. + */ + highest_security_level = 0x03; + break; + } else if ((flags & BLE_ATT_F_READ_ENC) || (flags & BLE_ATT_F_WRITE_ENC)) { + sec_level = 0x02; //Unauthenticated pairing with encryption + } else { + sec_level = 0x01; //No security (No authentication and no encryption) + } + + if (sec_level > highest_security_level) { + highest_security_level = sec_level; + } + } + + return highest_security_level; +} +#endif +#endif #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_ead.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_ead.c index 8f437fa8..be497b52 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_ead.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_ead.c @@ -68,15 +68,18 @@ static int ead_encrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], const uint8_ int err; uint8_t nonce[BLE_EAD_NONCE_SIZE]; + /** Nonce is concatenation of Randomizer and IV */ err = ble_ead_generate_nonce(iv, randomizer, nonce); if (err != 0) { return -1; } + /** Copying Randomizer to the start of encrypted advertisment data */ memcpy(encrypted_payload, nonce, BLE_EAD_RANDOMIZER_SIZE); err = ble_aes_ccm_encrypt(session_key, nonce, payload, payload_size, ble_ead_aad, BLE_EAD_AAD_SIZE, &encrypted_payload[BLE_EAD_RANDOMIZER_SIZE], BLE_EAD_MIC_SIZE); + if (err != 0) { BLE_HS_LOG(DEBUG, "Failed to encrypt the payload (ble_ccm_encrypt err %d)", err); return -1; @@ -178,30 +181,6 @@ int ble_ead_decrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], const uint8_t i return ead_decrypt(session_key, iv, encrypted_payload, encrypted_payload_size, payload); } -int ble_ead_serialize_data(const struct enc_adv_data *input, uint8_t *output) -{ - if ( input == NULL) { - BLE_HS_LOG(DEBUG, "input is NULL"); - return 0; - } - - if ( output == NULL) { - BLE_HS_LOG(DEBUG, "output is NULL"); - return 0; - } - - uint8_t adv_data_len = input->len; - uint8_t data_len = adv_data_len + 1; - - output[0] = data_len; - output[1] = input->type; - - memcpy(&output[2], input->data, adv_data_len); - - return data_len + 1; - -} - #endif /* ENC_ADV_DATA */ #ifdef __cplusplus diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_eatt.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_eatt.c new file mode 100644 index 00000000..1bbf02ac --- /dev/null +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_eatt.c @@ -0,0 +1,605 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "syscfg/syscfg.h" + +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + +#include +#include +#include "host/ble_hs_log.h" +#include "ble_att_cmd_priv.h" +#include "ble_hs_priv.h" +#include "ble_l2cap_priv.h" +#include "ble_eatt_priv.h" +#include "services/gatt/ble_svc_gatt.h" + +struct ble_eatt { + SLIST_ENTRY(ble_eatt) next; + uint16_t conn_handle; + struct ble_l2cap_chan *chan; + uint8_t client_op; + + /* Packet transmit queue */ + STAILQ_HEAD(, os_mbuf_pkthdr) eatt_tx_q; + + struct ble_npl_event setup_ev; + struct ble_npl_event wakeup_ev; +}; + +SLIST_HEAD(ble_eatt_list, ble_eatt); + +static struct ble_eatt_list g_ble_eatt_list; +static ble_eatt_att_rx_fn ble_eatt_att_rx_cb; + +#define BLE_EATT_DATABUF_SIZE ( \ + MYNEWT_VAL(BLE_EATT_MTU) + \ + 2 + \ + sizeof (struct os_mbuf_pkthdr) + \ + sizeof (struct os_mbuf)) + +#define BLE_EATT_MEMBLOCK_SIZE \ + (OS_ALIGN(BLE_EATT_DATABUF_SIZE, 4)) + +#define BLE_EATT_MEMPOOL_SIZE \ + OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_EATT_CHAN_NUM) + 1, BLE_EATT_MEMBLOCK_SIZE) +static os_membuf_t ble_eatt_conn_mem[ + OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_EATT_CHAN_NUM), + sizeof(struct ble_eatt)) +]; +static struct os_mempool ble_eatt_conn_pool; +static os_membuf_t ble_eatt_sdu_coc_mem[BLE_EATT_MEMPOOL_SIZE]; +struct os_mbuf_pool ble_eatt_sdu_os_mbuf_pool; +static struct os_mempool ble_eatt_sdu_mbuf_mempool; + +static struct ble_gap_event_listener ble_eatt_listener; + +static struct ble_npl_event g_read_sup_cl_feat_ev; +static struct ble_npl_event g_read_sup_srv_feat_ev; + +static void ble_eatt_setup_cb(struct ble_npl_event *ev); +static void ble_eatt_start(uint16_t conn_handle); + +static struct ble_eatt * +ble_eatt_find_not_busy(uint16_t conn_handle) +{ + struct ble_eatt *eatt; + + SLIST_FOREACH(eatt, &g_ble_eatt_list, next) { + if ((eatt->conn_handle == conn_handle) && !eatt->client_op && eatt->chan) { + return eatt; + } + } + return NULL; +} + +static struct ble_eatt * +ble_eatt_find_by_conn_handle(uint16_t conn_handle) +{ + struct ble_eatt *eatt; + + SLIST_FOREACH(eatt, &g_ble_eatt_list, next) { + if (eatt->conn_handle == conn_handle) { + return eatt; + } + } + return NULL; + +} + +static struct ble_eatt * +ble_eatt_find_by_conn_handle_and_busy_op(uint16_t conn_handle, uint8_t op) +{ + struct ble_eatt *eatt; + + SLIST_FOREACH(eatt, &g_ble_eatt_list, next) { + if (eatt->conn_handle == conn_handle && eatt->client_op == op) { + return eatt; + } + } + return NULL; + +} + +static struct ble_eatt * +ble_eatt_find(uint16_t conn_handle, uint16_t cid) +{ + struct ble_eatt *eatt; + + SLIST_FOREACH(eatt, &g_ble_eatt_list, next) { + if ((eatt->conn_handle == conn_handle) && + (eatt->chan) && + (eatt->chan->scid == cid)) { + return eatt; + } + } + return NULL; + +} + +static int +ble_eatt_prepare_rx_sdu(struct ble_l2cap_chan *chan) +{ + int rc; + struct os_mbuf *om; + + om = os_mbuf_get_pkthdr(&ble_eatt_sdu_os_mbuf_pool, 0); + if (!om) { + BLE_EATT_LOG_ERROR("eatt: no memory for sdu\n"); + return BLE_HS_ENOMEM; + } + + rc = ble_l2cap_recv_ready(chan, om); + if (rc) { + BLE_EATT_LOG_ERROR("eatt: Failed to supply RX SDU conn_handle 0x%04x (status=%d)\n", + chan->conn_handle, rc); + os_mbuf_free_chain(om); + } + return rc; +} + +static void +ble_eatt_wakeup_cb(struct ble_npl_event *ev) +{ + struct ble_eatt *eatt; + struct os_mbuf *txom; + struct os_mbuf_pkthdr *omp; + struct ble_l2cap_chan_info info; + + eatt = ble_npl_event_get_arg(ev); + assert(eatt); + + omp = STAILQ_FIRST(&eatt->eatt_tx_q); + if (omp != NULL) { + STAILQ_REMOVE_HEAD(&eatt->eatt_tx_q, omp_next); + + txom = OS_MBUF_PKTHDR_TO_MBUF(omp); + ble_l2cap_get_chan_info(eatt->chan, &info); + ble_eatt_tx(eatt->conn_handle, info.dcid, txom); + } +} + +static struct ble_eatt * +ble_eatt_alloc(void) +{ + struct ble_eatt *eatt; + + eatt = os_memblock_get(&ble_eatt_conn_pool); + if (eatt) { + SLIST_INSERT_HEAD(&g_ble_eatt_list, eatt, next); + } else { + BLE_EATT_LOG_DEBUG("eatt: Failed to allocate new eatt context\n"); + return NULL; + } + + eatt->conn_handle = BLE_HS_CONN_HANDLE_NONE; + eatt->chan = NULL; + eatt->client_op = 0; + + STAILQ_INIT(&eatt->eatt_tx_q); + ble_npl_event_init(&eatt->setup_ev, ble_eatt_setup_cb, eatt); + ble_npl_event_init(&eatt->wakeup_ev, ble_eatt_wakeup_cb, eatt); + return eatt; +} + +static void +ble_eatt_free(struct ble_eatt *eatt) +{ + struct os_mbuf_pkthdr *omp; + + while ((omp = STAILQ_FIRST(&eatt->eatt_tx_q)) != NULL) { + STAILQ_REMOVE_HEAD(&eatt->eatt_tx_q, omp_next); + os_mbuf_free_chain(OS_MBUF_PKTHDR_TO_MBUF(omp)); + } + + SLIST_REMOVE(&g_ble_eatt_list, eatt, ble_eatt, next); + os_memblock_put(&ble_eatt_conn_pool, eatt); +} + +static int +ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg) +{ + struct ble_eatt *eatt = arg; + struct ble_gap_conn_desc desc; + uint8_t opcode; + int rc; + + switch (event->type) { + case BLE_L2CAP_EVENT_COC_CONNECTED: + BLE_EATT_LOG_DEBUG("eatt: Connected \n"); + if (event->connect.status) { + ble_eatt_free(eatt); + return 0; + } + eatt->chan = event->connect.chan; + ble_gap_eatt_event(event->connect.conn_handle, 0, event->connect.chan->scid); + break; + case BLE_L2CAP_EVENT_COC_DISCONNECTED: + BLE_EATT_LOG_DEBUG("eatt: Disconnected \n"); + ble_eatt_free(eatt); + ble_gap_eatt_event(event->disconnect.conn_handle, 1, event->disconnect.chan->scid); + break; + case BLE_L2CAP_EVENT_COC_ACCEPT: + BLE_EATT_LOG_DEBUG("eatt: Accept request\n"); + + eatt = ble_eatt_alloc(); + if (!eatt) { + return BLE_HS_ENOMEM; + } + eatt->conn_handle = event->accept.conn_handle; + event->accept.chan->cb_arg = eatt; + + rc = ble_eatt_prepare_rx_sdu(event->accept.chan); + if (rc) { + ble_eatt_free(eatt); + return rc; + } + break; + case BLE_L2CAP_EVENT_COC_TX_UNSTALLED: + ble_npl_eventq_put(ble_hs_evq_get(), &eatt->wakeup_ev); + break; + case BLE_L2CAP_EVENT_COC_DATA_RECEIVED: + assert(eatt->chan == event->receive.chan); + opcode = event->receive.sdu_rx->om_data[0]; + if (ble_att_is_response_op(opcode)) { + ble_npl_eventq_put(ble_hs_evq_get(), &eatt->wakeup_ev); + } else if (!ble_att_is_att_pdu_op(opcode)) { + /* As per BLE 5.4 Standard, Vol. 3, Part G, section 5.3.2 + * (ENHANCED ATT BEARER L2CAP INTEROPERABILITY REQUIREMENTS: + * Channel Requirements): + * All packets sent on this L2CAP channel shall be Attribute PDUs. + * + * Disconnect peer with invalid behavior. + */ + ble_l2cap_disconnect(eatt->chan); + return BLE_HS_EREJECT; + } + + assert (!ble_gap_conn_find(event->receive.conn_handle, &desc)); + /* As per BLE 5.4 Standard, Vol. 3, Part G, section 5.3.2 + * (ENHANCED ATT BEARER L2CAP INTEROPERABILITY REQUIREMENTS: + * Channel Requirements): + * The channel shall be encrypted. + * + * Disconnect peer with invalid behavior - ATT PDU received before + * encryption. + */ + if (!desc.sec_state.encrypted) { + ble_l2cap_disconnect(eatt->chan); + return BLE_HS_EREJECT; + } + + ble_eatt_att_rx_cb(event->receive.conn_handle, eatt->chan->scid, &event->receive.sdu_rx); + if (event->receive.sdu_rx) { + os_mbuf_free_chain(event->receive.sdu_rx); + event->receive.sdu_rx = NULL; + } + rc = ble_eatt_prepare_rx_sdu(event->receive.chan); + if (rc) { + /* Receiving L2CAP data is no longer possible, terminate connection */ + ble_l2cap_disconnect(eatt->chan); + return BLE_HS_ENOMEM; + } + break; + default: + break; + } + + return 0; +} + +static void +ble_eatt_setup_cb(struct ble_npl_event *ev) +{ + struct ble_eatt *eatt; + struct os_mbuf *om; + int rc; + + eatt = ble_npl_event_get_arg(ev); + assert(eatt); + + om = os_mbuf_get_pkthdr(&ble_eatt_sdu_os_mbuf_pool, 0); + if (!om) { + ble_eatt_free(eatt); + BLE_EATT_LOG_ERROR("eatt: no memory for sdu\n"); + return; + } + + BLE_EATT_LOG_DEBUG("eatt: connecting eatt on conn_handle 0x%04x\n", eatt->conn_handle); + rc = ble_l2cap_enhanced_connect(eatt->conn_handle, BLE_EATT_PSM, + MYNEWT_VAL(BLE_EATT_MTU), 1, &om, ble_eatt_l2cap_event_fn, eatt); + if (rc) { + BLE_EATT_LOG_ERROR("eatt: Failed to connect EATT on conn_handle 0x%04x (status=%d)\n", + eatt->conn_handle, rc); + os_mbuf_free_chain(om); + ble_eatt_free(eatt); + } +} + +static int +ble_gatt_eatt_write_cl_cb(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, void *arg) +{ + if (error == NULL || (error->status != 0 && error->status != BLE_HS_EDONE)) { + BLE_EATT_LOG_DEBUG("eatt: Cannot write to Client Supported features on peer device\n"); + return 0; + } + + ble_eatt_start(conn_handle); + return 0; +} + +static int +ble_gatt_eatt_read_cl_uuid_cb(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, void *arg) +{ + uint8_t client_supported_feat; + int rc; + + if (error == NULL || (error->status != 0 && error->status != BLE_HS_EDONE)) { + BLE_EATT_LOG_DEBUG("eatt: Cannot find Client Supported features on peer device\n"); + return BLE_HS_EDONE; + } + + if (attr == NULL) { + BLE_EATT_LOG_ERROR("eatt: Invalid attribute \n"); + return BLE_HS_EDONE; + } + + if (error->status == 0) { + client_supported_feat = MYNEWT_VAL(BLE_CLIENT_SUPPORTED_FEATURES); + rc = ble_gattc_write_flat(conn_handle, attr->handle, &client_supported_feat, 1, + ble_gatt_eatt_write_cl_cb, NULL); + BLE_EATT_LOG_DEBUG("eatt: %s , write rc = %d \n", __func__, rc); + assert(rc == 0); + return 0; + } + + return BLE_HS_EDONE; +} + +static int +ble_gatt_eatt_read_uuid_cb(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, void *arg) +{ + uint8_t supported_features; + int rc; + + if (error == NULL || (error->status != 0 && error->status != BLE_HS_EDONE)) { + BLE_EATT_LOG_DEBUG("eatt: Cannot find Server Supported features on peer device\n"); + return BLE_HS_EDONE; + } + + if (attr == NULL) { + BLE_EATT_LOG_ERROR("eatt: Invalid attribute \n"); + return BLE_HS_EDONE; + } + + rc = os_mbuf_copydata(attr->om, 0, 1, &supported_features); + if (rc) { + BLE_EATT_LOG_ERROR("eatt: Cannot read srv supported features \n"); + return BLE_HS_EDONE; + } + + if (supported_features & 0x01) { + ble_npl_event_set_arg(&g_read_sup_cl_feat_ev, (void *)((uintptr_t) conn_handle)); + ble_npl_eventq_put(ble_hs_evq_get(), &g_read_sup_cl_feat_ev); + } + return BLE_HS_EDONE; +} + +static void +ble_gatt_eatt_read_svr_uuid(struct ble_npl_event *ev) +{ + uint16_t conn_handle; + + conn_handle = (uint16_t)((uintptr_t)(ble_npl_event_get_arg(ev))); + + ble_gattc_read_by_uuid(conn_handle, 1, 0xffff, + BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_SERVER_SUPPORTED_FEAT_UUID16), + ble_gatt_eatt_read_uuid_cb, NULL); +} + +static void +ble_gatt_eatt_read_cl_uuid(struct ble_npl_event *ev) +{ + uint16_t conn_handle; + + conn_handle = (uint16_t)((uintptr_t)(ble_npl_event_get_arg(ev))); + + ble_gattc_read_by_uuid(conn_handle, 1, 0xffff, + BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_CLIENT_SUPPORTED_FEAT_UUID16), + ble_gatt_eatt_read_cl_uuid_cb, NULL); +} + +static int +ble_eatt_gap_event(struct ble_gap_event *event, void *arg) +{ + struct ble_eatt *eatt; + + switch (event->type) { + case BLE_GAP_EVENT_ENC_CHANGE: + if (event->enc_change.status != 0) { + return 0; + } + + if (ble_hs_cfg.eatt == 0) { + return 0; + } + + /* Don't try to connect if already connected */ + if (ble_eatt_find_by_conn_handle(event->enc_change.conn_handle)) { + return 0; + } + + BLE_EATT_LOG_DEBUG("eatt: Encryption enabled, connecting EATT (conn_handle=0x%04x)\n", + event->enc_change.conn_handle); + + ble_npl_event_set_arg(&g_read_sup_srv_feat_ev, (void *)((uintptr_t)(event->enc_change.conn_handle))); + ble_npl_eventq_put(ble_hs_evq_get(), &g_read_sup_srv_feat_ev); + + break; + case BLE_GAP_EVENT_DISCONNECT: + eatt = ble_eatt_find_by_conn_handle(event->disconnect.conn.conn_handle); + assert(eatt == NULL); + break; + default: + break; + } + return 0; +} + +uint16_t +ble_eatt_get_available_chan_cid(uint16_t conn_handle, uint8_t op) +{ + uint16_t default_cid; + struct ble_eatt * eatt; + + default_cid = ble_att_get_default_bearer_cid(conn_handle); + if (default_cid) { + eatt = ble_eatt_find(conn_handle, default_cid); + } else { + eatt = ble_eatt_find_not_busy(conn_handle); + } + if (!eatt) { + return BLE_L2CAP_CID_ATT; + } + + eatt->client_op = op; + return eatt->chan->scid; +} + + +void +ble_eatt_release_chan(uint16_t conn_handle, uint8_t op) +{ + struct ble_eatt * eatt; + + eatt = ble_eatt_find_by_conn_handle_and_busy_op(conn_handle, op); + if (!eatt) { + BLE_EATT_LOG_DEBUG("ble_eatt_release_chan:" + "EATT not found for conn_handle 0x%04x, operation 0x%02\n", conn_handle, op); + return; + } + + eatt->client_op = 0; +} + +int +ble_eatt_tx(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom) +{ + struct ble_eatt *eatt; + int rc; + + BLE_EATT_LOG_DEBUG("eatt: %s, size %d ", __func__, OS_MBUF_PKTLEN(txom)); + eatt = ble_eatt_find(conn_handle, cid); + if (!eatt || !eatt->chan) { + BLE_EATT_LOG_ERROR("Eatt not available"); + rc = BLE_HS_ENOENT; + goto error; + } + + ble_att_truncate_to_mtu(eatt->chan, txom); + rc = ble_l2cap_send(eatt->chan, txom); + if (rc == 0) { + goto done; + } + + if (rc == BLE_HS_ESTALLED) { + BLE_EATT_LOG_DEBUG("ble_eatt_tx: Eatt stalled"); + } else if (rc == BLE_HS_EBUSY) { + BLE_EATT_LOG_DEBUG("ble_eatt_tx: Message queued"); + STAILQ_INSERT_HEAD(&eatt->eatt_tx_q, OS_MBUF_PKTHDR(txom), omp_next); + ble_npl_eventq_put(ble_hs_evq_get(), &eatt->wakeup_ev); + } else { + BLE_EATT_LOG_ERROR("eatt: %s, ERROR %d ", __func__, rc); + assert(0); + } +done: + return 0; + +error: + os_mbuf_free_chain(txom); + return rc; +} + +static void +ble_eatt_start(uint16_t conn_handle) +{ + struct ble_gap_conn_desc desc; + struct ble_eatt *eatt; + int rc; + + rc = ble_gap_conn_find(conn_handle, &desc); + assert(rc == 0); + if (desc.role != BLE_GAP_ROLE_MASTER) { + /* Let master to create ecoc. + */ + return; + } + + for (int i = 0; i < ble_hs_cfg.eatt; i++) { + eatt = ble_eatt_alloc(); + if (!eatt) { + return; + } + + eatt->conn_handle = conn_handle; + + /* Setup EATT */ + ble_npl_eventq_put(ble_hs_evq_get(), &eatt->setup_ev); + eatt = NULL; + } +} + +void +ble_eatt_init(ble_eatt_att_rx_fn att_rx_cb) +{ + int rc; + + rc = os_mempool_init(&ble_eatt_sdu_mbuf_mempool, + MYNEWT_VAL(BLE_EATT_CHAN_NUM) + 1, + BLE_EATT_MEMBLOCK_SIZE, + ble_eatt_sdu_coc_mem, + "ble_eatt_sdu"); + BLE_HS_DBG_ASSERT_EVAL(rc == 0); + + rc = os_mbuf_pool_init(&ble_eatt_sdu_os_mbuf_pool, + &ble_eatt_sdu_mbuf_mempool, + BLE_EATT_MEMBLOCK_SIZE, + MYNEWT_VAL(BLE_EATT_CHAN_NUM) + 1); + BLE_HS_DBG_ASSERT_EVAL(rc == 0); + + rc = os_mempool_init(&ble_eatt_conn_pool, MYNEWT_VAL(BLE_EATT_CHAN_NUM), + sizeof (struct ble_eatt), + ble_eatt_conn_mem, "ble_eatt_conn_pool"); + BLE_HS_DBG_ASSERT_EVAL(rc == 0); + + rc = ble_gap_event_listener_register(&ble_eatt_listener, ble_eatt_gap_event, NULL); + ble_l2cap_create_server(BLE_EATT_PSM, MYNEWT_VAL(BLE_EATT_MTU), ble_eatt_l2cap_event_fn, NULL); + + ble_npl_event_init(&g_read_sup_srv_feat_ev, ble_gatt_eatt_read_svr_uuid, NULL); + ble_npl_event_init(&g_read_sup_cl_feat_ev, ble_gatt_eatt_read_cl_uuid, NULL); + + ble_eatt_att_rx_cb = att_rx_cb; +} +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_eatt_priv.h b/lib/bt/host/nimble/nimble/nimble/host/src/ble_eatt_priv.h new file mode 100644 index 00000000..1797ce67 --- /dev/null +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_eatt_priv.h @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "syscfg/syscfg.h" +#include "os/os_mbuf.h" +#include "host/ble_l2cap.h" + +#ifndef BLE_EATT_H_ +#define BLE_EATT_H_ + +typedef int (* ble_eatt_att_rx_fn)(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rx_buf); + +#define BLE_EATT_PSM (0x0027) + +#define BLE_GATT_OP_SERVER 0xF1 +#define BLE_GATT_OP_DUMMY 0xF2 + +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 +void ble_eatt_init(ble_eatt_att_rx_fn att_rx_fn); +uint16_t ble_eatt_get_available_chan_cid(uint16_t conn_handle, uint8_t op); +void ble_eatt_release_chan(uint16_t conn_handle, uint8_t op); +int ble_eatt_tx(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom); +#else +static inline void +ble_eatt_init(ble_eatt_att_rx_fn att_rx_fn) +{ +} + +static inline void +ble_eatt_release_chan(uint16_t conn_handle, uint8_t op) +{ + +} + +static inline uint16_t +ble_eatt_get_available_chan_cid(uint16_t conn_handle, uint8_t op) +{ + return BLE_L2CAP_CID_ATT; +} + +#endif +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gap.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gap.c index d896565e..072b415b 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gap.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gap.c @@ -108,7 +108,7 @@ #define BLE_GAP_UPDATE_TIMEOUT_MS 40000 /* ms */ -#if MYNEWT_VAL(BLE_ROLE_CENTRAL) +#if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) static const struct ble_gap_conn_params ble_gap_conn_params_dflt = { .scan_itvl = 0x0010, .scan_window = 0x0010, @@ -127,9 +127,21 @@ struct ble_gap_connect_reattempt_ctxt { ble_addr_t peer_addr; uint8_t peer_addr_present:1; int32_t duration_ms; - struct ble_gap_conn_params conn_params; + struct ble_gap_conn_params conn_params_1m; ble_gap_event_fn *cb; void *cb_arg; +#if MYNEWT_VAL(BLE_EXT_ADV) + uint8_t phy_mask; + struct ble_gap_conn_params conn_params_2m; + struct ble_gap_conn_params conn_params_coded; +#endif // MYNEWT_VAL(BLE_EXT_ADV) +#if MYNEWT_VAL(BLE_PERIODIC_ADV) + ble_addr_t periodic_addr; + uint8_t adv_sid; + int sync_reattempt; + int count; + struct ble_gap_periodic_sync_params periodic_params; +#endif // MYNEWT_VAL(BLE_PERIODIC_ADV) }ble_conn_reattempt; struct ble_gap_adv_reattempt_ctxt { @@ -159,7 +171,6 @@ struct ble_gap_adv_reattempt_ctxt { }ble_adv_reattempt; #endif - /** * The state of the in-progress master connection. If no master connection is * currently in progress, then the op field is set to BLE_GAP_OP_NULL. @@ -188,6 +199,7 @@ struct ble_gap_master_state { struct { uint8_t limited:1; + uint8_t observer:1; } disc; }; }; @@ -276,6 +288,12 @@ struct ble_gap_multi_conn_state static struct ble_gap_multi_conn_state ble_gap_multi_conn; #endif +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +static uint8_t pawr_adv_handle; +static uint16_t pawr_sync_handle; +#endif + +int slave_conn[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; static void ble_gap_update_entry_free(struct ble_gap_update_entry *entry); #if NIMBLE_BLE_CONNECT @@ -302,6 +320,11 @@ static int ble_gap_conn_cancel_tx(void); static int ble_gap_disc_enable_tx(int enable, int filter_duplicates); #endif +uint16_t g_max_tx_time[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; +uint16_t g_max_rx_time[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1 ]; +uint16_t g_max_tx_octets[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; +uint16_t g_max_rx_octets[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; + STATS_SECT_DECL(ble_gap_stats) ble_gap_stats; STATS_NAME_START(ble_gap_stats) STATS_NAME(ble_gap_stats, wl_set) @@ -559,6 +582,29 @@ ble_gap_conn_find(uint16_t handle, struct ble_gap_conn_desc *out_desc) #endif } +int +ble_gap_read_rem_ver_info(uint16_t conn_handle, uint8_t *version, uint16_t *manufacturer, uint16_t *subversion) +{ +#if NIMBLE_BLE_CONNECT + struct ble_hs_conn *conn; + + ble_hs_lock(); + + conn = ble_hs_conn_find(conn_handle); + + ble_hs_unlock(); + + if (conn == NULL ) { + return BLE_HS_ENOTCONN; + } + + *version = conn->bhc_rd_rem_ver_params.version; + *manufacturer = conn->bhc_rd_rem_ver_params.manufacturer; + *subversion = conn->bhc_rd_rem_ver_params.subversion; +#endif + return 0; +} + int ble_gap_conn_find_by_addr(const ble_addr_t *addr, struct ble_gap_conn_desc *out_desc) @@ -998,7 +1044,7 @@ ble_gap_master_extract_state(struct ble_gap_master_state *out_state, } #endif -#if NIMBLE_BLE_ADVERTISE || NIMBLE_BLE_CONNECT +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) || NIMBLE_BLE_ADVERTISE static void ble_gap_slave_extract_cb(uint8_t instance, ble_gap_event_fn **out_cb, void **out_cb_arg) @@ -1011,7 +1057,9 @@ ble_gap_slave_extract_cb(uint8_t instance, ble_hs_unlock(); } +#endif +#if NIMBLE_BLE_ADVERTISE static void ble_gap_adv_finished(uint8_t instance, int reason, uint16_t conn_handle, uint8_t num_events) @@ -1052,7 +1100,22 @@ ble_gap_master_connect_failure(int status) event.type = BLE_GAP_EVENT_CONNECT; event.connect.status = status; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.connect.sync_handle = pawr_sync_handle; + event.connect.adv_handle = pawr_adv_handle; +#endif + rc = state.cb(&event, state.cb_arg); + +//TODO Remove duplication of event fields + event.type = BLE_GAP_EVENT_LINK_ESTAB; + event.link_estab.status = status; + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.link_estab.sync_handle = pawr_sync_handle; + event.link_estab.adv_handle = pawr_adv_handle; +#endif rc = state.cb(&event, state.cb_arg); + } else { rc = 0; } @@ -1078,11 +1141,33 @@ ble_gap_master_connect_cancelled(void) /* Connect procedure timed out. */ event.connect.status = BLE_HS_ETIMEOUT; } + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.connect.sync_handle = pawr_sync_handle; + event.connect.adv_handle = pawr_adv_handle; +#endif + state.cb(&event, state.cb_arg); + +//TODO Remove duplication of event fields + event.type = BLE_GAP_EVENT_LINK_ESTAB; + event.link_estab.conn_handle = BLE_HS_CONN_HANDLE_NONE; + if (state.conn.cancel) { + /* Connect procedure successfully cancelled. */ + event.link_estab.status = BLE_HS_EAPP; + } else { + /* Connect procedure timed out. */ + event.link_estab.status = BLE_HS_ETIMEOUT; + } + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.link_estab.sync_handle = pawr_sync_handle; + event.link_estab.adv_handle = pawr_adv_handle; +#endif state.cb(&event, state.cb_arg); } } -#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) && NIMBLE_BLE_CONNECT static void ble_gap_update_notify(uint16_t conn_handle, int status); @@ -1115,8 +1200,12 @@ ble_gap_master_connect_reattempt(uint16_t conn_handle) ble_l2cap_sig_conn_broken(conn_handle, BLE_ERR_CONN_ESTABLISHMENT); ble_sm_connection_broken(conn_handle); - ble_gatts_connection_broken(conn_handle); - ble_gattc_connection_broken(conn_handle); +#if MYNEWT_VAL(BLE_GATTS) + ble_gatts_connection_broken(conn_handle); +#endif +#if MYNEWT_VAL(BLE_GATTC) + ble_gattc_connection_broken(conn_handle); +#endif ble_hs_flow_connection_broken(conn_handle);; rc = ble_hs_atomic_conn_delete(conn_handle); @@ -1124,12 +1213,33 @@ ble_gap_master_connect_reattempt(uint16_t conn_handle) return rc; } +#if MYNEWT_VAL(OPTIMIZE_MULTI_CONN) + /* This reattempt will be done automatically. The `scheduling_len` maybe set in the ble_gap_multi_connect(). */ + ble_gap_multi_conn.scheduling_len_set = true; +#endif // MYNEWT_VAL(OPTIMIZE_MULTI_CONN) + +#if MYNEWT_VAL(BLE_EXT_ADV) + rc = ble_gap_ext_connect(ble_conn_reattempt.own_addr_type, + (ble_conn_reattempt.peer_addr_present == 1 ? &ble_conn_reattempt.peer_addr : NULL), + ble_conn_reattempt.duration_ms, ble_conn_reattempt.phy_mask, + ble_conn_reattempt.phy_mask & BLE_GAP_LE_PHY_1M_MASK ? &ble_conn_reattempt.conn_params_1m : NULL, + ble_conn_reattempt.phy_mask & BLE_GAP_LE_PHY_2M_MASK ? &ble_conn_reattempt.conn_params_2m : NULL, + ble_conn_reattempt.phy_mask & BLE_GAP_LE_PHY_CODED_MASK ? &ble_conn_reattempt.conn_params_coded : NULL, + ble_conn_reattempt.cb, + ble_conn_reattempt.cb_arg); +#else rc = ble_gap_connect(ble_conn_reattempt.own_addr_type, (ble_conn_reattempt.peer_addr_present == 1 ? &ble_conn_reattempt.peer_addr : NULL), ble_conn_reattempt.duration_ms, - &ble_conn_reattempt.conn_params, + &ble_conn_reattempt.conn_params_1m, ble_conn_reattempt.cb, - &conn); + ble_conn_reattempt.cb_arg); +#endif // #if MYNEWT_VAL(BLE_EXT_ADV) + +#if MYNEWT_VAL(OPTIMIZE_MULTI_CONN) + ble_gap_multi_conn.scheduling_len_set = false; +#endif // MYNEWT_VAL(OPTIMIZE_MULTI_CONN) + if (rc != 0) { return rc; } @@ -1366,7 +1476,10 @@ ble_gap_update_next_exp(int32_t *out_ticks_from_now) } -#if NIMBLE_BLE_SCAN + +#if (MYNEWT_VAL(BLE_ROLE_CENTRAL) || \ + (MYNEWT_VAL(BLE_ROLE_CENTRAL) && !MYNEWT_VAL(BLE_EXT_ADV)) || \ + (NIMBLE_BLE_SCAN && !MYNEWT_VAL(BLE_EXT_ADV))) static void ble_gap_master_set_timer(uint32_t ticks_from_now) { @@ -1444,6 +1557,8 @@ ble_gap_conn_broken(uint16_t conn_handle, int reason) struct ble_gap_update_entry *entry; struct ble_gap_snapshot snap; struct ble_gap_event event; + struct ble_hs_conn *conn; + bool send = 1; int rc; memset(&event, 0, sizeof event); @@ -1473,20 +1588,46 @@ ble_gap_conn_broken(uint16_t conn_handle, int reason) */ ble_l2cap_sig_conn_broken(conn_handle, reason); ble_sm_connection_broken(conn_handle); +#if MYNEWT_VAL(BLE_GATTS) ble_gatts_connection_broken(conn_handle); +#endif + +#if MYNEWT_VAL(BLE_GATTC) ble_gattc_connection_broken(conn_handle); +#endif + #if MYNEWT_VAL(BLE_GATT_CACHING) ble_gattc_cache_conn_broken(conn_handle); #endif ble_hs_flow_connection_broken(conn_handle);; + ble_hs_lock(); + conn = ble_hs_conn_find(conn_handle); + ble_hs_unlock(); + + // Send disconnect event in slave role if connect was sent + if ((conn != NULL) && !(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) { + if (slave_conn[conn_handle]) { + slave_conn[conn_handle] = 0; + } else { + send = 0; + } + } + ble_hs_atomic_conn_delete(conn_handle); + g_max_tx_time[conn_handle] = 0; + g_max_rx_time[conn_handle] = 0; + g_max_tx_octets[conn_handle] = 0; + g_max_rx_octets[conn_handle] = 0; + event.type = BLE_GAP_EVENT_DISCONNECT; event.disconnect.reason = reason; - ble_gap_event_listener_call(&event); - ble_gap_call_event_cb(&event, snap.cb, snap.cb_arg); + if (send) { + ble_gap_event_listener_call(&event); + ble_gap_call_event_cb(&event, snap.cb, snap.cb_arg); + } STATS_INC(ble_gap_stats, disconnect); #endif @@ -1634,7 +1775,11 @@ int ble_gap_ext_adv_active(uint8_t instance) if (instance >= BLE_ADV_INSTANCES) { return 0; } +#if NIMBLE_BLE_ADVERTISE || NIMBLE_BLE_CONNECT return ble_gap_adv_active_instance(instance); +#else + return 0; +#endif } #endif @@ -1710,11 +1855,16 @@ ble_gap_accept_master_conn(void) static int ble_gap_accept_slave_conn(uint8_t instance) { - int rc; - + int rc = 0; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + if (instance >= BLE_ADV_INSTANCES) { + rc = BLE_HS_ENOENT; +} +#else if (instance >= BLE_ADV_INSTANCES) { - rc = BLE_HS_ENOENT; + rc = BLE_HS_ENOENT; } else if (!ble_gap_adv_active_instance(instance)) { + rc = BLE_HS_ENOENT; } else { if (ble_gap_slave[instance].connectable) { @@ -1728,6 +1878,7 @@ ble_gap_accept_slave_conn(uint8_t instance) STATS_INC(ble_gap_stats, connect_slv); } +#endif return rc; } #endif @@ -1741,11 +1892,16 @@ ble_gap_rx_adv_report_sanity_check(const uint8_t *adv_data, uint8_t adv_data_len STATS_INC(ble_gap_stats, rx_adv_report); +#if MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN) + /* In case to allow scan with connect, return directly */ + return 0; +#endif + if (ble_gap_master.op != BLE_GAP_OP_M_DISC) { return -1; } - if (MYNEWT_VAL(BLE_ROLE_OBSERVER)) { + if (ble_gap_master.disc.observer) { /* Observer role is enabled; All adv reports regardless of * Flags AD Type need to be discovered. */ @@ -1812,6 +1968,7 @@ ble_gap_rx_ext_adv_report(struct ble_gap_ext_disc_desc *desc) void ble_gap_rx_adv_set_terminated(const struct ble_hci_ev_le_subev_adv_set_terminated *ev) { +#if NIMBLE_BLE_ADVERTISE uint16_t conn_handle; int reason; @@ -1826,6 +1983,7 @@ ble_gap_rx_adv_set_terminated(const struct ble_hci_ev_le_subev_adv_set_terminate } ble_gap_adv_finished(ev->adv_handle, reason, conn_handle, ev->num_events); +#endif } static void @@ -1861,7 +2019,6 @@ ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd *ev) /* Periodic adv events */ #if MYNEWT_VAL(BLE_PERIODIC_ADV) - void ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev) { @@ -1869,7 +2026,9 @@ ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv struct ble_gap_event event; ble_gap_event_fn *cb; void *cb_arg; - +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) && NIMBLE_BLE_CONNECT + int rc; +#endif memset(&event, 0, sizeof event); event.type = BLE_GAP_EVENT_PERIODIC_SYNC; @@ -1882,6 +2041,11 @@ ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv if (!ev->status) { sync_handle = le16toh(ev->sync_handle); +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) && NIMBLE_BLE_CONNECT + if (ble_conn_reattempt.sync_reattempt) { + ble_conn_reattempt.sync_reattempt = 0; + } +#endif ble_gap_sync.psync->sync_handle = sync_handle; ble_gap_sync.psync->adv_sid = ev->sid; memcpy(ble_gap_sync.psync->advertiser_addr.val, ev->peer_addr, 6); @@ -1896,26 +2060,62 @@ ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv event.periodic_sync.adv_phy = ev->phy; event.periodic_sync.per_adv_ival = ev->interval; event.periodic_sync.adv_clk_accuracy = ev->aca; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.periodic_sync.num_subevents = ev->num_subevents; + event.periodic_sync.subevent_interval = ev->subevent_interval; + event.periodic_sync.response_slot_delay = ev->response_slot_delay; + event.periodic_sync.response_slot_spacing = ev->response_slot_spacing; +#endif ble_hs_periodic_sync_insert(ble_gap_sync.psync); } else { ble_hs_periodic_sync_free(ble_gap_sync.psync); - } +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) && NIMBLE_BLE_CONNECT + if (ev->status == BLE_ERR_CONN_ESTABLISHMENT) { + if (ble_conn_reattempt.count < MAX_REATTEMPT_ALLOWED) { + if (ble_gap_sync.op == BLE_GAP_OP_SYNC) { + memset(&ble_gap_sync, 0, sizeof(ble_gap_sync)); + } + ble_conn_reattempt.count += 1; + ble_conn_reattempt.sync_reattempt = 1; - cb = ble_gap_sync.cb; - cb_arg = ble_gap_sync.cb_arg; + ble_hs_unlock(); - ble_gap_sync.op = BLE_GAP_OP_NULL; - ble_gap_sync.cb_arg = NULL; - ble_gap_sync.cb_arg = NULL; - ble_gap_sync.psync = NULL; + rc = ble_gap_periodic_adv_sync_create(&ble_conn_reattempt.periodic_addr, ble_conn_reattempt.adv_sid, + &ble_conn_reattempt.periodic_params, + ble_conn_reattempt.cb, ble_conn_reattempt.cb_arg); + if (rc != 0) { + return; + } - ble_hs_unlock(); + ble_hs_lock(); + } + } +#endif + } +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) && NIMBLE_BLE_CONNECT + if (!ble_conn_reattempt.sync_reattempt || ble_conn_reattempt.count >= MAX_REATTEMPT_ALLOWED) { + memset(&ble_conn_reattempt.periodic_addr, 0, sizeof(ble_addr_t)); + ble_conn_reattempt.adv_sid = 0; + ble_conn_reattempt.count = 0; + memset(&ble_conn_reattempt.periodic_params, 0x0, sizeof(struct ble_gap_periodic_sync_params)); +#endif + cb = ble_gap_sync.cb; + cb_arg = ble_gap_sync.cb_arg; - ble_gap_event_listener_call(&event); - if (cb) { - cb(&event, cb_arg); + ble_gap_sync.op = BLE_GAP_OP_NULL; + ble_gap_sync.cb_arg = NULL; + ble_gap_sync.cb_arg = NULL; + ble_gap_sync.psync = NULL; + + ble_gap_event_listener_call(&event); + if (cb) { + cb(&event, cb_arg); + } +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) && NIMBLE_BLE_CONNECT } +#endif + ble_hs_unlock(); } void @@ -1947,6 +2147,10 @@ ble_gap_rx_periodic_adv_rpt(const struct ble_hci_ev_le_subev_periodic_adv_rpt *e event.periodic_report.data_status = ev->data_status; event.periodic_report.data_length = ev->data_len; event.periodic_report.data = ev->data; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.periodic_report.event_counter = ev->event_counter; + event.periodic_report.subevent = ev->subevent; +#endif /* TODO should we allow for listener too? this can be spammy and is more * like ACL data, not general event @@ -2033,6 +2237,92 @@ ble_gap_rx_transmit_power_report(const struct ble_hci_ev_le_subev_transmit_power } #endif + +#if MYNEWT_VAL(BLE_AOA_AOD) + +void +ble_gap_rx_connless_iq_report(const struct ble_hci_ev_le_subev_connless_iq_rpt *ev) +{ + struct ble_hs_periodic_sync *psync; + struct ble_gap_event event; + ble_gap_event_fn *cb = NULL; + void *cb_arg = NULL; + uint16_t sync_handle = le16toh(ev->sync_handle); + + /* The handle must be in the list */ + ble_hs_lock(); + psync = ble_hs_periodic_sync_find_by_handle(sync_handle); + cb = psync->cb; + cb_arg = psync->cb_arg; + ble_hs_unlock(); + + memset(&event, 0, sizeof event); + + event.type = BLE_GAP_EVENT_CONNLESS_IQ_REPORT; + event.connless_iq_report.sync_handle = sync_handle; + event.connless_iq_report.channel_index = ev->channel_index; + event.connless_iq_report.rssi = le16toh(ev->rssi); + event.connless_iq_report.rssi_antenna_id = ev->rssi_antenna_id; + event.connless_iq_report.cte_type = ev->cte_type; + event.connless_iq_report.slot_durations = ev->slot_durations; + event.connless_iq_report.packet_status = ev->packet_status; + event.connless_iq_report.periodic_event_counter = le16toh(ev->periodic_event_counter); + event.connless_iq_report.sample_count = ev->sample_count; + event.connless_iq_report.i_samples = (int8_t *)(ev->iq_samples); + event.connless_iq_report.q_samples = (int8_t *)(ev->iq_samples + ev->sample_count); + + ble_gap_event_listener_call(&event); + + if (cb) { + cb(&event, cb_arg); + } +} + + +void +ble_gap_rx_conn_iq_report(const struct ble_hci_ev_le_subev_conn_iq_rpt *ev) +{ + struct ble_gap_event event; + memset(&event, 0, sizeof event); + + event.type = BLE_GAP_EVENT_CONN_IQ_REPORT; + event.conn_iq_report.conn_handle = le16toh(ev->conn_handle); + event.conn_iq_report.data_channel_index = ev->data_channel_index; + event.conn_iq_report.rx_phy = ev->rx_phy; + event.conn_iq_report.rssi = le16toh(ev->rssi); + event.conn_iq_report.rssi_antenna_id = ev->rssi_antenna_id; + event.conn_iq_report.cte_type = ev->cte_type; + event.conn_iq_report.slot_durations = ev->slot_durations; + event.conn_iq_report.packet_status = ev->packet_status; + event.conn_iq_report.conn_event_counter = le16toh(ev->conn_event_counter); + event.conn_iq_report.sample_count = ev->sample_count; + event.conn_iq_report.i_samples = (int8_t *)(ev->iq_samples); + event.conn_iq_report.q_samples = (int8_t *)(ev->iq_samples + ev->sample_count); + + ble_gap_event_listener_call(&event); + ble_gap_call_conn_event_cb(&event, event.conn_iq_report.conn_handle); + +} + +void +ble_gap_rx_cte_req_failed(const struct ble_hci_ev_le_subev_cte_req_failed *ev) +{ + struct ble_gap_event event; + uint16_t conn_handle; + conn_handle = le16toh(ev->conn_handle); + + memset(&event, 0x0, sizeof event); + + event.type = BLE_GAP_EVENT_CTE_REQ_FAILED; + event.cte_req_fail.status = ev->status; + event.cte_req_fail.conn_handle = conn_handle; + + ble_gap_event_listener_call(&event); + ble_gap_call_conn_event_cb(&event, conn_handle); +} + +#endif + #if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER) static int periodic_adv_transfer_disable(uint16_t conn_handle) @@ -2098,7 +2388,11 @@ ble_gap_rx_periodic_adv_sync_transfer(const struct ble_hci_ev_le_subev_periodic_ memset(&event, 0, sizeof event); +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.type = BLE_GAP_EVENT_PERIODIC_TRANSFER_V2; +#else event.type = BLE_GAP_EVENT_PERIODIC_TRANSFER; +#endif // MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) event.periodic_transfer.status = ev->status; /* only sync handle is not valid on error */ @@ -2127,7 +2421,12 @@ ble_gap_rx_periodic_adv_sync_transfer(const struct ble_hci_ev_le_subev_periodic_ event.periodic_transfer.adv_phy = ev->phy; event.periodic_transfer.per_adv_itvl = le16toh(ev->interval); event.periodic_transfer.adv_clk_accuracy = ev->aca; - +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.periodic_transfer.num_subevents = ev->num_subevents; + event.periodic_transfer.subevent_interval = ev->subevent_interval; + event.periodic_transfer.response_slot_delay = ev->response_slot_delay; + event.periodic_transfer.response_slot_spacing = ev->response_slot_spacing; +#endif ble_hs_unlock(); cb(&event, cb_arg); @@ -2183,6 +2482,9 @@ void ble_gap_rx_subrate_change(const struct ble_hci_ev_le_subev_subrate_change *ev) { struct ble_gap_event event; + uint16_t conn_handle; + + conn_handle = le16toh(ev->conn_handle); memset(&event, 0x0, sizeof event); @@ -2195,6 +2497,88 @@ ble_gap_rx_subrate_change(const struct ble_hci_ev_le_subev_subrate_change *ev) event.subrate_change.supervision_tmo = le16toh(ev->supervision_tmo); ble_gap_event_listener_call(&event); + ble_gap_call_conn_event_cb(&event, conn_handle); +} +#endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +void +ble_gap_rx_periodic_adv_subev_data_req(const struct ble_hci_ev_le_subev_periodic_adv_subev_data_req *ev) +{ + struct ble_gap_event event; + ble_gap_event_fn *cb; + void *cb_arg; + + memset(&event, 0x0, sizeof event); + + event.type = BLE_GAP_EVENT_PER_SUBEV_DATA_REQ; + event.periodic_adv_subev_data_req.adv_handle = ev->adv_handle; + event.periodic_adv_subev_data_req.subevent_start = ev->subevent_start; + event.periodic_adv_subev_data_req.subevent_data_count = ev->subevent_data_count; + + ble_gap_slave_extract_cb(ev->adv_handle, &cb, &cb_arg); + if (cb != NULL) { + cb(&event, cb_arg); + } + + ble_gap_event_listener_call(&event); +} + +void +ble_gap_rx_periodic_adv_response(const struct ble_gap_periodic_adv_response resp) +{ + struct ble_gap_event event; + ble_gap_event_fn *cb; + void *cb_arg; + + memset(&event, 0x0, sizeof event); + + event.type = BLE_GAP_EVENT_PER_SUBEV_RESP; + memcpy(&event.periodic_adv_response, &resp, + sizeof(struct ble_gap_periodic_adv_response)); + + ble_gap_slave_extract_cb(resp.adv_handle, &cb, &cb_arg); + if (cb != NULL) { + cb(&event, cb_arg); + } + + ble_gap_event_listener_call(&event); +} + +void +ble_gap_rx_conn_comp_failed(const struct ble_gap_conn_complete *evt) +{ + struct ble_gap_event event, event_link_estab; + ble_gap_event_fn *cb; + void *cb_arg; + + memset(&event, 0x0, sizeof event); + memset(&event_link_estab, 0x0, sizeof event); + + event.type = BLE_GAP_EVENT_CONNECT; + event.connect.conn_handle = evt->connection_handle; + event.connect.status = BLE_ERR_CONN_ESTABLISHMENT; + + event.connect.sync_handle = evt->sync_handle; + event.connect.adv_handle = evt->adv_handle; + +//TODO Remove duplication of event fields + event_link_estab.type = BLE_GAP_EVENT_LINK_ESTAB; + event_link_estab.link_estab.conn_handle = evt->connection_handle; + event_link_estab.link_estab.status = BLE_ERR_CONN_ESTABLISHMENT; + + event_link_estab.link_estab.sync_handle = evt->sync_handle; + event_link_estab.link_estab.adv_handle = evt->adv_handle; + + ble_gap_master_reset_state(); + ble_gap_slave_extract_cb(evt->adv_handle, &cb, &cb_arg); + if (cb != NULL) { + cb(&event, cb_arg); + cb(&event_link_estab, cb_arg); + } + + ble_gap_event_listener_call(&event); + ble_gap_event_listener_call(&event_link_estab); } #endif @@ -2210,6 +2594,18 @@ ble_gap_rd_rem_sup_feat_tx(uint16_t handle) BLE_HCI_OCF_LE_RD_REM_FEAT), &cmd, sizeof(cmd), NULL, 0); } + +static int +ble_gap_rd_rem_ver_tx(uint16_t handle) +{ + struct ble_hci_rd_rem_ver_info_cp cmd; + + cmd.conn_handle = htole16(handle); + + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LINK_CTRL, + BLE_HCI_OCF_RD_REM_VER_INFO), + &cmd, sizeof(cmd), NULL, 0); +} #endif /** @@ -2220,14 +2616,19 @@ int ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) { #if NIMBLE_BLE_CONNECT - struct ble_gap_event event; struct ble_hs_conn *conn; int rc; #if MYNEWT_VAL(BLE_GATT_CACHING) - struct ble_hs_conn_addrs addrs + struct ble_hs_conn_addrs addrs; #endif STATS_INC(ble_gap_stats, rx_conn_complete); +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + uint8_t v1_evt = 0; + if (evt->adv_handle == 0xFF && evt->sync_handle == 0xFFFF) { + v1_evt = 1; + } +#endif // MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) /* in that case *only* status field is valid so we determine role * based on error code @@ -2240,9 +2641,11 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) * with ext advertising this is send from set terminated event */ #if !MYNEWT_VAL(BLE_EXT_ADV) +#if NIMBLE_BLE_ADVERTISE if (ble_gap_adv_active()) { ble_gap_adv_finished(0, 0, 0, 0); } +#endif #endif break; case BLE_ERR_UNK_CONN_ID: @@ -2256,6 +2659,13 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) } } break; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + case BLE_ERR_CONN_ESTABLISHMENT: + if (!v1_evt) { + ble_gap_rx_conn_comp_failed(evt); + } + break; +#endif // MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) default: /* this should never happen, unless controller is broken */ BLE_HS_LOG(INFO, "controller reported invalid error code in conn" @@ -2309,6 +2719,17 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) conn->bhc_our_addr_type = ble_gap_master.conn.our_addr_type; ble_gap_master_reset_state(); } else { +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + if (!v1_evt) { + conn->bhc_cb = ble_gap_master.cb; + conn->bhc_cb_arg = ble_gap_master.cb_arg; + conn->bhc_our_addr_type = ble_gap_master.conn.our_addr_type; + } else { + conn->bhc_cb = ble_gap_slave[instance].cb; + conn->bhc_cb_arg = ble_gap_slave[instance].cb_arg; + conn->bhc_our_addr_type = ble_gap_slave[instance].our_addr_type; + } +#else conn->bhc_cb = ble_gap_slave[instance].cb; conn->bhc_cb_arg = ble_gap_slave[instance].cb_arg; conn->bhc_our_addr_type = ble_gap_slave[instance].our_addr_type; @@ -2316,7 +2737,8 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) memcpy(conn->bhc_our_rnd_addr, ble_gap_slave[instance].rnd_addr, 6); #endif ble_gap_slave_reset_state(instance); - } +#endif +} conn->bhc_peer_addr.type = evt->peer_addr_type; memcpy(conn->bhc_peer_addr.val, evt->peer_addr, 6); @@ -2339,26 +2761,39 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) ble_hs_lock(); - memset(&event, 0, sizeof event); ble_hs_conn_insert(conn); ble_hs_unlock(); - event.type = BLE_GAP_EVENT_CONNECT; - event.connect.conn_handle = evt->connection_handle; - event.connect.status = 0; - /* add gatt connection */ #if MYNEWT_VAL(BLE_GATT_CACHING) if (evt->role == BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER) { ble_hs_conn_addrs(conn, &addrs); rc = ble_gattc_cache_conn_create(conn->bhc_handle, addrs.peer_id_addr); + } else { + conn->bhc_gatt_svr.aware_state = true; + conn->bhc_gatt_svr.half_aware = 0; + /* This is also done when bonding is restored, so `conn` and `ble_gatts_conn_aware_states` need to be kept in sync */ + ble_hs_conn_addrs(conn, &addrs); + for (int i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { + if (memcmp(ble_gatts_conn_aware_states[i].peer_id_addr, + addrs.peer_id_addr.val, sizeof addrs.peer_id_addr.val)) { + conn->bhc_gatt_svr.half_aware = ble_gatts_conn_aware_states[i].half_aware; + conn->bhc_gatt_svr.aware_state = ble_gatts_conn_aware_states[i].aware; + } + } } #endif - ble_gap_event_listener_call(&event); - ble_gap_call_conn_event_cb(&event, evt->connection_handle); +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + pawr_sync_handle = evt->sync_handle; + pawr_adv_handle = evt->adv_handle; +#endif - ble_gap_rd_rem_sup_feat_tx(evt->connection_handle); + if (evt->role == BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE) { + ble_gap_rd_rem_ver_tx(evt->connection_handle); + } else { + ble_gap_rd_rem_sup_feat_tx(evt->connection_handle); + } return 0; #else @@ -2366,6 +2801,46 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) #endif } +void +ble_gap_event_connect_call(uint16_t conn_handle, int status) +{ + struct ble_gap_event event; + uint16_t handle = le16toh(conn_handle); + + memset(&event, 0, sizeof event); + event.type = BLE_GAP_EVENT_CONNECT; + event.connect.status = status; + event.connect.conn_handle = handle; + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.connect.sync_handle = pawr_sync_handle; + event.connect.adv_handle = pawr_adv_handle; +#endif + + ble_gap_event_listener_call(&event); +#if NIMBLE_BLE_CONNECT + ble_gap_call_conn_event_cb(&event, handle); +#endif + +//TODO : Remove duplication of event + event.type = BLE_GAP_EVENT_LINK_ESTAB; + event.link_estab.status = status; + event.link_estab.conn_handle = handle; + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.link_estab.sync_handle = pawr_sync_handle; + event.link_estab.adv_handle = pawr_adv_handle; +#endif + + ble_gap_event_listener_call(&event); +#if NIMBLE_BLE_CONNECT + ble_gap_call_conn_event_cb(&event, handle); +#endif + + ble_hs_hci_util_set_data_len(le16toh(conn_handle), BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MAX, + BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MAX); +} + void ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used_feat *ev) { @@ -2375,11 +2850,48 @@ ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used ble_hs_lock(); conn = ble_hs_conn_find(le16toh(ev->conn_handle)); - if ((conn != NULL) && (ev->status == 0)) { + + ble_hs_unlock(); + + if ((conn != NULL) && (conn->bhc_flags & BLE_HS_CONN_F_MASTER)) { conn->supported_feat = get_le32(ev->features); + ble_gap_rd_rem_ver_tx(ev->conn_handle); + } else { + if ((conn != NULL) && (ev->status == 0)) { + conn->supported_feat = get_le32(ev->features); + } + + if (conn != NULL) { + ble_gap_event_connect_call(ev->conn_handle, ev->status); + slave_conn[ev->conn_handle] = 1; + } } +#endif +} + +void +ble_gap_rx_rd_rem_ver_info_complete(const struct ble_hci_ev_rd_rem_ver_info_cmp *ev) +{ +#if NIMBLE_BLE_CONNECT + struct ble_hs_conn *conn; + + ble_hs_lock(); + + conn = ble_hs_conn_find(le16toh(ev->conn_handle)); ble_hs_unlock(); + + conn->bhc_rd_rem_ver_params.version = ev->version; + conn->bhc_rd_rem_ver_params.manufacturer = ev->manufacturer; + conn->bhc_rd_rem_ver_params.subversion = ev->subversion; + + if ((conn != NULL) && !(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) { + ble_gap_rd_rem_sup_feat_tx(ev->conn_handle); + } else { + if ((conn != NULL) && (ev->status == 0)) { + ble_gap_event_connect_call(ev->conn_handle, ev->status); + } + } #endif } @@ -2436,6 +2948,11 @@ ble_gap_rx_data_len_change(const struct ble_hci_ev_le_subev_data_len_chg *ev) event.data_len_chg.max_tx_time = le16toh(ev->max_tx_time); event.data_len_chg.max_rx_time = le16toh(ev->max_rx_time); + g_max_tx_octets[conn_handle] = event.data_len_chg.max_tx_octets; + g_max_rx_octets[conn_handle] = event.data_len_chg.max_rx_octets; + g_max_tx_time[conn_handle] = event.data_len_chg.max_tx_time; + g_max_rx_time[conn_handle] = event.data_len_chg.max_rx_time; + ble_gap_event_listener_call(&event); ble_gap_call_conn_event_cb(&event, conn_handle); #endif @@ -2445,7 +2962,7 @@ static int32_t ble_gap_master_timer(void) { uint32_t ticks_until_exp; -#if NIMBLE_BLE_SCAN || NIMBLE_BLE_CONNECT +#if NIMBLE_BLE_CONNECT || (NIMBLE_BLE_SCAN && !MYNEWT_VAL(BLE_EXT_ADV)) int rc; #endif @@ -2632,12 +3149,13 @@ ble_gap_wl_busy(void) ble_gap_master.conn.using_wl; } -static int +int ble_gap_wl_tx_add(const ble_addr_t *addr) { struct ble_hci_le_add_whte_list_cp cmd; - if (addr->type > BLE_ADDR_RANDOM) { + if (addr->type > BLE_ADDR_RANDOM && + addr->type != BLE_ADDR_ANONYMOUS) { return BLE_HS_EINVAL; } @@ -2717,7 +3235,8 @@ ble_gap_wl_set(const ble_addr_t *addrs, uint8_t white_list_count) for (i = 0; i < white_list_count; i++) { if (addrs[i].type != BLE_ADDR_PUBLIC && - addrs[i].type != BLE_ADDR_RANDOM) { + addrs[i].type != BLE_ADDR_RANDOM && + addrs[i].type != BLE_ADDR_ANONYMOUS) { rc = BLE_HS_EINVAL; goto done; @@ -2983,12 +3502,14 @@ ble_gap_adv_validate(uint8_t own_addr_type, const ble_addr_t *peer_addr, return BLE_HS_EINVAL; } +#if NIMBLE_BLE_CONNECT /* Don't allow connectable advertising if we won't be able to allocate * a new connection. */ if (!ble_hs_conn_can_alloc()) { return BLE_HS_ENOMEM; } +#endif break; case BLE_GAP_CONN_MODE_DIR: @@ -3043,7 +3564,7 @@ ble_gap_adv_start(uint8_t own_addr_type, const ble_addr_t *direct_addr, goto done; } -#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) && NIMBLE_BLE_CONNECT ble_adv_reattempt.type = 0; ble_adv_reattempt.own_addr_type = own_addr_type; @@ -3193,7 +3714,7 @@ ble_gap_adv_set_fields(const struct ble_hs_adv_fields *adv_fields) if (!ble_hs_is_enabled()) { return BLE_HS_EDISABLED; } -#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) && NIMBLE_BLE_CONNECT memcpy(&ble_adv_reattempt.fields, adv_fields, sizeof( struct ble_hs_adv_fields)); #endif @@ -3249,45 +3770,38 @@ ble_gap_adv_active(void) #if MYNEWT_VAL(BLE_EXT_ADV) static int -ble_gap_ext_adv_params_tx(uint8_t instance, - const struct ble_gap_ext_adv_params *params, - int8_t *selected_tx_power) - +ble_gap_set_ext_adv_params(struct ble_hci_le_set_ext_adv_params_cp *cmd, + uint8_t instance, const struct ble_gap_ext_adv_params *params, + int8_t *selected_tx_power) { - struct ble_hci_le_set_ext_adv_params_cp cmd; - struct ble_hci_le_set_ext_adv_params_rp rsp; - int rc; - - memset(&cmd, 0, sizeof(cmd)); - - cmd.adv_handle = instance; + cmd->adv_handle = instance; if (params->connectable) { - cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE; + cmd->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE; } if (params->scannable) { - cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE; + cmd->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE; } if (params->directed) { - cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED; - cmd.peer_addr_type = params->peer.type; - memcpy(cmd.peer_addr, params->peer.val, BLE_DEV_ADDR_LEN); + cmd->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED; + cmd->peer_addr_type = params->peer.type; + memcpy(cmd->peer_addr, params->peer.val, BLE_DEV_ADDR_LEN); } if (params->high_duty_directed) { - cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED; + cmd->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED; } if (params->anonymous) { - cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV; + cmd->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV; } if (params->include_tx_power) { - cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR; + cmd->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR; } if (params->legacy_pdu) { - cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY; + cmd->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY; /* check right away if the applied configuration is valid before handing * the command to the controller to improve error reporting */ - switch (cmd.props) { + switch (cmd->props) { case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_IND: case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_LD_DIR: case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_HD_DIR: @@ -3302,38 +3816,96 @@ ble_gap_ext_adv_params_tx(uint8_t instance, /* Fill optional fields if application did not specify them. */ if (params->itvl_min == 0 && params->itvl_max == 0) { /* TODO for now limited to legacy values*/ - put_le24(cmd.pri_itvl_min, BLE_GAP_ADV_FAST_INTERVAL1_MIN); - put_le24(cmd.pri_itvl_max, BLE_GAP_ADV_FAST_INTERVAL2_MAX); + put_le24(cmd->pri_itvl_min, BLE_GAP_ADV_FAST_INTERVAL1_MIN); + put_le24(cmd->pri_itvl_max, BLE_GAP_ADV_FAST_INTERVAL2_MAX); } else { - put_le24(cmd.pri_itvl_min, params->itvl_min); - put_le24(cmd.pri_itvl_max, params->itvl_max); + put_le24(cmd->pri_itvl_min, params->itvl_min); + put_le24(cmd->pri_itvl_max, params->itvl_max); } if (params->channel_map == 0) { - cmd.pri_chan_map = BLE_GAP_ADV_DFLT_CHANNEL_MAP; + cmd->pri_chan_map = BLE_GAP_ADV_DFLT_CHANNEL_MAP; } else { - cmd.pri_chan_map = params->channel_map; + cmd->pri_chan_map = params->channel_map; } /* Zero is the default value for filter policy and high duty cycle */ - cmd.filter_policy = params->filter_policy; - cmd.tx_power = params->tx_power; + cmd->filter_policy = params->filter_policy; + cmd->tx_power = params->tx_power; if (params->legacy_pdu) { - cmd.pri_phy = BLE_HCI_LE_PHY_1M; - cmd.sec_phy = BLE_HCI_LE_PHY_1M; + cmd->pri_phy = BLE_HCI_LE_PHY_1M; + cmd->sec_phy = BLE_HCI_LE_PHY_1M; } else { - cmd.pri_phy = params->primary_phy; - cmd.sec_phy = params->secondary_phy; + cmd->pri_phy = params->primary_phy; + cmd->sec_phy = params->secondary_phy; + } + + cmd->own_addr_type = params->own_addr_type; + cmd->sec_max_skip = 0; + cmd->sid = params->sid; + cmd->scan_req_notif = params->scan_req_notif; + + return 0; +} + +static int +ble_gap_ext_adv_params_tx_v1(uint8_t instance, + const struct ble_gap_ext_adv_params *params, + int8_t *selected_tx_power) +{ + struct ble_hci_le_set_ext_adv_params_cp cmd; + struct ble_hci_le_set_ext_adv_params_rp rsp; + int rc; + + memset(&cmd, 0, sizeof(cmd)); + + rc = ble_gap_set_ext_adv_params(&cmd, instance, params, selected_tx_power); + + if (rc != 0) { + return rc; + } + + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM), + &cmd, sizeof(cmd), &rsp, sizeof(rsp)); + + if (rc != 0) { + return rc; + } + + if (selected_tx_power) { + *selected_tx_power = rsp.tx_power; + } + + return 0; + +} + +#if MYNEWT_VAL(BLE_EXT_ADV_V2) +static int +ble_gap_ext_adv_params_tx_v2(uint8_t instance, + const struct ble_gap_ext_adv_params *params, + int8_t *selected_tx_power) +{ + + struct ble_hci_le_set_ext_adv_params_v2_cp cmd; + struct ble_hci_le_set_ext_adv_params_rp rsp; + int rc; + + memset(&cmd, 0, sizeof(cmd)); + + rc = ble_gap_set_ext_adv_params(&(cmd.cmd), instance, params, selected_tx_power); + + if (rc != 0) { + return rc; } - cmd.own_addr_type = params->own_addr_type; - cmd.sec_max_skip = 0; - cmd.sid = params->sid; - cmd.scan_req_notif = params->scan_req_notif; + cmd.pri_phy_opt = params->primary_phy_opt; + cmd.sec_phy_opt = params->secondary_phy_opt; rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, - BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM), + BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM_V2), &cmd, sizeof(cmd), &rsp, sizeof(rsp)); if (rc != 0) { @@ -3346,6 +3918,35 @@ ble_gap_ext_adv_params_tx(uint8_t instance, return 0; } +#endif + +static int +ble_gap_ext_adv_params_tx(uint8_t instance, + const struct ble_gap_ext_adv_params *params, + int8_t *selected_tx_power) +{ + int rc = 0; + +#if MYNEWT_VAL(BLE_EXT_ADV_V2) + struct ble_hs_hci_sup_cmd sup_cmd; + sup_cmd = ble_hs_hci_get_hci_supported_cmd(); + + /* Return Error if phy is non-zero and controller doesn't support V2 */ + if (!((sup_cmd.commands[46] & 0x04) != 0) && + (params->primary_phy_opt || params->secondary_phy_opt)) { + return BLE_HS_EINVAL; + } + + if ((sup_cmd.commands[46] & 0x04) != 0) { + rc = ble_gap_ext_adv_params_tx_v2(instance, params, selected_tx_power); + return rc; + } +#endif + + rc = ble_gap_ext_adv_params_tx_v1(instance, params, selected_tx_power); + + return rc; +} static int ble_gap_ext_adv_params_validate(const struct ble_gap_ext_adv_params *params) @@ -3428,7 +4029,7 @@ ble_gap_ext_adv_configure(uint8_t instance, return rc; } -#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) && NIMBLE_BLE_CONNECT ble_adv_reattempt.instance = instance; memcpy(&ble_adv_reattempt.params, params, sizeof(struct ble_gap_ext_adv_params)); @@ -3447,10 +4048,12 @@ ble_gap_ext_adv_configure(uint8_t instance, ble_hs_lock(); +#if NIMBLE_BLE_ADVERTISE || NIMBLE_BLE_CONNECT if (ble_gap_adv_active_instance(instance)) { ble_hs_unlock(); return BLE_HS_EBUSY; } +#endif rc = ble_gap_ext_adv_params_tx(instance, params, selected_tx_power); if (rc) { @@ -3562,7 +4165,7 @@ ble_gap_ext_adv_start(uint8_t instance, int duration, int max_events) return BLE_HS_EDISABLED; } -#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) && NIMBLE_BLE_CONNECT ble_adv_reattempt.type = 1; ble_adv_reattempt.instance = instance; ble_adv_reattempt.duration = duration; @@ -3663,14 +4266,18 @@ ble_gap_ext_adv_stop_no_lock(uint8_t instance) struct ble_hci_le_set_ext_adv_enable_cp *cmd; uint8_t buf[sizeof(*cmd) + sizeof(cmd->sets[0])]; uint16_t opcode; +#if NIMBLE_BLE_ADVERTISE || NIMBLE_BLE_CONNECT bool active; +#endif int rc; if (!ble_gap_slave[instance].configured) { return BLE_HS_EINVAL; } +#if NIMBLE_BLE_ADVERTISE || NIMBLE_BLE_CONNECT active = ble_gap_adv_active_instance(instance); +#endif BLE_HS_LOG(INFO, "GAP procedure initiated: stop extended advertising.\n"); @@ -3691,11 +4298,15 @@ ble_gap_ext_adv_stop_no_lock(uint8_t instance) ble_gap_slave[instance].op = BLE_GAP_OP_NULL; +#if NIMBLE_BLE_ADVERTISE || NIMBLE_BLE_CONNECT if (!active) { return BLE_HS_EALREADY; } else { return 0; } +#endif + + return 0; } int @@ -3855,7 +4466,7 @@ ble_gap_ext_adv_set_data(uint8_t instance, struct os_mbuf *data) goto done; } -#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) && NIMBLE_BLE_CONNECT uint16_t len = OS_MBUF_PKTLEN(data); ble_adv_reattempt.type = 1; @@ -4051,7 +4662,11 @@ ble_gap_periodic_adv_params_tx(uint8_t instance, const struct ble_gap_periodic_adv_params *params) { +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + struct ble_hci_le_set_periodic_adv_params_v2 cmd; +#else struct ble_hci_le_set_periodic_adv_params_cp cmd; +#endif uint16_t opcode; cmd.adv_handle = instance; @@ -4072,8 +4687,19 @@ ble_gap_periodic_adv_params_tx(uint8_t instance, cmd.props = 0; } - opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS); +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + cmd.num_subevents = params->num_subevents; + cmd.subevent_interval = params->subevent_interval; + cmd.response_slot_delay = params->response_slot_delay; + cmd.response_slot_spacing = params->response_slot_spacing; + cmd.num_response_slots = params->num_response_slots; +#endif +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS_V2); +#else + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS); +#endif return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); } @@ -4110,7 +4736,7 @@ ble_gap_periodic_adv_configure(uint8_t instance, rc = ble_gap_periodic_adv_params_validate(params); if (rc) { - return rc; + return rc; } ble_hs_lock(); @@ -4509,6 +5135,18 @@ ble_gap_periodic_adv_sync_create(const ble_addr_t *addr, uint8_t adv_sid, return BLE_HS_ENOMEM; } +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) && NIMBLE_BLE_CONNECT + ble_conn_reattempt.adv_sid = adv_sid; + + if (addr != NULL ) { + memcpy(&ble_conn_reattempt.periodic_addr, addr, sizeof(ble_addr_t)); + } + if (params != NULL ) { + memcpy(&ble_conn_reattempt.periodic_params, params, sizeof(struct ble_gap_periodic_sync_params)); + } + ble_conn_reattempt.cb = cb; + ble_conn_reattempt.cb_arg = cb_arg; +#endif ble_npl_event_init(&psync->lost_ev, ble_gap_npl_sync_lost, psync); if (addr) { @@ -4533,7 +5171,11 @@ ble_gap_periodic_adv_sync_create(const ble_addr_t *addr, uint8_t adv_sid, cmd.sid = adv_sid; cmd.skip = params->skip; cmd.sync_timeout = htole16(params->sync_timeout); +#if MYNEWT_VAL(BLE_AOA_AOD) + cmd.sync_cte_type = params->sync_cte_type; +#else cmd.sync_cte_type = 0x00; +#endif opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC); rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); @@ -4781,17 +5423,26 @@ periodic_adv_transfer_enable(uint16_t conn_handle, opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER_PARAMS); + memset(&cmd, 0, sizeof(cmd)); cmd.conn_handle = htole16(conn_handle); - cmd.sync_cte_type = 0x00; - cmd.mode = params->reports_disabled ? 0x01 : 0x02; + + if (params != NULL) { +#if MYNEWT_VAL(BLE_AOA_AOD) + cmd.sync_cte_type = params->sync_cte_type; +#else + cmd.sync_cte_type = 0x00; +#endif + cmd.mode = params->reports_disabled ? 0x01 : 0x02; #if MYNEWT_VAL(BLE_PERIODIC_ADV_ENH) - if (params->filter_duplicates) - cmd.mode = 0x03; + if (!params->reports_disabled && params->filter_duplicates) { + cmd.mode = 0x03; + } #endif - cmd.skip = htole16(params->skip); - cmd.sync_timeout = htole16(params->sync_timeout); + cmd.skip = htole16(params->skip); + cmd.sync_timeout = htole16(params->sync_timeout); + } rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), &rsp, sizeof(rsp)); if (!rc) { @@ -4816,7 +5467,11 @@ periodic_adv_set_default_sync_params(const struct ble_gap_periodic_sync_params * memset(&cmd, 0, sizeof(cmd)); if (params != NULL) { +#if MYNEWT_VAL(BLE_AOA_AOD) + cmd.sync_cte_type = params->sync_cte_type; +#else cmd.sync_cte_type = 0x00; +#endif cmd.mode = params->reports_disabled ? 0x01 : 0x02; #if MYNEWT_VAL(BLE_PERIODIC_ADV_ENH) @@ -4973,6 +5628,157 @@ ble_gap_read_periodic_adv_list_size(uint8_t *per_adv_list_size) return 0; } +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +static int +ble_gap_calc_periodic_adv_data_size(uint8_t num_subevents, + const struct ble_gap_set_periodic_adv_subev_data_params *params) { + int len = 0; + const struct ble_gap_set_periodic_adv_subev_data_params *param; + int raw_subev_size = sizeof(*param) - sizeof(struct os_mbuf*); + + for(int i = 0; i < num_subevents; i++) { + param = params + i; + len += raw_subev_size; + len += OS_MBUF_PKTLEN(param->data); + } + return len; +} +int +ble_gap_set_periodic_adv_subev_data(uint8_t instance, uint8_t num_subevents, + const struct ble_gap_set_periodic_adv_subev_data_params *params) +{ + struct ble_hci_le_set_periodic_adv_subev_data_cp *cmd; + struct periodic_adv_subevents *subevents; + uint8_t len = ble_gap_calc_periodic_adv_data_size(num_subevents, params); + uint8_t buf[len + 2]; + uint16_t opcode; + uint16_t subev_data_len; + int rc; + + if (instance >= BLE_ADV_INSTANCES) { + rc = BLE_HS_EINVAL; + goto done; + } + + if (!ble_hs_is_enabled()) { + rc = BLE_HS_EDISABLED; + goto done; + } + + /* Check if we can set all of data in one hci command. */ + if ((len + 2) >= 0xff) { + rc = BLE_HS_EINVAL; + goto done; + } + + ble_hs_lock(); + + /* Periodic advertising cannot start unless it is configured before */ + if (!ble_gap_slave[instance].periodic_configured) { + ble_hs_unlock(); + rc = BLE_HS_EINVAL; + goto done; + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_SUBEV_DATA); + + cmd = (void *) buf; + subevents = cmd->subevents; + + cmd->adv_handle = instance; + cmd->num_subevents = num_subevents; + + for (int i = 0; i < num_subevents; i++) { + subevents->subevent = params[i].subevent; + subevents->response_slot_start = params[i].response_slot_start; + subevents->response_slot_count = params[i].response_slot_count; + ble_hs_mbuf_to_flat(params[i].data, subevents->subevent_data, OS_MBUF_PKTLEN(params[i].data), + (void*)&subev_data_len); + subevents->subevent_data_length = OS_MBUF_PKTLEN(params[i].data); + subevents = (struct periodic_adv_subevents *)( + (uint32_t)subevents + sizeof(struct periodic_adv_subevents) + subev_data_len); + } + + rc = ble_hs_hci_cmd_tx(opcode, cmd, len + 2, NULL, 0); + if (rc != 0) { + ble_hs_unlock(); + goto done; + } + + ble_gap_slave[instance].periodic_op = BLE_GAP_OP_S_PERIODIC_ADV; + + ble_hs_unlock(); + +done: + for (int i = 0; i < num_subevents; i++) { + os_mbuf_free_chain(params[i].data); + } + return rc; +} + +int ble_gap_periodic_adv_set_response_data(uint16_t sync_handle, + struct ble_gap_periodic_adv_response_params *param, + struct os_mbuf *data) +{ + struct ble_hci_le_set_periodic_adv_response_data *cmd; + uint16_t opcode; + int len = sizeof(*cmd); + int data_len = 0; + if (data) { + data_len = OS_MBUF_PKTLEN(data); + } + uint8_t buf[len + data_len]; + + //!TODO: Check if we can set all of data in one hci command. + + cmd = (void *) buf; + + (void)memset(cmd, 0, sizeof(*cmd)); + put_le16(&cmd->sync_handle, sync_handle); + put_le16(&cmd->request_event, param->request_event); + cmd->request_subevent = param->request_subevent; + cmd->response_subevent = param->response_subevent; + cmd->response_slot = param->response_slot; + cmd->response_data_length = data_len; + if (data_len) { + ble_hs_mbuf_to_flat(data, cmd->response_data, data_len, NULL); + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_RESPONSE_DATA); + + return ble_hs_hci_cmd_tx(opcode, cmd, len + data_len, NULL, 0); +} + +int ble_gap_periodic_adv_sync_subev(uint16_t sync_handle, uint8_t include_tx_power, + uint8_t num_subevents, uint8_t *subevents) +{ + struct ble_hci_le_set_periodic_adv_sync_subevent *cmd; + struct ble_hci_le_set_periodic_adv_sync_subevent_rp rsp; + struct ble_hs_periodic_sync *psync; + uint8_t cmd_buf[sizeof(*cmd) + num_subevents]; + uint16_t opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_SYNC_SUBEVENT); + int rc; + + psync = ble_hs_periodic_sync_find_by_handle(sync_handle); + if (!psync) { + ble_hs_unlock(); + return BLE_HS_ENOTCONN; + } + + cmd = (void *)cmd_buf; + + put_le16(&cmd->sync_handle, sync_handle); + put_le16(&cmd->periodic_adv_properties, (uint16_t)(include_tx_power << 6)); + cmd->num_subevents = num_subevents; + memcpy(cmd->subevents, subevents, num_subevents); + + rc = ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + num_subevents, &rsp, sizeof(rsp)); + if (!rc) { + BLE_HS_DBG_ASSERT(le16toh(rsp.sync_handle) == sync_handle); + } + return rc; +} +#endif #endif /***************************************************************************** @@ -5054,7 +5860,201 @@ ble_gap_ext_disc_enable_tx(uint8_t enable, uint8_t filter_duplicates, &cmd, sizeof(cmd), NULL, 0); } #endif + +#if MYNEWT_VAL(BLE_AOA_AOD) +int +ble_gap_set_connless_cte_transmit_params(uint8_t instance, const struct ble_gap_periodic_adv_cte_params *params) +{ + uint8_t buf[sizeof(struct ble_hci_le_set_connless_cte_tx_params_cp) + + params->switching_pattern_length]; + struct ble_hci_le_set_connless_cte_tx_params_cp *cmd = (void *)buf; + uint8_t len = sizeof(buf); + uint16_t opcode; + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_CONNLESS_CTE_TX_PARAMS); + + cmd->adv_handle = instance; + cmd->cte_length = params->cte_length; + cmd->cte_type = params->cte_type; + cmd->cte_count = params->cte_count; + cmd->switching_pattern_len = params->switching_pattern_length; + memcpy(cmd->switching_pattern, params->antenna_ids, params->switching_pattern_length); + + return ble_hs_hci_cmd_tx(opcode, cmd, len, NULL, 0); +} + +int +ble_gap_set_connless_cte_transmit_enable(uint8_t instance, uint8_t cte_enable) +{ + struct ble_hci_le_set_connless_cte_tx_enable_cp cmd; + uint16_t opcode; + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_CONNLESS_CTE_TX_ENABLE); + + cmd.adv_handle = instance; + cmd.cte_enable = cte_enable; + + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); +} + +int +ble_gap_set_connless_iq_sampling_enable(uint16_t sync_handle, uint8_t sampling_enable, uint8_t max_sampled_ctes, + const struct ble_gap_cte_sampling_params *cte_sampling_params) +{ + uint8_t buf[sizeof(struct ble_hci_le_set_connless_iq_sampling_enable_cp) + + cte_sampling_params->switching_pattern_length]; + struct ble_hci_le_set_connless_iq_sampling_enable_cp *cmd = (struct ble_hci_le_set_connless_iq_sampling_enable_cp*)buf; + struct ble_hci_le_set_connless_iq_sampling_enable_rp rsp; + uint8_t len = sizeof(buf); + uint16_t opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_CONNLESS_IQ_SAMPLING_ENABLE); + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + cmd->sync_handle = htole16(sync_handle); + cmd->sampling_enable = sampling_enable; + cmd->max_sampled_ctes = max_sampled_ctes; + cmd->slot_durations = cte_sampling_params->slot_durations; + cmd->switching_pattern_len = cte_sampling_params->switching_pattern_length; + memcpy(cmd->antenna_ids, cte_sampling_params->antenna_ids, cte_sampling_params->switching_pattern_length); + + return ble_hs_hci_cmd_tx(opcode, cmd, len, &rsp, sizeof(rsp)); +} + +int +ble_gap_set_conn_cte_recv_param(uint16_t conn_handle, uint8_t sampling_enable, const struct ble_gap_cte_sampling_params *cte_sampling_params) +{ + uint8_t buf[sizeof(struct ble_hci_le_set_conn_cte_rx_params_cp) + cte_sampling_params->switching_pattern_length]; + struct ble_hci_le_set_conn_cte_rx_params_cp *cmd = (void *)buf; + struct ble_hci_le_set_conn_cte_rx_params_rp rsp; + uint8_t len = sizeof(buf); + uint16_t opcode; + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_CONN_CTE_RX_PARAMS); + + cmd->conn_handle = conn_handle; + cmd->sampling_enable = sampling_enable; + cmd->slot_durations = cte_sampling_params->slot_durations; + cmd->switching_pattern_len = cte_sampling_params->switching_pattern_length; + memcpy(cmd->antenna_ids, cte_sampling_params->antenna_ids, cte_sampling_params->switching_pattern_length); + + return ble_hs_hci_cmd_tx(opcode, cmd, len, &rsp, sizeof(rsp)); +} + +int +ble_gap_set_conn_cte_transmit_param(uint16_t conn_handle, uint8_t cte_types, uint8_t switching_pattern_len, const uint8_t *antenna_ids) +{ + uint8_t buf[sizeof(struct ble_hci_le_set_conn_cte_tx_params_cp) + switching_pattern_len]; + struct ble_hci_le_set_conn_cte_tx_params_cp *cmd = (void *)buf; + struct ble_hci_le_set_conn_cte_tx_params_rp rsp; + uint8_t len = sizeof(buf); + uint16_t opcode; + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_CONN_CTE_TX_PARAMS); + + cmd->conn_handle = htole16(conn_handle); + cmd->cte_types = cte_types; + if (cmd->cte_types != BIT(0) && (switching_pattern_len == 0 || antenna_ids == NULL)) { + BLE_HS_LOG(ERROR, "Invalid antenna_ids!\n"); + return BLE_HS_EINVAL; + } + cmd->switching_pattern_len = switching_pattern_len; + memcpy(cmd->antenna_ids, antenna_ids, switching_pattern_len); + + + return ble_hs_hci_cmd_tx(opcode, cmd, len, &rsp, sizeof(rsp)); +} + +int +ble_gap_conn_cte_req_enable(uint16_t conn_handle, uint8_t enable, uint16_t cte_request_interval, + uint8_t requested_cte_length, uint8_t requested_cte_type) +{ + uint8_t buf[sizeof(struct ble_gap_conn_cte_req_enable_cp)]; + struct ble_gap_conn_cte_req_enable_cp *cmd = (void *)buf; + struct ble_gap_conn_cte_req_enable_rp rsp; + uint8_t len = sizeof(buf); + uint16_t opcode; + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_CONN_CTE_REQ_ENABLE); + + cmd->conn_handle = htole16(conn_handle); + cmd->enable = enable; + cmd->cte_request_interval = htole16(cte_request_interval); + cmd->requested_cte_length = requested_cte_length; + cmd->requested_cte_type = requested_cte_type; + + return ble_hs_hci_cmd_tx(opcode, cmd, len, &rsp, sizeof(rsp)); +} + +int +ble_gap_conn_cte_rsp_enable(uint16_t conn_handle, uint8_t enable) +{ + struct ble_hci_le_set_conn_cte_rsp_enable_cp cmd; + struct ble_hci_le_set_conn_cte_rsp_enable_rp rsp; + uint16_t opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_CONN_CTE_RESP_ENABLE); + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + cmd.conn_handle = htole16(conn_handle); + cmd.enable = enable; + + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), &rsp, sizeof(rsp)); +} + +int +ble_gap_read_antenna_information(uint8_t *switch_sampling_rates, uint8_t *num_antennae, uint8_t *max_switch_pattern_len, uint8_t *max_cte_len) +{ + struct ble_hci_le_rd_antenna_info_rp rsp; + uint16_t opcode; + int rc = 0; + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_ANTENNA_INFO); + + rc = ble_hs_hci_cmd_tx(opcode, NULL, 0, &rsp, sizeof(rsp)); + + if (rc != 0) { + return rc; + } + + *switch_sampling_rates = rsp.switch_sampling_rates; + *num_antennae = rsp.num_antennae; + *max_switch_pattern_len = rsp.max_switch_pattern_len; + *max_cte_len = rsp.max_cte_len; + + return 0; +} + +#endif // MYNEWT_VAL(BLE_AOA_AOD) + #endif + #if NIMBLE_BLE_SCAN #if !MYNEWT_VAL(BLE_EXT_ADV) static int @@ -5112,10 +6112,12 @@ ble_gap_disc_cancel_no_lock(void) STATS_INC(ble_gap_stats, discover_cancel); +#if !MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN) if (!ble_gap_disc_active()) { rc = BLE_HS_EALREADY; goto done; } +#endif rc = ble_gap_disc_disable_tx(); if (rc != 0) { @@ -5258,6 +6260,7 @@ ble_gap_ext_disc(uint8_t own_addr_type, uint16_t duration, uint16_t period, if (uncoded_params) { ble_gap_ext_scan_params_to_hci(uncoded_params, &ucp); ble_gap_ext_disc_fill_dflts(limited, &ucp); + ble_gap_master.disc.observer = !uncoded_params->disable_observer_mode; /* XXX: We should do it only once */ if (!uncoded_params->passive) { @@ -5271,6 +6274,7 @@ ble_gap_ext_disc(uint8_t own_addr_type, uint16_t duration, uint16_t period, if (coded_params) { ble_gap_ext_scan_params_to_hci(coded_params, &cp); ble_gap_ext_disc_fill_dflts(limited, &cp); + ble_gap_master.disc.observer = !coded_params->disable_observer_mode; /* XXX: We should do it only once */ if (!coded_params->passive) { @@ -5384,6 +6388,7 @@ ble_gap_disc(uint8_t own_addr_type, int32_t duration_ms, p.itvl = disc_params->itvl; p.passive = disc_params->passive; p.window = disc_params->window; + p.disable_observer_mode = disc_params->disable_observer_mode; if (duration_ms == BLE_HS_FOREVER) { duration_ms = 0; @@ -5440,6 +6445,7 @@ ble_gap_disc(uint8_t own_addr_type, int32_t duration_ms, } ble_gap_master.disc.limited = params.limited; + ble_gap_master.disc.observer = !params.disable_observer_mode; ble_gap_master.cb = cb; ble_gap_master.cb_arg = cb_arg; @@ -5559,64 +6565,300 @@ ble_gap_subrate_req(uint16_t conn_handle, uint16_t subrate_min, uint16_t subrate struct ble_hci_le_subrate_req_cp cmd; uint16_t opcode; - cmd.conn_handle = htole16(conn_handle); - cmd.subrate_min = htole16(subrate_min); - cmd.subrate_max = htole16(subrate_max); - cmd.max_latency = htole16(max_latency); - cmd.cont_num = htole16(cont_num); - cmd.supervision_tmo = htole16(supervision_tmo); + cmd.conn_handle = htole16(conn_handle); + cmd.subrate_min = htole16(subrate_min); + cmd.subrate_max = htole16(subrate_max); + cmd.max_latency = htole16(max_latency); + cmd.cont_num = htole16(cont_num); + cmd.supervision_tmo = htole16(supervision_tmo); + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SUBRATE_REQ); + + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); +} +#endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) || (MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_ROLE_CENTRAL)) +static int +ble_gap_check_conn_params(uint8_t phy, const struct ble_gap_conn_params *params) +{ + if (phy != BLE_HCI_LE_PHY_2M) { + /* Check scan interval and window */ + if ((params->scan_itvl < BLE_HCI_SCAN_ITVL_MIN) || + (params->scan_itvl > BLE_HCI_SCAN_ITVL_MAX) || + (params->scan_window < BLE_HCI_SCAN_WINDOW_MIN) || + (params->scan_window > BLE_HCI_SCAN_WINDOW_MAX) || + (params->scan_itvl < params->scan_window)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + /* Check connection interval min */ + if ((params->itvl_min < BLE_HCI_CONN_ITVL_MIN) || + (params->itvl_min > BLE_HCI_CONN_ITVL_MAX)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + /* Check connection interval max */ + if ((params->itvl_max < BLE_HCI_CONN_ITVL_MIN) || + (params->itvl_max > BLE_HCI_CONN_ITVL_MAX) || + (params->itvl_max < params->itvl_min)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check connection latency */ + if (params->latency > BLE_HCI_CONN_LATENCY_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check supervision timeout */ + if ((params->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) || + (params->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check connection event length */ + if (params->min_ce_len > params->max_ce_len) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return 0; +} +#endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +static int +ble_gap_ext_conn_create_conn_synced_tx(uint8_t own_addr_type, + uint8_t advertising_handle, uint8_t subevent, + const ble_addr_t *peer_addr, uint8_t phy_mask, + const struct ble_gap_conn_params *phy_1m_conn_params, + const struct ble_gap_conn_params *phy_2m_conn_params, + const struct ble_gap_conn_params *phy_coded_conn_params) +{ + struct ble_hci_le_ext_create_conn_v2_cp *cmd; + struct conn_params *params; + uint8_t buf[sizeof(*cmd) + 3 * sizeof(*params)]; + uint8_t len = sizeof(*cmd); + int rc; + + /* Check own addr type */ + if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (phy_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK | + BLE_HCI_LE_PHY_2M_PREF_MASK | + BLE_HCI_LE_PHY_CODED_PREF_MASK)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + cmd = (void *) buf; + params = cmd->conn_params; + if (peer_addr == NULL) { + /* Application wants to connect to any device in the white list. The + * peer address type and peer address fields are ignored by the + * controller; fill them with dummy values. + */ + cmd->filter_policy = BLE_HCI_CONN_FILT_USE_WL; + cmd->peer_addr_type = 0; + memset(cmd->peer_addr, 0, sizeof(cmd->peer_addr)); + } else { + /* Check peer addr type */ + if (peer_addr->type > BLE_HCI_CONN_PEER_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + cmd->filter_policy = BLE_HCI_CONN_FILT_NO_WL; + cmd->peer_addr_type = peer_addr->type; + memcpy(cmd->peer_addr, peer_addr->val, sizeof(cmd->peer_addr)); + } + + cmd->own_addr_type = own_addr_type; + cmd->init_phy_mask = phy_mask; + + cmd->adv_handle = advertising_handle; + cmd->subevent = subevent; + + if (phy_mask & BLE_GAP_LE_PHY_1M_MASK) { + rc = ble_gap_check_conn_params(BLE_HCI_LE_PHY_1M, phy_1m_conn_params); + if (rc) { + return rc; + } + + params->scan_itvl = htole16(phy_1m_conn_params->scan_itvl); + params->scan_window = htole16(phy_1m_conn_params->scan_window); + params->conn_min_itvl = htole16(phy_1m_conn_params->itvl_min); + params->conn_max_itvl = htole16(phy_1m_conn_params->itvl_max); + params->conn_latency = htole16(phy_1m_conn_params->latency); + params->supervision_timeout = htole16(phy_1m_conn_params->supervision_timeout); + params->min_ce = htole16(phy_1m_conn_params->min_ce_len); + params->max_ce = htole16(phy_1m_conn_params->max_ce_len); + + params++; + len += sizeof(*params); + } + + if (phy_mask & BLE_GAP_LE_PHY_2M_MASK) { + rc = ble_gap_check_conn_params(BLE_HCI_LE_PHY_2M, phy_2m_conn_params); + if (rc) { + return rc; + } + + params->scan_itvl = htole16(phy_2m_conn_params->scan_itvl); + params->scan_window = htole16(phy_2m_conn_params->scan_window); + params->conn_min_itvl = htole16(phy_2m_conn_params->itvl_min); + params->conn_max_itvl = htole16(phy_2m_conn_params->itvl_max); + params->conn_latency = htole16(phy_2m_conn_params->latency); + params->supervision_timeout = htole16(phy_2m_conn_params->supervision_timeout); + params->min_ce = htole16(phy_2m_conn_params->min_ce_len); + params->max_ce = htole16(phy_2m_conn_params->max_ce_len); + + params++; + len += sizeof(*params); + } + + if (phy_mask & BLE_GAP_LE_PHY_CODED_MASK) { + rc = ble_gap_check_conn_params(BLE_HCI_LE_PHY_CODED, phy_coded_conn_params); + if (rc) { + return rc; + } + + params->scan_itvl = htole16(phy_coded_conn_params->scan_itvl); + params->scan_window = htole16(phy_coded_conn_params->scan_window); + params->conn_min_itvl = htole16(phy_coded_conn_params->itvl_min); + params->conn_max_itvl = htole16(phy_coded_conn_params->itvl_max); + params->conn_latency = htole16(phy_coded_conn_params->latency); + params->supervision_timeout = htole16(phy_coded_conn_params->supervision_timeout); + params->min_ce = htole16(phy_coded_conn_params->min_ce_len); + params->max_ce = htole16(phy_coded_conn_params->max_ce_len); + + params++; + len += sizeof(*params); + } + + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_LE_EXT_CREATE_CONN_V2), + cmd, len, NULL, 0); +} + + +int +ble_gap_connect_with_synced(uint8_t own_addr_type, uint8_t advertising_handle, + uint8_t subevent, const ble_addr_t *peer_addr, + int32_t duration_ms, uint8_t phy_mask, + const struct ble_gap_conn_params *phy_1m_conn_params, + const struct ble_gap_conn_params *phy_2m_conn_params, + const struct ble_gap_conn_params *phy_coded_conn_params, + ble_gap_event_fn *cb, void *cb_arg) +{ + int rc; + + STATS_INC(ble_gap_stats, initiate); + + ble_hs_lock(); + + if (ble_gap_conn_active()) { + rc = BLE_HS_EALREADY; + goto done; + } + + if (ble_gap_disc_active()) { + rc = BLE_HS_EBUSY; + goto done; + } + + if (!ble_hs_is_enabled()) { + rc = BLE_HS_EDISABLED; + goto done; + } + + if (ble_gap_is_preempted()) { + rc = BLE_HS_EPREEMPTED; + goto done; + } + + if (!ble_hs_conn_can_alloc()) { + rc = BLE_HS_ENOMEM; + goto done; + } + + if (peer_addr && + peer_addr->type != BLE_ADDR_PUBLIC && + peer_addr->type != BLE_ADDR_RANDOM && + peer_addr->type != BLE_ADDR_PUBLIC_ID && + peer_addr->type != BLE_ADDR_RANDOM_ID) { + + rc = BLE_HS_EINVAL; + goto done; + } + + if ((phy_mask & BLE_GAP_LE_PHY_1M_MASK) && phy_1m_conn_params == NULL) { + phy_1m_conn_params = &ble_gap_conn_params_dflt; + } - opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SUBRATE_REQ); + if ((phy_mask & BLE_GAP_LE_PHY_2M_MASK) && phy_2m_conn_params == NULL) { + phy_2m_conn_params = &ble_gap_conn_params_dflt; + } - return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); -} -#endif + if ((phy_mask & BLE_GAP_LE_PHY_CODED_MASK) && + phy_coded_conn_params == NULL) { -#if MYNEWT_VAL(BLE_EXT_ADV) -#if MYNEWT_VAL(BLE_ROLE_CENTRAL) -static int -ble_gap_check_conn_params(uint8_t phy, const struct ble_gap_conn_params *params) -{ - if (phy != BLE_HCI_LE_PHY_2M) { - /* Check scan interval and window */ - if ((params->scan_itvl < BLE_HCI_SCAN_ITVL_MIN) || - (params->scan_itvl > BLE_HCI_SCAN_ITVL_MAX) || - (params->scan_window < BLE_HCI_SCAN_WINDOW_MIN) || - (params->scan_window > BLE_HCI_SCAN_WINDOW_MAX) || - (params->scan_itvl < params->scan_window)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } + phy_coded_conn_params = &ble_gap_conn_params_dflt; } - /* Check connection interval min */ - if ((params->itvl_min < BLE_HCI_CONN_ITVL_MIN) || - (params->itvl_min > BLE_HCI_CONN_ITVL_MAX)) { - return BLE_ERR_INV_HCI_CMD_PARMS; + + if (duration_ms == 0) { + duration_ms = BLE_GAP_CONN_DUR_DFLT; } - /* Check connection interval max */ - if ((params->itvl_max < BLE_HCI_CONN_ITVL_MIN) || - (params->itvl_max > BLE_HCI_CONN_ITVL_MAX) || - (params->itvl_max < params->itvl_min)) { - return BLE_ERR_INV_HCI_CMD_PARMS; + + /* The connection creation timeout is not really useful for PAwR. + * The controller will give a result for the connection attempt + * within a periodic interval. We do not know the periodic interval + * used, so disable the timeout. + */ + + /* Verify peer not already connected. */ + if (ble_hs_conn_find_by_addr(peer_addr) != NULL) { + rc = BLE_HS_EDONE; + goto done; } - /* Check connection latency */ - if (params->latency > BLE_HCI_CONN_LATENCY_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; + /* XXX: Verify conn_params. */ + + rc = ble_hs_id_use_addr(own_addr_type); + if (rc != 0) { + goto done; } - /* Check supervision timeout */ - if ((params->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) || - (params->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) { - return BLE_ERR_INV_HCI_CMD_PARMS; + BLE_HS_LOG(INFO, "GAP procedure initiated: extended connect; \n"); + + ble_gap_master.cb = cb; + ble_gap_master.cb_arg = cb_arg; + ble_gap_master.conn.using_wl = peer_addr == NULL; + ble_gap_master.conn.our_addr_type = own_addr_type; + + ble_gap_master.op = BLE_GAP_OP_M_CONN; + + rc = ble_gap_ext_conn_create_conn_synced_tx(own_addr_type,advertising_handle,subevent, peer_addr, phy_mask, + phy_1m_conn_params, phy_2m_conn_params, + phy_coded_conn_params); + if (rc != 0) { + ble_gap_master_reset_state(); + goto done; } - /* Check connection event length */ - if (params->min_ce_len > params->max_ce_len) { - return BLE_ERR_INV_HCI_CMD_PARMS; + rc = 0; + +done: + ble_hs_unlock(); + + if (rc != 0) { + STATS_INC(ble_gap_stats, initiate_fail); } + return rc; - return 0; } +#endif + +#if MYNEWT_VAL(BLE_EXT_ADV) +#if MYNEWT_VAL(BLE_ROLE_CENTRAL) static int ble_gap_ext_conn_create_tx( @@ -5728,7 +6970,60 @@ ble_gap_ext_conn_create_tx( BLE_HCI_OCF_LE_EXT_CREATE_CONN), cmd, len, NULL, 0); } -#endif + +/** + * Initiates a connect procedure. + * + * @param own_addr_type The type of address the stack should use for + * itself during connection establishment. + * o BLE_OWN_ADDR_PUBLIC + * o BLE_OWN_ADDR_RANDOM + * o BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT + * o BLE_OWN_ADDR_RPA_RANDOM_DEFAULT + * @param peer_addr The address of the peer to connect to. + * If this parameter is NULL, the white list + * is used. + * @param duration_ms The duration of the discovery procedure. + * On expiration, the procedure ends and a + * BLE_GAP_EVENT_DISC_COMPLETE event is + * reported. Units are milliseconds. + * @param phy_mask Define on which PHYs connection attempt should + * be done + * @param phy_1m_conn_params Additional arguments specifying the + * particulars of the connect procedure. When + * BLE_GAP_LE_PHY_1M_MASK is set in phy_mask + * this parameter can be specify to null for + * default values. + * @param phy_2m_conn_params Additional arguments specifying the + * particulars of the connect procedure. When + * BLE_GAP_LE_PHY_2M_MASK is set in phy_mask + * this parameter can be specify to null for + * default values. + * @param phy_coded_conn_params Additional arguments specifying the + * particulars of the connect procedure. When + * BLE_GAP_LE_PHY_CODED_MASK is set in + * phy_mask this parameter can be specify to + * null for default values. + * @param cb The callback to associate with this connect + * procedure. When the connect procedure + * completes, the result is reported through + * this callback. If the connect procedure + * succeeds, the connection inherits this + * callback as its event-reporting mechanism. + * @param cb_arg The optional argument to pass to the callback + * function. + * + * @return 0 on success; + * BLE_HS_EALREADY if a connection attempt is + * already in progress; + * BLE_HS_EBUSY if initiating a connection is not + * possible because scanning is in progress; + * BLE_HS_EDONE if the specified peer is already + * connected; + * Other nonzero on error. + */ + +#endif // MYNEWT_VAL(BLE_ROLE_CENTRAL) /** * Initiates a connect procedure. @@ -5811,10 +7106,12 @@ ble_gap_ext_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, goto done; } +#if !MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN) if (ble_gap_disc_active()) { rc = BLE_HS_EBUSY; goto done; } +#endif if (!ble_hs_is_enabled()) { rc = BLE_HS_EDISABLED; @@ -5890,7 +7187,7 @@ ble_gap_ext_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, ble_gap_master.op = BLE_GAP_OP_M_CONN; -#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) && NIMBLE_BLE_CONNECT ble_conn_reattempt.own_addr_type = own_addr_type; if (peer_addr != NULL) { @@ -5902,21 +7199,22 @@ ble_gap_ext_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, } ble_conn_reattempt.duration_ms = duration_ms; + ble_conn_reattempt.phy_mask = phy_mask; if (phy_mask & BLE_GAP_LE_PHY_1M_MASK) { - memcpy(&ble_conn_reattempt.conn_params, + memcpy(&ble_conn_reattempt.conn_params_1m, phy_1m_conn_params, sizeof(struct ble_gap_conn_params)); } if (phy_mask & BLE_GAP_LE_PHY_2M_MASK) { - memcpy(&ble_conn_reattempt.conn_params, + memcpy(&ble_conn_reattempt.conn_params_2m, phy_2m_conn_params, sizeof(struct ble_gap_conn_params)); } if (phy_mask & BLE_GAP_LE_PHY_CODED_MASK) { - memcpy(&ble_conn_reattempt.conn_params, + memcpy(&ble_conn_reattempt.conn_params_coded, phy_coded_conn_params, sizeof(struct ble_gap_conn_params)); } @@ -5988,10 +7286,12 @@ ble_gap_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, goto done; } +#if !MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN) if (ble_gap_disc_active()) { rc = BLE_HS_EBUSY; goto done; } +#endif if (!ble_hs_is_enabled()) { rc = BLE_HS_EDISABLED; @@ -6079,7 +7379,7 @@ ble_gap_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, memset(&bhc_peer_addr, 0, sizeof bhc_peer_addr); } -#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) && NIMBLE_BLE_CONNECT ble_conn_reattempt.own_addr_type = own_addr_type; if (peer_addr != NULL) { ble_conn_reattempt.peer_addr_present = 1; @@ -6092,7 +7392,7 @@ ble_gap_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, } ble_conn_reattempt.duration_ms = duration_ms; - memcpy(&ble_conn_reattempt.conn_params, + memcpy(&ble_conn_reattempt.conn_params_1m, conn_params, sizeof(struct ble_gap_conn_params)); ble_conn_reattempt.cb = cb; @@ -6208,6 +7508,7 @@ ble_gap_multi_connect(struct ble_gap_multi_conn_params *multi_conn_params, #endif // MYNEWT_VAL(BLE_EXT_ADV) scheduling_len_us = multi_conn_params->scheduling_len_us; + /* `scheduling_len_us == 0` is allowed. It indicates that the optimization for this connection * is disabled. The connection interval must be an integer multiple of `common factor`. Note * that the unit of the connection interval is 1.25ms, while the common factor's unit is 0.625ms. @@ -6266,7 +7567,7 @@ ble_gap_multi_connect(struct ble_gap_multi_conn_params *multi_conn_params, multi_conn_params->phy_2m_conn_params, multi_conn_params->phy_coded_conn_params, cb, cb_arg); #else - rc = ble_gap_ext_connect(multi_conn_params->own_addr_type, multi_conn_params->peer_addr, + rc = ble_gap_connect(multi_conn_params->own_addr_type, multi_conn_params->peer_addr, multi_conn_params->duration_ms, multi_conn_params->phy_1m_conn_params, cb, cb_arg); #endif // MYNEWT_VAL(BLE_EXT_ADV) @@ -6764,6 +8065,30 @@ int ble_gap_set_data_len(uint16_t conn_handle, uint16_t tx_octets, uint16_t tx_time) { + /* Check if host has triggered Set data len for same parameters + * which are currently set in controller. + * If yes, then just return event to host indicating success + * since controller will not send any event in this scenario + */ + if (g_max_tx_time[conn_handle] == tx_time && g_max_tx_octets[conn_handle] == tx_octets) { + + struct ble_gap_event event; + + memset(&event, 0, sizeof event); + event.type = BLE_GAP_EVENT_DATA_LEN_CHG; + event.data_len_chg.max_tx_octets = g_max_tx_octets[conn_handle]; + event.data_len_chg.max_rx_octets = g_max_rx_octets[conn_handle]; + event.data_len_chg.max_tx_time = g_max_tx_time[conn_handle]; + event.data_len_chg.max_rx_time = g_max_rx_time[conn_handle]; + event.data_len_chg.conn_handle = conn_handle; + + ble_gap_event_listener_call(&event); +#if NIMBLE_BLE_CONNECT + ble_gap_call_conn_event_cb(&event, conn_handle); +#endif + return 0; + } + return ble_hs_hci_util_set_data_len(conn_handle, tx_octets, tx_time); } @@ -6863,7 +8188,9 @@ done: int ble_gap_dev_authorization(uint16_t conn_handle, bool authorized) { + ble_hs_lock(); struct ble_hs_conn *conn = ble_hs_conn_find(conn_handle); + ble_hs_unlock(); if (conn != NULL) { if (!(conn->bhc_sec_state.authenticated)) { @@ -6935,14 +8262,59 @@ ble_gap_encryption_initiate(uint16_t conn_handle, #endif } +#if NIMBLE_BLE_SM && MYNEWT_VAL(BLE_SMP_ID_RESET) +static void +ble_gap_reset_irk(void) +{ + ble_addr_t oldest_peer_id_addr[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; + struct ble_store_value_local_irk value_local_irk; + struct ble_store_key_local_irk key_local_irk; + uint8_t *local_id = NULL; + int rc, num_peers; + uint8_t tmp_addr[6]; + + ble_store_util_bonded_peers(&oldest_peer_id_addr[0], &num_peers, + MYNEWT_VAL(BLE_STORE_MAX_BONDS)); + + if (num_peers != 0) { + return ; + } + + memset(&key_local_irk, 0, sizeof key_local_irk); + memset(&value_local_irk, 0x0, sizeof value_local_irk); + + ble_hs_id_addr(BLE_ADDR_PUBLIC, (const uint8_t **) &local_id, NULL); + + if (local_id) { + memcpy (key_local_irk.addr.val , local_id, BLE_DEV_ADDR_LEN); + } + + key_local_irk.addr.type = BLE_ADDR_PUBLIC; + + ble_store_delete_local_irk(&key_local_irk); + + ble_hs_pvcy_set_default_irk(); + + //Remove the previous entry pertaining to 00:00:00:00:00:00 address + memset(tmp_addr, 0, 6); + rc = ble_hs_pvcy_remove_entry(0, tmp_addr); + if (rc != 0) { + BLE_HS_LOG(INFO, "Failed to remove old all zero IRK"); + return; + } + + ble_hs_pvcy_set_our_irk(NULL); + + BLE_HS_LOG(INFO,"Local IRK Reset"); +} +#endif + int ble_gap_unpair(const ble_addr_t *peer_addr) { #if NIMBLE_BLE_SM - int rc; - int ltk_rc = 0; - int irk_rc = 0; + int rc, err = 0; struct ble_hs_conn *conn; union ble_store_value value; union ble_store_key key; @@ -6985,32 +8357,46 @@ ble_gap_unpair(const ble_addr_t *peer_addr) // Checking if the device is in ble_store if (!rc) { if (value.sec.irk_present) { + /* We cannot delete entry from resolving list if there is ongoing + * discovery or advertising in progress */ + + if (ble_gap_adv_active() || + ble_gap_disc_active()) { + return BLE_HS_EBUSY; + } + // Delete the IRK as it is Distributed - irk_rc = ble_hs_pvcy_remove_entry(key.sec.peer_addr.type, - key.sec.peer_addr.val); - if (irk_rc != 0) { - BLE_HS_LOG(ERROR, "Error while removing IRK , rc = %x\n",irk_rc); + rc = ble_hs_pvcy_remove_entry(key.sec.peer_addr.type,key.sec.peer_addr.val); + if (rc != 0) { + BLE_HS_LOG(ERROR, "Error while removing IRK , rc = %x\n",rc); } } - if (value.sec.ltk_present || value.sec.irk_present || value.sec.csrk_present) { - // Delete the Peer record from store as LTK is present - ltk_rc = ble_store_util_delete_peer(&key.sec.peer_addr); - if (ltk_rc != 0) { - BLE_HS_LOG(ERROR, "Error while removing LTK , rc = %x\n",ltk_rc); - } + // Delete the Peer record from store as LTK is present + rc = ble_store_util_delete_peer(&key.sec.peer_addr); + if (rc != 0) { + BLE_HS_LOG(ERROR, "Error while removing LTK , rc = %x\n",rc); } - } - else { - rc = ble_store_read(BLE_STORE_OBJ_TYPE_OUR_SEC, &key, &value); - if(!rc) { + } else { + rc = ble_store_read(BLE_STORE_OBJ_TYPE_OUR_SEC, &key, &value); + if (!rc) { ble_store_util_delete_peer(&key.sec.peer_addr); - } - else { - BLE_HS_LOG(ERROR,"No record found for the given address in ble store , rc = %x\n",rc); - return rc; - } + } else { + BLE_HS_LOG(ERROR,"No record found for the given address in ble store , rc = %x\n",rc); + err = rc ; + } + } +#if MYNEWT_VAL(BLE_SMP_ID_RESET) + /* There are tracking risks associated with using a fixed or static IRK. + * A best-practices approach, when all pairing and bonding records are deleted, + * assign a new randomly-generated IRK. + */ + ble_gap_reset_irk(); +#endif + + if (err) { + return err; } return 0; @@ -7022,7 +8408,7 @@ ble_gap_unpair(const ble_addr_t *peer_addr) int ble_gap_unpair_oldest_peer(void) { -#if NIMBLE_BLE_SM +#if NIMBLE_BLE_SM && MYNEWT_VAL(BLE_STORE_MAX_BONDS) ble_addr_t oldest_peer_id_addr[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; int num_peers; int rc; @@ -7134,6 +8520,7 @@ ble_gap_enc_event(uint16_t conn_handle, int status, /* If encryption succeeded and encryption has been restored for bonded device, * notify gatt server so it has chance to send notification/indication if needed. */ +#if MYNEWT_VAL(BLE_GATTS) if (security_restored) { ble_gatts_bonding_restored(conn_handle); #if MYNEWT_VAL(BLE_GATT_CACHING) @@ -7141,17 +8528,22 @@ ble_gap_enc_event(uint16_t conn_handle, int status, #endif return; } +#endif /* If this is fresh pairing and bonding has been established, * notify gatt server about that so previous subscriptions (before bonding) * can be stored. */ +#if MYNEWT_VAL(BLE_GATTS) if (bonded) { ble_gatts_bonding_established(conn_handle); #if MYNEWT_VAL(BLE_GATT_CACHING) ble_gattc_cache_conn_bonding_established(conn_handle); #endif } + +#endif + #endif } @@ -7175,14 +8567,23 @@ int ble_gap_repeat_pairing_event(const struct ble_gap_repeat_pairing *rp) { #if NIMBLE_BLE_SM && NIMBLE_BLE_CONNECT + int rc; + +#if MYNEWT_VAL(BLE_HANDLE_REPEAT_PAIRING_DELETION) + /* Delete pairing internally instead of expecting host to do so */ + struct ble_gap_conn_desc desc; + rc = ble_gap_conn_find(rp->conn_handle, &desc); + assert(rc == 0); + ble_store_util_delete_peer(&desc.peer_id_addr); + return BLE_GAP_REPEAT_PAIRING_RETRY; +#else struct ble_gap_event event; - int rc; - memset(&event, 0, sizeof event); event.type = BLE_GAP_EVENT_REPEAT_PAIRING; event.repeat_pairing = *rp; rc = ble_gap_call_conn_event_cb(&event, rp->conn_handle); return rc; +#endif #else return 0; #endif @@ -7339,6 +8740,19 @@ ble_gap_vs_hci_event(const void *buf, uint8_t len) ble_gap_event_listener_call(&event); } + +int +ble_hs_send_vs_event_mask(uint32_t event_mask) +{ + struct ble_hci_vs_set_event_mask_cp cmd; + + /* Populate command */ + cmd.event_mask = htole32(event_mask); + + /* Send command via HCI */ + return ble_hs_hci_send_vs_cmd(BLE_HCI_OCF_VS_SET_EVT_MASK, + &cmd, sizeof(cmd), NULL, 0); +} #endif int @@ -7426,6 +8840,27 @@ ble_gap_end_test_evt(const void *buf, uint8_t len) ble_gap_event_listener_call(&event); } +/***************************************************************************** + * EATT * + *****************************************************************************/ +void +ble_gap_eatt_event(uint16_t conn_handle, uint8_t status, uint16_t cid) +{ +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + struct ble_gap_event event; + + memset(&event, 0, sizeof event); + event.type = BLE_GAP_EVENT_EATT; + + event.eatt.conn_handle = conn_handle; + event.eatt.status = status; + event.eatt.cid = cid; + + ble_gap_event_listener_call(&event); + ble_gap_call_conn_event_cb(&event, conn_handle); +#endif +} + /***************************************************************************** * $preempt * *****************************************************************************/ @@ -7811,6 +9246,30 @@ ble_gap_set_transmit_power_reporting_enable(uint16_t conn_handle, return BLE_HS_ENOTSUP; #endif } +int +ble_gap_rd_local_resolv_addr(uint8_t peer_addr_type, const ble_addr_t *peer_addr, + uint8_t *out_addr) +{ + struct ble_hci_le_rd_local_resolv_addr_cp cmd; + struct ble_hci_le_rd_local_resolv_addr_rp rsp; + uint16_t opcode; + int rc; + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_LOCAL_RESOLV_ADDR); + + cmd.peer_addr_type = peer_addr_type; + memcpy(&cmd.peer_id_addr, peer_addr->val, sizeof(cmd.peer_id_addr)); + + rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), &rsp, sizeof(rsp)); + + if (rc!=0) { + return rc; + } + + memcpy(out_addr, &rsp.rpa, sizeof(rsp.rpa)); + + return 0; +} #if MYNEWT_VAL(BLE_HCI_VS) #if MYNEWT_VAL(BLE_POWER_CONTROL) @@ -7985,8 +9444,10 @@ ble_gap_host_check_status(void) uint16_t sync_handle = 0; #endif struct ble_hs_conn *conn; +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) ble_addr_t oldest_peer_id_addr[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; - int num_peers; + int num_peers = 0; +#endif /* Stop Advertising */ #if MYNEWT_VAL(BLE_EXT_ADV) @@ -8001,10 +9462,12 @@ ble_gap_host_check_status(void) } #else +#if NIMBLE_BLE_ADVERTISE || NIMBLE_BLE_CONNECT if (ble_gap_adv_active_instance(0)) { BLE_HS_LOG(ERROR, "Gap Advertising is active \n"); status |= BIT(BLE_GAP_STATUS_ADV); } +#endif #endif /* Stop scanning */ @@ -8027,6 +9490,7 @@ ble_gap_host_check_status(void) } } +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) /* Check for paired devices*/ ble_store_util_bonded_peers(&oldest_peer_id_addr[0], &num_peers, MYNEWT_VAL(BLE_STORE_MAX_BONDS)); @@ -8035,6 +9499,7 @@ ble_gap_host_check_status(void) BLE_HS_LOG(ERROR, "Unpaired device exists\n"); status |= BIT(BLE_GAP_STATUS_PAIRED); } +#endif /* gatts reset */ if (ble_gatts_get_cfgable_chrs()) { diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gap_priv.h b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gap_priv.h index 5e05b8c6..a9f029f9 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gap_priv.h +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gap_priv.h @@ -95,6 +95,8 @@ void ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd *ev #endif void ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc); void ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used_feat *ev); +void ble_gap_rx_rd_rem_ver_info_complete(const struct ble_hci_ev_rd_rem_ver_info_cmp *ev); +void ble_gap_event_connect_call(uint16_t conn_handle, int status); #if MYNEWT_VAL(BLE_CONN_SUBRATING) void ble_gap_rx_subrate_change(const struct ble_hci_ev_le_subev_subrate_change *ev); #endif @@ -102,6 +104,11 @@ void ble_gap_rx_subrate_change(const struct ble_hci_ev_le_subev_subrate_change * void ble_gap_rx_transmit_power_report(const struct ble_hci_ev_le_subev_transmit_power_report *ev); void ble_gap_rx_le_pathloss_threshold(const struct ble_hci_ev_le_subev_path_loss_threshold *ev); #endif +#if MYNEWT_VAL(BLE_AOA_AOD) +void ble_gap_rx_connless_iq_report(const struct ble_hci_ev_le_subev_connless_iq_rpt *ev); +void ble_gap_rx_conn_iq_report(const struct ble_hci_ev_le_subev_conn_iq_rpt *ev); +void ble_gap_rx_cte_req_failed(const struct ble_hci_ev_le_subev_cte_req_failed *ev); +#endif struct ble_gap_conn_complete { @@ -116,8 +123,17 @@ struct ble_gap_conn_complete uint8_t master_clk_acc; uint8_t local_rpa[BLE_DEV_ADDR_LEN]; uint8_t peer_rpa[BLE_DEV_ADDR_LEN]; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + uint8_t adv_handle; + uint16_t sync_handle; +#endif }; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +void ble_gap_rx_periodic_adv_subev_data_req(const struct ble_hci_ev_le_subev_periodic_adv_subev_data_req *ev); +void ble_gap_rx_periodic_adv_response(const struct ble_gap_periodic_adv_response resp); +void ble_gap_rx_conn_comp_failed(const struct ble_gap_conn_complete *evt); +#endif int ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance); void ble_gap_rx_disconn_complete(const struct ble_hci_ev_disconn_cmp *ev); void ble_gap_rx_update_complete(const struct ble_hci_ev_le_subev_conn_upd_complete *ev); @@ -143,6 +159,7 @@ int ble_gap_repeat_pairing_event(const struct ble_gap_repeat_pairing *rp); void ble_gap_pairing_complete_event(uint16_t conn_handle, int status); void ble_gap_vs_hci_event(const void *buf, uint8_t len); int ble_gap_authorize_event(uint16_t conn_handle, uint16_t attr_handle, int is_read); +void ble_gap_eatt_event(uint16_t conn_handle, uint8_t status, uint16_t cid); int ble_gap_master_in_progress(void); void ble_gap_preempt(void); diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gatt_priv.h b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gatt_priv.h index 34c10ed1..eda5b85e 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gatt_priv.h +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gatt_priv.h @@ -68,6 +68,8 @@ STATS_SECT_START(ble_gattc_stats) STATS_SECT_ENTRY(write_reliable_fail) STATS_SECT_ENTRY(notify) STATS_SECT_ENTRY(notify_fail) + STATS_SECT_ENTRY(multi_notify) + STATS_SECT_ENTRY(multi_notify_fail) STATS_SECT_ENTRY(indicate) STATS_SECT_ENTRY(indicate_fail) STATS_SECT_ENTRY(proc_timeout) @@ -90,7 +92,6 @@ extern STATS_SECT_DECL(ble_gatts_stats) ble_gatts_stats; #define BLE_GATT_CHR_DECL_SZ_16 5 #define BLE_GATT_CHR_DECL_SZ_128 19 -#define BLE_GATT_CHR_CLI_SUP_FEAT_SZ 1 /** * For now only 3 bits in first octet are defined * @@ -108,6 +109,7 @@ struct ble_gatts_conn { int num_clt_cfgs; #if MYNEWT_VAL(BLE_GATT_CACHING) bool aware_state; + uint8_t half_aware:1; bool sent_err; #endif @@ -119,7 +121,7 @@ struct ble_gatts_conn { * future proof if more octets might be used. * (Vol. 3, Part G, 7.2) */ - uint8_t peer_cl_sup_feat[BLE_GATT_CHR_CLI_SUP_FEAT_SZ]; + uint8_t peer_cl_sup_feat[MYNEWT_VAL(BLE_GATT_CSFC_SIZE)]; }; /*** @client. */ @@ -127,32 +129,32 @@ struct ble_gatts_conn { int ble_gattc_locked_by_cur_task(void); void ble_gatts_indicate_fail_notconn(uint16_t conn_handle); -void ble_gattc_rx_err(uint16_t conn_handle, uint16_t handle, uint16_t status); -void ble_gattc_rx_mtu(uint16_t conn_handle, int status, uint16_t chan_mtu); -void ble_gattc_rx_read_type_adata(uint16_t conn_handle, +void ble_gattc_rx_err(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t status); +void ble_gattc_rx_mtu(uint16_t conn_handle, uint16_t cid, int status, uint16_t chan_mtu); +void ble_gattc_rx_read_type_adata(uint16_t conn_handle, uint16_t cid, struct ble_att_read_type_adata *adata); -void ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status); -void ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, +void ble_gattc_rx_read_type_complete(uint16_t conn_handle, uint16_t cid, int status); +void ble_gattc_rx_read_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **rxom); -void ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, +void ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **rxom); -void ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, +void ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **rxom, bool variable); -void ble_gattc_rx_read_group_type_adata( - uint16_t conn_handle, struct ble_att_read_group_type_adata *adata); -void ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int rc); -void ble_gattc_rx_find_type_value_hinfo( - uint16_t conn_handle, struct ble_att_find_type_value_hinfo *hinfo); -void ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status); -void ble_gattc_rx_write_rsp(uint16_t conn_handle); -void ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, +void ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, uint16_t cid, + struct ble_att_read_group_type_adata *adata); +void ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, uint16_t cid, int rc); +void ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, uint16_t cid, + struct ble_att_find_type_value_hinfo *hinfo); +void ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, uint16_t cid, int status); +void ble_gattc_rx_write_rsp(uint16_t conn_handle, uint16_t cid); +void ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, uint16_t cid, int status, uint16_t handle, uint16_t offset, struct os_mbuf **rxom); -void ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status); -void ble_gatts_rx_indicate_rsp(uint16_t conn_handle); -void ble_gattc_rx_find_info_idata(uint16_t conn_handle, +void ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, uint16_t cid, int status); +void ble_gatts_rx_indicate_rsp(uint16_t conn_handle, uint16_t cid); +void ble_gattc_rx_find_info_idata(uint16_t conn_handle, uint16_t cid, struct ble_att_find_info_idata *idata); -void ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status); +void ble_gattc_rx_find_info_complete(uint16_t conn_handle, uint16_t cid, int status); void ble_gattc_connection_txable(uint16_t conn_handle); void ble_gattc_connection_broken(uint16_t conn_handle); int32_t ble_gattc_timer(void); @@ -222,11 +224,13 @@ int ble_gatts_register_svcs(const struct ble_gatt_svc_def *svcs, int ble_gatts_clt_cfg_access(uint16_t conn_handle, uint16_t attr_handle, uint8_t op, uint16_t offset, struct os_mbuf **om, void *arg); +void ble_gatts_set_clt_cfg_perm_flags(uint8_t flags); #if MYNEWT_VAL(BLE_GATT_CACHING) struct ble_gatts_aware_state { uint8_t peer_id_addr[6]; bool aware; + uint8_t half_aware:1; }; extern struct ble_gatts_aware_state ble_gatts_conn_aware_states[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc.c index 0669b6c2..037b5f46 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc.c @@ -61,9 +61,12 @@ #include "host/ble_gap.h" #include "ble_hs_priv.h" #include "ble_gattc_cache_priv.h" - +#if MYNEWT_VAL(BLE_GATT_CACHING) +#include "host/ble_esp_gattc_cache.h" +#endif #if NIMBLE_BLE_CONNECT +#if MYNEWT_VAL(BLE_GATTC) #ifndef min #define min(a, b) ((a) < (b) ? (a) : (b)) #endif @@ -72,6 +75,7 @@ #define max(a, b) ((a) > (b) ? (a) : (b)) #endif +#endif /***************************************************************************** * $definitions / declarations * *****************************************************************************/ @@ -83,6 +87,7 @@ #define BLE_GATTC_UNRESPONSIVE_TIMEOUT_MS 30000 /* ms */ #define BLE_GATT_OP_NONE UINT8_MAX + #define BLE_GATT_OP_MTU 0 #define BLE_GATT_OP_DISC_ALL_SVCS 1 #define BLE_GATT_OP_DISC_SVC_UUID 2 @@ -110,6 +115,7 @@ struct ble_gattc_proc { uint32_t exp_os_ticks; uint16_t conn_handle; + uint16_t cid; uint8_t op; uint8_t flags; @@ -139,7 +145,11 @@ struct ble_gattc_proc { uint16_t cur_start; uint16_t cur_end; +#if MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + ble_gatt_disc_incl_svc_fn *cb; +#else ble_gatt_disc_svc_fn *cb; +#endif void *cb_arg; } find_inc_svcs; @@ -224,6 +234,10 @@ struct ble_gattc_proc { }; }; + +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) +static struct ble_gattc_proc_list temp_proc_list; +#endif STAILQ_HEAD(ble_gattc_proc_list, ble_gattc_proc); /** @@ -232,6 +246,8 @@ STAILQ_HEAD(ble_gattc_proc_list, ble_gattc_proc); */ typedef void ble_gattc_err_fn(struct ble_gattc_proc *proc, int status, uint16_t att_handle); + +#if MYNEWT_VAL(BLE_GATTC) static ble_gattc_err_fn ble_gattc_mtu_err; static ble_gattc_err_fn ble_gattc_disc_all_svcs_err; static ble_gattc_err_fn ble_gattc_disc_svc_uuid_err; @@ -243,12 +259,18 @@ static ble_gattc_err_fn ble_gattc_read_err; static ble_gattc_err_fn ble_gattc_read_uuid_err; static ble_gattc_err_fn ble_gattc_read_long_err; static ble_gattc_err_fn ble_gattc_read_mult_err; +static ble_gattc_err_fn ble_gattc_read_mult_var_err; static ble_gattc_err_fn ble_gattc_write_err; static ble_gattc_err_fn ble_gattc_write_long_err; static ble_gattc_err_fn ble_gattc_write_reliable_err; +#endif + +#if MYNEWT_VAL(BLE_GATTS) static ble_gattc_err_fn ble_gatts_indicate_err; +#endif static ble_gattc_err_fn * const ble_gattc_err_dispatch[BLE_GATT_OP_CNT] = { +#if MYNEWT_VAL(BLE_GATTC) [BLE_GATT_OP_MTU] = ble_gattc_mtu_err, [BLE_GATT_OP_DISC_ALL_SVCS] = ble_gattc_disc_all_svcs_err, [BLE_GATT_OP_DISC_SVC_UUID] = ble_gattc_disc_svc_uuid_err, @@ -260,12 +282,17 @@ static ble_gattc_err_fn * const ble_gattc_err_dispatch[BLE_GATT_OP_CNT] = { [BLE_GATT_OP_READ_UUID] = ble_gattc_read_uuid_err, [BLE_GATT_OP_READ_LONG] = ble_gattc_read_long_err, [BLE_GATT_OP_READ_MULT] = ble_gattc_read_mult_err, + [BLE_GATT_OP_READ_MULT_VAR] = ble_gattc_read_mult_var_err, [BLE_GATT_OP_WRITE] = ble_gattc_write_err, [BLE_GATT_OP_WRITE_LONG] = ble_gattc_write_long_err, [BLE_GATT_OP_WRITE_RELIABLE] = ble_gattc_write_reliable_err, +#endif +#if MYNEWT_VAL(BLE_GATTS) [BLE_GATT_OP_INDICATE] = ble_gatts_indicate_err, +#endif }; +#if MYNEWT_VAL(BLE_GATTC) /** * Resume functions - these handle periodic retries of procedures that have * stalled due to memory exhaustion. @@ -295,6 +322,7 @@ ble_gattc_resume_dispatch[BLE_GATT_OP_CNT] = { [BLE_GATT_OP_READ_UUID] = NULL, [BLE_GATT_OP_READ_LONG] = ble_gattc_read_long_resume, [BLE_GATT_OP_READ_MULT] = NULL, + [BLE_GATT_OP_READ_MULT_VAR] = NULL, [BLE_GATT_OP_WRITE] = NULL, [BLE_GATT_OP_WRITE_LONG] = ble_gattc_write_long_resume, [BLE_GATT_OP_WRITE_RELIABLE] = ble_gattc_write_reliable_resume, @@ -318,6 +346,7 @@ static ble_gattc_tmo_fn ble_gattc_read_tmo; static ble_gattc_tmo_fn ble_gattc_read_uuid_tmo; static ble_gattc_tmo_fn ble_gattc_read_long_tmo; static ble_gattc_tmo_fn ble_gattc_read_mult_tmo; +static ble_gattc_tmo_fn ble_gattc_read_mult_var_tmo; static ble_gattc_tmo_fn ble_gattc_write_tmo; static ble_gattc_tmo_fn ble_gattc_write_long_tmo; static ble_gattc_tmo_fn ble_gattc_write_reliable_tmo; @@ -336,6 +365,7 @@ ble_gattc_tmo_dispatch[BLE_GATT_OP_CNT] = { [BLE_GATT_OP_READ_UUID] = ble_gattc_read_uuid_tmo, [BLE_GATT_OP_READ_LONG] = ble_gattc_read_long_tmo, [BLE_GATT_OP_READ_MULT] = ble_gattc_read_mult_tmo, + [BLE_GATT_OP_READ_MULT_VAR] = ble_gattc_read_mult_var_tmo, [BLE_GATT_OP_WRITE] = ble_gattc_write_tmo, [BLE_GATT_OP_WRITE_LONG] = ble_gattc_write_long_tmo, [BLE_GATT_OP_WRITE_RELIABLE] = ble_gattc_write_reliable_tmo, @@ -420,6 +450,7 @@ static const struct ble_gattc_rx_exec_entry { { BLE_GATT_OP_WRITE_RELIABLE, ble_gattc_write_reliable_rx_exec }, }; +#endif static os_membuf_t ble_gattc_proc_mem[ OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_GATT_MAX_PROCS), sizeof (struct ble_gattc_proc)) @@ -430,6 +461,7 @@ static struct os_mempool ble_gattc_proc_pool; /* The list of active GATT client procedures. */ static struct ble_gattc_proc_list ble_gattc_procs; +#if MYNEWT_VAL(BLE_GATTC) /* The time when we should attempt to resume stalled procedures, in OS ticks. * A value of 0 indicates no stalled procedures. */ @@ -472,6 +504,8 @@ STATS_NAME_START(ble_gattc_stats) STATS_NAME(ble_gattc_stats, write_reliable_fail) STATS_NAME(ble_gattc_stats, notify) STATS_NAME(ble_gattc_stats, notify_fail) + STATS_NAME(ble_gattc_stats, multi_notify) + STATS_NAME(ble_gattc_stats, multi_notify_fail) STATS_NAME(ble_gattc_stats, indicate) STATS_NAME(ble_gattc_stats, indicate_fail) STATS_NAME(ble_gattc_stats, proc_timeout) @@ -480,6 +514,7 @@ STATS_NAME_END(ble_gattc_stats) /***************************************************************************** * $debug * *****************************************************************************/ +#endif static void ble_gattc_dbg_assert_proc_not_inserted(struct ble_gattc_proc *proc) @@ -497,6 +532,7 @@ ble_gattc_dbg_assert_proc_not_inserted(struct ble_gattc_proc *proc) #endif } + /***************************************************************************** * $log * *****************************************************************************/ @@ -507,6 +543,7 @@ ble_gattc_log_proc_init(const char *name) BLE_HS_LOG(INFO, "GATT procedure initiated: %s", name); } +#if MYNEWT_VAL(BLE_GATTC) static void ble_gattc_log_uuid(const ble_uuid_t *uuid) { @@ -645,6 +682,7 @@ ble_gattc_log_write_reliable(struct ble_gattc_proc *proc) } BLE_HS_LOG(INFO, "\n"); } +#endif static void ble_gattc_log_notify(uint16_t att_handle) @@ -653,6 +691,18 @@ ble_gattc_log_notify(uint16_t att_handle) BLE_HS_LOG(INFO, "att_handle=%d\n", att_handle); } + +#if MYNEWT_VAL(BLE_GATTC) +static void +ble_gattc_log_multi_notify(struct ble_gatt_notif * tuples, uint16_t num) +{ + ble_gattc_log_proc_init("multi handle notify; "); + for (int i = 0; i < num; i++) { + BLE_HS_LOG(INFO, "att_handle=%d", tuples[i].handle); + } +} + +#endif static void ble_gattc_log_indicate(uint16_t att_handle) { @@ -660,6 +710,7 @@ ble_gattc_log_indicate(uint16_t att_handle) BLE_HS_LOG(INFO, "att_handle=%d\n", att_handle); } +#if MYNEWT_VAL(BLE_GATTC) /***************************************************************************** * $rx entry * *****************************************************************************/ @@ -688,7 +739,7 @@ ble_gattc_rx_entry_find(uint8_t op, const void *rx_entries, int num_entries) /***************************************************************************** * $proc * *****************************************************************************/ - +#endif /** * Allocates a proc entry. * @@ -707,6 +758,15 @@ ble_gattc_proc_alloc(void) return proc; } + +static void +ble_gattc_proc_prepare(struct ble_gattc_proc *proc, uint16_t conn_handle, uint8_t op) +{ + proc->conn_handle = conn_handle; + proc->op = op; + proc->cid = ble_eatt_get_available_chan_cid(conn_handle, op); +} + /** * Frees the specified proc entry. No-op if passed a null pointer. */ @@ -738,6 +798,12 @@ ble_gattc_proc_free(struct ble_gattc_proc *proc) break; } +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + if (ble_hs_cfg.eatt && proc->cid != BLE_L2CAP_CID_ATT) { + ble_eatt_release_chan(proc->conn_handle, proc->op); + } +#endif + #if MYNEWT_VAL(BLE_HS_DEBUG) memset(proc, 0xff, sizeof *proc); #endif @@ -763,6 +829,7 @@ ble_gattc_proc_set_exp_timer(struct ble_gattc_proc *proc) ble_npl_time_ms_to_ticks32(BLE_GATTC_UNRESPONSIVE_TIMEOUT_MS); } +#if MYNEWT_VAL(BLE_GATTC) static void ble_gattc_proc_set_resume_timer(struct ble_gattc_proc *proc) { @@ -782,6 +849,8 @@ ble_gattc_proc_set_resume_timer(struct ble_gattc_proc *proc) } } +#endif + static void ble_gattc_process_status(struct ble_gattc_proc *proc, int status) { @@ -801,6 +870,7 @@ ble_gattc_process_status(struct ble_gattc_proc *proc, int status) } } +#if MYNEWT_VAL(BLE_GATTC) /** * Processes the return code that results from an attempt to resume a * procedure. If the resume attempt failed due to memory exhaustion at a lower @@ -826,6 +896,7 @@ ble_gattc_process_resume_status(struct ble_gattc_proc *proc, int status) /***************************************************************************** * $util * *****************************************************************************/ +#endif /** * Retrieves the error dispatch entry with the specified op code. @@ -837,6 +908,7 @@ ble_gattc_err_dispatch_get(uint8_t op) return ble_gattc_err_dispatch[op]; } +#if MYNEWT_VAL(BLE_GATTC) /** * Retrieves the error dispatch entry with the specified op code. */ @@ -854,10 +926,12 @@ ble_gattc_tmo_dispatch_get(uint8_t op) return ble_gattc_tmo_dispatch[op]; } +#endif typedef int ble_gattc_match_fn(struct ble_gattc_proc *proc, void *arg); struct ble_gattc_criteria_conn_op { uint16_t conn_handle; + uint16_t psm; uint8_t op; }; @@ -889,6 +963,29 @@ ble_gattc_proc_matches_conn_op(struct ble_gattc_proc *proc, void *arg) return 1; } +#if MYNEWT_VAL(BLE_GATTC) +static int +ble_gattc_proc_matches_conn_cid_op(struct ble_gattc_proc *proc, void *arg) +{ + const struct ble_gattc_criteria_conn_op *criteria; + + criteria = arg; + + if (criteria->conn_handle != proc->conn_handle) { + return 0; + } + + if (criteria->psm != proc->cid) { + return 0; + } + + if (criteria->op != proc->op && criteria->op != BLE_GATT_OP_NONE) { + return 0; + } + + return 1; +} + struct ble_gattc_criteria_exp { ble_npl_time_t now; int32_t next_exp_in; @@ -918,6 +1015,7 @@ ble_gattc_proc_matches_expired(struct ble_gattc_proc *proc, void *arg) struct ble_gattc_criteria_conn_rx_entry { uint16_t conn_handle; + uint16_t cid; const void *rx_entries; int num_rx_entries; const void *matching_rx_entry; @@ -931,7 +1029,8 @@ ble_gattc_proc_matches_conn_rx_entry(struct ble_gattc_proc *proc, void *arg) criteria = arg; if (criteria->conn_handle != BLE_HS_CONN_HANDLE_NONE && - criteria->conn_handle != proc->conn_handle) { + (criteria->conn_handle != proc->conn_handle || + criteria->cid != proc->cid)) { return 0; } @@ -943,6 +1042,8 @@ ble_gattc_proc_matches_conn_rx_entry(struct ble_gattc_proc *proc, void *arg) return (criteria->matching_rx_entry != NULL); } +#endif + static void ble_gattc_extract(ble_gattc_match_fn *cb, void *arg, int max_procs, struct ble_gattc_proc_list *dst_list) @@ -950,6 +1051,10 @@ ble_gattc_extract(ble_gattc_match_fn *cb, void *arg, int max_procs, struct ble_gattc_proc *proc; struct ble_gattc_proc *prev; struct ble_gattc_proc *next; +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + struct ble_gattc_proc *cur; + uint8_t flag = 0; +#endif int num_extracted; /* Only the parent task is allowed to remove entries from the list. */ @@ -961,6 +1066,28 @@ ble_gattc_extract(ble_gattc_match_fn *cb, void *arg, int max_procs, ble_hs_lock(); prev = NULL; + +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + proc = STAILQ_FIRST(&temp_proc_list); + while (proc != NULL) { + next = STAILQ_NEXT(proc, next); + STAILQ_FOREACH(cur, &ble_gattc_procs, next) { + if (proc == cur) { + flag = 1; + break; + } + } + if (!flag) { + /* Detected a preemption case */ + STAILQ_INSERT_TAIL(&ble_gattc_procs, proc, next); + } + flag = 0; + proc = next; + } + /* Clear the temp proc list */ + STAILQ_INIT(&temp_proc_list); +#endif + proc = STAILQ_FIRST(&ble_gattc_procs); while (proc != NULL) { next = STAILQ_NEXT(proc, next); @@ -989,6 +1116,7 @@ ble_gattc_extract(ble_gattc_match_fn *cb, void *arg, int max_procs, ble_hs_unlock(); } +#if MYNEWT_VAL(BLE_GATTC) static struct ble_gattc_proc * ble_gattc_extract_one(ble_gattc_match_fn *cb, void *arg) { @@ -998,6 +1126,8 @@ ble_gattc_extract_one(ble_gattc_match_fn *cb, void *arg) return STAILQ_FIRST(&dst_list); } +#endif + static void ble_gattc_extract_by_conn_op(uint16_t conn_handle, uint8_t op, int max_procs, struct ble_gattc_proc_list *dst_list) @@ -1010,12 +1140,28 @@ ble_gattc_extract_by_conn_op(uint16_t conn_handle, uint8_t op, int max_procs, ble_gattc_extract(ble_gattc_proc_matches_conn_op, &criteria, max_procs, dst_list); } + +#if MYNEWT_VAL(BLE_GATTC) +static void +ble_gattc_extract_by_conn_cid_op(uint16_t conn_handle, uint16_t psm, uint8_t op, + int max_procs, + struct ble_gattc_proc_list *dst_list) +{ + struct ble_gattc_criteria_conn_op criteria; + + criteria.conn_handle = conn_handle; + criteria.op = op; + criteria.psm = psm; + + ble_gattc_extract(ble_gattc_proc_matches_conn_cid_op, &criteria, max_procs, dst_list); +} + static struct ble_gattc_proc * -ble_gattc_extract_first_by_conn_op(uint16_t conn_handle, uint8_t op) +ble_gattc_extract_first_by_conn_cid_op(uint16_t conn_handle, uint16_t cid, uint8_t op) { struct ble_gattc_proc_list dst_list; - ble_gattc_extract_by_conn_op(conn_handle, op, 1, &dst_list); + ble_gattc_extract_by_conn_cid_op(conn_handle, cid, op, 1, &dst_list); return STAILQ_FIRST(&dst_list); } @@ -1050,7 +1196,7 @@ ble_gattc_extract_expired(struct ble_gattc_proc_list *dst_list) } static struct ble_gattc_proc * -ble_gattc_extract_with_rx_entry(uint16_t conn_handle, +ble_gattc_extract_with_rx_entry(uint16_t conn_handle, uint16_t cid, const void *rx_entries, int num_rx_entries, const void **out_rx_entry) { @@ -1058,6 +1204,7 @@ ble_gattc_extract_with_rx_entry(uint16_t conn_handle, struct ble_gattc_proc *proc; criteria.conn_handle = conn_handle; + criteria.cid = cid; criteria.rx_entries = rx_entries; criteria.num_rx_entries = num_rx_entries; criteria.matching_rx_entry = NULL; @@ -1075,6 +1222,7 @@ ble_gattc_extract_with_rx_entry(uint16_t conn_handle, * list and returned. * * @param conn_handle The connection handle to match against. + * @param cid Source CID of L2CAP channel used * @param rx_entries The array of rx entries corresponding to the * op code of the incoming response. * @param out_rx_entry On success, the address of the matching rx @@ -1083,12 +1231,12 @@ ble_gattc_extract_with_rx_entry(uint16_t conn_handle, * @return The matching proc entry on success; * null on failure. */ -#define BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, rx_entries, out_rx_entry) \ +#define BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, cid, rx_entries, out_rx_entry) \ ble_gattc_extract_with_rx_entry( \ - (conn_handle), (rx_entries), \ + (conn_handle), (cid), (rx_entries), \ sizeof (rx_entries) / sizeof (rx_entries)[0], \ (const void **)(out_rx_entry)) - +#endif /** * Causes all GATT procedures matching the specified criteria to fail with the @@ -1118,6 +1266,7 @@ ble_gattc_fail_procs(uint16_t conn_handle, uint8_t op, int status) } } +#if MYNEWT_VAL(BLE_GATTC) static void ble_gattc_resume_procs(void) { @@ -1303,7 +1452,7 @@ ble_gattc_mtu_tx(struct ble_gattc_proc *proc) int rc; ble_hs_lock(); - rc = ble_att_conn_chan_find(proc->conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(proc->conn_handle, proc->cid, &conn, &chan); if (rc == 0) { mtu = chan->my_mtu; } @@ -1332,6 +1481,7 @@ ble_gattc_exchange_mtu(uint16_t conn_handle, ble_gatt_mtu_fn *cb, void *cb_arg) proc->op = BLE_GATT_OP_MTU; proc->conn_handle = conn_handle; + proc->cid = BLE_L2CAP_CID_ATT; proc->mtu.cb = cb; proc->mtu.cb_arg = cb_arg; @@ -1408,7 +1558,7 @@ ble_gattc_disc_all_svcs_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); - rc = ble_att_clt_tx_read_group_type(proc->conn_handle, + rc = ble_att_clt_tx_read_group_type(proc->conn_handle, proc->cid, proc->disc_all_svcs.prev_handle + 1, 0xffff, &uuid.u); if (rc != 0) { @@ -1561,12 +1711,17 @@ ble_gattc_disc_all_svcs(uint16_t conn_handle, ble_gatt_disc_svc_fn *cb, goto done; } - proc->op = BLE_GATT_OP_DISC_ALL_SVCS; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_ALL_SVCS); + proc->disc_all_svcs.prev_handle = 0x0000; proc->disc_all_svcs.cb = cb; proc->disc_all_svcs.cb_arg = cb_arg; +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + ble_hs_lock(); + STAILQ_INSERT_TAIL(&temp_proc_list, proc, next); + ble_hs_unlock(); +#endif ble_gattc_log_proc_init("discover all services\n"); rc = ble_gattc_disc_all_svcs_tx(proc); @@ -1577,6 +1732,11 @@ ble_gattc_disc_all_svcs(uint16_t conn_handle, ble_gatt_disc_svc_fn *cb, done: if (rc != 0) { STATS_INC(ble_gattc_stats, disc_all_svcs_fail); +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + ble_hs_lock(); + STAILQ_REMOVE(&temp_proc_list,proc,ble_gattc_proc, next); + ble_hs_unlock(); +#endif } ble_gattc_process_status(proc, rc); @@ -1641,7 +1801,7 @@ ble_gattc_disc_svc_uuid_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); ble_uuid_flat(&proc->disc_svc_uuid.service_uuid.u, val); - rc = ble_att_clt_tx_find_type_value(proc->conn_handle, + rc = ble_att_clt_tx_find_type_value(proc->conn_handle, proc->cid, proc->disc_svc_uuid.prev_handle + 1, 0xffff, BLE_ATT_UUID_PRIMARY_SERVICE, val, @@ -1780,8 +1940,8 @@ ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, const ble_uuid_t *uuid, goto done; } - proc->op = BLE_GATT_OP_DISC_SVC_UUID; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_SVC_UUID); + ble_uuid_to_any(uuid, &proc->disc_svc_uuid.service_uuid); proc->disc_svc_uuid.prev_handle = 0x0000; proc->disc_svc_uuid.cb = cb; @@ -1814,15 +1974,22 @@ done: * @return The return code of the callback (or 0 if there * is no callback). */ +#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)) static int ble_gattc_find_inc_svcs_cb(struct ble_gattc_proc *proc, int status, uint16_t att_handle, - struct ble_gatt_svc *service) + struct ble_gatt_incl_svc *incl_svc) +#else +static int +ble_gattc_find_inc_svcs_cb(struct ble_gattc_proc *proc, int status, + uint16_t att_handle, + struct ble_gatt_svc *incl_svc) +#endif { int rc; BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task()); - BLE_HS_DBG_ASSERT(service != NULL || status != 0); + BLE_HS_DBG_ASSERT(incl_svc != NULL || status != 0); ble_gattc_dbg_assert_proc_not_inserted(proc); if (status != 0 && status != BLE_HS_EDONE) { @@ -1834,7 +2001,7 @@ ble_gattc_find_inc_svcs_cb(struct ble_gattc_proc *proc, int status, } else { rc = proc->find_inc_svcs.cb(proc->conn_handle, ble_gattc_error(status, att_handle), - service, proc->find_inc_svcs.cb_arg); + incl_svc, proc->find_inc_svcs.cb_arg); } return rc; @@ -1862,7 +2029,7 @@ ble_gattc_find_inc_svcs_tx(struct ble_gattc_proc *proc) if (proc->find_inc_svcs.cur_start == 0) { /* Find the next included service. */ - rc = ble_att_clt_tx_read_type(proc->conn_handle, + rc = ble_att_clt_tx_read_type(proc->conn_handle, proc->cid, proc->find_inc_svcs.prev_handle + 1, proc->find_inc_svcs.end_handle, &uuid.u); if (rc != 0) { @@ -1870,7 +2037,7 @@ ble_gattc_find_inc_svcs_tx(struct ble_gattc_proc *proc) } } else { /* Read the UUID of the previously found service. */ - rc = ble_att_clt_tx_read(proc->conn_handle, + rc = ble_att_clt_tx_read(proc->conn_handle, proc->cid, proc->find_inc_svcs.cur_start); if (rc != 0) { return rc; @@ -1924,7 +2091,11 @@ static int ble_gattc_find_inc_svcs_rx_read_rsp(struct ble_gattc_proc *proc, int status, struct os_mbuf **om) { +#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)) + struct ble_gatt_incl_svc service; +#else struct ble_gatt_svc service; +#endif int rc; ble_gattc_dbg_assert_proc_not_inserted(proc); @@ -1953,6 +2124,7 @@ ble_gattc_find_inc_svcs_rx_read_rsp(struct ble_gattc_proc *proc, int status, /* Report discovered service to application. */ service.start_handle = proc->find_inc_svcs.cur_start; service.end_handle = proc->find_inc_svcs.cur_end; + rc = ble_gattc_find_inc_svcs_cb(proc, 0, 0, &service); if (rc != 0) { /* Application has indicated that the procedure should be aborted. */ @@ -1982,7 +2154,11 @@ static int ble_gattc_find_inc_svcs_rx_adata(struct ble_gattc_proc *proc, struct ble_att_read_type_adata *adata) { +#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)) + struct ble_gatt_incl_svc service = {0}; +#else struct ble_gatt_svc service = {0}; +#endif int call_cb; int cbrc; int rc; @@ -2016,6 +2192,9 @@ ble_gattc_find_inc_svcs_rx_adata(struct ble_gattc_proc *proc, break; case BLE_GATTS_INC_SVC_LEN_UUID: +#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)) + service.handle = adata->att_handle; +#endif service.start_handle = get_le16(adata->value + 0); service.end_handle = get_le16(adata->value + 2); rc = ble_uuid_init_from_att_buf(&service.uuid, adata->value + 4, 2); @@ -2076,10 +2255,17 @@ ble_gattc_find_inc_svcs_rx_complete(struct ble_gattc_proc *proc, int status) return 0; } +#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)) +int +ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle, + uint16_t end_handle, + ble_gatt_disc_incl_svc_fn *cb, void *cb_arg) +#else int ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, ble_gatt_disc_svc_fn *cb, void *cb_arg) +#endif { #if !MYNEWT_VAL(BLE_GATT_FIND_INC_SVCS) return BLE_HS_ENOTSUP; @@ -2088,6 +2274,12 @@ ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle, struct ble_gattc_proc *proc; int rc; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + rc = ble_gattc_cache_conn_search_inc_svcs(conn_handle, start_handle, end_handle, cb, cb_arg); + if (rc == 0) { + return rc; + } +#endif STATS_INC(ble_gattc_stats, find_inc_svcs); proc = ble_gattc_proc_alloc(); @@ -2096,8 +2288,8 @@ ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle, goto done; } - proc->op = BLE_GATT_OP_FIND_INC_SVCS; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_FIND_INC_SVCS); + proc->find_inc_svcs.prev_handle = start_handle - 1; proc->find_inc_svcs.end_handle = end_handle; proc->find_inc_svcs.cb = cb; @@ -2176,7 +2368,7 @@ ble_gattc_disc_all_chrs_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); - rc = ble_att_clt_tx_read_type(proc->conn_handle, + rc = ble_att_clt_tx_read_type(proc->conn_handle, proc->cid, proc->disc_all_chrs.prev_handle + 1, proc->disc_all_chrs.end_handle, &uuid.u); if (rc != 0) { @@ -2330,13 +2522,18 @@ ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle, goto done; } - proc->op = BLE_GATT_OP_DISC_ALL_CHRS; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_ALL_CHRS); + proc->disc_all_chrs.prev_handle = start_handle - 1; proc->disc_all_chrs.end_handle = end_handle; proc->disc_all_chrs.cb = cb; proc->disc_all_chrs.cb_arg = cb_arg; +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + ble_hs_lock(); + STAILQ_INSERT_TAIL(&temp_proc_list, proc, next); + ble_hs_unlock(); +#endif ble_gattc_log_disc_all_chrs(proc); rc = ble_gattc_disc_all_chrs_tx(proc); @@ -2347,6 +2544,11 @@ ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle, done: if (rc != 0) { STATS_INC(ble_gattc_stats, disc_all_chrs_fail); +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + ble_hs_lock(); + STAILQ_REMOVE(&temp_proc_list,proc,ble_gattc_proc, next); + ble_hs_unlock(); +#endif } ble_gattc_process_status(proc, rc); @@ -2410,7 +2612,7 @@ ble_gattc_disc_chr_uuid_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); - rc = ble_att_clt_tx_read_type(proc->conn_handle, + rc = ble_att_clt_tx_read_type(proc->conn_handle, proc->cid, proc->disc_chr_uuid.prev_handle + 1, proc->disc_chr_uuid.end_handle, &uuid.u); if (rc != 0) { @@ -2575,8 +2777,8 @@ ble_gattc_disc_chrs_by_uuid(uint16_t conn_handle, uint16_t start_handle, goto done; } - proc->op = BLE_GATT_OP_DISC_CHR_UUID; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_CHR_UUID); + ble_uuid_to_any(uuid, &proc->disc_chr_uuid.chr_uuid); proc->disc_chr_uuid.prev_handle = start_handle - 1; proc->disc_chr_uuid.end_handle = end_handle; @@ -2655,7 +2857,7 @@ ble_gattc_disc_all_dscs_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); - rc = ble_att_clt_tx_find_info(proc->conn_handle, + rc = ble_att_clt_tx_find_info(proc->conn_handle, proc->cid, proc->disc_all_dscs.prev_handle + 1, proc->disc_all_dscs.end_handle); if (rc != 0) { @@ -2791,14 +2993,19 @@ ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t start_handle, goto done; } - proc->op = BLE_GATT_OP_DISC_ALL_DSCS; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_ALL_DSCS); + proc->disc_all_dscs.chr_val_handle = start_handle; proc->disc_all_dscs.prev_handle = start_handle; proc->disc_all_dscs.end_handle = end_handle; proc->disc_all_dscs.cb = cb; proc->disc_all_dscs.cb_arg = cb_arg; +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + ble_hs_lock(); + STAILQ_INSERT_TAIL(&temp_proc_list, proc, next); + ble_hs_unlock(); +#endif ble_gattc_log_disc_all_dscs(proc); rc = ble_gattc_disc_all_dscs_tx(proc); @@ -2809,12 +3016,421 @@ ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t start_handle, done: if (rc != 0) { STATS_INC(ble_gattc_stats, disc_all_dscs_fail); +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + ble_hs_lock(); + STAILQ_REMOVE(&temp_proc_list,proc,ble_gattc_proc, next); + ble_hs_unlock(); +#endif } ble_gattc_process_status(proc, rc); return rc; } +#if MYNEWT_VAL(BLE_GATT_CACHING) +int ble_gattc_check_valid_param(uint16_t num, uint16_t offset) +{ + if (num == 0) { + return BLE_ATT_ERR_ATTR_NOT_FOUND; + } else if (offset >= num) { + return BLE_ATT_ERR_INVALID_OFFSET; + } + + return 0; // Success +} + +static void ble_gattc_fill_gatt_db_conversion(uint16_t *count, uint16_t num, esp_ble_gatt_db_attr_type_t type, + uint16_t offset, void *result, ble_gattc_db_elem_t *db) +{ + uint16_t db_size = ((*count + offset) > num) ? (num - offset) : *count; + switch (type) { + case ESP_BLE_GATT_DB_PRIMARY_SERVICE: + case ESP_BLE_GATT_DB_SECONDARY_SERVICE: { + ble_gattc_service_elem_t *svc_result = (ble_gattc_service_elem_t *)result; + for (int i = 0; i < db_size; i++) { + svc_result->is_primary = (db[offset + i].type == (int)BLE_GATT_DB_PRIMARY_SERVICE); + svc_result->start_handle = db[offset + i].start_handle; + svc_result->end_handle = db[offset + i].end_handle; + svc_result->uuid = db[offset + i].uuid; + svc_result++; + } + break; + } + case ESP_BLE_GATT_DB_CHARACTERISTIC: { + ble_gattc_char_elem_t *char_result = (ble_gattc_char_elem_t *)result; + for (int i = 0; i < db_size; i++) { + char_result->char_handle = db[offset + i].handle; + char_result->properties = db[offset + i].properties; + char_result->uuid = db[offset + i].uuid; + char_result++; + } + break; + } + case ESP_BLE_GATT_DB_DESCRIPTOR: { + ble_gattc_descr_elem_t *descr_result = (ble_gattc_descr_elem_t *)result; + for (int i = 0; i < db_size; i++) { + descr_result->handle = db[offset + i].handle; + descr_result->uuid = db[offset + i].uuid; + descr_result++; + } + break; + } + case BLE_GATT_DB_INCLUDED_SERVICE: { + ble_gattc_included_svc_elem_t *incl_result = (ble_gattc_included_svc_elem_t *)result; + for (int i = 0; i < db_size; i++) { + incl_result->handle = db[offset + i].handle; + incl_result->incl_svc_s_handle = db[offset + i].start_handle; + incl_result->incl_svc_e_handle = db[offset + i].end_handle; + incl_result->uuid = db[offset + i].uuid; + incl_result++; + } + break; + } + default: + BLE_HS_LOG(DEBUG,"%s(), Not support type(%d)", __func__, type); + break; + } +} + +void ble_gattc_get_cached_service_by_uuid_db(uint16_t conn_id, + ble_uuid_t *svc_uuid, + ble_gattc_db_elem_t **db, + uint16_t *count) +{ + ble_gattc_get_service_with_uuid(conn_id, svc_uuid, db, count); +} + +void ble_gattc_get_cached_all_char_db(uint16_t conn_id, uint16_t start_handle, + uint16_t end_handle, ble_gattc_db_elem_t **db, + uint16_t *count) +{ + ble_gattc_get_db_with_operation(conn_id, BLE_GATT_OP_GET_ALL_CHAR, + 0, NULL, NULL, NULL, + start_handle, end_handle, db, count); + +} + +void ble_gattc_get_cached_all_descriptor_db(uint16_t conn_id, uint16_t char_handle, + ble_gattc_db_elem_t **db, uint16_t *count) +{ + ble_gattc_get_db_with_operation(conn_id, BLE_GATT_OP_GET_ALL_DESC, + char_handle, NULL, NULL, NULL, + 0, 0xFFFF, db, count); + +} + +void ble_gattc_get_cached_char_by_uuid_db(uint16_t conn_id, uint16_t start_handle, + uint16_t end_handle, ble_uuid_t *char_uuid, + ble_gattc_db_elem_t **db, uint16_t *count) +{ + ble_gattc_get_db_with_operation(conn_id, BLE_GATT_OP_GET_CHAR_BY_UUID, + 0, char_uuid, NULL, NULL, + start_handle, end_handle, db, count); + +} + +void ble_gatt_get_cached_descr_by_uuid_db(uint16_t conn_id, uint16_t start_handle, uint16_t end_handle, + ble_uuid_t *char_uuid, ble_uuid_t *descr_uuid, + ble_gattc_db_elem_t **db, uint16_t *count) +{ + ble_gattc_get_db_with_operation(conn_id, BLE_GATT_OP_GET_DESC_BY_UUID, + 0, char_uuid, descr_uuid, NULL, + start_handle, end_handle, db, count); +} + +void ble_gattc_get_cached_descr_by_char_handle_db(uint16_t conn_id, uint16_t char_handle, + ble_uuid_t *descr_uuid, + ble_gattc_db_elem_t **db, uint16_t *count) +{ + ble_gattc_get_db_with_operation(conn_id, BLE_GATT_OP_GET_DESC_BY_HANDLE, + char_handle, NULL, descr_uuid, NULL, + 0, 0xFFFF, db, count); +} + +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) +void ble_gattc_get_cached_include_service_db(uint16_t conn_id, uint16_t start_handle, uint16_t end_handle, + ble_uuid_t *incl_uuid, + ble_gattc_db_elem_t **db, uint16_t *count) +{ + ble_gattc_get_db_with_operation(conn_id, BLE_GATT_OP_GET_INCLUDE_SVC, + 0, NULL, NULL, incl_uuid, + start_handle, end_handle, db, count); +} +#endif + +void ble_gattc_get_db_size(uint16_t conn_handle, uint16_t start_handle, + uint16_t end_handle, uint16_t *count) +{ + ble_gattc_get_db_size_handle(conn_handle, start_handle, end_handle, count); +} + +void ble_gattc_get_db_size_by_type(uint16_t conn_handle, ble_gattc_db_attr_type type, + uint16_t start_handle, uint16_t end_handle, + uint16_t char_handle, uint16_t *count) +{ + ble_gattc_get_db_size_with_type_handle(conn_handle, type, start_handle, end_handle, char_handle, count); +} + +void ble_gattc_get_cached_gatt_db(uint16_t conn_handle, + uint16_t start_handle, + uint16_t end_handle, + ble_gattc_db_elem_t **db, + uint16_t *count, uint16_t *db_num) +{ + ble_gattc_get_gatt_db(conn_handle, start_handle, end_handle, db,count, db_num); +} + +int ble_gattc_get_service(uint16_t conn_handle, + ble_uuid_t *svc_uuid, + ble_gattc_service_elem_t *result, + uint16_t *count, uint16_t offset) +{ + int rc; + ble_gattc_db_elem_t *db = NULL; + uint16_t svc_num = 0; + + ble_gattc_get_cached_service_by_uuid_db(conn_handle, svc_uuid, &db, &svc_num); + rc = ble_gattc_check_valid_param(svc_num, offset); + if (rc != 0) { + if (db) { + free(db); + } + *count = 0; + return rc; + } else { + ble_gattc_fill_gatt_db_conversion(count, svc_num, ESP_BLE_GATT_DB_PRIMARY_SERVICE, offset, (void *)result, db); + } + + *count = svc_num; + //free the db buffer after used. + if (db) { + free(db); + } + return 0; +} + +int ble_gattc_get_all_char(uint16_t conn_handle, + uint16_t start_handle, + uint16_t end_handle, + ble_gattc_char_elem_t *result, + uint16_t *count, uint16_t offset) +{ + int rc; + ble_gattc_db_elem_t *db = NULL; + uint16_t char_num = 0; + + ble_gattc_get_cached_all_char_db(conn_handle, start_handle, end_handle, &db, &char_num); + rc = ble_gattc_check_valid_param(char_num, offset); + if (rc != 0) { + if (db) { + free(db); + } + *count = 0; + return rc; + } else { + ble_gattc_fill_gatt_db_conversion(count, char_num, ESP_BLE_GATT_DB_CHARACTERISTIC, offset, (void *)result, db); + } + + *count = char_num; + //free the db buffer after used. + if (db) { + free(db); + } + return 0; +} + +int ble_gattc_get_all_descr(uint16_t conn_handle, + uint16_t char_handle, + ble_gattc_descr_elem_t *result, + uint16_t *count, uint16_t offset) +{ + int rc; + ble_gattc_db_elem_t *db = NULL; + uint16_t descr_num = 0; + + ble_gattc_get_cached_all_descriptor_db(conn_handle, char_handle, &db, &descr_num); + rc = ble_gattc_check_valid_param(descr_num, offset); + if (rc != 0) { + if (db) { + free(db); + } + *count = 0; + return rc; + } else { + ble_gattc_fill_gatt_db_conversion(count, descr_num, ESP_BLE_GATT_DB_DESCRIPTOR, offset, (void *)result, db); + } + + *count = descr_num; + // free the db buffer after used. + if (db) { + free(db); + } + return 0; +} + +int ble_gattc_get_char_by_uuid(uint16_t conn_handle, + uint16_t start_handle, + uint16_t end_handle, + ble_uuid_t *char_uuid, + ble_gattc_char_elem_t *result, uint16_t *count) +{ + int rc; + ble_gattc_db_elem_t *db = NULL; + uint16_t char_num = 0; + + ble_gattc_get_cached_char_by_uuid_db(conn_handle, start_handle, end_handle, char_uuid, &db, &char_num); + + rc = ble_gattc_check_valid_param(char_num, 0); + if (rc != 0) { + if (db) { + free(db); + } + *count = 0; + return rc; + } else { + ble_gattc_fill_gatt_db_conversion(count, char_num, ESP_BLE_GATT_DB_CHARACTERISTIC, 0, (void *)result, db); + } + + *count = char_num; + // free the db buffer after used. + if (db) { + free(db); + } + return 0; + +} + +int ble_gattc_get_descr_by_uuid(uint16_t conn_handle, + uint16_t start_handle, + uint16_t end_handle, + ble_uuid_t *char_uuid, + ble_uuid_t *descr_uuid, + ble_gattc_descr_elem_t *result, uint16_t *count) +{ + int rc; + ble_gattc_db_elem_t *db = NULL; + uint16_t descr_num = 0; + + ble_gatt_get_cached_descr_by_uuid_db(conn_handle, start_handle, end_handle, char_uuid, descr_uuid, &db, &descr_num); + + rc = ble_gattc_check_valid_param(descr_num, 0); + if (rc != 0) { + if (db) { + free(db); + } + *count = 0; + return rc; + } else { + ble_gattc_fill_gatt_db_conversion(count, descr_num, ESP_BLE_GATT_DB_DESCRIPTOR, 0, (void *)result, db); + } + + *count = descr_num; + // free the db buffer after used. + if (db) { + free(db); + } + return 0; +} + +int ble_gattc_get_descr_by_char_handle(uint16_t conn_handle, + uint16_t char_handle, + ble_uuid_t *descr_uuid, + ble_gattc_descr_elem_t *result, uint16_t *count) +{ + int rc; + ble_gattc_db_elem_t *db = NULL; + uint16_t descr_num = 0; + + ble_gattc_get_cached_descr_by_char_handle_db(conn_handle, char_handle, descr_uuid, &db, &descr_num); + + rc = ble_gattc_check_valid_param(descr_num, 0); + if (rc != 0) { + if (db) { + free(db); + } + *count = 0; + return rc; + } else { + ble_gattc_fill_gatt_db_conversion(count, descr_num, ESP_BLE_GATT_DB_DESCRIPTOR, 0, (void *)result, db); + } + + *count = descr_num; + // free the db buffer after used. + if (db) { + free(db); + } + return 0; + +} + +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) +int ble_gattc_get_include_service(uint16_t conn_handle, + uint16_t start_handle, + uint16_t end_handle, + ble_uuid_t *incl_uuid, + ble_gattc_included_svc_elem_t *result, uint16_t *count) +{ + int rc; + ble_gattc_db_elem_t *db = NULL; + uint16_t incl_num = 0; + + ble_gattc_get_cached_include_service_db(conn_handle, start_handle, end_handle, incl_uuid, &db, &incl_num); + + rc = ble_gattc_check_valid_param(incl_num,0); + if (rc != 0) { + if (db) { + free(db); + } + *count = 0; + return rc; + } else { + ble_gattc_fill_gatt_db_conversion(count, incl_num, ESP_BLE_GATT_DB_INCLUDED_SERVICE, 0, (void *)result, db); + } + + *count = incl_num; + //free the db buffer after used. + if (db) { + free(db); + } + return 0; + +} +#endif + +int ble_gattc_get_attr_count(uint16_t conn_handle, esp_ble_gatt_db_attr_type_t type, + uint16_t start_handle, uint16_t end_handle, + uint16_t char_handle, uint16_t *count) +{ + if (type == ESP_BLE_GATT_DB_ALL) { + ble_gattc_get_db_size(conn_handle, start_handle, end_handle, count); + } else { + ble_gattc_get_db_size_by_type(conn_handle, type, start_handle, end_handle, char_handle, count); + } + return 0; +} + +int ble_gattc_get_db(uint16_t conn_handle, + uint16_t start_handle, uint16_t end_handle, + ble_gattc_db_elem_t *result, uint16_t *count) +{ + uint16_t num = 0; + ble_gattc_db_elem_t *db = NULL; + + ble_gattc_get_cached_gatt_db(conn_handle, start_handle, end_handle, &db, &num, count); + + if (num == 0) { + return BLE_ATT_ERR_ATTR_NOT_FOUND; + } + if (db) { + memcpy(result, db, num * sizeof(ble_gattc_db_elem_t)); // Copy data + free(db); // Free allocated memory + } + + return 0; +} + +#endif + /***************************************************************************** * $read * *****************************************************************************/ @@ -2907,7 +3523,7 @@ ble_gattc_read_tx(struct ble_gattc_proc *proc) { int rc; - rc = ble_att_clt_tx_read(proc->conn_handle, proc->read.handle); + rc = ble_att_clt_tx_read(proc->conn_handle, proc->cid, proc->read.handle); if (rc != 0) { return rc; } @@ -2934,8 +3550,8 @@ ble_gattc_read(uint16_t conn_handle, uint16_t attr_handle, goto done; } - proc->op = BLE_GATT_OP_READ; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_READ); + proc->read.handle = attr_handle; proc->read.cb = cb; proc->read.cb_arg = cb_arg; @@ -3070,7 +3686,7 @@ ble_gattc_read_uuid_rx_complete(struct ble_gattc_proc *proc, int status) static int ble_gattc_read_uuid_tx(struct ble_gattc_proc *proc) { - return ble_att_clt_tx_read_type(proc->conn_handle, + return ble_att_clt_tx_read_type(proc->conn_handle, proc->cid, proc->read_uuid.start_handle, proc->read_uuid.end_handle, &proc->read_uuid.chr_uuid.u); @@ -3096,8 +3712,8 @@ ble_gattc_read_by_uuid(uint16_t conn_handle, uint16_t start_handle, goto done; } - proc->op = BLE_GATT_OP_READ_UUID; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_READ_UUID); + ble_uuid_to_any(uuid, &proc->read_uuid.chr_uuid); proc->read_uuid.start_handle = start_handle; proc->read_uuid.end_handle = end_handle; @@ -3180,12 +3796,12 @@ ble_gattc_read_long_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); if (proc->read_long.offset == 0) { - rc = ble_att_clt_tx_read(proc->conn_handle, proc->read_long.handle); + rc = ble_att_clt_tx_read(proc->conn_handle, proc->cid, proc->read_long.handle); if (rc != 0) { return rc; } } else { - rc = ble_att_clt_tx_read_blob(proc->conn_handle, + rc = ble_att_clt_tx_read_blob(proc->conn_handle, proc->cid, proc->read_long.handle, proc->read_long.offset); if (rc != 0) { @@ -3256,7 +3872,7 @@ ble_gattc_read_long_rx_read_rsp(struct ble_gattc_proc *proc, int status, } /* Determine if this is the end of the attribute value. */ - mtu = ble_att_mtu(proc->conn_handle); + mtu = ble_att_mtu_by_cid(proc->conn_handle, proc->cid); if (mtu == 0) { /* No longer connected. */ return BLE_HS_EDONE; @@ -3297,8 +3913,8 @@ ble_gattc_read_long(uint16_t conn_handle, uint16_t handle, uint16_t offset, goto done; } - proc->op = BLE_GATT_OP_READ_LONG; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_READ_LONG); + proc->read_long.handle = handle; proc->read_long.offset = offset; proc->read_long.cb = cb; @@ -3337,7 +3953,7 @@ ble_gattc_read_mult_cb_var(struct ble_gattc_proc *proc, int status, return 0; } - memset(attr, 0, sizeof(*attr)); + memset(attr, 0, sizeof(attr)); for (i = 0; i < proc->read_mult.num_handles; i++) { attr[i].handle = proc->read_mult.handles[i]; @@ -3455,6 +4071,15 @@ ble_gattc_read_mult_tmo(struct ble_gattc_proc *proc) ble_gattc_read_mult_cb(proc, BLE_HS_ETIMEOUT, 0, 0); } +static void +ble_gattc_read_mult_var_tmo(struct ble_gattc_proc *proc) +{ + BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task()); + ble_gattc_dbg_assert_proc_not_inserted(proc); + + ble_gattc_read_mult_cb_var(proc, BLE_HS_ETIMEOUT, 0, 0); +} + /** * Handles an incoming ATT error response for the specified * read-multiple-characteristics proc. @@ -3467,12 +4092,24 @@ ble_gattc_read_mult_err(struct ble_gattc_proc *proc, int status, ble_gattc_read_mult_cb(proc, status, att_handle, NULL); } +/** + * Handles an incoming ATT error response for the specified + * read-multiple-variable-lengthcharacteristics proc. + */ +static void +ble_gattc_read_mult_var_err(struct ble_gattc_proc *proc, int status, + uint16_t att_handle) +{ + ble_gattc_dbg_assert_proc_not_inserted(proc); + ble_gattc_read_mult_cb_var(proc, status, att_handle, NULL); +} + static int ble_gattc_read_mult_tx(struct ble_gattc_proc *proc) { int rc; - rc = ble_att_clt_tx_read_mult(proc->conn_handle, proc->read_mult.handles, + rc = ble_att_clt_tx_read_mult(proc->conn_handle, proc->cid, proc->read_mult.handles, proc->read_mult.num_handles, proc->read_mult.variable); if (rc != 0) { return rc; @@ -3510,12 +4147,9 @@ ble_gattc_read_mult_internal(uint16_t conn_handle, const uint16_t *handles, goto done; } - if (variable) { - proc->op = BLE_GATT_OP_READ_MULT_VAR; - } else { - proc->op = BLE_GATT_OP_READ_MULT; - } - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, + variable ? BLE_GATT_OP_READ_MULT_VAR : BLE_GATT_OP_READ_MULT); + memcpy(proc->read_mult.handles, handles, num_handles * sizeof *handles); proc->read_mult.num_handles = num_handles; proc->read_mult.variable = variable; @@ -3573,15 +4207,18 @@ ble_gattc_write_no_rsp(uint16_t conn_handle, uint16_t attr_handle, #endif int rc; + uint16_t cid; STATS_INC(ble_gattc_stats, write_no_rsp); ble_gattc_log_write(attr_handle, OS_MBUF_PKTLEN(txom), 0); - rc = ble_att_clt_tx_write_cmd(conn_handle, attr_handle, txom); + cid = ble_eatt_get_available_chan_cid(conn_handle, BLE_GATT_OP_DUMMY); + rc = ble_att_clt_tx_write_cmd(conn_handle, cid, attr_handle, txom); if (rc != 0) { STATS_INC(ble_gattc_stats, write); } + ble_eatt_release_chan(conn_handle, BLE_GATT_OP_DUMMY); return rc; } @@ -3653,7 +4290,7 @@ ble_gattc_signed_write(uint16_t conn_handle, uint16_t attr_handle, /* Converting the csrk to little endian */ swap_buf(csrk, value_sec.csrk, 16); - rc = ble_att_clt_tx_signed_write_cmd(conn_handle, attr_handle, + rc = ble_att_clt_tx_signed_write_cmd(conn_handle, BLE_L2CAP_CID_ATT, attr_handle, csrk, value_sec.sign_counter, txom); if (rc != 0) { goto err; @@ -3749,15 +4386,15 @@ ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle, goto done; } - proc->op = BLE_GATT_OP_WRITE; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_WRITE); + proc->write.att_handle = attr_handle; proc->write.cb = cb; proc->write.cb_arg = cb_arg; ble_gattc_log_write(attr_handle, OS_MBUF_PKTLEN(txom), 1); - rc = ble_att_clt_tx_write_req(conn_handle, attr_handle, txom); + rc = ble_att_clt_tx_write_req(conn_handle, proc->cid, attr_handle, txom); txom = NULL; if (rc != 0) { goto done; @@ -3862,7 +4499,7 @@ ble_gattc_write_long_tx(struct ble_gattc_proc *proc) om = NULL; - max_sz = ble_att_mtu(proc->conn_handle) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; + max_sz = ble_att_mtu_by_cid(proc->conn_handle, proc->cid) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; if (max_sz <= 0) { /* Not connected. */ rc = BLE_HS_ENOTCONN; @@ -3874,7 +4511,7 @@ ble_gattc_write_long_tx(struct ble_gattc_proc *proc) proc->write_long.attr.offset); if (write_len <= 0) { - rc = ble_att_clt_tx_exec_write(proc->conn_handle, + rc = ble_att_clt_tx_exec_write(proc->conn_handle, proc->cid, BLE_ATT_EXEC_WRITE_F_EXECUTE); goto done; } @@ -3894,7 +4531,7 @@ ble_gattc_write_long_tx(struct ble_gattc_proc *proc) goto done; } - rc = ble_att_clt_tx_prep_write(proc->conn_handle, + rc = ble_att_clt_tx_prep_write(proc->conn_handle, proc->cid, proc->write_long.attr.handle, proc->write_long.attr.offset, om); om = NULL; @@ -3938,9 +4575,9 @@ ble_gattc_write_long_err(struct ble_gattc_proc *proc, int status, */ if (proc->write_long.attr.offset > 0 && proc->write_long.attr.offset < - OS_MBUF_PKTLEN(proc->write_long.attr.om)) { + OS_MBUF_PKTLEN(proc->write_long.attr.om)) { - ble_att_clt_tx_exec_write(proc->conn_handle, + ble_att_clt_tx_exec_write(proc->conn_handle, proc->cid, BLE_ATT_EXEC_WRITE_F_CANCEL); } @@ -4006,7 +4643,8 @@ ble_gattc_write_long_rx_prep(struct ble_gattc_proc *proc, rc = BLE_HS_EBADDATA; /* if data doesn't match up send cancel write */ - ble_att_clt_tx_exec_write(proc->conn_handle, BLE_ATT_EXEC_WRITE_F_CANCEL); + ble_att_clt_tx_exec_write(proc->conn_handle, proc->cid, + BLE_ATT_EXEC_WRITE_F_CANCEL); goto err; } else { /* Send follow-up request. */ @@ -4067,8 +4705,8 @@ ble_gattc_write_long(uint16_t conn_handle, uint16_t attr_handle, goto done; } - proc->op = BLE_GATT_OP_WRITE_LONG; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_WRITE_LONG); + proc->write_long.attr.handle = attr_handle; proc->write_long.attr.offset = offset; proc->write_long.attr.om = txom; @@ -4078,6 +4716,11 @@ ble_gattc_write_long(uint16_t conn_handle, uint16_t attr_handle, /* The mbuf is consumed by the procedure. */ txom = NULL; + if (proc->write_long.attr.offset > OS_MBUF_PKTLEN(proc->write_long.attr.om)) { + rc = BLE_ATT_ERR_INVALID_OFFSET; + goto done; + } + ble_gattc_log_write_long(proc); rc = ble_gattc_write_long_tx(proc); @@ -4168,14 +4811,14 @@ ble_gattc_write_reliable_tx(struct ble_gattc_proc *proc) attr_idx = proc->write_reliable.cur_attr; if (attr_idx >= proc->write_reliable.num_attrs) { - rc = ble_att_clt_tx_exec_write(proc->conn_handle, + rc = ble_att_clt_tx_exec_write(proc->conn_handle, proc->cid, BLE_ATT_EXEC_WRITE_F_EXECUTE); goto done; } attr = proc->write_reliable.attrs + attr_idx; - max_sz = ble_att_mtu(proc->conn_handle) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; + max_sz = ble_att_mtu_by_cid(proc->conn_handle, proc->cid) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; if (max_sz <= 0) { /* Not connected. */ rc = BLE_HS_ENOTCONN; @@ -4198,8 +4841,8 @@ ble_gattc_write_reliable_tx(struct ble_gattc_proc *proc) goto done; } - rc = ble_att_clt_tx_prep_write(proc->conn_handle, attr->handle, - attr->offset, om); + rc = ble_att_clt_tx_prep_write(proc->conn_handle, proc->cid, + attr->handle, attr->offset, om); om = NULL; if (rc != 0) { goto done; @@ -4242,7 +4885,7 @@ ble_gattc_write_reliable_err(struct ble_gattc_proc *proc, int status, */ if (proc->write_reliable.cur_attr < proc->write_reliable.num_attrs) { - ble_att_clt_tx_exec_write(proc->conn_handle, + ble_att_clt_tx_exec_write(proc->conn_handle, proc->cid, BLE_ATT_EXEC_WRITE_F_CANCEL); } } @@ -4355,8 +4998,8 @@ ble_gattc_write_reliable(uint16_t conn_handle, goto done; } - proc->op = BLE_GATT_OP_WRITE_RELIABLE; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_WRITE_RELIABLE); + proc->write_reliable.num_attrs = num_attrs; proc->write_reliable.cur_attr = 0; proc->write_reliable.cb = cb; @@ -4407,6 +5050,8 @@ static int ble_gatts_check_conn_aware(uint16_t conn_handle, bool *aware) { } #endif +#endif + int ble_gatts_notify_custom(uint16_t conn_handle, uint16_t chr_val_handle, struct os_mbuf *txom) @@ -4473,6 +5118,119 @@ done: return rc; } +#if MYNEWT_VAL(BLE_GATTC) +int +ble_gatts_notify_multiple_custom(uint16_t conn_handle, + size_t chr_count, + struct ble_gatt_notif *tuples) +{ +#if !MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE) + return BLE_HS_ENOTSUP; +#endif + + int rc = 0; + int i = 0; + uint16_t cur_chr_cnt = 0; + /* mtu = MTU - 1 octet (OP code) */ + uint16_t mtu = ble_att_mtu(conn_handle) - 1; + struct os_mbuf *txom; + struct ble_hs_conn *conn; + + txom = ble_hs_mbuf_att_pkt(); + if (txom == NULL) { + return BLE_HS_ENOMEM; + } + + conn = ble_hs_conn_find(conn_handle); + if (conn == NULL) { + return ENOTCONN; + } + + STATS_INC(ble_gattc_stats, multi_notify); + ble_gattc_log_multi_notify(tuples, chr_count); + + /* Read missing values */ + for (i = 0; i < chr_count; i++) { + if (tuples->handle == 0) { + rc = BLE_HS_EINVAL; + goto done; + } + if (tuples[i].value == NULL) { + /* No custom attribute data; read the value from the specified + * attribute + */ + rc = ble_att_svr_read_local(tuples[i].handle, &tuples[i].value); + if (rc != 0) { + BLE_HS_LOG(ERROR, "Attribute read failed (err=0x%02x)", rc); + goto done; + } + } + } + + /* If peer does not support fall back to multiple single value + * Notifications */ + if ((conn->bhc_gatt_svr.peer_cl_sup_feat[0] & 0x04) == 0) { + for (i = 0; i < chr_count; i++) { + rc = ble_att_clt_tx_notify(conn_handle, tuples[i].handle, tuples[i].value); + if (rc != 0) { + goto done; + } + } + goto done; + } + + for (i = 0; i < chr_count; i++) { + if (OS_MBUF_PKTLEN(txom) + OS_MBUF_PKTLEN(tuples[i].value) > mtu && cur_chr_cnt < 2) { + rc = ble_att_clt_tx_notify(conn_handle, tuples[i].handle, + tuples[i].value); + if (rc != 0) { + goto done; + } + continue; + } else if (OS_MBUF_PKTLEN(txom) + OS_MBUF_PKTLEN(tuples[i].value) > mtu) { + rc = ble_att_clt_tx_notify_mult(conn_handle, txom); + if (rc != 0) { + goto done; + } + cur_chr_cnt = 0; + /* buffer was consumed, allocate new one */ + txom = ble_hs_mbuf_att_pkt(); + if (txom == NULL) { + return BLE_HS_ENOMEM; + } + } + + /* Handle */ + os_mbuf_append(txom, &tuples[i].handle, sizeof(uint16_t)); + + /* Length */ + os_mbuf_append(txom, &OS_MBUF_PKTLEN(tuples[i].value), + sizeof(uint16_t)); + + /* Value */ + os_mbuf_concat(txom, tuples[i].value); + cur_chr_cnt++; + } + + if (cur_chr_cnt == 1) { + rc = ble_att_clt_tx_notify(conn_handle, tuples[chr_count].handle, + tuples[chr_count].value); + } else { + rc = ble_att_clt_tx_notify_mult(conn_handle, txom); + } + +done: + if (rc != 0) { + STATS_INC(ble_gattc_stats, multi_notify_fail); + } + + /* Tell the application that multiple notification transmissions were attempted. */ + for (i = 0; i < chr_count; i++) { + ble_gap_notify_tx_event(rc, conn_handle, tuples[i].handle, 0); + } + return rc; +} + /** * Deprecated. Should not be used. Use ble_gatts_notify_custom instead. */ @@ -4482,6 +5240,7 @@ ble_gattc_notify_custom(uint16_t conn_handle, uint16_t chr_val_handle, { return ble_gatts_notify_custom(conn_handle, chr_val_handle, txom); } +#endif int ble_gatts_notify(uint16_t conn_handle, uint16_t chr_val_handle) @@ -4497,6 +5256,7 @@ ble_gatts_notify(uint16_t conn_handle, uint16_t chr_val_handle) return rc; } +#if MYNEWT_VAL(BLE_GATTC) /** * Deprecated. Should not be used. Use ble_gatts_notify instead. */ @@ -4506,10 +5266,12 @@ ble_gattc_notify(uint16_t conn_handle, uint16_t chr_val_handle) return ble_gatts_notify(conn_handle, chr_val_handle); } +#endif + /***************************************************************************** * $indicate * *****************************************************************************/ - +#if MYNEWT_VAL(BLE_GATTS) /** * Handles an incoming ATT error response for the specified indication proc. * A device should never send an error in response to an indication. If this @@ -4539,7 +5301,9 @@ ble_gatts_indicate_err(struct ble_gattc_proc *proc, int status, /* Send the next indication if one is pending. */ ble_gatts_send_next_indicate(proc->conn_handle); } +#endif +#if MYNEWT_VAL(BLE_GATTC) static void ble_gatts_indicate_tmo(struct ble_gattc_proc *proc) { @@ -4557,24 +5321,28 @@ ble_gatts_indicate_tmo(struct ble_gattc_proc *proc) static void ble_gatts_indicate_rx_rsp(struct ble_gattc_proc *proc) { - int rc; - ble_gattc_dbg_assert_proc_not_inserted(proc); +#if MYNEWT_VAL(BLE_GATTS) + int rc; rc = ble_gatts_rx_indicate_ack(proc->conn_handle, proc->indicate.chr_val_handle); if (rc != 0) { return; } +#endif /* Tell the application about the received acknowledgment. */ ble_gap_notify_tx_event(BLE_HS_EDONE, proc->conn_handle, proc->indicate.chr_val_handle, 1); - +#if MYNEWT_VAL(BLE_GATTS) /* Send the next indication if one is pending. */ ble_gatts_send_next_indicate(proc->conn_handle); +#endif } +#endif + /** * Causes the indication in progress for the specified connection (if any) to * fail with a status code of BLE_HS_ENOTCONN; @@ -4608,8 +5376,8 @@ ble_gatts_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle, goto done; } - proc->op = BLE_GATT_OP_INDICATE; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_INDICATE); + proc->indicate.chr_val_handle = chr_val_handle; ble_gattc_log_indicate(chr_val_handle); @@ -4648,7 +5416,7 @@ ble_gatts_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle, } } - rc = ble_att_clt_tx_indicate(conn_handle, chr_val_handle, txom); + rc = ble_att_clt_tx_indicate(conn_handle, proc->cid, chr_val_handle, txom); txom = NULL; if (rc != 0) { goto done; @@ -4675,6 +5443,7 @@ done: return rc; } +#if MYNEWT_VAL(BLE_GATTC) /** * Deprecated. Should not be used. Use ble_gatts_indicate_custom instead. */ @@ -4684,6 +5453,8 @@ ble_gattc_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle, { return ble_gatts_indicate_custom(conn_handle, chr_val_handle, txom); } +#endif + int ble_gatts_indicate(uint16_t conn_handle, uint16_t chr_val_handle) @@ -4691,6 +5462,8 @@ ble_gatts_indicate(uint16_t conn_handle, uint16_t chr_val_handle) return ble_gatts_indicate_custom(conn_handle, chr_val_handle, NULL); } + +#if MYNEWT_VAL(BLE_GATTC) /** * Deprecated. Should not be used. Use ble_gatts_indicate instead. */ @@ -4709,12 +5482,12 @@ ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle) * procedure. */ void -ble_gattc_rx_err(uint16_t conn_handle, uint16_t handle, uint16_t status) +ble_gattc_rx_err(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t status) { struct ble_gattc_proc *proc; ble_gattc_err_fn *err_cb; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, BLE_GATT_OP_NONE); + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_NONE); if (proc != NULL) { err_cb = ble_gattc_err_dispatch_get(proc->op); if (err_cb != NULL) { @@ -4729,11 +5502,13 @@ ble_gattc_rx_err(uint16_t conn_handle, uint16_t handle, uint16_t status) * GATT procedure. */ void -ble_gattc_rx_mtu(uint16_t conn_handle, int status, uint16_t chan_mtu) +ble_gattc_rx_mtu(uint16_t conn_handle, uint16_t cid, int status, uint16_t chan_mtu) { struct ble_gattc_proc *proc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, BLE_GATT_OP_MTU); + assert(cid == BLE_L2CAP_CID_ATT); + + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, BLE_L2CAP_CID_ATT, BLE_GATT_OP_MTU); if (proc != NULL) { ble_gattc_mtu_cb(proc, status, 0, chan_mtu); ble_gattc_process_status(proc, BLE_HS_EDONE); @@ -4745,7 +5520,7 @@ ble_gattc_rx_mtu(uint16_t conn_handle, int status, uint16_t chan_mtu) * find-information-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_find_info_idata(uint16_t conn_handle, +ble_gattc_rx_find_info_idata(uint16_t conn_handle, uint16_t cid, struct ble_att_find_info_idata *idata) { #if !NIMBLE_BLE_ATT_CLT_FIND_INFO @@ -4755,7 +5530,7 @@ ble_gattc_rx_find_info_idata(uint16_t conn_handle, struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_DISC_ALL_DSCS); if (proc != NULL) { rc = ble_gattc_disc_all_dscs_rx_idata(proc, idata); @@ -4768,7 +5543,7 @@ ble_gattc_rx_find_info_idata(uint16_t conn_handle, * find-information-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status) +ble_gattc_rx_find_info_complete(uint16_t conn_handle, uint16_t cid, int status) { #if !NIMBLE_BLE_ATT_CLT_FIND_INFO return; @@ -4777,8 +5552,8 @@ ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status) struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, - BLE_GATT_OP_DISC_ALL_DSCS); + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, + BLE_GATT_OP_DISC_ALL_DSCS); if (proc != NULL) { rc = ble_gattc_disc_all_dscs_rx_complete(proc, status); ble_gattc_process_status(proc, rc); @@ -4790,7 +5565,7 @@ ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status) * find-by-type-value-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, +ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, uint16_t cid, struct ble_att_find_type_value_hinfo *hinfo) { #if !NIMBLE_BLE_ATT_CLT_FIND_TYPE @@ -4800,7 +5575,7 @@ ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_DISC_SVC_UUID); if (proc != NULL) { rc = ble_gattc_disc_svc_uuid_rx_hinfo(proc, hinfo); @@ -4813,7 +5588,7 @@ ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, * find-by-type-value-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status) +ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, uint16_t cid, int status) { #if !NIMBLE_BLE_ATT_CLT_FIND_TYPE return; @@ -4822,8 +5597,8 @@ ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status) struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, - BLE_GATT_OP_DISC_SVC_UUID); + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, + BLE_GATT_OP_DISC_SVC_UUID); if (proc != NULL) { rc = ble_gattc_disc_svc_uuid_rx_complete(proc, status); ble_gattc_process_status(proc, rc); @@ -4835,7 +5610,7 @@ ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status) * to the appropriate active GATT procedure. */ void -ble_gattc_rx_read_type_adata(uint16_t conn_handle, +ble_gattc_rx_read_type_adata(uint16_t conn_handle, uint16_t cid, struct ble_att_read_type_adata *adata) { #if !NIMBLE_BLE_ATT_CLT_READ_TYPE @@ -4846,7 +5621,7 @@ ble_gattc_rx_read_type_adata(uint16_t conn_handle, struct ble_gattc_proc *proc; int rc; - proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, + proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, cid, ble_gattc_rx_read_type_elem_entries, &rx_entry); if (proc != NULL) { @@ -4860,7 +5635,7 @@ ble_gattc_rx_read_type_adata(uint16_t conn_handle, * the appropriate active GATT procedure. */ void -ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status) +ble_gattc_rx_read_type_complete(uint16_t conn_handle, uint16_t cid, int status) { #if !NIMBLE_BLE_ATT_CLT_READ_TYPE return; @@ -4871,7 +5646,7 @@ ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status) int rc; proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY( - conn_handle, ble_gattc_rx_read_type_complete_entries, + conn_handle, cid, ble_gattc_rx_read_type_complete_entries, &rx_entry); if (proc != NULL) { rc = rx_entry->cb(proc, status); @@ -4884,7 +5659,7 @@ ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status) * read-by-group-type-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, +ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, uint16_t cid, struct ble_att_read_group_type_adata *adata) { #if !NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE @@ -4894,7 +5669,7 @@ ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_DISC_ALL_SVCS); if (proc != NULL) { rc = ble_gattc_disc_all_svcs_rx_adata(proc, adata); @@ -4907,7 +5682,7 @@ ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, * read-by-group-type-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int status) +ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, uint16_t cid, int status) { #if !NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE return; @@ -4916,8 +5691,8 @@ ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int status) struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, - BLE_GATT_OP_DISC_ALL_SVCS); + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, + BLE_GATT_OP_DISC_ALL_SVCS); if (proc != NULL) { rc = ble_gattc_disc_all_svcs_rx_complete(proc, status); ble_gattc_process_status(proc, rc); @@ -4929,7 +5704,7 @@ ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int status) * procedure. */ void -ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, struct os_mbuf **om) +ble_gattc_rx_read_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **om) { #if !NIMBLE_BLE_ATT_CLT_READ return; @@ -4939,7 +5714,7 @@ ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, struct os_mbuf **om) struct ble_gattc_proc *proc; int rc; - proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, + proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, cid, ble_gattc_rx_read_rsp_entries, &rx_entry); if (proc != NULL) { @@ -4953,7 +5728,7 @@ ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, struct os_mbuf **om) * procedure. */ void -ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, +ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **om) { #if !NIMBLE_BLE_ATT_CLT_READ_BLOB @@ -4963,7 +5738,7 @@ ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_READ_LONG); if (proc != NULL) { rc = ble_gattc_read_long_rx_read_rsp(proc, status, om); @@ -4976,7 +5751,7 @@ ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, * GATT procedure. */ void -ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, +ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **om, bool variable) { #if !NIMBLE_BLE_ATT_CLT_READ_MULT @@ -4988,7 +5763,7 @@ ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, op = variable ? BLE_GATT_OP_READ_MULT_VAR : BLE_GATT_OP_READ_MULT; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, op); + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, op); if (proc != NULL) { ble_gattc_read_mult_cb(proc, status, 0, om); ble_gattc_process_status(proc, BLE_HS_EDONE); @@ -5000,7 +5775,7 @@ ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, * procedure. */ void -ble_gattc_rx_write_rsp(uint16_t conn_handle) +ble_gattc_rx_write_rsp(uint16_t conn_handle, uint16_t cid) { #if !NIMBLE_BLE_ATT_CLT_WRITE return; @@ -5008,7 +5783,7 @@ ble_gattc_rx_write_rsp(uint16_t conn_handle) struct ble_gattc_proc *proc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_WRITE); if (proc != NULL) { ble_gattc_write_cb(proc, 0, 0); @@ -5021,7 +5796,7 @@ ble_gattc_rx_write_rsp(uint16_t conn_handle) * GATT procedure. */ void -ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, +ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, uint16_t cid, int status, uint16_t handle, uint16_t offset, struct os_mbuf **om) { @@ -5033,7 +5808,7 @@ ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, struct ble_gattc_proc *proc; int rc; - proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, + proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, cid, ble_gattc_rx_prep_entries, &rx_entry); if (proc != NULL) { @@ -5047,7 +5822,7 @@ ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, * GATT procedure. */ void -ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status) +ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, uint16_t cid, int status) { #if !NIMBLE_BLE_ATT_CLT_EXEC_WRITE return; @@ -5057,7 +5832,7 @@ ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status) struct ble_gattc_proc *proc; int rc; - proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, + proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, cid, ble_gattc_rx_exec_entries, &rx_entry); if (proc != NULL) { rc = rx_entry->cb(proc, status); @@ -5065,12 +5840,13 @@ ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status) } } +#if MYNEWT_VAL(BLE_GATTC) /** * Dispatches an incoming ATT handle-value-confirmation to the appropriate * active GATT procedure. */ void -ble_gatts_rx_indicate_rsp(uint16_t conn_handle) +ble_gatts_rx_indicate_rsp(uint16_t conn_handle, uint16_t cid) { #if !NIMBLE_BLE_ATT_CLT_INDICATE return; @@ -5078,13 +5854,14 @@ ble_gatts_rx_indicate_rsp(uint16_t conn_handle) struct ble_gattc_proc *proc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_INDICATE); if (proc != NULL) { ble_gatts_indicate_rx_rsp(proc); ble_gattc_process_status(proc, BLE_HS_EDONE); } } +#endif /***************************************************************************** * $misc * @@ -5101,7 +5878,19 @@ ble_gatts_rx_indicate_rsp(uint16_t conn_handle) void ble_gattc_connection_broken(uint16_t conn_handle) { + struct ble_hs_conn *conn; + struct os_mbuf_pkthdr *omp; + ble_gattc_fail_procs(conn_handle, BLE_GATT_OP_NONE, BLE_HS_ENOTCONN); + + ble_hs_lock(); + conn = ble_hs_conn_find(conn_handle); + ble_hs_unlock(); + + while ((omp = STAILQ_FIRST(&conn->att_tx_q)) != NULL) { + STAILQ_REMOVE_HEAD(&conn->att_tx_q, omp_next); + os_mbuf_free_chain(OS_MBUF_PKTHDR_TO_MBUF(omp)); + } } /** @@ -5113,11 +5902,16 @@ ble_gattc_any_jobs(void) return !STAILQ_EMPTY(&ble_gattc_procs); } +#endif + int ble_gattc_init(void) { int rc; +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + STAILQ_INIT(&temp_proc_list); +#endif STAILQ_INIT(&ble_gattc_procs); if (MYNEWT_VAL(BLE_GATT_MAX_PROCS) > 0) { diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc_cache.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc_cache.c index 7f0bf310..497393c3 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc_cache.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc_cache.c @@ -31,7 +31,7 @@ #define GATT_CACHE_PREFIX "gatt_" #define INVALID_ADDR_NUM 0xff #define MAX_DEVICE_IN_CACHE 50 -#define MAX_ADDR_LIST_CACHE_BUF 2048 +#define MAX_ADDR_LIST_CACHE_BUF 4096 #if MYNEWT_VAL(BLE_GATT_CACHING) static const char *cache_key = "gattc_cache_key"; @@ -305,7 +305,8 @@ static void check_uuid(ble_uuid_any_t *uuid) static void ble_gattc_fill_nv_attr_entry(ble_uuid_any_t uuid, uint16_t s_handle, uint16_t e_handle, ble_gatt_attr_type attr_type, bool is_primary, - struct ble_gatt_nv_attr *nv_attr, int index, uint8_t properties) + struct ble_gatt_nv_attr *nv_attr, int index, uint8_t properties, + uint16_t incl_svc_s_handle, uint16_t incl_svc_e_handle) { ble_uuid_copy(&nv_attr[index].uuid, &uuid.u); check_uuid(&nv_attr[index].uuid); @@ -314,6 +315,8 @@ ble_gattc_fill_nv_attr_entry(ble_uuid_any_t uuid, uint16_t s_handle, uint16_t e_ nv_attr[index].is_primary = is_primary; nv_attr[index].attr_type = attr_type; nv_attr[index].properties = properties; + nv_attr[index].incl_svc_s_handle = incl_svc_s_handle; + nv_attr[index].incl_svc_e_handle = incl_svc_e_handle; if (s_handle >= svc_end_handle) { svc_end_handle = s_handle; @@ -327,6 +330,9 @@ static void ble_gattc_fill_nv_attr(struct ble_gattc_cache_conn *peer, size_t num_attr, struct ble_gatt_nv_attr *nv_attr) { struct ble_gattc_cache_conn_svc *svc; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + struct ble_gattc_cache_conn_incl_svc *included_svc; +#endif struct ble_gattc_cache_conn_chr *chr; struct ble_gattc_cache_conn_dsc *dsc; @@ -336,18 +342,29 @@ ble_gattc_fill_nv_attr(struct ble_gattc_cache_conn *peer, size_t num_attr, struc SLIST_FOREACH(svc, &peer->svcs, next) { ble_gattc_fill_nv_attr_entry(svc->svc.uuid, svc->svc.start_handle, svc->svc.end_handle, BLE_GATT_ATTR_TYPE_SRVC, svc->type == BLE_GATT_SVC_TYPE_PRIMARY, - nv_attr, index, 0); + nv_attr, index, 0, 0, 0); svc_index = index; index++; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + if (!SLIST_EMPTY(&svc->incl_svc)) { + SLIST_FOREACH(included_svc, &svc->incl_svc, next) { + ble_gattc_fill_nv_attr_entry(included_svc->svc.uuid, included_svc->svc.handle, + 0, BLE_GATT_ATTR_TYPE_INCL_SRVC, false, + nv_attr, index, 0, included_svc->svc.start_handle, included_svc->svc.end_handle); + index++; + } + + } +#endif SLIST_FOREACH(chr, &svc->chrs, next) { ble_gattc_fill_nv_attr_entry(chr->chr.uuid, chr->chr.val_handle, chr->chr.def_handle, BLE_GATT_ATTR_TYPE_CHAR, false, - nv_attr, index, chr->chr.properties); + nv_attr, index, chr->chr.properties, 0, 0); index++; SLIST_FOREACH(dsc, &chr->dscs, next) { ble_gattc_fill_nv_attr_entry(dsc->dsc.uuid, dsc->dsc.handle, 0, BLE_GATT_ATTR_TYPE_CHAR_DESCR, false, nv_attr, index, - 0); + 0, 0, 0); index++; } } @@ -388,6 +405,7 @@ ble_gattc_cache_addr_save(uint8_t *out_index, ble_addr_t addr, uint8_t * hash_ke address list. */ if(num > MYNEWT_VAL(BLE_GATT_CACHING_MAX_CONNS)) { + nimble_platform_mem_free(p_buf); return BLE_HS_ENOMEM; } BLE_HS_LOG(DEBUG, "BD addr not present"); @@ -396,6 +414,7 @@ ble_gattc_cache_addr_save(uint8_t *out_index, ble_addr_t addr, uint8_t * hash_ke } else { BLE_HS_LOG(DEBUG, "Hash key not present, saving new data"); if(num > MYNEWT_VAL(BLE_GATT_CACHING_MAX_CONNS)) { + nimble_platform_mem_free(p_buf); return BLE_HS_ENOMEM; } insert_ind = num - 1; @@ -485,6 +504,7 @@ ble_gattc_cache_save(struct ble_gattc_cache_conn *peer, size_t num_attr) if(rc != 0) { /* cannot save address, return */ BLE_HS_LOG(ERROR, "Failed to save cache %d", rc); + nimble_platform_mem_free(nv_attr); return; } @@ -530,6 +550,7 @@ static int ble_gattc_add_svc_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_attr) { struct ble_gatt_svc *gatt_svc; + int rc; gatt_svc = (struct ble_gatt_svc *)nimble_platform_mem_malloc(sizeof(struct ble_gatt_svc)); if (gatt_svc == NULL) { @@ -540,29 +561,39 @@ ble_gattc_add_svc_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_at gatt_svc->end_handle = nv_attr.e_handle; ble_uuid_copy(&gatt_svc->uuid, &nv_attr.uuid.u); - return ble_gattc_cache_conn_svc_add(peer_addr, gatt_svc); + rc = ble_gattc_cache_conn_svc_add(peer_addr, gatt_svc, nv_attr.is_primary); + nimble_platform_mem_free(gatt_svc); + return rc; } +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) static int ble_gattc_add_inc_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_attr) { - struct ble_gatt_svc *gatt_svc; + int rc; + struct ble_gatt_incl_svc *gatt_incl_svc; - gatt_svc = (struct ble_gatt_svc *)nimble_platform_mem_malloc(sizeof(struct ble_gatt_svc)); - if (gatt_svc == NULL) { + gatt_incl_svc = (struct ble_gatt_incl_svc *)nimble_platform_mem_malloc(sizeof(struct ble_gatt_incl_svc)); + if (gatt_incl_svc == NULL) { return BLE_HS_ENOMEM; } - gatt_svc->start_handle = nv_attr.s_handle; - gatt_svc->end_handle = nv_attr.e_handle; - ble_uuid_copy(&gatt_svc->uuid, &nv_attr.uuid.u); - return ble_gattc_cache_conn_inc_add(peer_addr, gatt_svc); + gatt_incl_svc->handle = nv_attr.s_handle; + gatt_incl_svc->start_handle = nv_attr.incl_svc_s_handle; + gatt_incl_svc->end_handle = nv_attr.incl_svc_e_handle; + ble_uuid_copy(&gatt_incl_svc->uuid, &nv_attr.uuid.u); + + rc = ble_gattc_cache_conn_inc_add(peer_addr, gatt_incl_svc); + nimble_platform_mem_free(gatt_incl_svc); + return rc; } +#endif static int ble_gattc_add_chr_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_attr) { struct ble_gatt_chr *gatt_chr; + int rc; gatt_chr = (struct ble_gatt_chr *)nimble_platform_mem_malloc(sizeof(struct ble_gatt_chr)); if (gatt_chr == NULL) { return BLE_HS_ENOMEM; @@ -573,13 +604,16 @@ ble_gattc_add_chr_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_at ble_uuid_copy(&gatt_chr->uuid, &nv_attr.uuid.u); gatt_chr->properties = nv_attr.properties; - return ble_gattc_cache_conn_chr_add(peer_addr, 0, gatt_chr); + rc = ble_gattc_cache_conn_chr_add(peer_addr, 0, gatt_chr); + nimble_platform_mem_free(gatt_chr); + return rc; } static int ble_gattc_add_dsc_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_attr) { struct ble_gatt_dsc *gatt_dsc; + int rc; gatt_dsc = (struct ble_gatt_dsc *)nimble_platform_mem_malloc(sizeof(struct ble_gatt_dsc)); if (gatt_dsc == NULL) { return BLE_HS_ENOMEM; @@ -588,7 +622,9 @@ ble_gattc_add_dsc_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_at gatt_dsc->handle = nv_attr.s_handle; ble_uuid_copy(&gatt_dsc->uuid, &nv_attr.uuid.u); - return ble_gattc_cache_conn_dsc_add(peer_addr, 0, gatt_dsc); + rc = ble_gattc_cache_conn_dsc_add(peer_addr, 0, gatt_dsc); + nimble_platform_mem_free(gatt_dsc); + return rc; } int @@ -613,11 +649,7 @@ ble_gattc_cache_load(ble_addr_t peer_addr) for (int i = 0; i < num_attr; i++) { switch (nv_attr[i].attr_type) { case BLE_GATT_ATTR_TYPE_SRVC: - if (nv_attr[i].is_primary) { - rc = ble_gattc_add_svc_from_cache(peer_addr, nv_attr[i]); - } else { - rc = ble_gattc_add_inc_from_cache(peer_addr, nv_attr[i]); - } + rc = ble_gattc_add_svc_from_cache(peer_addr, nv_attr[i]); break; case BLE_GATT_ATTR_TYPE_CHAR: @@ -628,6 +660,11 @@ ble_gattc_cache_load(ble_addr_t peer_addr) rc = ble_gattc_add_dsc_from_cache(peer_addr, nv_attr[i]); break; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + case BLE_GATT_ATTR_TYPE_INCL_SRVC: + rc = ble_gattc_add_inc_from_cache(peer_addr, nv_attr[i]); + break; +#endif default: break; } diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc_cache_conn.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc_cache_conn.c index 8ec8fdaa..d46ab111 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc_cache_conn.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc_cache_conn.c @@ -35,6 +35,9 @@ #define CHECK_CACHE_CONN_STATE(cache_state, cb, cb_arg, opcode, \ s_handle, e_handle, p_uuid) \ + if (ble_hs_cfg.gatt_use_cache == 0) { \ + return BLE_HS_ENOTSUP; \ + } \ op = &conn->pending_op; \ switch(cache_state) { \ case SVC_DISC_IN_PROGRESS: \ @@ -86,6 +89,11 @@ static void *ble_gattc_cache_conn_svc_mem; static struct os_mempool ble_gattc_cache_conn_svc_pool; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) +static void *ble_gattc_cache_conn_incl_svc_mem; +static struct os_mempool ble_gattc_cache_conn_incl_svc_pool; +#endif + static void *ble_gattc_cache_conn_chr_mem; static struct os_mempool ble_gattc_cache_conn_chr_pool; @@ -337,6 +345,13 @@ ble_gattc_cache_conn_chr_find(const struct ble_gattc_cache_conn_svc *svc, uint16 return chr; } +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) +static void +ble_gattc_cache_conn_incl_svc_delete(struct ble_gattc_cache_conn_incl_svc *incl_svc) +{ + os_memblock_put(&ble_gattc_cache_conn_incl_svc_pool, incl_svc); +} +#endif static void ble_gattc_cache_conn_chr_delete(struct ble_gattc_cache_conn_chr *chr) { @@ -546,13 +561,68 @@ ble_gattc_cache_conn_dsc_find_uuid(const struct ble_gattc_cache_conn *ble_gattc_ return NULL; } +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) +static struct ble_gattc_cache_conn_incl_svc * +ble_gattc_cache_conn_incl_svc_find_prev(const struct ble_gattc_cache_conn_svc *svc, uint16_t incl_svc_handle) +{ + struct ble_gattc_cache_conn_incl_svc *prev; + struct ble_gattc_cache_conn_incl_svc *incl_svc; + + prev = NULL; + SLIST_FOREACH(incl_svc, &svc->incl_svc, next) { + if (incl_svc->svc.handle >= incl_svc_handle) { + break; + } + + prev = incl_svc; + } + + return prev; +} + +static struct ble_gattc_cache_conn_incl_svc * +ble_gattc_cache_conn_incl_svc_find(const struct ble_gattc_cache_conn_svc *svc, uint16_t incl_svc_handle, + struct ble_gattc_cache_conn_incl_svc **out_prev) +{ + struct ble_gattc_cache_conn_incl_svc *prev; + struct ble_gattc_cache_conn_incl_svc *incl_svc; + + prev = ble_gattc_cache_conn_incl_svc_find_prev(svc, incl_svc_handle); + if (prev == NULL) { + incl_svc = SLIST_FIRST(&svc->incl_svc); + } else { + incl_svc = SLIST_NEXT(prev, next); + } + + if (incl_svc != NULL && incl_svc->svc.handle != incl_svc_handle) { + incl_svc = NULL; + } + + if (out_prev != NULL) { + *out_prev = prev; + } + return incl_svc; +} +#endif + +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) +int +ble_gattc_cache_conn_inc_add(ble_addr_t peer_addr, const struct ble_gatt_incl_svc *gatt_svc) +#else int ble_gattc_cache_conn_inc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *gatt_svc) +#endif { - struct ble_gattc_cache_conn_svc *prev; struct ble_gattc_cache_conn_svc *svc; + struct ble_gattc_cache_conn_svc *prev; struct ble_gattc_cache_conn *peer; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + struct ble_gattc_cache_conn_incl_svc *incl_svc; + struct ble_gattc_cache_conn_incl_svc *incl_svc_prev; + struct ble_gattc_cache_conn_svc *cur_svc; +#endif + peer = ble_gattc_cache_conn_find_by_addr(peer_addr); if (peer == NULL) { BLE_HS_LOG(ERROR, "Peer not found"); @@ -560,36 +630,79 @@ ble_gattc_cache_conn_inc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *ga } svc = ble_gattc_cache_conn_svc_find(peer, gatt_svc->start_handle, &prev); - if (svc != NULL) { - /* Inc already discovered. */ + + if (!svc) { + /* Secondary Service */ + svc = os_memblock_get(&ble_gattc_cache_conn_svc_pool); + if (svc == NULL) { + /* Out of memory. */ + return BLE_HS_ENOMEM; + } + + memset(svc, 0, sizeof * svc); + + svc->type = BLE_GATT_SVC_TYPE_SECONDARY; + svc->svc.start_handle = gatt_svc->start_handle; + svc->svc.end_handle = gatt_svc->end_handle; + memcpy(&svc->svc.uuid, &gatt_svc->uuid, sizeof(ble_uuid_any_t)); + + SLIST_INIT(&svc->chrs); +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + SLIST_INIT(&svc->incl_svc); +#endif + if (prev == NULL) { + SLIST_INSERT_HEAD(&peer->svcs, svc, next); + } else { + SLIST_INSERT_AFTER(prev, svc, next); + } + + BLE_HS_LOG(DEBUG, "Secondary Svc added with start_handle = %d , end_handle = %d", + gatt_svc->start_handle, gatt_svc->end_handle); + } + +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + /* Including the services into including list of current service*/ + cur_svc = ble_gattc_cache_conn_svc_find_range(peer, gatt_svc->handle); + + if (cur_svc == NULL) { + /* Can't find service for discovered included service; this shouldn't + * happen. + */ + BLE_HS_LOG(WARN, "Current Service is NULL.\n"); + assert(0); + return BLE_HS_EUNKNOWN; + } + + incl_svc = ble_gattc_cache_conn_incl_svc_find(cur_svc, gatt_svc->handle, &incl_svc_prev); + if (incl_svc != NULL) { + /* Already discovered */ return 0; } - svc = os_memblock_get(&ble_gattc_cache_conn_svc_pool); - if (svc == NULL) { - /* Out of memory. */ + incl_svc = os_memblock_get(&ble_gattc_cache_conn_incl_svc_pool); + if (incl_svc == NULL) { return BLE_HS_ENOMEM; } - memset(svc, 0, sizeof * svc); - svc->type = BLE_GATT_SVC_TYPE_SECONDARY; - svc->svc = *gatt_svc; - SLIST_INIT(&svc->chrs); + incl_svc->svc.handle = gatt_svc->handle; + incl_svc->svc.start_handle = gatt_svc->start_handle; + incl_svc->svc.end_handle = gatt_svc->end_handle; + memcpy(&incl_svc->svc.uuid, &gatt_svc->uuid, sizeof(ble_uuid_any_t)); - if (prev == NULL) { - SLIST_INSERT_HEAD(&peer->svcs, svc, next); + if (incl_svc_prev == NULL) { + SLIST_INSERT_HEAD(&cur_svc->incl_svc, incl_svc, next); } else { - SLIST_INSERT_AFTER(prev, svc, next); + SLIST_INSERT_AFTER(incl_svc_prev, incl_svc, next); } - BLE_HS_LOG(DEBUG, "Inc added with start_handle = %d and end_handle = %d", - gatt_svc->start_handle, gatt_svc->end_handle); - + BLE_HS_LOG(DEBUG, "Inc added with handle = %d", + gatt_svc->handle); +#endif return 0; } int -ble_gattc_cache_conn_svc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *gatt_svc) +ble_gattc_cache_conn_svc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *gatt_svc, bool is_primary) { struct ble_gattc_cache_conn_svc *prev; struct ble_gattc_cache_conn_svc *svc; @@ -614,8 +727,16 @@ ble_gattc_cache_conn_svc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *ga } memset(svc, 0, sizeof * svc); - svc->type = BLE_GATT_SVC_TYPE_PRIMARY; + if (is_primary) { + svc->type = BLE_GATT_SVC_TYPE_PRIMARY; + } else { + svc->type = BLE_GATT_SVC_TYPE_SECONDARY; + } + svc->svc = *gatt_svc; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + SLIST_INIT(&svc->incl_svc); +#endif SLIST_INIT(&svc->chrs); if (prev == NULL) { @@ -635,6 +756,14 @@ ble_gattc_cache_conn_svc_delete(struct ble_gattc_cache_conn_svc *svc) { struct ble_gattc_cache_conn_chr *chr; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + struct ble_gattc_cache_conn_incl_svc *incl_svc; + // Free included services + while ((incl_svc = SLIST_FIRST(&svc->incl_svc)) != NULL) { + SLIST_REMOVE_HEAD(&svc->incl_svc, next); + ble_gattc_cache_conn_incl_svc_delete(incl_svc); + } +#endif while ((chr = SLIST_FIRST(&svc->chrs)) != NULL) { SLIST_REMOVE_HEAD(&svc->chrs, next); ble_gattc_cache_conn_chr_delete(chr); @@ -652,14 +781,83 @@ ble_gattc_cache_conn_get_db_size(struct ble_gattc_cache_conn *peer) size_t db_size = 0; struct ble_gattc_cache_conn_svc *svc; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + struct ble_gattc_cache_conn_incl_svc *included_svc; +#endif + struct ble_gattc_cache_conn_chr *chr; + struct ble_gattc_cache_conn_dsc *dsc; + + SLIST_FOREACH(svc, &peer->svcs, next) { + db_size++; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + SLIST_FOREACH(included_svc, &svc->incl_svc, next) { + db_size++; + } +#endif + SLIST_FOREACH(chr, &svc->chrs, next) { + db_size++; + SLIST_FOREACH(dsc, &chr->dscs, next) { + db_size++; + } + } + } + + return db_size; +} + +size_t +ble_gattc_get_db_size_with_handle(struct ble_gattc_cache_conn *peer, uint16_t start_handle, uint16_t end_handle) +{ + if (peer == NULL || SLIST_EMPTY(&peer->svcs)) { + return 0; + } + + struct ble_gattc_cache_conn_svc *svc; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + struct ble_gattc_cache_conn_incl_svc *included_svc; +#endif struct ble_gattc_cache_conn_chr *chr; struct ble_gattc_cache_conn_dsc *dsc; + size_t db_size = 0; SLIST_FOREACH(svc, &peer->svcs, next) { + if (svc->svc.end_handle < start_handle) { + continue; + } + if (svc->svc.start_handle > end_handle) { + break; + } + db_size++; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + SLIST_FOREACH(included_svc, &svc->incl_svc, next) { + if (included_svc->svc.handle < start_handle) { + continue; + } + if (included_svc->svc.handle > end_handle) { + return db_size; + } + + db_size++; + } +#endif SLIST_FOREACH(chr, &svc->chrs, next) { + if (chr->chr.val_handle < start_handle) { + continue; + } + if (chr->chr.val_handle > end_handle) { + return db_size; + } db_size++; + SLIST_FOREACH(dsc, &chr->dscs, next) { + if (dsc->dsc.handle < start_handle) { + continue; + } + + if (dsc->dsc.handle > end_handle) { + return db_size; + } db_size++; } } @@ -668,6 +866,492 @@ ble_gattc_cache_conn_get_db_size(struct ble_gattc_cache_conn *peer) return db_size; } +size_t +ble_gattc_get_db_size_with_type(struct ble_gattc_cache_conn *peer, uint8_t type, + uint16_t start_handle, uint16_t end_handle, uint16_t char_handle) +{ + if (peer == NULL || SLIST_EMPTY(&peer->svcs)) { + return 0; + } + struct ble_gattc_cache_conn_svc *svc; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + struct ble_gattc_cache_conn_incl_svc *included_svc; +#endif + struct ble_gattc_cache_conn_chr *chr; + struct ble_gattc_cache_conn_dsc *dsc; + size_t db_size = 0; + // Iterate through the services in the cache connection. + SLIST_FOREACH(svc, &peer->svcs, next) { + // Skip services that are out of the requested handle range. + if (svc->svc.end_handle < start_handle || svc->svc.start_handle > end_handle) { + continue; + } + + // Handle the different types of GATT database entries. + switch (type) { + case BLE_GATT_DB_PRIMARY_SERVICE: + if (svc->type == BLE_GATT_SVC_TYPE_PRIMARY && + svc->svc.start_handle >= start_handle && + svc->svc.end_handle <= end_handle) { + db_size++; + } + break; + + case BLE_GATT_DB_SECONDARY_SERVICE: + if (svc->type == BLE_GATT_SVC_TYPE_SECONDARY && + svc->svc.start_handle >= start_handle && + svc->svc.end_handle <= end_handle) { + db_size++; + } + break; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + case BLE_GATT_DB_INCLUDED_SERVICE: + // Iterate through included service. + SLIST_FOREACH(included_svc, &svc->incl_svc, next) { + if (included_svc->svc.handle >= start_handle && included_svc->svc.handle <= end_handle) { + db_size++; + } + } + break; +#endif + case BLE_GATT_DB_CHARACTERISTIC: + // Iterate through characteristics. + SLIST_FOREACH(chr, &svc->chrs, next) { + if (chr->chr.val_handle >= start_handle && chr->chr.val_handle <= end_handle) { + db_size++; + } + } + break; + + case BLE_GATT_DB_DESCRIPTOR: + // Iterate through characteristics and their descriptors. + SLIST_FOREACH(chr, &svc->chrs, next) { + if (chr->chr.val_handle >= start_handle && chr->chr.val_handle <= end_handle) { + if (chr->chr.val_handle == char_handle) { + SLIST_FOREACH(dsc, &chr->dscs, next) { + if (dsc->dsc.handle >= start_handle && + dsc->dsc.handle <= end_handle && + chr->chr.val_handle == char_handle) { + db_size++; + } + } + } + } + } + break; + } + } + + return db_size; +} + +// fill a element into database +void ble_gattc_fill_gatt_db_el(ble_gattc_db_elem_t *attr, + ble_gattc_db_attr_type type, + uint16_t handle, + uint16_t s_handle, + uint16_t e_handle, + uint8_t prop, + ble_uuid_any_t uuid) +{ + attr->type = type; + attr->handle = handle; + attr->start_handle = s_handle; + attr->end_handle = e_handle; + attr->properties = prop; + attr->uuid = uuid; +} + +void ble_gattc_get_service_with_uuid(uint16_t conn_handle, + ble_uuid_t *svc_uuid, + ble_gattc_db_elem_t **svc_db, + uint16_t *count) +{ + + struct ble_gattc_cache_conn *cache_conn; + struct ble_gattc_cache_conn_svc *svc; + + // Find the connection in the cache + cache_conn = ble_gattc_cache_conn_find(conn_handle); + if (cache_conn == NULL || SLIST_EMPTY(&cache_conn->svcs)) { + BLE_HS_LOG(WARN, "%s(), no service.", __func__); + *count = 0; + *svc_db = NULL; + return; + } + + size_t db_size = 0; + SLIST_FOREACH(svc, &cache_conn->svcs, next) { + if (svc_uuid == NULL || ble_uuid_cmp(&svc->svc.uuid.u, svc_uuid) == 0) { + db_size++; + } + } + + if (!db_size) { + BLE_HS_LOG(DEBUG, "the db size is 0."); + *count = 0; + *svc_db = NULL; + return; + } + + // Allocate memory for the GATT database + void *buffer = malloc(db_size * sizeof(ble_gattc_db_elem_t)); + if (!buffer) { + BLE_HS_LOG(WARN, "%s(), no resource.", __func__); + *count = 0; + *svc_db = NULL; + return; + } + ble_gattc_db_elem_t *curr_db_attr = buffer; + db_size = 0; + + // Iterate through services in the cache + SLIST_FOREACH(svc, &cache_conn->svcs, next) { + if (svc_uuid == NULL || ble_uuid_cmp(&svc->svc.uuid.u, svc_uuid) == 0) { + ble_gattc_fill_gatt_db_el(curr_db_attr, + svc->type == BLE_GATT_SVC_TYPE_PRIMARY ? /* attr type */ + BLE_GATT_DB_PRIMARY_SERVICE:BLE_GATT_DB_SECONDARY_SERVICE, + 0, /* handle */ + svc->svc.start_handle, /* s_handle */ + svc->svc.end_handle, /* e_handle */ + 0, /* property */ + svc->svc.uuid); /* uuid */ + curr_db_attr++; + db_size++; + } + } + + *svc_db = buffer; + *count = db_size; +} + +void ble_gattc_get_db_with_operation(uint16_t conn_handle, + ble_gatt_get_db_op_t op, + uint16_t char_handle, + ble_uuid_t *char_uuid, + ble_uuid_t *descr_uuid, + ble_uuid_t *incl_uuid, + uint16_t start_handle, uint16_t end_handle, + ble_gattc_db_elem_t **char_db, + uint16_t *count) +{ + + struct ble_gattc_cache_conn *cache_conn; + struct ble_gattc_cache_conn_svc *svc; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + struct ble_gattc_cache_conn_incl_svc *included_svc; +#endif + struct ble_gattc_cache_conn_chr *chr; + struct ble_gattc_cache_conn_dsc *dsc; + + // Find the connection in the cache + cache_conn = ble_gattc_cache_conn_find(conn_handle); + if (cache_conn == NULL || SLIST_EMPTY(&cache_conn->svcs)) { + BLE_HS_LOG(WARN, "the service cache is empty."); + *count = 0; + *char_db = NULL; + return; + } + size_t db_size = ble_gattc_get_db_size_with_handle(cache_conn, start_handle, end_handle); + + if (!db_size) { + BLE_HS_LOG(DEBUG, "the db size is 0."); + *count = 0; + *char_db = NULL; + return; + } + + // Allocate memory for the GATT database + void *buffer = malloc(db_size * sizeof(ble_gattc_db_elem_t)); + if (!buffer) { + BLE_HS_LOG(WARN, "%s(), no resource.", __func__); + *count = 0; + *char_db = NULL; + return; + } + ble_gattc_db_elem_t *curr_db_attr = buffer; + db_size = 0; + + // Iterate through services in the cache + SLIST_FOREACH(svc, &cache_conn->svcs, next) { + if (svc->svc.end_handle < start_handle || svc->svc.start_handle > end_handle) { + continue; + } + +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + // Check for included services + if (op == BLE_GATT_OP_GET_INCLUDE_SVC) { + if (SLIST_EMPTY(&svc->incl_svc)) { + continue; + } + SLIST_FOREACH(included_svc, &svc->incl_svc, next) { + if (included_svc->svc.handle < start_handle || included_svc->svc.handle > end_handle) { + continue; + } + + if (incl_uuid == NULL || ble_uuid_cmp(&included_svc->svc.uuid.u, incl_uuid) == 0) { + ble_gattc_fill_gatt_db_el(curr_db_attr, + BLE_GATT_DB_INCLUDED_SERVICE, /* attr type*/ + included_svc->svc.handle, /* handle */ + included_svc->svc.start_handle, /* s_handle */ + included_svc->svc.end_handle, /* e_handle */ + 0, /* property */ + included_svc->svc.uuid); /* uuid */ + curr_db_attr++; + db_size++; + } + } + continue; + } +#endif + // Check for characteristics + SLIST_FOREACH(chr, &svc->chrs, next) { + if (chr->chr.val_handle < start_handle || chr->chr.val_handle > end_handle) { + continue; + } + if ((op == BLE_GATT_OP_GET_ALL_CHAR || op == BLE_GATT_OP_GET_CHAR_BY_UUID) && + (char_uuid == NULL || ble_uuid_cmp(&chr->chr.uuid.u, char_uuid) == 0)) { + ble_gattc_fill_gatt_db_el(curr_db_attr, + BLE_GATT_DB_CHARACTERISTIC, /* attr type*/ + chr->chr.val_handle, /* handle */ + 0, /* s_handle */ + 0, /* e_handle */ + chr->chr.properties, /* property */ + chr->chr.uuid); /* uuid */ + curr_db_attr++; + db_size++; + continue; + } + + if ((op == BLE_GATT_OP_GET_DESC_BY_HANDLE || op == BLE_GATT_OP_GET_ALL_DESC) && + (chr->chr.val_handle != char_handle)) { + continue; + } + + if ((op == BLE_GATT_OP_GET_DESC_BY_UUID && ble_uuid_cmp(&chr->chr.uuid.u, char_uuid) != 0)) { + continue; + } + + // Check for descriptors + if (!SLIST_EMPTY(&chr->dscs)) { + SLIST_FOREACH(dsc, &chr->dscs, next) { + if (dsc->dsc.handle < start_handle || dsc->dsc.handle > end_handle) { + continue; + } + if (((op == BLE_GATT_OP_GET_ALL_DESC || op == BLE_GATT_OP_GET_DESC_BY_UUID) && + (descr_uuid == NULL || ble_uuid_cmp(&dsc->dsc.uuid.u, descr_uuid) == 0)) || + (op == BLE_GATT_OP_GET_DESC_BY_HANDLE && ble_uuid_cmp(&dsc->dsc.uuid.u, descr_uuid) == 0)) { + ble_gattc_fill_gatt_db_el(curr_db_attr, + BLE_GATT_DB_DESCRIPTOR, /* attr type*/ + dsc->dsc.handle, /* handle */ + 0, /* s_handle */ + 0, /* e_handle */ + 0, /* property */ + dsc->dsc.uuid); /* uuid */ + curr_db_attr++; + db_size++; + } + } + } + + } + } + + *char_db = buffer; + *count = db_size; + return; +} + +void ble_gattc_get_db_size_with_type_handle(uint16_t conn_handle, + ble_gattc_db_attr_type type, + uint16_t start_handle, + uint16_t end_handle, + uint16_t char_handle, uint16_t *count) +{ + struct ble_gattc_cache_conn *cache_conn; + + cache_conn = ble_gattc_cache_conn_find(conn_handle); + if (cache_conn == NULL) { + *count = 0; + return ; + } + + *count = ble_gattc_get_db_size_with_type(cache_conn, type, start_handle, end_handle, char_handle); +} + +void ble_gattc_get_db_size_handle(uint16_t conn_handle, + uint16_t start_handle, + uint16_t end_handle, + uint16_t *count) +{ + struct ble_gattc_cache_conn *cache_conn; + + cache_conn = ble_gattc_cache_conn_find(conn_handle); + if (cache_conn == NULL) { + *count = 0; + return; + } + *count = ble_gattc_get_db_size_with_handle(cache_conn, start_handle, end_handle); +} + +// Copy the server GATT database into db parameter. + +static void ble_gattc_get_gatt_db_impl(struct ble_gattc_cache_conn *peer, + uint16_t start_handle, + uint16_t end_handle, + ble_gattc_db_elem_t **db, + uint16_t *count, uint16_t *db_num) +{ + if (!peer || SLIST_EMPTY(&peer->svcs)) { + *count = 0; + *db = NULL; + return; + } + + size_t db_size = ble_gattc_get_db_size_with_handle(peer, start_handle, end_handle); + if (!db_size) { + BLE_HS_LOG(DEBUG, "the db size is 0."); + *count = 0; + *db = NULL; + return; + } + db_size = (*db_num > db_size) ? db_size : (*db_num); + // Allocate memory for the GATT database + void *buffer = malloc(db_size * sizeof(ble_gattc_db_elem_t)); + if (!buffer) { + BLE_HS_LOG(WARN, "%s(), no resource.", __func__); + *count = 0; + *db = NULL; + return; + } + + ble_gattc_db_elem_t *curr_db_attr = buffer; + struct ble_gattc_cache_conn_svc *svc; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + struct ble_gattc_cache_conn_incl_svc *included_svc; +#endif + struct ble_gattc_cache_conn_chr *chr; + struct ble_gattc_cache_conn_dsc *dsc; + + + SLIST_FOREACH(svc, &peer->svcs, next) { + if (svc->svc.end_handle < start_handle) { + continue; + } + + if (svc->svc.start_handle > end_handle) { + break; + } + ble_gattc_fill_gatt_db_el(curr_db_attr, + svc->type == BLE_GATT_SVC_TYPE_PRIMARY ? /* attr type */ + BLE_GATT_DB_PRIMARY_SERVICE: + BLE_GATT_DB_SECONDARY_SERVICE, + 0, /* attr handle */ + svc->svc.start_handle, /* start handle*/ + svc->svc.end_handle, /* end handle */ + 0, /* property */ + svc->svc.uuid); /* uuid */ + curr_db_attr++; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + // Iterate over included services + SLIST_FOREACH(included_svc, &svc->incl_svc, next) { + if (included_svc->svc.handle < start_handle) { + continue; + } + + if (included_svc->svc.handle > end_handle) { + *db = buffer; + *count = db_size; + return; + } + + ble_gattc_fill_gatt_db_el(curr_db_attr, + BLE_GATT_DB_INCLUDED_SERVICE, /* attr type */ + included_svc->svc.handle, /* attr handle */ + included_svc->svc.start_handle, /* s_handle */ + included_svc->svc.end_handle, /* e_handle */ + 0, /* property */ + included_svc->svc.uuid); /* uuid */ + curr_db_attr++; + } +#endif + // Iterate over characterstic + SLIST_FOREACH(chr, &svc->chrs, next) { + if (chr->chr.val_handle < start_handle) { + continue; + } + + if (chr->chr.val_handle > end_handle) { + *db = buffer; + *count = db_size; + return; + } + ble_gattc_fill_gatt_db_el(curr_db_attr, + BLE_GATT_DB_CHARACTERISTIC, /* attr type */ + chr->chr.val_handle, /* attr handle */ + 0, /* s_handle */ + 0, /* e_handle */ + chr->chr.properties, /* property */ + chr->chr.uuid); /* uuid */ + curr_db_attr++; + // Iterate over descriptors + SLIST_FOREACH(dsc, &chr->dscs, next) { + if (dsc->dsc.handle < start_handle) { + continue; + } + + if (dsc->dsc.handle > end_handle) { + *db = buffer; + *count = db_size; + return; + } + ble_gattc_fill_gatt_db_el(curr_db_attr, + BLE_GATT_DB_DESCRIPTOR, /* attr type */ + dsc->dsc.handle, /* attr handle */ + 0, /* s_handle */ + 0, /* e_handle */ + 0, /* property */ + dsc->dsc.uuid); /* uuid */ + curr_db_attr++; + } + } + } + + *db = buffer; + *count = db_size; + + return; +} + +// Copy the server GATT database into db parameter +void ble_gattc_get_gatt_db(uint16_t conn_handle, + uint16_t start_handle, + uint16_t end_handle, + ble_gattc_db_elem_t **db, + uint16_t *count, uint16_t *db_num) +{ + struct ble_gattc_cache_conn *cache_conn; + + cache_conn = ble_gattc_cache_conn_find(conn_handle); + + if (cache_conn == NULL) { + BLE_HS_LOG(ERROR, "Unknown conn ID: %d", conn_handle); + return; + } + + if (cache_conn->cache_state != CACHE_VERIFIED){ + BLE_HS_LOG(ERROR, "server cache not available, server state = %d",cache_conn->cache_state); + return; + } + + if (SLIST_EMPTY(&cache_conn->svcs)) { + BLE_HS_LOG(ERROR, "the service cache is empty."); + return; + } + ble_gattc_get_gatt_db_impl(cache_conn, start_handle, end_handle, db, count, db_num); + +} + static void ble_gattc_cache_conn_cache_peer(struct ble_gattc_cache_conn *peer) { @@ -718,6 +1402,7 @@ ble_gattc_cache_conn_bonding_established(uint16_t conn_handle) BLE_HS_DBG_ASSERT(conn != NULL); ble_hs_conn_addrs(conn, &addrs); peer->ble_gattc_cache_conn_addr = conn->bhc_peer_addr; + peer->ble_gattc_cache_conn_addr.type = ble_hs_misc_peer_addr_type_to_id(conn->bhc_peer_addr.type); @@ -811,6 +1496,7 @@ ble_gattc_cache_conn_disc_complete(struct ble_gattc_cache_conn *peer, int rc) BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16)); if (bonded || chr != NULL) { /* persist the cache */ + ble_gattc_cacheReset(&hs_conn->bhc_peer_addr); ble_gattc_cache_conn_cache_peer(peer); /* TODO */ } } else { @@ -827,7 +1513,7 @@ ble_gattc_cache_conn_disc_complete(struct ble_gattc_cache_conn *peer, int rc) } break; case BLE_GATT_OP_DISC_SVC_UUID : - rc = ble_gattc_cache_conn_search_svc_by_uuid(peer->conn_handle, &op->uuid, op->cb, op->cb_arg); + rc = ble_gattc_cache_conn_search_svc_by_uuid(peer->conn_handle, op->uuid, op->cb, op->cb_arg); if (rc != 0) { BLE_HS_LOG(ERROR, "search service by uuid failed"); } @@ -845,7 +1531,7 @@ ble_gattc_cache_conn_disc_complete(struct ble_gattc_cache_conn *peer, int rc) } break; case BLE_GATT_OP_DISC_CHR_UUID : - rc = ble_gattc_cache_conn_search_chrs_by_uuid(peer->conn_handle, op->start_handle, op->end_handle, &op->uuid, op->cb, op->cb_arg); + rc = ble_gattc_cache_conn_search_chrs_by_uuid(peer->conn_handle, op->start_handle, op->end_handle, op->uuid, op->cb, op->cb_arg); if (rc != 0) { BLE_HS_LOG(ERROR, "search chars by uuid failed"); } @@ -860,9 +1546,15 @@ ble_gattc_cache_conn_disc_complete(struct ble_gattc_cache_conn *peer, int rc) } } -static void -ble_gattc_cache_conn_undisc_all(struct ble_gattc_cache_conn *peer) +void +ble_gattc_cache_conn_undisc_all(ble_addr_t peer_addr) { + struct ble_gattc_cache_conn * peer = NULL; + + peer = ble_gattc_cache_conn_find_by_addr(peer_addr); + if (peer == NULL) { + return; + } ble_gattc_cacheReset(&peer->ble_gattc_cache_conn_addr); struct ble_gattc_cache_conn_svc *svc; @@ -873,9 +1565,15 @@ ble_gattc_cache_conn_undisc_all(struct ble_gattc_cache_conn *peer) } } +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) +static int +ble_gattc_cache_conn_inc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, + const struct ble_gatt_incl_svc *service, void *arg) +#else static int ble_gattc_cache_conn_inc_disced(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service, void *arg) +#endif { struct ble_gattc_cache_conn *peer; int rc; @@ -890,7 +1588,7 @@ ble_gattc_cache_conn_inc_disced(uint16_t conn_handle, const struct ble_gatt_erro case BLE_HS_EDONE: /* All services discovered; start discovering incs. */ - ble_gattc_cache_conn_disc_chrs(peer); + ble_gattc_cache_conn_disc_incs(peer); rc = 0; break; @@ -918,7 +1616,7 @@ ble_gattc_cache_conn_svc_disced(uint16_t conn_handle, const struct ble_gatt_erro switch (error->status) { case 0: - rc = ble_gattc_cache_conn_svc_add(peer->ble_gattc_cache_conn_addr, service); + rc = ble_gattc_cache_conn_svc_add(peer->ble_gattc_cache_conn_addr, service, true); break; case BLE_HS_EDONE: @@ -946,7 +1644,7 @@ ble_gattc_cache_conn_disc(struct ble_gattc_cache_conn *peer) { int rc; - ble_gattc_cache_conn_undisc_all(peer); + ble_gattc_cache_conn_undisc_all(peer->ble_gattc_cache_conn_addr); peer->disc_prev_chr_val = 1; @@ -964,6 +1662,11 @@ ble_gattc_cache_conn_on_read(uint16_t conn_handle, { uint16_t res; + if (error->status == BLE_HS_EDONE) { + /* Ignore Read by UUID follow-up callback */ + return 0; + } + if (error->status != 0) { res = error->status; ble_gattc_cache_conn_disc_complete((struct ble_gattc_cache_conn *)arg, res); @@ -975,9 +1678,10 @@ ble_gattc_cache_conn_on_read(uint16_t conn_handle, BLE_HS_LOG(INFO, "Hash value up to date, skipping Discovery"); ble_gattc_cache_conn_disc_complete((struct ble_gattc_cache_conn *)arg, res); return 0; + } else { + res = ble_gattc_cache_conn_disc((struct ble_gattc_cache_conn *)arg); + return res; } - return 0; - } int @@ -1194,6 +1898,7 @@ ble_gattc_cache_conn_disc_incs(struct ble_gattc_cache_conn *peer) if (peer->cur_svc == NULL) { if (peer->disc_prev_chr_val > 0) { ble_gattc_cache_conn_disc_chrs(peer); + return; } } } @@ -1204,7 +1909,7 @@ ble_gattc_cache_conn_disc_incs(struct ble_gattc_cache_conn *peer) svc->svc.end_handle, ble_gattc_cache_conn_inc_disced, peer); if (rc != 0) { - ble_gattc_cache_conn_disc_complete(peer, rc); + ble_gattc_cache_conn_disc_chrs(peer); } return; } @@ -1226,6 +1931,10 @@ ble_gattc_cache_conn_update(uint16_t conn_handle, uint16_t start_handle, uint16_ } peer->cache_state = CACHE_INVALID; + if (MYNEWT_VAL(BLE_GATT_CACHING_DISABLE_AUTO)) { + /* Do not automatically re-discover and correct cache */ + return; + } rc = ble_gattc_cache_conn_disc(peer); if (rc != 0) { peer->cache_state = CACHE_INVALID; @@ -1249,7 +1958,7 @@ ble_gattc_cache_conn_get_svc_changed_handle(uint16_t conn_handle) BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_SERVICE_CHANGED_UUID16)); if (chr == NULL) { - BLE_HS_LOG(ERROR, "Cannot find service change characteristic"); + BLE_HS_LOG(DEBUG, "Cannot find service change characteristic"); return -1; } return chr->chr.val_handle; @@ -1264,6 +1973,10 @@ ble_gattc_cache_conn_free_mem(void) free(ble_gattc_cache_conn_svc_mem); ble_gattc_cache_conn_svc_mem = NULL; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + free(ble_gattc_cache_conn_incl_svc_mem); + ble_gattc_cache_conn_incl_svc_mem = NULL; +#endif free(ble_gattc_cache_conn_chr_mem); ble_gattc_cache_conn_chr_mem = NULL; @@ -1277,16 +1990,23 @@ ble_gattc_cache_conn_init() int rc; int max_ble_gattc_cache_conns; int max_svcs; +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + int max_incl_svcs; +#endif int max_chrs; int max_dscs; void *storage_cb; - max_ble_gattc_cache_conns = MYNEWT_VAL(BLE_MAX_CONNECTIONS); - max_svcs = (MYNEWT_VAL(BLE_MAX_CONNECTIONS)) * + max_ble_gattc_cache_conns = MYNEWT_VAL(BLE_GATT_CACHING_MAX_CONNS); + max_svcs = (MYNEWT_VAL(BLE_GATT_CACHING_MAX_CONNS)) * (MYNEWT_VAL(BLE_GATT_CACHING_MAX_SVCS)); - max_chrs = (MYNEWT_VAL(BLE_MAX_CONNECTIONS)) * +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + max_incl_svcs = (MYNEWT_VAL(BLE_GATT_CACHING_MAX_CONNS)) * + (MYNEWT_VAL(BLE_GATT_CACHING_MAX_INCL_SVCS)); +#endif + max_chrs = (MYNEWT_VAL(BLE_GATT_CACHING_MAX_CONNS)) * (MYNEWT_VAL(BLE_GATT_CACHING_MAX_CHRS)); - max_dscs = (MYNEWT_VAL(BLE_MAX_CONNECTIONS)) * + max_dscs = (MYNEWT_VAL(BLE_GATT_CACHING_MAX_CONNS)) * (MYNEWT_VAL(BLE_GATT_CACHING_MAX_DSCS)); /* Free memory first in case this function gets called more than once. */ ble_gattc_cache_conn_free_mem(); @@ -1321,6 +2041,22 @@ ble_gattc_cache_conn_init() goto err; } +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + ble_gattc_cache_conn_incl_svc_mem = malloc( + OS_MEMPOOL_BYTES(max_incl_svcs, sizeof(struct ble_gattc_cache_conn_incl_svc))); + if (ble_gattc_cache_conn_incl_svc_mem == NULL) { + rc = BLE_HS_ENOMEM; + goto err; + } + + rc = os_mempool_init(&ble_gattc_cache_conn_incl_svc_pool, max_incl_svcs, + sizeof(struct ble_gattc_cache_conn_incl_svc), ble_gattc_cache_conn_incl_svc_mem, + "ble_gattc_cache_conn_incl_svc_pool"); + if (rc != 0) { + rc = BLE_HS_EOS; + goto err; + } +#endif ble_gattc_cache_conn_chr_mem = malloc( OS_MEMPOOL_BYTES(max_chrs, sizeof(struct ble_gattc_cache_conn_chr))); if (ble_gattc_cache_conn_chr_mem == NULL) { @@ -1385,7 +2121,6 @@ ble_gattc_cache_error(int status, uint16_t att_handle) static int ble_gattc_cache_conn_verify(struct ble_gattc_cache_conn *conn) { struct ble_hs_conn *gap_conn; - const struct ble_gattc_cache_conn_chr *chr; int rc; if (conn->cache_state == CACHE_VERIFIED) { @@ -1404,16 +2139,10 @@ static int ble_gattc_cache_conn_verify(struct ble_gattc_cache_conn *conn) conn->cache_state = CACHE_VERIFIED; return 0; } - chr = ble_gattc_cache_conn_chr_find_uuid(conn, - BLE_UUID16_DECLARE(BLE_GATT_SVC_UUID16), - BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16)); - if (chr == NULL) { - /* no way to verify */ - conn->cache_state = CACHE_INVALID; - return 0; - } - rc = ble_gattc_read(conn->conn_handle, chr->chr.val_handle, - ble_gattc_cache_conn_on_read, conn); + + rc = ble_gattc_read_by_uuid(conn->conn_handle, 0x0001, 0xFFFF, + BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16), + ble_gattc_cache_conn_on_read, conn); if (rc != 0) { /* no way to verify */ conn->cache_state = CACHE_INVALID; @@ -1440,6 +2169,9 @@ static void ble_gattc_cache_search_all_svcs_cb(struct ble_npl_event *ev) if (conn == NULL) { return; } + + ble_npl_event_deinit(&conn->disc_ev); + op = &conn->pending_op; dcb = op->cb; SLIST_FOREACH(svc, &conn->svcs, next) { @@ -1449,13 +2181,14 @@ static void ble_gattc_cache_search_all_svcs_cb(struct ble_npl_event *ev) } status = BLE_HS_EDONE; dcb(conn->conn_handle, ble_gattc_cache_error(status, 0), &svc->svc, op->cb_arg); + return; } static void ble_gattc_cache_conn_fill_op(struct ble_gattc_cache_conn_op *op, uint16_t start_handle, uint16_t end_handle, - ble_uuid_t uuid, + const ble_uuid_t *uuid, void *cb, void *cb_arg, uint8_t cb_type) @@ -1490,7 +2223,7 @@ ble_gattc_cache_conn_search_all_svcs(uint16_t conn_handle, } CHECK_CACHE_CONN_STATE(conn->cache_state, cb, cb_arg, BLE_GATT_OP_DISC_ALL_SVCS, - 0, 0, uuid); + 0, 0, &uuid); /* put the event in the queue to mimic the gattc behaviour */ ble_npl_event_init(&conn->disc_ev, ble_gattc_cache_search_all_svcs_cb, &conn->conn_handle); ble_npl_eventq_put((struct ble_npl_eventq *)ble_hs_evq_get(), &conn->disc_ev); @@ -1513,15 +2246,19 @@ ble_gattc_cache_conn_search_svc_by_uuid_cb(struct ble_npl_event *ev) if (conn == NULL) { return; } + + ble_npl_event_deinit(&conn->disc_ev); + op = &conn->pending_op; dcb = op->cb; SLIST_FOREACH(svc, &conn->svcs, next) { - if (svc->type == BLE_GATT_SVC_TYPE_PRIMARY && ble_uuid_cmp(&svc->svc.uuid.u, &op->uuid) == 0) { + if (svc->type == BLE_GATT_SVC_TYPE_PRIMARY && ble_uuid_cmp(&svc->svc.uuid.u, op->uuid) == 0) { dcb(conn_handle, ble_gattc_cache_error(status, 0), &svc->svc, op->cb_arg); } } status = BLE_HS_EDONE; dcb(conn_handle, ble_gattc_cache_error(status, 0), &svc->svc, op->cb_arg); + return; } @@ -1547,7 +2284,7 @@ ble_gattc_cache_conn_search_svc_by_uuid(uint16_t conn_handle, const ble_uuid_t * } CHECK_CACHE_CONN_STATE(conn->cache_state, cb, cb_arg, BLE_GATT_OP_DISC_SVC_UUID, - 0, 0, *uuid); + 0, 0, uuid); /* put the event in the queue to mimic the gattc behaviour */ ble_npl_event_init(&conn->disc_ev, ble_gattc_cache_conn_search_svc_by_uuid_cb, &conn->conn_handle); ble_npl_eventq_put((struct ble_npl_eventq *)ble_hs_evq_get(), &conn->disc_ev); @@ -1563,15 +2300,35 @@ ble_gattc_cache_conn_search_inc_svcs_cb(struct ble_npl_event *ev) struct ble_gattc_cache_conn_op *op; int status = 0; uint16_t conn_handle; + +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + struct ble_gattc_cache_conn_incl_svc *incl_svc; + ble_gatt_disc_incl_svc_fn *dcb; +#else ble_gatt_disc_svc_fn *dcb; +#endif conn_handle = *(uint16_t*)ble_npl_event_get_arg(ev); conn = ble_gattc_cache_conn_find(conn_handle); if (conn == NULL) { return; } + + ble_npl_event_deinit(&conn->disc_ev); + op = &conn->pending_op; dcb = op->cb; + +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + svc = ble_gattc_cache_conn_svc_find_range(conn, op->start_handle); + + SLIST_FOREACH(incl_svc, &svc->incl_svc, next) { + dcb(conn->conn_handle, ble_gattc_cache_error(status, 0), &incl_svc->svc, op->cb_arg); + + } + status = BLE_HS_EDONE; + dcb(conn->conn_handle, ble_gattc_cache_error(status, 0), &incl_svc->svc, op->cb_arg); +#else SLIST_FOREACH(svc, &conn->svcs, next) { if (svc->type == BLE_GATT_SVC_TYPE_SECONDARY && (svc->svc.start_handle >= op->start_handle && svc->svc.end_handle <= op->end_handle)) { @@ -1580,12 +2337,21 @@ ble_gattc_cache_conn_search_inc_svcs_cb(struct ble_npl_event *ev) } status = BLE_HS_EDONE; dcb(conn->conn_handle, ble_gattc_cache_error(status, 0), &svc->svc, op->cb_arg); +#endif return; } + +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) +int +ble_gattc_cache_conn_search_inc_svcs(uint16_t conn_handle, uint16_t start_handle, + uint16_t end_handle, + ble_gatt_disc_incl_svc_fn *cb, void *cb_arg) +#else int ble_gattc_cache_conn_search_inc_svcs(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, ble_gatt_disc_svc_fn *cb, void *cb_arg) +#endif { struct ble_gattc_cache_conn *conn; struct ble_gattc_cache_conn_op *op; @@ -1605,8 +2371,8 @@ ble_gattc_cache_conn_search_inc_svcs(uint16_t conn_handle, uint16_t start_handle return rc; } - CHECK_CACHE_CONN_STATE(conn->cache_state, cb, cb_arg, BLE_GATT_OP_DISC_ALL_CHRS, - start_handle, end_handle, uuid); + CHECK_CACHE_CONN_STATE(conn->cache_state, cb, cb_arg, BLE_GATT_OP_FIND_INC_SVCS, + start_handle, end_handle, &uuid); /* put the event in the queue to mimic the gattc behaviour */ ble_npl_event_init(&conn->disc_ev, ble_gattc_cache_conn_search_inc_svcs_cb, &conn->conn_handle); ble_npl_eventq_put((struct ble_npl_eventq *)ble_hs_evq_get(), &conn->disc_ev); @@ -1629,6 +2395,9 @@ ble_gattc_cache_conn_search_all_chrs_cb(struct ble_npl_event *ev) if (conn == NULL) { return; } + + ble_npl_event_deinit(&conn->disc_ev); + op = &conn->pending_op; dcb = op->cb; svc = ble_gattc_cache_conn_svc_find_range(conn, op->start_handle); @@ -1638,6 +2407,7 @@ ble_gattc_cache_conn_search_all_chrs_cb(struct ble_npl_event *ev) } status = BLE_HS_EDONE; dcb(conn_handle, ble_gattc_cache_error(status, 0), &chr->chr, op->cb_arg); + return; } @@ -1665,7 +2435,7 @@ ble_gattc_cache_conn_search_all_chrs(uint16_t conn_handle, uint16_t start_handle } CHECK_CACHE_CONN_STATE(conn->cache_state, cb, cb_arg, BLE_GATT_OP_DISC_ALL_CHRS, - start_handle, end_handle, uuid); + start_handle, end_handle, &uuid); /* put the event in the queue to mimic the gattc behaviour */ ble_npl_event_init(&conn->disc_ev, ble_gattc_cache_conn_search_all_chrs_cb, &conn->conn_handle); ble_npl_eventq_put((struct ble_npl_eventq *)ble_hs_evq_get(), &conn->disc_ev); @@ -1688,17 +2458,21 @@ ble_gattc_cache_conn_search_chrs_by_uuid_cb(struct ble_npl_event *ev) if (conn == NULL) { return; } + + ble_npl_event_deinit(&conn->disc_ev); + op = &conn->pending_op; dcb = op->cb; svc = ble_gattc_cache_conn_svc_find_range(conn, op->start_handle); /* return all chrs */ SLIST_FOREACH(chr, &svc->chrs, next) { - if (ble_uuid_cmp(&chr->chr.uuid.u, &op->uuid) == 0) { + if (ble_uuid_cmp(&chr->chr.uuid.u, op->uuid) == 0) { dcb(conn_handle, ble_gattc_cache_error(status, 0), &chr->chr, op->cb_arg); } } status = BLE_HS_EDONE; dcb(conn_handle, ble_gattc_cache_error(status, 0), &chr->chr, op->cb_arg); + return; } @@ -1725,7 +2499,7 @@ ble_gattc_cache_conn_search_chrs_by_uuid(uint16_t conn_handle, uint16_t start_ha } CHECK_CACHE_CONN_STATE(conn->cache_state, cb, cb_arg, BLE_GATT_OP_DISC_CHR_UUID, - start_handle, end_handle, *uuid); + start_handle, end_handle, uuid); /* put the event in the queue to mimic the gattc behaviour */ ble_npl_event_init(&conn->disc_ev, ble_gattc_cache_conn_search_chrs_by_uuid_cb, &conn->conn_handle); ble_npl_eventq_put((struct ble_npl_eventq *)ble_hs_evq_get(), &conn->disc_ev); @@ -1749,6 +2523,9 @@ ble_gattc_cache_conn_search_all_dscs_cb(struct ble_npl_event *ev) if (conn == NULL) { return; } + + ble_npl_event_deinit(&conn->disc_ev); + op = &conn->pending_op; dcb = op->cb; svc = ble_gattc_cache_conn_svc_find_range(conn, op->start_handle); @@ -1758,6 +2535,7 @@ ble_gattc_cache_conn_search_all_dscs_cb(struct ble_npl_event *ev) } status = BLE_HS_EDONE; dcb(conn_handle, ble_gattc_cache_error(status, 0), chr->chr.val_handle, &dsc->dsc, op->cb_arg); + return; } @@ -1785,7 +2563,7 @@ ble_gattc_cache_conn_search_all_dscs(uint16_t conn_handle, uint16_t start_handle } CHECK_CACHE_CONN_STATE(conn->cache_state, cb, cb_arg, BLE_GATT_OP_DISC_ALL_DSCS, - start_handle, end_handle, uuid); + start_handle, end_handle, &uuid); /* put the event in the queue to mimic the gattc behaviour */ ble_npl_event_init(&conn->disc_ev, ble_gattc_cache_conn_search_all_dscs_cb, &conn->conn_handle); ble_npl_eventq_put((struct ble_npl_eventq *)ble_hs_evq_get(), &conn->disc_ev); diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc_cache_priv.h b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc_cache_priv.h index 85b9c8fb..a9d3ef14 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc_cache_priv.h +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gattc_cache_priv.h @@ -47,6 +47,8 @@ typedef struct ble_gatt_nv_attr { ble_uuid_any_t uuid; uint8_t properties; /* used for characteristic only */ unsigned int is_primary : 1; /* used for service only */ + uint16_t incl_svc_s_handle; + uint16_t incl_svc_e_handle; } ble_gatt_nv_attr; /* cache conn */ @@ -65,6 +67,15 @@ struct ble_gattc_cache_conn_chr { }; SLIST_HEAD(ble_gattc_cache_conn_chr_list, ble_gattc_cache_conn_chr); +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) +struct ble_gattc_cache_conn_incl_svc { + SLIST_ENTRY(ble_gattc_cache_conn_incl_svc) next; + struct ble_gatt_incl_svc svc; +}; + +SLIST_HEAD(ble_gattc_cache_conn_incl_list, ble_gattc_cache_conn_incl_svc); +#endif + struct ble_gattc_cache_conn_svc { SLIST_ENTRY(ble_gattc_cache_conn_svc) next; /** @@ -74,7 +85,9 @@ struct ble_gattc_cache_conn_svc { */ uint8_t type; struct ble_gatt_svc svc; - +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) + struct ble_gattc_cache_conn_incl_list incl_svc; +#endif struct ble_gattc_cache_conn_chr_list chrs; }; SLIST_HEAD(ble_gattc_cache_conn_svc_list, ble_gattc_cache_conn_svc); @@ -96,7 +109,7 @@ struct ble_gattc_cache_conn_op { request comes while the cache is building */ uint16_t start_handle; uint16_t end_handle; - ble_uuid_t uuid; + const ble_uuid_t *uuid; void *cb; void *cb_arg; uint8_t cb_type; @@ -122,6 +135,35 @@ struct ble_gattc_cache_conn { the application about the discovery results */ struct ble_npl_event disc_ev; }; + +/** Enumerates types of GATT database attributes */ +typedef enum { + BLE_GATT_DB_PRIMARY_SERVICE, /*!< Primary service attribute. */ + BLE_GATT_DB_SECONDARY_SERVICE, /*!< Secondary service attribute. */ + BLE_GATT_DB_INCLUDED_SERVICE, /*!< Included service attribute. */ + BLE_GATT_DB_CHARACTERISTIC, /*!< Characteristic attribute. */ + BLE_GATT_DB_DESCRIPTOR, /*!< Descriptor attribute. */ +} ble_gattc_db_attr_type; + +typedef enum { + BLE_GATT_OP_GET_SVC_BY_UUID, /*!< Get primary service from cache using service UUID. */ + BLE_GATT_OP_GET_ALL_CHAR, /*!< Get all characteristics for a given service from cache. */ + BLE_GATT_OP_GET_ALL_DESC, /*!< Get all descriptors for a given characteristic from cache. */ + BLE_GATT_OP_GET_CHAR_BY_UUID, /*!< Get characteristic from a service using characteristic UUID. */ + BLE_GATT_OP_GET_DESC_BY_UUID, /*!< Get descriptor from a characteristic using descriptor UUID. */ + BLE_GATT_OP_GET_DESC_BY_HANDLE, /*!< Get descriptor from cache using descriptor handle. */ + BLE_GATT_OP_GET_INCLUDE_SVC, /*!< Get included services from a given service in cache. */ +} ble_gatt_get_db_op_t; + +typedef struct { + ble_gatt_get_db_op_t type; /*!< Attribute type (e.g., characteristic, descriptor) */ + uint16_t handle; /*!< Attribute handle (unique identifier) */ + uint16_t start_handle; /*!< Service start handle */ + uint16_t end_handle; /*!< Service end handle */ + uint8_t properties; /*!< Characteristic properties (read, write, notify, etc.) */ + ble_uuid_any_t uuid; /*!< Attribute UUID */ +} ble_gattc_db_elem_t; + /* apis from gatt service */ uint16_t ble_svc_gatt_changed_handle(); uint16_t ble_svc_gatt_hash_handle(); @@ -132,12 +174,100 @@ uint8_t ble_svc_gatt_get_csfs(); void ble_svc_gatt_changed(uint16_t start_handle, uint16_t end_handle); #endif int ble_gattc_cache_conn_add(uint16_t conn_handle, ble_addr_t ble_gattc_cache_conn_addr); -int ble_gattc_cache_conn_svc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *gatt_svc); -int ble_gattc_cache_conn_inc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *gatt_svc); +int ble_gattc_cache_conn_svc_add(ble_addr_t peer_addr, const struct ble_gatt_svc *gatt_svc, bool is_primary); +#if MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES) +int ble_gattc_cache_conn_inc_add(ble_addr_t peer_addr, const struct ble_gatt_incl_svc *gatt_svc); +#else +int ble_gattc_cache_conn_inc_add(ble_addr_t peer_addr,const struct ble_gatt_svc *gatt_svc); +#endif int ble_gattc_cache_conn_chr_add(ble_addr_t peer_addr, uint16_t svc_start_handle, const struct ble_gatt_chr *gatt_chr); int ble_gattc_cache_conn_dsc_add(ble_addr_t peer_addr, uint16_t chr_val_handle, const struct ble_gatt_dsc *gatt_dsc); + + +/** + * These APIs fetch previously discovered GATT information (like services, + * characteristics, or descriptors) from the local cache without triggering + * a new discovery procedure. + */ + +void ble_gattc_get_cached_service_by_uuid_db(uint16_t conn_handle, + ble_uuid_t *svc_uuid, + ble_gattc_db_elem_t **db, + uint16_t *count); + +void ble_gattc_get_cached_all_char_db(uint16_t conn_id, uint16_t start_handle, + uint16_t end_handle, ble_gattc_db_elem_t **db, + uint16_t *count); + +void ble_gattc_get_cached_all_descriptor_db(uint16_t conn_id, uint16_t char_handle, + ble_gattc_db_elem_t **db, uint16_t *count); + +void ble_gattc_get_cached_char_by_uuid_db(uint16_t conn_id, uint16_t start_handle, + uint16_t end_handle, ble_uuid_t *char_uuid, + ble_gattc_db_elem_t **db, uint16_t *count); + +void ble_gatt_get_cached_descr_by_uuid_db(uint16_t conn_id, uint16_t start_handle, uint16_t end_handle, + ble_uuid_t *char_uuid, ble_uuid_t *descr_uuid, + ble_gattc_db_elem_t **db, uint16_t *count); + +void ble_gattc_get_cached_descr_by_char_handle_db(uint16_t conn_id, uint16_t char_handle, + ble_uuid_t *descr_uuid, + ble_gattc_db_elem_t **db, uint16_t *count); + +void ble_gattc_get_cached_gatt_db(uint16_t conn_handle, + uint16_t start_handle, + uint16_t end_handle, + ble_gattc_db_elem_t **db, + uint16_t *count, uint16_t *db_num); +void ble_gattc_get_db_size(uint16_t conn_handle, uint16_t start_handle, + uint16_t end_handle, uint16_t *count); + +void ble_gattc_get_db_size_by_type(uint16_t conn_handle, ble_gattc_db_attr_type type, + uint16_t start_handle, uint16_t end_handle, + uint16_t char_handle, uint16_t *count); + +void ble_gattc_fill_gatt_db_el(ble_gattc_db_elem_t *attr, + ble_gattc_db_attr_type type, + uint16_t handle, + uint16_t s_handle, + uint16_t e_handle, + uint8_t prop, + ble_uuid_any_t uuid); + +void ble_gattc_get_service_with_uuid(uint16_t conn_handle, + ble_uuid_t *svc_uuid, + ble_gattc_db_elem_t **svc_db, + uint16_t *count); + +void ble_gattc_get_db_with_operation(uint16_t conn_handle, + ble_gatt_get_db_op_t op, + uint16_t char_handle, + ble_uuid_t *char_uuid, + ble_uuid_t *descr_uuid, + ble_uuid_t *incl_uuid, + uint16_t start_handle, uint16_t end_handle, + ble_gattc_db_elem_t **char_db, + uint16_t *count); + +void ble_gattc_get_db_size_with_type_handle(uint16_t conn_handle, + ble_gattc_db_attr_type type, + uint16_t start_handle, + uint16_t end_handle, + uint16_t char_handle, + uint16_t *count); + +void ble_gattc_get_db_size_handle(uint16_t conn_handle, + uint16_t start_handle, + uint16_t end_handle, + uint16_t *count); + +void ble_gattc_get_gatt_db(uint16_t conn_id, + uint16_t start_handle, + uint16_t end_handle, + ble_gattc_db_elem_t **db, + uint16_t *count, uint16_t *db_num); /** * Loads the cache for the connection given by conn_handle */ @@ -162,9 +292,15 @@ int ble_gattc_cache_conn_search_all_svcs(uint16_t conn_handle, ble_gatt_disc_svc_fn *cb, void *cb_arg); int ble_gattc_cache_conn_search_svc_by_uuid(uint16_t conn_handle, const ble_uuid_t *uuid, ble_gatt_disc_svc_fn *cb, void *cb_arg); +#if (MYNEWT_VAL(BLE_INCL_SVC_DISCOVERY) || MYNEWT_VAL(BLE_GATT_CACHING_INCLUDE_SERVICES)) +int ble_gattc_cache_conn_search_inc_svcs(uint16_t conn_handle, uint16_t start_handle, + uint16_t end_handle, + ble_gatt_disc_incl_svc_fn *cb, void *cb_arg); +#else int ble_gattc_cache_conn_search_inc_svcs(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, ble_gatt_disc_svc_fn *cb, void *cb_arg); +#endif int ble_gattc_cache_conn_search_all_chrs(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, ble_gatt_chr_fn *cb, void *cb_arg); @@ -176,6 +312,8 @@ ble_gattc_cache_conn_search_all_dscs(uint16_t conn_handle, uint16_t start_handle uint16_t end_handle, ble_gatt_dsc_fn *cb, void *cb_arg); +struct ble_gattc_cache_conn * +ble_gattc_cache_conn_find(uint16_t conn_handle); #ifdef __cplusplus } #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gatts.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gatts.c index bec30c4e..8c7efa39 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_gatts.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_gatts.c @@ -26,6 +26,10 @@ #include "host/ble_store.h" #include "ble_hs_priv.h" #include "esp_nimble_mem.h" + +#if MYNEWT_VAL(BLE_GATTS) +static uint8_t perm_flags = BLE_ATT_F_READ | BLE_ATT_F_WRITE ; + #if MYNEWT_VAL(BLE_DYNAMIC_SERVICE) #include "services/gatt/ble_svc_gatt.h" #endif @@ -175,6 +179,11 @@ ble_gatts_clt_cfg_free(struct ble_gatts_clt_cfg *cfg) } #endif +void ble_gatts_set_clt_cfg_perm_flags(uint8_t flags) +{ + perm_flags = flags ; +} + static int ble_gatts_svc_access(uint16_t conn_handle, uint16_t attr_handle, uint8_t op, uint16_t offset, struct os_mbuf **om, @@ -512,6 +521,7 @@ ble_gatts_chr_val_access(uint16_t conn_handle, uint16_t attr_handle, gatt_ctxt.op = ble_gatts_chr_op(att_op); gatt_ctxt.chr = chr_def; + gatt_ctxt.offset = offset; ble_gatts_chr_inc_val_stat(gatt_ctxt.op); rc = ble_gatts_val_access(conn_handle, attr_handle, offset, &gatt_ctxt, om, @@ -605,16 +615,20 @@ ble_gatts_calculate_hash(uint8_t *out_hash_key) rc = ble_att_fill_database_info(buf); if(rc != 0) { - return rc; + goto done; } rc = ble_sm_alg_aes_cmac(key, buf, size, out_hash_key); if(rc != 0) { - return rc; + goto done; } swap_in_place(out_hash_key, 16); - return 0; + + rc = 0; +done: + nimble_platform_mem_free(buf); + return rc; } #endif @@ -1000,8 +1014,7 @@ static int ble_gatts_register_clt_cfg_dsc(uint16_t *att_handle) { int rc; - - rc = ble_att_svr_register(uuid_ccc, BLE_ATT_F_READ | BLE_ATT_F_WRITE, 0, + rc = ble_att_svr_register(uuid_ccc, perm_flags, 0, att_handle, ble_gatts_clt_cfg_access, NULL); if (rc != 0) { return rc; @@ -1508,7 +1521,13 @@ ble_gatts_connection_broken(uint16_t conn_handle) for(i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { if(memcmp(ble_gatts_conn_aware_states[i].peer_id_addr, addrs.peer_id_addr.val, sizeof addrs.peer_id_addr.val)) { - ble_gatts_conn_aware_states[i].aware = conn->bhc_gatt_svr.aware_state; + if(conn->bhc_gatt_svr.half_aware) { + ble_gatts_conn_aware_states[i].aware = false; + ble_gatts_conn_aware_states[i].half_aware = 0; + } else { + ble_gatts_conn_aware_states[i].aware = conn->bhc_gatt_svr.aware_state; + ble_gatts_conn_aware_states[i].half_aware = conn->bhc_gatt_svr.half_aware; + } } } } @@ -2173,8 +2192,8 @@ ble_gatts_peer_cl_sup_feat_get(uint16_t conn_handle, uint8_t *out_supported_feat goto done; } - if (BLE_GATT_CHR_CLI_SUP_FEAT_SZ < len) { - len = BLE_GATT_CHR_CLI_SUP_FEAT_SZ; + if (MYNEWT_VAL(BLE_GATT_CSFC_SIZE) < len) { + len = MYNEWT_VAL(BLE_GATT_CSFC_SIZE); } memcpy(out_supported_feat, conn->bhc_gatt_svr.peer_cl_sup_feat, @@ -2189,7 +2208,9 @@ int ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, struct os_mbuf *om) { struct ble_hs_conn *conn; - uint8_t feat[BLE_GATT_CHR_CLI_SUP_FEAT_SZ] = {}; + struct ble_store_value_csfc value_csfc; + struct ble_store_key_csfc key_csfc; + uint8_t feat[MYNEWT_VAL(BLE_GATT_CSFC_SIZE)] = {}; uint16_t len; int rc = 0; int i; @@ -2202,8 +2223,8 @@ ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, struct os_mbuf *om) /* RFU bits are ignored so we can skip any bytes larger than supported */ len = os_mbuf_len(om); - if (len > BLE_GATT_CHR_CLI_SUP_FEAT_SZ) { - len = BLE_GATT_CHR_CLI_SUP_FEAT_SZ; + if (len > MYNEWT_VAL(BLE_GATT_CSFC_SIZE)) { + len = MYNEWT_VAL(BLE_GATT_CSFC_SIZE); } if (os_mbuf_copydata(om, 0, len, feat) < 0) { @@ -2211,7 +2232,7 @@ ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, struct os_mbuf *om) } /* clear RFU bits */ - for (i = 0; i < BLE_GATT_CHR_CLI_SUP_FEAT_SZ; i++) { + for (i = 0; i < MYNEWT_VAL(BLE_GATT_CSFC_SIZE); i++) { feat[i] &= (BLE_GATT_CHR_CLI_SUP_FEAT_MASK >> (8 * i)); } @@ -2226,7 +2247,7 @@ ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, struct os_mbuf *om) * Disabling already enabled features is not permitted * (Vol. 3, Part F, 3.3.3) */ - for (i = 0; i < BLE_GATT_CHR_CLI_SUP_FEAT_SZ; i++) { + for (i = 0; i < MYNEWT_VAL(BLE_GATT_CSFC_SIZE); i++) { if ((conn->bhc_gatt_svr.peer_cl_sup_feat[i] & feat[i]) != conn->bhc_gatt_svr.peer_cl_sup_feat[i]) { rc = BLE_ATT_ERR_VALUE_NOT_ALLOWED; @@ -2234,7 +2255,26 @@ ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, struct os_mbuf *om) } } - memcpy(conn->bhc_gatt_svr.peer_cl_sup_feat, feat, BLE_GATT_CHR_CLI_SUP_FEAT_SZ); + memcpy(conn->bhc_gatt_svr.peer_cl_sup_feat, feat, MYNEWT_VAL(BLE_GATT_CSFC_SIZE)); + + if (conn->bhc_sec_state.bonded) { + memset(&key_csfc, 0, sizeof key_csfc); + key_csfc.peer_addr = conn->bhc_peer_addr; + + rc = ble_store_delete_csfc(&key_csfc); + if (rc != 0) { + goto done; + } + + memset(&value_csfc, 0, sizeof value_csfc); + value_csfc.peer_addr = conn->bhc_peer_addr; + memcpy(value_csfc.csfc, feat, MYNEWT_VAL(BLE_GATT_CSFC_SIZE)); + + rc = ble_store_write_csfc(&value_csfc); + if (rc != 0) { + goto done; + } + } done: ble_hs_unlock(); @@ -2350,6 +2390,7 @@ void ble_gatts_bonding_established(uint16_t conn_handle) { struct ble_store_value_cccd cccd_value; + struct ble_store_value_csfc csfc; struct ble_gatts_clt_cfg *clt_cfg; struct ble_gatts_conn *gatt_srv; struct ble_hs_conn *conn; @@ -2394,6 +2435,19 @@ ble_gatts_bonding_established(uint16_t conn_handle) } } + csfc.peer_addr = conn->bhc_peer_addr; + csfc.peer_addr.type = + ble_hs_misc_peer_addr_type_to_id(conn->bhc_peer_addr.type); + + memcpy(csfc.csfc, conn->bhc_gatt_svr.peer_cl_sup_feat, MYNEWT_VAL(BLE_GATT_CSFC_SIZE)); + + ble_hs_unlock(); + ble_store_write_csfc(&csfc); + ble_hs_lock(); + + conn = ble_hs_conn_find(conn_handle); + BLE_HS_DBG_ASSERT(conn != NULL); + #if MYNEWT_VAL(BLE_GATT_CACHING) /* store the bonded peer aware_state if space not available delete the @@ -2405,6 +2459,8 @@ ble_gatts_bonding_established(uint16_t conn_handle) sizeof(struct ble_gatts_aware_state)); memcpy(ble_gatts_conn_aware_states[new_idx].peer_id_addr, addrs.peer_id_addr.val, sizeof addrs.peer_id_addr.val); + ble_gatts_conn_aware_states[new_idx].aware = conn->bhc_gatt_svr.aware_state; + ble_gatts_conn_aware_states[new_idx].half_aware = conn->bhc_gatt_svr.half_aware; last_conn_aware_state_index = new_idx; #endif ble_hs_unlock(); @@ -2423,6 +2479,8 @@ ble_gatts_bonding_restored(uint16_t conn_handle) { struct ble_store_value_cccd cccd_value; struct ble_store_key_cccd cccd_key; + struct ble_store_value_csfc csfc_value; + struct ble_store_key_csfc csfc_key; struct ble_gatts_clt_cfg *clt_cfg; struct ble_hs_conn *conn; uint8_t att_op; @@ -2450,6 +2508,7 @@ ble_gatts_bonding_restored(uint16_t conn_handle) for(i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { if(memcmp(ble_gatts_conn_aware_states[i].peer_id_addr, addrs.peer_id_addr.val, sizeof addrs.peer_id_addr.val)) { + conn->bhc_gatt_svr.half_aware = ble_gatts_conn_aware_states[i].half_aware; conn->bhc_gatt_svr.aware_state = ble_gatts_conn_aware_states[i].aware; } } @@ -2522,6 +2581,14 @@ ble_gatts_bonding_restored(uint16_t conn_handle) cccd_key.idx++; } + + memset(&csfc_key, 0, sizeof csfc_key); + csfc_key.peer_addr = conn->bhc_peer_addr; + rc = ble_store_read_csfc(&csfc_key, &csfc_value); + if (rc != 0) { + return; + } + memcpy(conn->bhc_gatt_svr.peer_cl_sup_feat, csfc_value.csfc, MYNEWT_VAL(BLE_GATT_CSFC_SIZE)); } #if MYNEWT_VAL(BLE_DYNAMIC_SERVICE) @@ -2726,6 +2793,7 @@ static void ble_gatts_remove_clt_cfg(struct ble_gatts_clt_cfg_list *clt_cfgs, ui static int ble_gatts_conn_unaware(struct ble_hs_conn *conn, void *arg) { conn->bhc_gatt_svr.aware_state = false; + conn->bhc_gatt_svr.half_aware = 0; return 0; } #endif @@ -2825,6 +2893,7 @@ int ble_gatts_add_dynamic_svcs(const struct ble_gatt_svc_def *svcs) { #if MYNEWT_VAL(BLE_GATT_CACHING) /* make all bonded connections unaware */ for(i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { + ble_gatts_conn_aware_states[i].half_aware = 0; ble_gatts_conn_aware_states[i].aware = false; } ble_hs_conn_foreach(ble_gatts_conn_unaware, NULL); @@ -2926,6 +2995,7 @@ done: /* make all bonded connections them unaware */ for(i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { ble_gatts_conn_aware_states[i].aware = false; + ble_gatts_conn_aware_states[i].half_aware = 0; } ble_hs_conn_foreach(ble_gatts_conn_unaware, NULL); #endif @@ -2968,6 +3038,19 @@ done: return rc; } +void ble_gatts_free_svcs(void) +{ + /* Ensure the memory is freed only if it was previously allocated */ + if (ble_gatts_svc_defs != NULL) { + /* Free the memory for the service definitions */ + free(ble_gatts_svc_defs); + /* Set the pointer to NULL to avoid dangling pointer */ + ble_gatts_svc_defs = NULL; + /* Reset the number of service definitions to 0 */ + ble_gatts_num_svc_defs = 0; + } +} + int ble_gatts_svc_set_visibility(uint16_t handle, int visible) { @@ -3178,6 +3261,17 @@ ble_gatts_lcl_svc_foreach(ble_gatt_svc_foreach_fn cb, void *arg) #endif } +#if MYNEWT_VAL(BLE_SVC_GAP_GATT_SECURITY_LEVEL) +uint8_t +ble_gatts_security_mode_1_level() { + uint8_t security_level; + + security_level = ble_att_svr_security_mode_1_level(); + + return security_level; +} +#endif + int ble_gatts_reset(void) { @@ -3244,3 +3338,5 @@ ble_gatts_init(void) return 0; } + +#endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs.c index 1ed13f82..7036fecc 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs.c @@ -40,7 +40,7 @@ MYNEWT_VAL(BLE_TRANSPORT_EVT_DISCARDABLE_COUNT)) static void ble_hs_event_rx_hci_ev(struct ble_npl_event *ev); -#if NIMBLE_BLE_CONNECT +#if NIMBLE_BLE_CONNECT && MYNEWT_VAL(BLE_GATTS) static void ble_hs_event_tx_notify(struct ble_npl_event *ev); #endif static void ble_hs_event_reset(struct ble_npl_event *ev); @@ -100,7 +100,11 @@ uint16_t ble_hs_max_services; uint16_t ble_hs_max_client_configs; #if MYNEWT_VAL(BLE_HS_DEBUG) +#define MAX_NESTED_LOCKS 5 +static TaskHandle_t ble_hs_task_handles[MAX_NESTED_LOCKS]; +static int ble_hs_task_handle_index = 0; static uint8_t ble_hs_mutex_locked; +static uint8_t counter_lock = 0; static TaskHandle_t ble_hs_task_handle; static uint8_t ble_hs_dbg_mutex_locked; #endif @@ -179,8 +183,11 @@ ble_hs_lock_nested(void) rc = ble_npl_mutex_pend(&ble_hs_mutex, 0xffffffff); #if MYNEWT_VAL(BLE_HS_DEBUG) + counter_lock++; ble_hs_mutex_locked = 1; ble_hs_task_handle = xTaskGetCurrentTaskHandle(); + ble_hs_task_handles[ble_hs_task_handle_index] = xTaskGetCurrentTaskHandle(); + ble_hs_task_handle_index++; #endif BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED); } @@ -198,14 +205,22 @@ ble_hs_unlock_nested(void) ble_hs_dbg_mutex_locked = 0; return; } - if(ble_hs_task_handle == xTaskGetCurrentTaskHandle()) { - ble_hs_task_handle = NULL; - ble_hs_mutex_locked = 0; + if (counter_lock > 0) { + counter_lock--; + if (counter_lock == 0) { + ble_hs_mutex_locked = 0; + } + if (ble_hs_task_handles[ble_hs_task_handle_index - 1] == xTaskGetCurrentTaskHandle()) { + ble_hs_task_handle_index--; + ble_hs_task_handles[ble_hs_task_handle_index] = NULL; + ble_hs_task_handle = ble_hs_task_handles[ble_hs_task_handle_index -1]; + } } #endif rc = ble_npl_mutex_release(&ble_hs_mutex); BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED); + } /** @@ -417,9 +432,10 @@ ble_hs_timer_exp(struct ble_npl_event *ev) switch (ble_hs_sync_state) { case BLE_HS_SYNC_STATE_GOOD: #if NIMBLE_BLE_CONNECT +#if MYNEWT_VAL(BLE_GATTC) ticks_until_next = ble_gattc_timer(); ble_hs_timer_sched(ticks_until_next); - +#endif ticks_until_next = ble_l2cap_sig_timer(); ble_hs_timer_sched(ticks_until_next); @@ -532,12 +548,14 @@ ble_hs_event_rx_hci_ev(struct ble_npl_event *ev) } #if NIMBLE_BLE_CONNECT +#if MYNEWT_VAL(BLE_GATTS) static void ble_hs_event_tx_notify(struct ble_npl_event *ev) { ble_gatts_tx_notifications(); } #endif +#endif static void ble_hs_event_rx_data(struct ble_npl_event *ev) @@ -673,10 +691,12 @@ ble_hs_start(void) ble_npl_callout_init(&ble_hs_timer, ble_hs_evq, ble_hs_timer_exp, NULL); #if NIMBLE_BLE_CONNECT +#if MYNEWT_VAL(BLE_GATTS) rc = ble_gatts_start(); if (rc != 0) { return rc; } +#endif #endif ble_hs_sync(); @@ -697,7 +717,7 @@ ble_hs_rx_data(struct os_mbuf *om, void *arg) { int rc; -#if (BT_HCI_LOG_INCLUDED == TRUE) +#if ((BT_HCI_LOG_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED) uint16_t len = OS_MBUF_PKTHDR(om)->omp_len + 1; uint8_t *data = (uint8_t *)malloc(len); assert(data != NULL); @@ -733,7 +753,7 @@ ble_hs_rx_data(struct os_mbuf *om, void *arg) int ble_hs_tx_data(struct os_mbuf *om) { -#if (BT_HCI_LOG_INCLUDED == TRUE) +#if ((BT_HCI_LOG_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED) uint16_t len = 0; uint8_t data[MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE) + 1]; data[0] = 0x02; @@ -768,8 +788,10 @@ ble_hs_init(void) ble_hs_enabled_state = BLE_HS_ENABLED_STATE_OFF; #if NIMBLE_BLE_CONNECT +#if MYNEWT_VAL(BLE_GATTS) ble_npl_event_init(&ble_hs_ev_tx_notifications, ble_hs_event_tx_notify, NULL); +#endif #endif ble_npl_event_init(&ble_hs_ev_reset, ble_hs_event_reset, NULL); ble_npl_event_init(&ble_hs_ev_start_stage1, ble_hs_event_start_stage1, @@ -787,15 +809,23 @@ ble_hs_init(void) SYSINIT_PANIC_ASSERT(rc == 0); #endif + #if NIMBLE_BLE_CONNECT rc = ble_l2cap_init(); SYSINIT_PANIC_ASSERT(rc == 0); +#endif + rc = ble_gap_init(); + SYSINIT_PANIC_ASSERT(rc == 0); + +#if NIMBLE_BLE_CONNECT rc = ble_att_init(); SYSINIT_PANIC_ASSERT(rc == 0); +#if MYNEWT_VAL(BLE_GATTS) rc = ble_att_svr_init(); SYSINIT_PANIC_ASSERT(rc == 0); +#endif rc = ble_gattc_init(); SYSINIT_PANIC_ASSERT(rc == 0); @@ -805,11 +835,11 @@ ble_hs_init(void) SYSINIT_PANIC_ASSERT(rc == 0); #endif +#if MYNEWT_VAL(BLE_GATTS) rc = ble_gatts_init(); SYSINIT_PANIC_ASSERT(rc == 0); #endif - rc = ble_gap_init(); - SYSINIT_PANIC_ASSERT(rc == 0); +#endif ble_hs_stop_init(); @@ -833,11 +863,6 @@ ble_hs_init(void) ble_hs_evq_set(nimble_port_get_dflt_eventq()); #endif -#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED - /* Configure the HCI transport to communicate with a host. */ - ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL); -#endif - /* Enqueue the start event to the default event queue. Using the default * queue ensures the event won't run until the end of main(). This allows * the application to configure this package in the meantime. @@ -891,10 +916,6 @@ ble_hs_deinit(void) ble_monitor_deinit(); #endif -#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED - ble_hci_trans_cfg_hs(NULL, NULL, NULL, NULL); -#endif - ble_npl_mutex_deinit(&ble_hs_mutex); ble_mqueue_deinit(&ble_hs_rx_q); diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_adv.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_adv.c index aef917f7..0403c479 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_adv.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_adv.c @@ -22,6 +22,9 @@ #include "nimble/ble.h" #include "host/ble_hs_adv.h" #include "ble_hs_priv.h" +#if MYNEWT_VAL(ENC_ADV_DATA) +#include "host/ble_ead.h" +#endif struct find_field_data { uint8_t type; @@ -526,6 +529,33 @@ adv_set_fields(const struct ble_hs_adv_fields *adv_fields, } } + /*** 0x27 - LE Supported Features. */ + if (adv_fields->le_supp_feat_is_present) { + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_LE_SUPP_FEAT, + BLE_HS_ADV_LE_SUPP_FEAT_LEN, + adv_fields->le_supp_feat, dst, &dst_len_local, + max_len, om); + } + + /*** 0x2f - Advertising interval - long. */ + if (adv_fields->adv_itvl_long_is_present && adv_fields->adv_itvl_long > 0xFFFF) { + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_ADV_ITVL_LONG, + BLE_HS_ADV_ADV_ITVL_LONG_LEN, + &adv_fields->adv_itvl_long, dst, &dst_len_local, + max_len, om); + } + +#if MYNEWT_VAL(ENC_ADV_DATA) + /*** 0x31 - Encrypted Advertising Data. */ + if ((adv_fields->enc_adv_data != NULL) && + (adv_fields->enc_adv_data_len > BLE_EAD_RANDOMIZER_SIZE + BLE_EAD_MIC_SIZE)) { + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_ENC_ADV_DATA, + adv_fields->enc_adv_data_len, + adv_fields->enc_adv_data, dst, &dst_len_local, + max_len, om); + } +#endif + /*** 0xff - Manufacturer specific data. */ if ((adv_fields->mfg_data != NULL) && (adv_fields->mfg_data_len >= 2)) { rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_MFG_DATA, @@ -862,6 +892,13 @@ ble_hs_adv_parse_one_field(struct ble_hs_adv_fields *adv_fields, } break; +#if MYNEWT_VAL(ENC_ADV_DATA) + case BLE_HS_ADV_TYPE_ENC_ADV_DATA: + adv_fields->enc_adv_data = data; + adv_fields->enc_adv_data_len = data_len; + break; +#endif + case BLE_HS_ADV_TYPE_MFG_DATA: adv_fields->mfg_data = data; adv_fields->mfg_data_len = data_len; diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_adv_priv.h b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_adv_priv.h index 5c8a6ecc..669850fc 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_adv_priv.h +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_adv_priv.h @@ -26,8 +26,6 @@ extern "C" { int ble_hs_adv_set_flat(uint8_t type, int data_len, const void *data, uint8_t *dst, uint8_t *dst_len, uint8_t max_len); -int ble_hs_adv_find_field(uint8_t type, const uint8_t *data, uint8_t length, - const struct ble_hs_adv_field **out); #ifdef __cplusplus } diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_cfg.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_cfg.c index a46a604a..d750fa04 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_cfg.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_cfg.c @@ -27,7 +27,11 @@ struct ble_hs_cfg ble_hs_cfg = { .sm_bonding = MYNEWT_VAL(BLE_SM_BONDING), .sm_mitm = MYNEWT_VAL(BLE_SM_MITM), .sm_sc = MYNEWT_VAL(BLE_SM_SC), + .sm_sc_only = MYNEWT_VAL(BLE_SM_SC_ONLY), + .sm_sec_lvl = MYNEWT_VAL(BLE_SM_LVL), .sm_keypress = MYNEWT_VAL(BLE_SM_KEYPRESS), .sm_our_key_dist = MYNEWT_VAL(BLE_SM_OUR_KEY_DIST), .sm_their_key_dist = MYNEWT_VAL(BLE_SM_THEIR_KEY_DIST), + .eatt = MYNEWT_VAL(BLE_EATT_CHAN_NUM), + .gatt_use_cache = MYNEWT_VAL(BLE_GATT_CACHING), }; diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_conn.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_conn.c index 0af96f28..5b8aca22 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_conn.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_conn.c @@ -45,9 +45,15 @@ ble_hs_conn_can_alloc(void) return 0; #endif - return ble_hs_conn_pool.mp_num_free >= 1 && - ble_l2cap_chan_pool.mp_num_free >= BLE_HS_CONN_MIN_CHANS && - ble_gatts_conn_can_alloc(); +#if MYNEWT_VAL(BLE_GATTS) + return ble_hs_conn_pool.mp_num_free >= 1 && + ble_l2cap_chan_pool.mp_num_free >= BLE_HS_CONN_MIN_CHANS && + ble_gatts_conn_can_alloc(); +#else + return ble_hs_conn_pool.mp_num_free >= 1 && + ble_l2cap_chan_pool.mp_num_free >= BLE_HS_CONN_MIN_CHANS; +#endif + } struct ble_l2cap_chan * @@ -187,13 +193,15 @@ ble_hs_conn_alloc(uint16_t conn_handle) if (rc != 0) { goto err; } - +#if MYNEWT_VAL(BLE_GATTS) rc = ble_gatts_conn_init(&conn->bhc_gatt_svr); if (rc != 0) { goto err; } +#endif STAILQ_INIT(&conn->bhc_tx_q); + STAILQ_INIT(&conn->att_tx_q); STATS_INC(ble_hs_stats, conn_create); @@ -244,7 +252,9 @@ ble_hs_conn_free(struct ble_hs_conn *conn) return; } +#if MYNEWT_VAL(BLE_GATTS) ble_att_svr_prep_clear(&conn->bhc_att_svr.basc_prep_list); +#endif while ((chan = SLIST_FIRST(&conn->bhc_channels)) != NULL) { ble_hs_conn_delete_chan(conn, chan); @@ -542,7 +552,7 @@ ble_hs_conn_timer(void) } #endif -#if BLE_HS_ATT_SVR_QUEUED_WRITE_TMO +#if BLE_HS_ATT_SVR_QUEUED_WRITE_TMO && MYNEWT_VAL(BLE_GATTS) /* Check each connection's rx queued write timer. If too much * time passes after a prep write is received, the queue is * cleared. diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_conn_priv.h b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_conn_priv.h index 0e451194..c994ed22 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_conn_priv.h +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_conn_priv.h @@ -95,6 +95,7 @@ struct ble_hs_conn { struct ble_gatts_conn bhc_gatt_svr; struct ble_gap_sec_state bhc_sec_state; + struct ble_gap_read_rem_ver_params bhc_rd_rem_ver_params; ble_gap_event_fn *bhc_cb; void *bhc_cb_arg; @@ -102,6 +103,12 @@ struct ble_hs_conn { #if MYNEWT_VAL(BLE_PERIODIC_ADV) struct ble_hs_periodic_sync *psync; #endif + + STAILQ_HEAD(, os_mbuf_pkthdr) att_tx_q; + bool client_att_busy; +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + uint16_t default_cid; +#endif }; struct ble_hs_conn_addrs { diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci.c index b1ac4bdb..606f8848 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci.c @@ -28,10 +28,236 @@ #include "bt_common.h" #if (BT_HCI_LOG_INCLUDED == TRUE) #include "hci_log/bt_hci_log.h" +#include "host/ble_hs.h" #endif // (BT_HCI_LOG_INCLUDED == TRUE) #define BLE_HCI_CMD_TIMEOUT_MS 2000 +#if MYNEWT_VAL(BLE_ERR_CHECK) +/* HCI ERROR */ +#define BLE_ERR_UNKNOWN_HCI_CMD 0x01 +#define BLE_ERR_UNK_CONN_ID 0x02 +#define BLE_ERR_HW_FAIL 0x03 +#define BLE_ERR_PAGE_TMO 0x04 +#define BLE_ERR_AUTH_FAIL 0x05 +#define BLE_ERR_PINKEY_MISSING 0x06 +#define BLE_ERR_MEM_CAPACITY 0x07 +#define BLE_ERR_CONN_SPVN_TMO 0x08 +#define BLE_ERR_CONN_LIMIT 0x09 +#define BLE_ERR_SYNCH_CONN_LIMIT 0x0a +#define BLE_ERR_ACL_CONN_EXISTS 0x0b +#define BLE_ERR_CMD_DISALLOWED 0x0c +#define BLE_ERR_CONN_REJ_RESOURCES 0x0d +#define BLE_ERR_CONN_REJ_SECURITY 0x0e +#define BLE_ERR_CONN_REJ_BD_ADDR 0x0f +#define BLE_ERR_CONN_ACCEPT_TMO 0x10 +#define BLE_ERR_UNSUPPORTED 0x11 +#define BLE_ERR_INV_HCI_CMD_PARMS 0x12 +#define BLE_ERR_REM_USER_CONN_TERM 0x13 +#define BLE_ERR_RD_CONN_TERM_RESRCS 0x14 +#define BLE_ERR_RD_CONN_TERM_PWROFF 0x15 +#define BLE_ERR_CONN_TERM_LOCAL 0x16 +#define BLE_ERR_REPEATED_ATTEMPTS 0x17 +#define BLE_ERR_NO_PAIRING 0x18 +#define BLE_ERR_UNK_LMP 0x19 +#define BLE_ERR_UNSUPP_REM_FEATURE 0x1a +#define BLE_ERR_SCO_OFFSET 0x1b +#define BLE_ERR_SCO_ITVL 0x1c +#define BLE_ERR_SCO_AIR_MODE 0x1d +#define BLE_ERR_INV_LMP_LL_PARM 0x1e +#define BLE_ERR_UNSPECIFIED 0x1f +#define BLE_ERR_UNSUPP_LMP_LL_PARM 0x20 +#define BLE_ERR_NO_ROLE_CHANGE 0x21 +#define BLE_ERR_LMP_LL_RSP_TMO 0x22 +#define BLE_ERR_LMP_COLLISION 0x23 +#define BLE_ERR_LMP_PDU 0x24 +#define BLE_ERR_ENCRYPTION_MODE 0x25 +#define BLE_ERR_LINK_KEY_CHANGE 0x26 +#define BLE_ERR_UNSUPP_QOS 0x27 +#define BLE_ERR_INSTANT_PASSED 0x28 +#define BLE_ERR_UNIT_KEY_PAIRING 0x29 +#define BLE_ERR_DIFF_TRANS_COLL 0x2a +/*#define BLE_ERR_RESERVED 0x2b*/ +#define BLE_ERR_QOS_PARM 0x2c +#define BLE_ERR_QOS_REJECTED 0x2d +#define BLE_ERR_CHAN_CLASS 0x2e +#define BLE_ERR_INSUFFICIENT_SEC 0x2f +#define BLE_ERR_PARM_OUT_OF_RANGE 0x30 +/*#define BLE_ERR_RESERVED 0x31*/ +#define BLE_ERR_PENDING_ROLE_SW 0x32 +/*#define BLE_ERR_RESERVED 0x33*/ +#define BLE_ERR_RESERVED_SLOT 0x34 +#define BLE_ERR_ROLE_SW_FAIL 0x35 +#define BLE_ERR_INQ_RSP_TOO_BIG 0x36 +#define BLE_ERR_SEC_SIMPLE_PAIR 0x37 +#define BLE_ERR_HOST_BUSY_PAIR 0x38 +#define BLE_ERR_CONN_REJ_CHANNEL 0x39 +#define BLE_ERR_CTLR_BUSY 0x3a +#define BLE_ERR_CONN_PARMS 0x3b +#define BLE_ERR_DIR_ADV_TMO 0x3c +#define BLE_ERR_CONN_TERM_MIC 0x3d +#define BLE_ERR_CONN_ESTABLISHMENT 0x3e +#define BLE_ERR_MAC_CONN_FAIL 0x3f +#define BLE_ERR_COARSE_CLK_ADJ 0x40 +#define BLE_ERR_TYPE0_SUBMAP_NDEF 0x41 +#define BLE_ERR_UNK_ADV_INDENT 0x42 +#define BLE_ERR_LIMIT_REACHED 0x43 +#define BLE_ERR_OPERATION_CANCELLED 0x44 +#define BLE_ERR_PACKET_TOO_LONG 0x45 +#define BLE_ERR_MAX 0xff + +struct err_code { + int error_code; + const char *msg; +}; + +static struct err_code core_err_code_list[] = { + { BLE_HS_EAGAIN, ": BLE_HS_EAGAIN (Temporary failure; try again)" }, + { BLE_HS_EALREADY, ": BLE_HS_EALREADY (Operation already in progress or completed)" }, + { BLE_HS_EINVAL, ": BLE_HS_EINVAL (One or more arguments are invalid)" }, + { BLE_HS_EMSGSIZE, ": BLE_HS_EMSGSIZE (The provided buffer is too small)" }, + { BLE_HS_ENOENT, ": BLE_HS_ENOENT (No entry matching the specified criteria)" }, + { BLE_HS_ENOMEM, ": BLE_HS_ENOMEM (Operation failed due to resource exhaustion)" }, + { BLE_HS_ENOTCONN, ": BLE_HS_ENOTCONN (No open connection with the specified handle)" }, + { BLE_HS_ENOTSUP, ": BLE_HS_ENOTSUP (Operation disabled at compile time)" }, + { BLE_HS_EAPP, ": BLE_HS_EAPP (Application callback behaved unexpectedly)" }, + { BLE_HS_EBADDATA, ": BLE_HS_EBADDATA (Command from peer is invalid)" }, + { BLE_HS_EOS, ": BLE_HS_EOS (Mynewt OS error)" }, + { BLE_HS_ECONTROLLER, ": BLE_HS_ECONTROLLER (Event from controller is invalid)" }, + { BLE_HS_ETIMEOUT, ": BLE_HS_ETIMEOUT (Operation timed out)" }, + { BLE_HS_EDONE, ": BLE_HS_EDONE (Operation completed successfully)" }, + { BLE_HS_EBUSY, ": BLE_HS_EBUSY (Operation cannot be performed until procedure completes)" }, + { BLE_HS_EREJECT, ": BLE_HS_EREJECT (Peer rejected a connection parameter update request)" }, + { BLE_HS_EUNKNOWN, ": BLE_HS_EUNKNOWN (Unexpected failure; catch all)" }, + { BLE_HS_EROLE, ": BLE_HS_EROLE (Operation requires different role (e.g., central vs. peripheral))" }, + { BLE_HS_ETIMEOUT_HCI, ": BLE_HS_ETIMEOUT_HCI (HCI request timed out; controller unresponsive)" }, + { BLE_HS_ENOMEM_EVT, ": BLE_HS_ENOMEM_EVT (Controller failed to send event due to memory exhaustion)" }, + { BLE_HS_ENOADDR, ": BLE_HS_ENOADDR (Operation requires an identity address but none configured)" }, + { BLE_HS_ENOTSYNCED, ": BLE_HS_ENOTSYNCED (Attempt to use the host before it is synced with controller)" }, + { BLE_HS_EAUTHEN, ": BLE_HS_EAUTHEN (Insufficient authentication)" }, + { BLE_HS_EAUTHOR, ": BLE_HS_EAUTHOR (Insufficient authorization)" }, + { BLE_HS_EENCRYPT, ": BLE_HS_EENCRYPT (Insufficient encryption level)" }, + { BLE_HS_EENCRYPT_KEY_SZ, ": BLE_HS_EENCRYPT_KEY_SZ (Insufficient key size" }, + { BLE_HS_ESTORE_CAP, ": BLE_HS_ESTORE_CAP (BLE_HS_ESTORE_FAIL,)" }, + { BLE_HS_ESTORE_FAIL, ": BLE_HS_ESTORE_FAIL (Storage IO error)" }, + { BLE_HS_EPREEMPTED, ": BLE_HS_EPREEMPTED (ation was preempted)" }, + { BLE_HS_EDISABLED, ": BLE_HS_EDISABLED (Operation disabled)" }, + { BLE_HS_ESTALLED, ": BLE_HS_ESTALLED (Operation stalled)" } +}; + +static struct err_code err_code_list[] = { + { BLE_HS_HCI_ERR(BLE_ERR_UNKNOWN_HCI_CMD), ": BLE_ERR_UNKNOWN_HCI_CMD (Unknown HCI Command)" }, + { BLE_HS_HCI_ERR(BLE_ERR_UNK_CONN_ID), ": BLE_ERR_UNK_CONN_ID (Unknown Connection Identifier)" }, + { BLE_HS_HCI_ERR(BLE_ERR_HW_FAIL), ": BLE_ERR_HW_FAIL (Hardware Failure)" }, + { BLE_HS_HCI_ERR(BLE_ERR_PAGE_TMO), ": BLE_ERR_PAGE_TMO (Page Timeout)" }, + { BLE_HS_HCI_ERR(BLE_ERR_AUTH_FAIL), ": BLE_ERR_AUTH_FAIL (Authentication Failure)" }, + { BLE_HS_HCI_ERR(BLE_ERR_PINKEY_MISSING), ": BLE_ERR_PINKEY_MISSING (PIN or Key Missing)" }, + { BLE_HS_HCI_ERR(BLE_ERR_MEM_CAPACITY), ": BLE_ERR_MEM_CAPACITY (Memory Capacity Exceeded)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_SPVN_TMO), ": BLE_ERR_CONN_SPVN_TMO (Connection Timeout)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_LIMIT), ": BLE_ERR_CONN_LIMIT (Connection Limit Exceeded)" }, + { BLE_HS_HCI_ERR(BLE_ERR_SYNCH_CONN_LIMIT), ": BLE_ERR_SYNCH_CONN_LIMIT (Synchronous Connection Limit To A Device Exceeded)" }, + { BLE_HS_HCI_ERR(BLE_ERR_ACL_CONN_EXISTS), ": BLE_ERR_ACL_CONN_EXISTS (ACL Connection Already Exists)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CMD_DISALLOWED), ": BLE_ERR_CMD_DISALLOWED (Command Disallowed)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_REJ_RESOURCES), ": BLE_ERR_CONN_REJ_RESOURCES (Connection Rejected due to Limited Resources)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_REJ_SECURITY), ": BLE_ERR_CONN_REJ_SECURITY (Connection Rejected Due To Security Reasons)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_REJ_BD_ADDR), ": BLE_ERR_CONN_REJ_BD_ADDR (Connection Rejected due to Unacceptable BD_ADDR)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_ACCEPT_TMO), ": BLE_ERR_CONN_ACCEPT_TMO (Connection Accept Timeout Exceeded)" }, + { BLE_HS_HCI_ERR(BLE_ERR_UNSUPPORTED), ": BLE_ERR_UNSUPPORTED (Unsupported Feature or Parameter Value)" }, + { BLE_HS_HCI_ERR(BLE_ERR_INV_HCI_CMD_PARMS), ": BLE_ERR_INV_HCI_CMD_PARMS (Invalid HCI Command Parameters)" }, + { BLE_HS_HCI_ERR(BLE_ERR_REM_USER_CONN_TERM), ": BLE_ERR_REM_USER_CONN_TERM (Remote User Terminated Connection)" }, + { BLE_HS_HCI_ERR(BLE_ERR_RD_CONN_TERM_RESRCS), ": BLE_ERR_RD_CONN_TERM_RESRCS (Remote Device Terminated Connection due to Low Resources)" }, + { BLE_HS_HCI_ERR(BLE_ERR_RD_CONN_TERM_PWROFF), ": BLE_ERR_RD_CONN_TERM_PWROFF (Remote Device Terminated Connection due to Power Off)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_TERM_LOCAL), ": BLE_ERR_CONN_TERM_LOCAL (Connection Terminated By Local Host)" }, + { BLE_HS_HCI_ERR(BLE_ERR_REPEATED_ATTEMPTS), ": BLE_ERR_REPEATED_ATTEMPTS (Repeated Attempts)" }, + { BLE_HS_HCI_ERR(BLE_ERR_NO_PAIRING), ": BLE_ERR_NO_PAIRING (Pairing Not Allowed)" }, + { BLE_HS_HCI_ERR(BLE_ERR_UNK_LMP), ": BLE_ERR_UNK_LMP (Unknown LMP PDU)" }, + { BLE_HS_HCI_ERR(BLE_ERR_UNSUPP_REM_FEATURE), ": BLE_ERR_UNSUPP_REM_FEATURE (Unsupported Remote Feature / Unsupported LMP Feature)" }, + { BLE_HS_HCI_ERR(BLE_ERR_SCO_OFFSET), ": BLE_ERR_SCO_OFFSET (SCO Offset Rejected)" }, + { BLE_HS_HCI_ERR(BLE_ERR_SCO_ITVL), ": BLE_ERR_SCO_ITVL (SCO Interval Rejected)" }, + { BLE_HS_HCI_ERR(BLE_ERR_SCO_AIR_MODE), ": BLE_ERR_SCO_AIR_MODE (SCO Air Mode Rejected)" }, + { BLE_HS_HCI_ERR(BLE_ERR_INV_LMP_LL_PARM), ": BLE_ERR_INV_LMP_LL_PARM (Invalid LMP Parameters / Invalid LL Parameters)" }, + { BLE_HS_HCI_ERR(BLE_ERR_UNSPECIFIED), ": BLE_ERR_UNSPECIFIED (Unspecified Error)" }, + { BLE_HS_HCI_ERR(BLE_ERR_UNSUPP_LMP_LL_PARM), ": BLE_ERR_UNSUPP_LMP_LL_PARM (Unsupported LMP Parameter Value / Unsupported LL Parameter Value)" }, + { BLE_HS_HCI_ERR(BLE_ERR_NO_ROLE_CHANGE), ": BLE_ERR_NO_ROLE_CHANGE (Role Change Not Allowed)" }, + { BLE_HS_HCI_ERR(BLE_ERR_LMP_LL_RSP_TMO), ": BLE_ERR_LMP_LL_RSP_TMO (LMP Response Timeout / LL Response Timeout)" }, + { BLE_HS_HCI_ERR(BLE_ERR_LMP_COLLISION), ": BLE_ERR_LMP_COLLISION (LMP Error Transaction Collision)" }, + { BLE_HS_HCI_ERR(BLE_ERR_LMP_PDU), ": BLE_ERR_LMP_PDU (LMP PDU Not Allowed)" }, + { BLE_HS_HCI_ERR(BLE_ERR_ENCRYPTION_MODE), ": BLE_ERR_ENCRYPTION_MODE (Encryption Mode Not Acceptable)"}, + { BLE_HS_HCI_ERR(BLE_ERR_LINK_KEY_CHANGE), ": BLE_ERR_LINK_KEY_CHANGE (Link Key cannot be Changed)"}, + { BLE_HS_HCI_ERR(BLE_ERR_UNSUPP_QOS), ": BLE_ERR_UNSUPP_QOS (Requested QoS Not Supported)"}, + { BLE_HS_HCI_ERR(BLE_ERR_INSTANT_PASSED), ": BLE_ERR_INSTANT_PASSED (Instant Passed)"}, + { BLE_HS_HCI_ERR(BLE_ERR_UNIT_KEY_PAIRING), ": BLE_ERR_UNIT_KEY_PAIRING (Pairing With Unit Key Not Supported)"}, + { BLE_HS_HCI_ERR(BLE_ERR_DIFF_TRANS_COLL), ": BLE_ERR_DIFF_TRANS_COLL (Different Transaction Collision)"}, + { BLE_HS_HCI_ERR(BLE_ERR_QOS_PARM), ": BLE_ERR_QOS_PARM (QoS Unacceptable Parameter)"}, + { BLE_HS_HCI_ERR(BLE_ERR_QOS_REJECTED), ": BLE_ERR_QOS_REJECTED (QoS Rejected)"}, + { BLE_HS_HCI_ERR(BLE_ERR_CHAN_CLASS), ": BLE_ERR_CHAN_CLASS (Channel Classification Not Supported)"}, + { BLE_HS_HCI_ERR(BLE_ERR_INSUFFICIENT_SEC), ": BLE_ERR_INSUFFICIENT_SEC (Insufficient Security)"}, + { BLE_HS_HCI_ERR(BLE_ERR_PARM_OUT_OF_RANGE), ": BLE_ERR_PARM_OUT_OF_RANGE (Parameter Out Of Mandatory Range)"}, + { BLE_HS_HCI_ERR(BLE_ERR_PENDING_ROLE_SW), ": BLE_ERR_PENDING_ROLE_SW (Role Switch Pending)"}, + { BLE_HS_HCI_ERR(BLE_ERR_RESERVED_SLOT), ": BLE_ERR_RESERVED_SLOT (Reserved Slot Violation)"}, + { BLE_HS_HCI_ERR(BLE_ERR_ROLE_SW_FAIL), ": BLE_ERR_ROLE_SW_FAIL (Role Switch Failed)"}, + { BLE_HS_HCI_ERR(BLE_ERR_INQ_RSP_TOO_BIG), ": BLE_ERR_INQ_RSP_TOO_BIG (Extended Inquiry Response Too Large)"}, + { BLE_HS_HCI_ERR(BLE_ERR_SEC_SIMPLE_PAIR), ": BLE_ERR_SEC_SIMPLE_PAIR (Secure Simple Pairing Not Supported By Host)"}, + { BLE_HS_HCI_ERR(BLE_ERR_HOST_BUSY_PAIR), ": BLE_ERR_HOST_BUSY_PAIR (Host Busy - Pairing)"}, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_REJ_CHANNEL), ": BLE_ERR_CONN_REJ_CHANNEL (Connection Rejected due to No Suitable Channel Found)"}, + { BLE_HS_HCI_ERR(BLE_ERR_CTLR_BUSY), ": BLE_ERR_CTLR_BUSY (Controller Busy)"}, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_PARMS), ": BLE_ERR_CONN_PARMS (Unacceptable Connection Parameters)"}, + { BLE_HS_HCI_ERR(BLE_ERR_DIR_ADV_TMO), ": BLE_ERR_DIR_ADV_TMO (Directed Advertising Timeout)"}, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_TERM_MIC), ": BLE_ERR_CONN_TERM_MIC (Connection Terminated due to MIC Failure)"}, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_ESTABLISHMENT), ": BLE_ERR_CONN_ESTABLISHMENT (Connection Failed to be Established)"}, + { BLE_HS_HCI_ERR(BLE_ERR_MAC_CONN_FAIL), ": BLE_ERR_MAC_CONN_FAIL (MAC Connection Failed)"}, + { BLE_HS_HCI_ERR(BLE_ERR_COARSE_CLK_ADJ), ": BLE_ERR_COARSE_CLK_ADJ (Coarse Clock Adjustment Rejected but Will Try to Adjust Using Clock Dragging)"}, + { BLE_HS_HCI_ERR(BLE_ERR_TYPE0_SUBMAP_NDEF), ": BLE_ERR_TYPE0_SUBMAP_NDEF (Type0 Submap Not Defined)"}, + { BLE_HS_HCI_ERR(BLE_ERR_UNK_ADV_INDENT), ": BLE_ERR_UNK_ADV_INDENT (Unknown Advertising Identifier)"}, + { BLE_HS_HCI_ERR(BLE_ERR_LIMIT_REACHED), ": BLE_ERR_LIMIT_REACHED (Limit Reached)"}, + { BLE_HS_HCI_ERR(BLE_ERR_OPERATION_CANCELLED), ": BLE_ERR_OPERATION_CANCELLED (Operation Cancelled by Host)"}, + { BLE_HS_HCI_ERR(BLE_ERR_PACKET_TOO_LONG), ": BLE_ERR_PACKET_TOO_LONG (Packet Too Long)"}, + { BLE_HS_HCI_ERR(BLE_ERR_MAX), ": BLE_ERR_MAX"} +}; + +static void esp_core_err_to_name(int error_code, uint16_t *opcode) +{ + for (int i = 0; ibhc_outstanding_pkts++; + ble_hs_hci_avail_pkts--; + rc = ble_hs_tx_data(frag); if (rc != 0) { + conn->bhc_outstanding_pkts--; + ble_hs_hci_avail_pkts++; goto err; } @@ -615,10 +850,6 @@ ble_hs_hci_acl_tx_now(struct ble_hs_conn *conn, struct os_mbuf **om) */ conn->bhc_flags |= BLE_HS_CONN_F_TX_FRAG; pb = BLE_HCI_PB_MIDDLE; - - /* Account for the controller buf that will hold the txed fragment. */ - conn->bhc_outstanding_pkts++; - ble_hs_hci_avail_pkts--; } if (txom != NULL) { @@ -690,6 +921,18 @@ ble_hs_hci_get_hci_version(void) return ble_hs_hci_version; } +void +ble_hs_hci_set_hci_supported_cmd(struct ble_hs_hci_sup_cmd sup_cmd) +{ + ble_hs_hci_sup_cmd = sup_cmd; +} + +struct ble_hs_hci_sup_cmd +ble_hs_hci_get_hci_supported_cmd(void) +{ + return ble_hs_hci_sup_cmd; +} + void ble_hs_hci_init(void) { diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci_cmd.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci_cmd.c index 76ec034d..a9487eaa 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci_cmd.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci_cmd.c @@ -91,7 +91,7 @@ ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) buf--; #endif -#if (BT_HCI_LOG_INCLUDED == TRUE) +#if ((BT_HCI_LOG_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED) uint8_t *data; #if !(SOC_ESP_NIMBLE_CONTROLLER) && CONFIG_BT_CONTROLLER_ENABLED data = (uint8_t *)buf + 1; diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci_evt.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci_evt.c index 64b37f01..7b410d35 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci_evt.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci_evt.c @@ -35,12 +35,7 @@ struct ble_gap_reattempt_ctxt { extern int ble_gap_master_connect_reattempt(uint16_t conn_handle); extern int ble_gap_slave_adv_reattempt(void); - -#ifdef CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT -#define MAX_REATTEMPT_ALLOWED CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT -#else -#define MAX_REATTEMPT_ALLOWED 0 -#endif +extern int slave_conn[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; #endif #if MYNEWT_VAL(BLE_QUEUE_CONG_CHECK) @@ -57,6 +52,7 @@ typedef int ble_hs_hci_evt_fn(uint8_t event_code, const void *data, unsigned int len); static ble_hs_hci_evt_fn ble_hs_hci_evt_hw_error; static ble_hs_hci_evt_fn ble_hs_hci_evt_num_completed_pkts; +static ble_hs_hci_evt_fn ble_hs_hci_evt_rd_rem_ver_complete; #if NIMBLE_BLE_CONNECT static ble_hs_hci_evt_fn ble_hs_hci_evt_disconn_complete; static ble_hs_hci_evt_fn ble_hs_hci_evt_encrypt_change; @@ -103,6 +99,15 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_transmit_power_report; #if MYNEWT_VAL(BLE_CONN_SUBRATING) static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_subrate_change; #endif +#if MYNEWT_VAL(BLE_AOA_AOD) +static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_connless_iq_report; +static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_iq_report; +static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_cte_req_failed; +#endif +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_subev_data_req; +static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_subev_resp_rep; +#endif /* Statistics */ struct host_hci_stats { @@ -122,6 +127,7 @@ struct ble_hs_hci_evt_dispatch_entry { static const struct ble_hs_hci_evt_dispatch_entry ble_hs_hci_evt_dispatch[] = { { BLE_HCI_EVCODE_LE_META, ble_hs_hci_evt_le_meta }, + { BLE_HCI_EVCODE_RD_REM_VER_INFO_CMP, ble_hs_hci_evt_rd_rem_ver_complete }, { BLE_HCI_EVCODE_NUM_COMP_PKTS, ble_hs_hci_evt_num_completed_pkts }, #if NIMBLE_BLE_CONNECT { BLE_HCI_EVCODE_DISCONN_CMP, ble_hs_hci_evt_disconn_complete }, @@ -177,6 +183,19 @@ static ble_hs_hci_evt_le_fn * const ble_hs_hci_evt_le_dispatch[] = { #if MYNEWT_VAL(BLE_CONN_SUBRATING) [BLE_HCI_LE_SUBEV_SUBRATE_CHANGE] = ble_hs_hci_evt_le_subrate_change, #endif +#if MYNEWT_VAL(BLE_AOA_AOD) + [BLE_HCI_LE_SUBEV_CONNLESS_IQ_RPT] = ble_hs_hci_evt_le_connless_iq_report, + [BLE_HCI_LE_SUBEV_CONN_IQ_RPT] = ble_hs_hci_evt_le_conn_iq_report, + [BLE_HCI_LE_SUBEV_CTE_REQ_FAILED] = ble_hs_hci_evt_le_cte_req_failed, +#endif +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + [BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB_V2] = ble_hs_hci_evt_le_periodic_adv_sync_estab, + [BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT_V2] = ble_hs_hci_evt_le_periodic_adv_rpt, + [BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER_V2] = ble_hs_hci_evt_le_periodic_adv_sync_transfer, + [BLE_HCI_LE_SUBEV_PERIODIC_ADV_SUBEV_DATA_REQ] = ble_hs_hci_evt_le_periodic_adv_subev_data_req, + [BLE_HCI_LE_SUBEV_PERIODIC_ADV_RESP_REPORT] = ble_hs_hci_evt_le_periodic_adv_subev_resp_rep, + [BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE_V2] = ble_hs_hci_evt_le_enh_conn_complete, +#endif }; #define BLE_HS_HCI_EVT_LE_DISPATCH_SZ \ @@ -206,7 +225,6 @@ ble_hs_hci_evt_le_dispatch_find(uint8_t event_code) if (event_code >= BLE_HS_HCI_EVT_LE_DISPATCH_SZ) { return NULL; } - return ble_hs_hci_evt_le_dispatch[event_code]; } @@ -230,18 +248,53 @@ ble_hs_hci_evt_disconn_complete(uint8_t event_code, const void *data, ble_hs_unlock(); #if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) - if (conn && ev->reason == BLE_ERR_CONN_ESTABLISHMENT) { + if (conn) { uint16_t handle; int rc; - if (!(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) { //slave - BLE_HS_LOG(INFO, "Reattempt advertising; reason: 0x%x, status = %x", - ev->reason, ev->status); + /* For master role, check if failure reason is 0x3E, to restart connect attempt + * For slave role, check whether + * a. Failure reason is 0x3E + * b. Connect event was not posted and 0x8 was received + * Restart advertising in above reasons for slave. + */ + + if ((conn->bhc_flags & BLE_HS_CONN_F_MASTER) && \ + (ev->reason == BLE_ERR_CONN_ESTABLISHMENT)) { // master + if (reattempt_conn.count < MAX_REATTEMPT_ALLOWED) { + /* Go for connection */ + BLE_HS_LOG(INFO, "Reattempt connection; reason = 0x%x, status = %d," + "reattempt count = %d ", ev->reason, ev->status, + reattempt_conn.count); + reattempt_conn.count += 1; + + handle = le16toh(ev->conn_handle); + /* Post event to interested application */ + ble_gap_reattempt_count(handle, reattempt_conn.count); + rc = ble_gap_master_connect_reattempt(ev->conn_handle); + if (rc != 0) { + BLE_HS_LOG(INFO, "Master reconnect attempt failed; rc = %d", rc); + } + } else { + /* Exhausted attempts */ + memset(&reattempt_conn, 0x0, sizeof (struct ble_gap_reattempt_ctxt)); + } + } + else if (!(conn->bhc_flags & BLE_HS_CONN_F_MASTER) && \ + ((ev->reason == BLE_ERR_CONN_ESTABLISHMENT) || \ + (!slave_conn[ev->conn_handle] && ev->reason == BLE_ERR_CONN_SPVN_TMO))) { //slave + + BLE_HS_LOG(INFO, "Reattempt advertising; reason: 0x%x, status = %x", + ev->reason, ev->status); ble_l2cap_sig_conn_broken(ev->conn_handle, BLE_ERR_CONN_ESTABLISHMENT); ble_sm_connection_broken(ev->conn_handle); - ble_gatts_connection_broken(ev->conn_handle); - ble_gattc_connection_broken(ev->conn_handle); +#if MYNEWT_VAL(BLE_GATTS) + ble_gatts_connection_broken(ev->conn_handle); +#endif +#if MYNEWT_VAL(BLE_GATTC) + ble_gattc_connection_broken(ev->conn_handle); +#endif ble_hs_flow_connection_broken(ev->conn_handle);; #if MYNEWT_VAL(BLE_GATT_CACHING) ble_gattc_cache_conn_broken(ev->conn_handle); @@ -253,36 +306,14 @@ ble_hs_hci_evt_disconn_complete(uint8_t event_code, const void *data, rc = ble_gap_slave_adv_reattempt(); if (rc != 0) { - BLE_HS_LOG(INFO, "Adv reattempt failed; rc= %d ", rc); + BLE_HS_LOG(INFO, "Adv reattempt failed; rc= %d ", rc); } return 0; // Restart advertising, so don't post disconnect event - - } else { // master - if (reattempt_conn.count < MAX_REATTEMPT_ALLOWED ) { - /* Got for connection */ - BLE_HS_LOG(INFO, "Reattempt connection; reason = 0x%x, status = %d," - "reattempt count = %d ", ev->reason, ev->status, - reattempt_conn.count); - reattempt_conn.count += 1; - - handle = le16toh(ev->conn_handle); - /* Post event to interested application */ - ble_gap_reattempt_count(handle, reattempt_conn.count); - - rc = ble_gap_master_connect_reattempt(ev->conn_handle); - if (rc != 0) { - BLE_HS_LOG(INFO, "Master reconnect attempt failed; rc = %d", rc); - } - } else { - /* Exhausted attempts */ - memset(&reattempt_conn, 0x0, sizeof (struct ble_gap_reattempt_ctxt)); - } - } - } - else { + } else { /* Normal disconnect. Reset the structure */ memset(&reattempt_conn, 0x0, sizeof (struct ble_gap_reattempt_ctxt)); + } } #endif @@ -352,6 +383,10 @@ ble_hs_hci_evt_num_completed_pkts(uint8_t event_code, const void *data, uint16_t num_pkts; int i; + if (len < sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + if (len != sizeof(*ev) + (ev->count * sizeof(ev->completed[0]))) { return BLE_HS_ECONTROLLER; } @@ -470,7 +505,7 @@ ble_hs_hci_evt_le_enh_conn_complete(uint8_t subevent, const void *data, #if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) /* RPA needs to be resolved here, as controller is not aware of the * address is RPA in Host based RPA */ - if (ble_host_rpa_enabled() && !memcmp(evt.local_rpa, ble_hs_conn_null_addr, 6) == 0) { + if (ble_host_rpa_enabled() && ((!memcmp(evt.local_rpa, ble_hs_conn_null_addr, 6)) == 0)) { uint8_t *local_id_rpa = ble_hs_get_rpa_local(); memcpy(evt.local_rpa, local_id_rpa, BLE_DEV_ADDR_LEN); } @@ -488,7 +523,7 @@ ble_hs_hci_evt_le_enh_conn_complete(uint8_t subevent, const void *data, evt.connection_handle = BLE_HS_CONN_HANDLE_NONE; #endif } -#if MYNEWT_VAL(BLE_EXT_ADV) +#if MYNEWT_VAL(BLE_EXT_ADV) && !MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) if (evt.status == BLE_ERR_DIR_ADV_TMO || evt.role == BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE) { /* store this until we get set terminated event with adv handle */ @@ -496,6 +531,16 @@ ble_hs_hci_evt_le_enh_conn_complete(uint8_t subevent, const void *data, return 0; } #endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + if (subevent == BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE) { + evt.adv_handle = 0xFF; + evt.sync_handle = 0xFFFF; + } else { + evt.adv_handle = ev->adv_handle; + evt.sync_handle = ev->sync_handle; + } +#endif return ble_gap_rx_conn_complete(&evt, 0); } @@ -582,15 +627,13 @@ ble_hs_hci_evt_le_adv_rpt_first_pass(const void *data, unsigned int len) rpt = data; - len -= sizeof(*rpt) + 1; - data += sizeof(rpt) + 1; - if (rpt->data_len > len) { return BLE_HS_ECONTROLLER; } - len -= rpt->data_len; - data += rpt->data_len; + /* extra byte for RSSI after adv data */ + len -= sizeof(*rpt) + 1 + rpt->data_len; + data += sizeof(*rpt) + 1 + rpt->data_len; } /* Make sure length was correct */ @@ -711,6 +754,22 @@ ble_hs_hci_evt_le_rd_rem_used_feat_complete(uint8_t subevent, const void *data, return 0; } +static int +ble_hs_hci_evt_rd_rem_ver_complete(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_rd_rem_ver_info_cmp *ev = data; + + if (len != sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + + ble_gap_rx_rd_rem_ver_info_complete(ev); + + return 0; +} + + #if MYNEWT_VAL(BLE_EXT_ADV) && NIMBLE_BLE_SCAN static int ble_hs_hci_decode_legacy_type(uint16_t evt_type) @@ -731,29 +790,66 @@ ble_hs_hci_decode_legacy_type(uint16_t evt_type) return -1; } } -#endif static int -ble_hs_hci_evt_le_ext_adv_rpt(uint8_t subevent, const void *data, - unsigned int len) +ble_hs_hci_evt_le_ext_adv_rpt_first_pass(const void *data, unsigned int len) { -#if MYNEWT_VAL(BLE_EXT_ADV) && NIMBLE_BLE_SCAN const struct ble_hci_ev_le_subev_ext_adv_rpt *ev = data; const struct ext_adv_report *report; - struct ble_gap_ext_disc_desc desc; int i; - int legacy_event_type; if (len < sizeof(*ev)) { - return BLE_HS_EBADDATA; + return BLE_HS_ECONTROLLER; } + len -= sizeof(*ev); + data += sizeof(*ev); + if (ev->num_reports < BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN || ev->num_reports > BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX) { return BLE_HS_EBADDATA; } - /* TODO properly validate len of the event */ + for (i = 0; i < ev->num_reports; i++) { + if (len < sizeof(*report)) { + return BLE_HS_ECONTROLLER; + } + + report = data; + + if (report->data_len > len) { + return BLE_HS_ECONTROLLER; + } + + len -= sizeof(*report) + report->data_len; + data += sizeof(*report) + report->data_len; + } + + /* Make sure length was correct */ + if (len) { + return BLE_HS_ECONTROLLER; + } + + return 0; +} +#endif + +static int +ble_hs_hci_evt_le_ext_adv_rpt(uint8_t subevent, const void *data, + unsigned int len) +{ +#if MYNEWT_VAL(BLE_EXT_ADV) && NIMBLE_BLE_SCAN + const struct ble_hci_ev_le_subev_ext_adv_rpt *ev = data; + const struct ext_adv_report *report; + struct ble_gap_ext_disc_desc desc; + int legacy_event_type; + int rc; + int i; + + rc = ble_hs_hci_evt_le_ext_adv_rpt_first_pass(data, len); + if (rc != 0) { + return rc; + } report = &ev->reports[0]; for (i = 0; i < ev->num_reports; i++) { @@ -946,6 +1042,13 @@ ble_hs_hci_evt_le_adv_set_terminated(uint8_t subevent, const void *data, return BLE_HS_ECONTROLLER; } + /* this indicates bug in controller as host uses instances from + * 0-BLE_ADV_INSTANCES range only + */ + if (ev->adv_handle >= BLE_ADV_INSTANCES) { + return BLE_HS_ECONTROLLER; + } + if (ev->status == 0) { /* ignore return code as we need to terminate advertising set anyway */ ble_gap_rx_conn_complete(&pend_conn_complete, ev->adv_handle); @@ -967,6 +1070,13 @@ ble_hs_hci_evt_le_scan_req_rcvd(uint8_t subevent, const void *data, return BLE_HS_ECONTROLLER; } + /* this indicates bug in controller as host uses instances from + * 0-BLE_ADV_INSTANCES range only + */ + if (ev->adv_handle >= BLE_ADV_INSTANCES) { + return BLE_HS_ECONTROLLER; + } + ble_gap_rx_scan_req_rcvd(ev); #endif @@ -990,6 +1100,116 @@ ble_hs_hci_evt_le_subrate_change(uint8_t subevent, const void *data, } #endif +#if MYNEWT_VAL(BLE_AOA_AOD) +static int +ble_hs_hci_evt_le_connless_iq_report(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_le_subev_connless_iq_rpt *ev = data; + + if (len < sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + + ble_gap_rx_connless_iq_report(ev); + + return 0; +} + +static int +ble_hs_hci_evt_le_conn_iq_report(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_le_subev_conn_iq_rpt *ev = data; + if (len < sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + + ble_gap_rx_conn_iq_report(ev); + + return 0; +} + +static int +ble_hs_hci_evt_le_cte_req_failed(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_le_subev_cte_req_failed *ev = data; + + if (len != sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + + ble_gap_rx_cte_req_failed(ev); + + return 0; +} +#endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +static int +ble_hs_hci_evt_le_periodic_adv_subev_data_req(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_le_subev_periodic_adv_subev_data_req *ev = data; + + if (len != sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + + ble_gap_rx_periodic_adv_subev_data_req(ev); + + return 0; +} + +static int +ble_hs_hci_evt_le_periodic_adv_subev_resp_rep(uint8_t subevent, const void *data, unsigned int len) +{ + const struct ble_hci_ev_le_subev_periodic_adv_resp_rep *ev = data; + const struct periodic_adv_response *response; + struct ble_gap_periodic_adv_response resp; + uint32_t size; + + /* TODO: compare with the total length including the response data. */ + size = sizeof(*ev); + for (uint8_t i = 0; i < ev->num_responses; i ++) { + size += sizeof(struct periodic_adv_response) + ev->responses[i].data_length; + } + if (len < size) { + return BLE_HS_ECONTROLLER; + } + + len -= sizeof(*ev); + data += sizeof(*ev); + + resp.adv_handle = ev->adv_handle; + resp.subevent = ev->subevent; + resp.tx_status = ev->tx_status; + + for (uint8_t i = 0; i < ev->num_responses; i++) { + response = data; + if (len < sizeof(*response) + response->data_length) { + return BLE_HS_ECONTROLLER; + } + + len -= sizeof(*response) + response->data_length; + data += sizeof(*response) + response->data_length; + + resp.tx_power = response->tx_power; + resp.rssi = response->rssi; + resp.cte_type = response->cte_type; + resp.response_slot = response->response_slot; + resp.data_length = response->data_length; + resp.data = response->data; + resp.data_status = response->data_status; + + ble_gap_rx_periodic_adv_response(resp); + } + + return 0; +} +#endif + #if NIMBLE_BLE_CONNECT static int ble_hs_hci_evt_le_conn_upd_complete(uint8_t subevent, const void *data, @@ -1098,8 +1318,8 @@ ble_hs_hci_evt_process(struct ble_hci_ev *ev) if(ev->opcode == BLE_HCI_EVCODE_COMMAND_COMPLETE) { /* Check if this Command complete has a parsable opcode */ - struct ble_hci_ev_command_complete *cmd_complete = (void *) ev->data; - entry = ble_hs_hci_evt_dispatch_find(cmd_complete->opcode); + struct ble_hci_ev_command_complete *cmd_complete = (void *) ev->data; + entry = ble_hs_hci_evt_dispatch_find(cmd_complete->opcode); } else { entry = ble_hs_hci_evt_dispatch_find(ev->opcode); @@ -1115,8 +1335,9 @@ ble_hs_hci_evt_process(struct ble_hci_ev *ev) BLE_HS_LOG(DEBUG, "ble_hs_event_rx_hci_ev; opcode=0x%x ", ev->opcode); /* For LE Meta, print subevent code */ - if(ev->opcode == 0x3e) + if(ev->opcode == 0x3e) { BLE_HS_LOG(DEBUG, "subevent: 0x%x", ev->data[0]); + } BLE_HS_LOG(DEBUG, "\n"); } diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci_priv.h b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci_priv.h index ab862dc5..db66c354 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci_priv.h +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_hci_priv.h @@ -79,6 +79,10 @@ struct hci_periodic_adv_params #endif #endif +struct ble_hs_hci_sup_cmd { + uint8_t commands[64]; +}; + extern uint16_t ble_hs_hci_avail_pkts; /* This function is not waiting for command status/complete HCI events */ @@ -92,6 +96,8 @@ void ble_hs_hci_set_le_supported_feat(uint32_t feat); uint32_t ble_hs_hci_get_le_supported_feat(void); void ble_hs_hci_set_hci_version(uint8_t hci_version); uint8_t ble_hs_hci_get_hci_version(void); +void ble_hs_hci_set_hci_supported_cmd(struct ble_hs_hci_sup_cmd sup_cmd); +struct ble_hs_hci_sup_cmd ble_hs_hci_get_hci_supported_cmd(void); #if MYNEWT_VAL(BLE_HS_PHONY_HCI_ACKS) typedef int ble_hs_hci_phony_ack_fn(uint8_t *ack, int ack_buf_len); diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_id.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_id.c index 3fa07187..ae423934 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_id.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_id.c @@ -224,11 +224,13 @@ ble_hs_id_addr(uint8_t id_addr_type, const uint8_t **out_id_addr, switch (id_addr_type) { case BLE_ADDR_PUBLIC: + case BLE_ADDR_PUBLIC_ID: id_addr = ble_hs_id_pub; nrpa = 0; break; case BLE_ADDR_RANDOM: + case BLE_ADDR_RANDOM_ID: id_addr = ble_hs_id_rnd; nrpa = (ble_hs_id_rnd[5] & 0xc0) == 0; break; diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_priv.h b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_priv.h index c5781ccc..cb97e537 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_priv.h +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_priv.h @@ -24,6 +24,7 @@ #include #include "ble_att_cmd_priv.h" #include "ble_att_priv.h" +#include "ble_eatt_priv.h" #include "ble_gap_priv.h" #include "ble_gatt_priv.h" #include "ble_hs_hci_priv.h" diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_pvcy.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_pvcy.c index 403fd4ec..a0cb261a 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_pvcy.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_pvcy.c @@ -51,11 +51,11 @@ ble_hs_pvcy_set_addr_timeout(uint16_t timeout) &cmd, sizeof(cmd), NULL, 0); } -void ble_hs_set_rpa_timeout (uint16_t timeout) +int ble_hs_set_rpa_timeout (uint16_t timeout) { rpa_timeout = timeout; - ble_hs_pvcy_set_addr_timeout(rpa_timeout); + return ble_hs_pvcy_set_addr_timeout(rpa_timeout); } uint16_t ble_hs_get_rpa_timeout(void) diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_resolv.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_resolv.c index 6fcbc051..217cef19 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_resolv.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_resolv.c @@ -36,13 +36,6 @@ #define BLE_RESOLV_LIST_SIZE (MYNEWT_VAL(BLE_STORE_MAX_BONDS) + 1) #define BLE_MAX_RPA_TIMEOUT_VAL 0xA1B8 -static struct ble_hs_resolv_data g_ble_hs_resolv_data; -static struct ble_hs_resolv_entry g_ble_hs_resolv_list[BLE_RESOLV_LIST_SIZE]; -/* Allocate one extra space for peer_records than no. of Bonds, it will take - * care of storage overflow */ -static struct ble_hs_dev_records peer_dev_rec[BLE_RESOLV_LIST_SIZE]; -static int ble_store_num_peer_dev_rec; - struct ble_hs_resolv_data { uint8_t addr_res_enabled; uint8_t rl_cnt; @@ -50,6 +43,13 @@ struct ble_hs_resolv_data { struct ble_npl_callout rpa_timer; }; +static struct ble_hs_resolv_data g_ble_hs_resolv_data; +static struct ble_hs_resolv_entry g_ble_hs_resolv_list[BLE_RESOLV_LIST_SIZE]; +/* Allocate one extra space for peer_records than no. of Bonds, it will take + * care of storage overflow */ +static struct ble_hs_dev_records peer_dev_rec[BLE_RESOLV_LIST_SIZE]; +static int ble_store_num_peer_dev_rec; + /* NRPA bit: Enables NRPA as private address. */ static bool nrpa_pvcy; diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_startup.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_startup.c index a9c9fe79..ff3ad055 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_startup.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_hs_startup.c @@ -68,6 +68,26 @@ ble_hs_startup_read_local_ver_tx(void) return 0; } +static int +ble_hs_startup_read_sup_cmd_tx(void) +{ + struct ble_hci_ip_rd_loc_supp_cmd_rp rsp; + struct ble_hs_hci_sup_cmd sup_cmd; + int rc; + + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS, + BLE_HCI_OCF_IP_RD_LOC_SUPP_CMD), + NULL, 0, &rsp, sizeof(rsp)); + if (rc != 0) { + return rc; + } + + memcpy(&sup_cmd.commands, &rsp.commands, sizeof(sup_cmd)); + ble_hs_hci_set_hci_supported_cmd(sup_cmd); + + return 0; +} + static int ble_hs_startup_le_read_sup_f_tx(void) { @@ -247,6 +267,7 @@ ble_hs_startup_le_set_evmask_tx(void) * 0x0000000400000000 LE Subrate change event */ mask |= 0x0000000400000000; + } #endif #if MYNEWT_VAL(BLE_POWER_CONTROL) @@ -281,6 +302,42 @@ ble_hs_startup_le_set_evmask_tx(void) } #endif +#if MYNEWT_VAL(BLE_AOA_AOD) + if (version >= BLE_HCI_VER_BCS_5_1) { + /** + * Enable the following LE events: + * 0x0000000000100000 LE Connectionless IQ Report event + * 0x0000000000200000 LE Connection IQ Report event + * 0x0000000000400000 LE CTE Request Failed event + */ + mask |= 0x0000000000700000; + } +#endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + if (version >= BLE_HCI_VER_BCS_5_4) { + /** + * Enable the following LE events: + * 0x0000000800000000 LE Periodic Advertising Sync Established event V2 + * 0x0000001000000000 LE Periodic Advertising Report Event V2 + * 0x0000004000000000 LE Periodic Advertising Subevent Data Request event + * 0x0000008000000000 LE Periodic Advertising Response Report event + * 0x0000010000000000 LE Enhanced Connection Complete event V2 + */ + mask |= 0x000001d800000000; + } +#endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER) + if (version >= BLE_HCI_VER_BCS_5_4) { + /** + * Enable the following LE events: + * 0x0000002000000000 LE Periodic Advertising Sync Transfer Received event V2 + */ + mask |= 0x0000002000000000; + } +#endif + cmd.event_mask = htole64(mask); rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, @@ -299,20 +356,23 @@ ble_hs_startup_set_evmask_tx(void) struct ble_hci_cb_set_event_mask_cp cmd; struct ble_hci_cb_set_event_mask2_cp cmd2; uint8_t version; + struct ble_hs_hci_sup_cmd sup_cmd; int rc; version = ble_hs_hci_get_hci_version(); + sup_cmd = ble_hs_hci_get_hci_supported_cmd(); /** * Enable the following events: * 0x0000000000000010 Disconnection Complete Event * 0x0000000000000080 Encryption Change Event + * 0x0000000000000800 Read Remote Version Information Complete event * 0x0000000000008000 Hardware Error Event * 0x0000000002000000 Data Buffer Overflow Event * 0x0000800000000000 Encryption Key Refresh Complete Event * 0x2000000000000000 LE Meta-Event */ - cmd.event_mask = htole64(0x2000800002008090); + cmd.event_mask = htole64(0x2000800002008890); rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_SET_EVENT_MASK), @@ -321,7 +381,7 @@ ble_hs_startup_set_evmask_tx(void) return rc; } - if (version >= BLE_HCI_VER_BCS_4_1) { + if ((version >= BLE_HCI_VER_BCS_4_1) && ((sup_cmd.commands[22] & 0x04) != 0)) { /** * Enable the following events: * 0x0000000000800000 Authenticated Payload Timeout Event @@ -349,7 +409,7 @@ ble_hs_startup_reset_tx(void) int ble_hs_startup_go(void) { - //struct ble_store_gen_key gen_key; + struct ble_store_gen_key gen_key; int rc; rc = ble_hs_startup_reset_tx(); @@ -362,7 +422,11 @@ ble_hs_startup_go(void) return rc; } - /* XXX: Read local supported commands. */ + /* Read local supported commands. */ + rc = ble_hs_startup_read_sup_cmd_tx(); + if (rc != 0) { + return rc; + } /* we need to check this only if using external controller */ #if !MYNEWT_VAL(BLE_CONTROLLER) @@ -403,7 +467,7 @@ ble_hs_startup_go(void) if (rc != 0) { return rc; } -#if 0 + if (ble_hs_cfg.store_gen_key_cb) { memset(&gen_key, 0, sizeof(gen_key)); rc = ble_hs_cfg.store_gen_key_cb(BLE_STORE_GEN_KEY_IRK, &gen_key, @@ -416,12 +480,10 @@ ble_hs_startup_go(void) } if (rc != 0) { + ble_hs_pvcy_set_default_irk(); + ble_hs_pvcy_set_our_irk(NULL); } -#endif - ble_hs_pvcy_set_default_irk(); - - ble_hs_pvcy_set_our_irk(NULL); /* If flow control is enabled, configure the controller to use it. */ ble_hs_flow_startup(); diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap.c index 50fe18c6..8bcd1fb6 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap.c @@ -208,7 +208,29 @@ ble_l2cap_reconfig(struct ble_l2cap_chan *chans[], uint8_t num, uint16_t new_mtu } } - return ble_l2cap_sig_coc_reconfig(conn_handle, chans, num, new_mtu); + return ble_l2cap_sig_coc_reconfig(conn_handle, chans, num, new_mtu, MYNEWT_VAL(BLE_L2CAP_COC_MPS)); +} + +int +ble_l2cap_reconfig_mtu_mps(struct ble_l2cap_chan *chans[], uint8_t num, uint16_t new_mtu, uint16_t new_mps) +{ + int i; + uint16_t conn_handle; + + if (num == 0 || !chans) { + return BLE_HS_EINVAL; + } + + conn_handle = chans[0]->conn_handle; + + for (i = 1; i < num; i++) { + if (conn_handle != chans[i]->conn_handle) { + BLE_HS_LOG(ERROR, "All channels should have same conn handle\n"); + return BLE_HS_EINVAL; + } + } + + return ble_l2cap_sig_coc_reconfig(conn_handle, chans, num, new_mtu, new_mps); } int @@ -385,7 +407,7 @@ ble_l2cap_rx(struct ble_hs_conn *conn, } /* For CIDs from dynamic range we check if SDU size isn't larger than MPS */ - if (chan->dcid >= 0x0040 && chan->dcid <= 0x007F && l2cap_hdr.len > chan->my_coc_mps) { + if (chan->dcid >= 0x0040 && chan->dcid <= 0x007F && l2cap_hdr.len > (chan->my_coc_mps + BLE_L2CAP_SDU_SZ)) { /* Data exceeds MPS */ BLE_HS_LOG(ERROR, "error: sdu_len > chan->my_coc_mps (%d>%d)\n", l2cap_hdr.len, chan->my_coc_mps); @@ -399,7 +421,7 @@ ble_l2cap_rx(struct ble_hs_conn *conn, ble_l2cap_remove_rx(conn, chan); } - if (l2cap_hdr.len > ble_l2cap_get_mtu(chan)) { + if (l2cap_hdr.len - BLE_L2CAP_SDU_SZ > ble_l2cap_get_mtu(chan)) { /* More data than we expected on the channel. * Disconnect peer with invalid behaviour */ diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_coc.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_coc.c index 90d2a057..21c91ef0 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_coc.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_coc.c @@ -211,7 +211,7 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan) sdu_len = get_le16((*om)->om_data); - BLE_HS_LOG(INFO, "First LE frame received %d, SDU len: %d\n", + BLE_HS_LOG(DEBUG, "First LE frame received %d, SDU len: %d\n", om_total, sdu_len + 2); /* We should receive payload of size sdu_len + 2 bytes of sdu_len field */ @@ -298,7 +298,7 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan) * However, we still have buffer to for next LE Frame so lets give one more * credit to peer so it can send us full SDU */ - if (rx->credits == 0) { + if (chan->disable_auto_credit_update == false && rx->credits == 0) { /* Remote did not send full SDU. Lets give him one more credits to do * so since we have still buffer to handle it */ @@ -637,7 +637,7 @@ ble_l2cap_coc_recv_ready(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_rx) /* We want to back only that much credits which remote side is missing * to be able to send complete SDU. */ - if (chan->coc_rx.credits < c->initial_credits) { + if (chan->disable_auto_credit_update == false && chan->coc_rx.credits < c->initial_credits) { ble_hs_unlock(); ble_l2cap_sig_le_credits(chan->conn_handle, chan->scid, c->initial_credits - chan->coc_rx.credits); diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_priv.h b/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_priv.h index 21e6a8bf..08ad3b3e 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_priv.h +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_priv.h @@ -55,6 +55,7 @@ extern struct os_mempool ble_l2cap_chan_pool; #define BLE_L2CAP_CID_BLACK_HOLE 0xffff #define BLE_L2CAP_HDR_SZ 4 +#define BLE_L2CAP_SDU_SZ 2 typedef uint8_t ble_l2cap_chan_flags; @@ -91,6 +92,19 @@ struct ble_l2cap_chan { struct ble_l2cap_coc_endpoint coc_rx; struct ble_l2cap_coc_endpoint coc_tx; uint16_t initial_credits; +/** + * Disable automatically sending credits to a remote + * + * This field disables automatically sending extra credit to a + * remote that has exhausted all of its available credits. + * Setting this field to "true" will enable behaviour to + * "not automatically send credits to a peer whose credits are exhausted" + * Setting this field to "false" will enable behaviour to + * "automatically send credits to a peer whose credits are exhausted" + * this behaviour. + * + */ + bool disable_auto_credit_update; ble_l2cap_event_fn *cb; void *cb_arg; #endif @@ -137,6 +151,7 @@ int ble_l2cap_enhanced_connect(uint16_t conn_handle, uint8_t num, struct os_mbuf *sdu_rx[], ble_l2cap_event_fn *cb, void *cb_arg); int ble_l2cap_reconfig(struct ble_l2cap_chan *chans[], uint8_t num, uint16_t new_mtu); +int ble_l2cap_reconfig_mtu_mps(struct ble_l2cap_chan *chans[], uint8_t num, uint16_t new_mtu, uint16_t new_mps); #ifdef __cplusplus } diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_sig.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_sig.c index 42459179..aca61cd0 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_sig.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_sig.c @@ -428,6 +428,10 @@ ble_l2cap_sig_update_req_rx(uint16_t conn_handle, return rc; } + if (OS_MBUF_PKTLEN(*om) != BLE_L2CAP_SIG_UPDATE_REQ_SZ) { + return BLE_HS_EBADDATA; + } + rc = ble_hs_atomic_conn_flags(conn_handle, &conn_flags); if (rc != 0) { return rc; @@ -506,6 +510,10 @@ ble_l2cap_sig_update_rsp_rx(uint16_t conn_handle, goto done; } + if (OS_MBUF_PKTLEN(*om) != BLE_L2CAP_SIG_UPDATE_RSP_SZ) { + return BLE_HS_EBADDATA; + } + rsp = (struct ble_l2cap_sig_update_rsp *)(*om)->om_data; switch (le16toh(rsp->result)) { @@ -904,6 +912,10 @@ ble_l2cap_sig_credit_base_reconfig_rsp_rx(uint16_t conn_handle, return rc; } + if (OS_MBUF_PKTLEN(*om) != sizeof(*rsp)) { + return BLE_HS_EBADDATA; + } + rsp = (struct ble_l2cap_sig_credit_base_reconfig_rsp *)(*om)->om_data; ble_l2cap_sig_coc_reconfig_cb(proc, (rsp->result > 0) ? BLE_HS_EREJECT : 0); ble_l2cap_sig_proc_free(proc); @@ -1181,11 +1193,15 @@ ble_l2cap_sig_coc_req_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, struct ble_hs_conn *conn; uint16_t scid; - rc = ble_hs_mbuf_pullup_base(om, sizeof(req)); + rc = ble_hs_mbuf_pullup_base(om, sizeof(*req)); if (rc != 0) { return rc; } + if (OS_MBUF_PKTLEN(*om) != sizeof(*req)) { + return BLE_HS_EBADDATA; + } + rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_LE_CREDIT_CONNECT_RSP, hdr->identifier, sizeof(*rsp), &txom); if (!rsp) { @@ -1300,6 +1316,10 @@ ble_l2cap_sig_coc_rsp_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, goto done; } + if (OS_MBUF_PKTLEN(*om) != sizeof(*rsp)) { + return BLE_HS_EBADDATA; + } + rsp = (struct ble_l2cap_sig_le_con_rsp *)(*om)->om_data; chan = proc->connect.chan[0]; @@ -1493,7 +1513,7 @@ done: int ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[], - uint8_t num, uint16_t new_mtu) + uint8_t num, uint16_t new_mtu, uint16_t new_mps) { struct ble_hs_conn *conn; struct ble_l2cap_sig_proc *proc; @@ -1529,7 +1549,7 @@ ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[], proc->op = BLE_L2CAP_SIG_PROC_OP_RECONFIG; proc->reconfig.cid_cnt = num; proc->reconfig.new_mtu = new_mtu; - proc->reconfig.new_mps = MYNEWT_VAL(BLE_L2CAP_COC_MPS); + proc->reconfig.new_mps = new_mps; proc->id = ble_l2cap_sig_next_id(); proc->conn_handle = conn_handle; @@ -1592,6 +1612,10 @@ ble_l2cap_sig_disc_req_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, ble_hs_lock(); conn = ble_hs_conn_find_assert(conn_handle); + if (OS_MBUF_PKTLEN(*om) != sizeof(*req)) { + return BLE_HS_EBADDATA; + } + req = (struct ble_l2cap_sig_disc_req *) (*om)->om_data; /* Let's find matching channel. Note that destination CID in the request @@ -1677,6 +1701,10 @@ ble_l2cap_sig_disc_rsp_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, goto done; } + if (OS_MBUF_PKTLEN(*om) != sizeof(*rsp)) { + return BLE_HS_EBADDATA; + } + chan = proc->disconnect.chan; if (!chan) { goto done; @@ -1752,6 +1780,10 @@ ble_l2cap_sig_le_credits_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, return 0; } + if (OS_MBUF_PKTLEN(*om) != sizeof(*req)) { + return BLE_HS_EBADDATA; + } + req = (struct ble_l2cap_sig_le_credits *) (*om)->om_data; /* Ignore when peer sends zero credits */ diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_sig_priv.h b/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_sig_priv.h index a698cd0d..b997ce35 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_sig_priv.h +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_l2cap_sig_priv.h @@ -154,7 +154,7 @@ int ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, uint8_t num, struct os_mbuf *sdu_rx[], ble_l2cap_event_fn *cb, void *cb_arg); int ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[], - uint8_t num, uint16_t new_mtu); + uint8_t num, uint16_t new_mtu, uint16_t new_mps); #else static inline int ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, @@ -166,7 +166,7 @@ ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, } static inline int ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[], - uint8_t num, uint16_t new_mtu) + uint8_t num, uint16_t new_mtu, uint16_t new_mps) { return BLE_HS_ENOTSUP; } diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_sm.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_sm.c index 527cd96d..1ce9be90 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_sm.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_sm.c @@ -557,11 +557,12 @@ ble_sm_persist_keys(struct ble_sm_proc *proc) switch (peer_addr.type) { case BLE_ADDR_PUBLIC: case BLE_ADDR_PUBLIC_ID: - conn->bhc_peer_addr.type = BLE_ADDR_PUBLIC_ID; #if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) /* In case of Host based privacy, we should not be changing * peer address type to BLE_ADDR_PUBLIC_ID */ conn->bhc_peer_addr.type = BLE_ADDR_PUBLIC; +#else + conn->bhc_peer_addr.type = BLE_ADDR_PUBLIC_ID; #endif break; @@ -974,7 +975,7 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res, &prev); if (proc != NULL) { - if (res->execute) { + if (res && res->execute) { ble_sm_exec(proc, res, res->state_arg); } @@ -993,36 +994,42 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res, } } - if (res->sm_err != 0 && tx_fail) { + if (res && (res->sm_err != 0) && tx_fail) { ble_sm_pair_fail_tx(conn_handle, res->sm_err); } ble_hs_unlock(); - if (res->enc_cb && - res->app_status != BLE_HS_ENOTCONN) { - /* Do not send this event on broken connection */ - ble_gap_pairing_complete_event(conn_handle, res->sm_err); - } - if (proc == NULL) { break; } - if (res->app_status == 518 ) { - conn = ble_hs_conn_find(conn_handle); + if (res->app_status == 518 ) { + conn = ble_hs_conn_find(conn_handle); conn_flags = conn->bhc_flags; ble_sm_proc_free(proc); - if (conn_flags & BLE_HS_CONN_F_MASTER) { - ble_sm_pair_initiate(conn_handle); - } - else { - ble_sm_slave_initiate(conn_handle); + if (conn_flags & BLE_HS_CONN_F_MASTER) { + ble_sm_pair_initiate(conn_handle); + } else { + ble_sm_slave_initiate(conn_handle); } - break; + break; + } + + if (res->enc_cb && + res->app_status != BLE_HS_ENOTCONN) { + /* Do not send this event on broken connection */ + ble_gap_pairing_complete_event(conn_handle, res->sm_err); + } + /* Persist keys if bonding has successfully completed. */ + if (res->app_status == 0 && + rm && + proc->flags & BLE_SM_PROC_F_BONDING) { + + ble_sm_persist_keys(proc); } if (res->enc_cb) { @@ -1036,13 +1043,6 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res, ble_gap_passkey_event(conn_handle, &res->passkey_params); } - /* Persist keys if bonding has successfully completed. */ - if (res->app_status == 0 && - rm && - proc->flags & BLE_SM_PROC_F_BONDING) { - - ble_sm_persist_keys(proc); - } if (rm) { ble_sm_proc_free(proc); @@ -1838,7 +1838,7 @@ ble_sm_verify_auth_requirements(uint8_t cmd) /* Fail if security level forces MITM protection and remote does not * support it */ - if (MYNEWT_VAL(BLE_SM_LVL) >= 3 && !(cmd & BLE_SM_PAIR_AUTHREQ_MITM)) { + if (ble_hs_cfg.sm_sec_lvl >= 3 && !(cmd & BLE_SM_PAIR_AUTHREQ_MITM)) { return false; } return true; @@ -1922,7 +1922,7 @@ ble_sm_pair_req_rx(uint16_t conn_handle, struct os_mbuf **om, if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) { res->sm_err = BLE_SM_ERR_CMD_NOT_SUPP; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP); - } else if (MYNEWT_VAL(BLE_SM_LVL) == 1) { + } else if (ble_hs_cfg.sm_sec_lvl == 1) { res->sm_err = BLE_SM_ERR_CMD_NOT_SUPP; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP); } else if (req->max_enc_key_size < BLE_SM_PAIR_KEY_SZ_MIN) { @@ -1931,18 +1931,18 @@ ble_sm_pair_req_rx(uint16_t conn_handle, struct os_mbuf **om, } else if (req->max_enc_key_size > BLE_SM_PAIR_KEY_SZ_MAX) { res->sm_err = BLE_SM_ERR_INVAL; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL); - } else if (MYNEWT_VAL(BLE_SM_SC_ONLY)) { - /* Fail if Secure Connections Only mode is on and remote does not - * meet key size requirements - MITM was checked in last step. - * Fail if SC is not supported by peer or key size is too small + } else if (ble_hs_cfg.sm_sc_only && !(req->authreq & BLE_SM_PAIR_AUTHREQ_SC)) { + /* Fail if Secure Connections Only mode is on and SC is not supported by peer */ - if (!(req->authreq & BLE_SM_PAIR_AUTHREQ_SC)) { - res->sm_err = BLE_SM_ERR_AUTHREQ; - res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_AUTHREQ); - } else if (req->max_enc_key_size != BLE_SM_PAIR_KEY_SZ_MAX) { - res->sm_err = BLE_SM_ERR_ENC_KEY_SZ; - res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_ENC_KEY_SZ); - } + res->sm_err = BLE_SM_ERR_AUTHREQ; + res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_AUTHREQ); + res->enc_cb = 1; + } else if (ble_hs_cfg.sm_sc_only && (req->max_enc_key_size != BLE_SM_PAIR_KEY_SZ_MAX)) { + /* Fail if Secure Connections Only mode is on and key size is too small + */ + res->sm_err = BLE_SM_ERR_ENC_KEY_SZ; + res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_ENC_KEY_SZ); + res->enc_cb = 1; } else if (!ble_sm_verify_auth_requirements(req->authreq)) { res->sm_err = BLE_SM_ERR_AUTHREQ; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_AUTHREQ); @@ -2006,7 +2006,7 @@ ble_sm_pair_rsp_rx(uint16_t conn_handle, struct os_mbuf **om, } else if (rsp->max_enc_key_size > BLE_SM_PAIR_KEY_SZ_MAX) { res->sm_err = BLE_SM_ERR_INVAL; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL); - } else if (MYNEWT_VAL(BLE_SM_SC_ONLY) && (rsp->max_enc_key_size != BLE_SM_PAIR_KEY_SZ_MAX)) { + } else if (ble_hs_cfg.sm_sc_only && (rsp->max_enc_key_size != BLE_SM_PAIR_KEY_SZ_MAX)) { /* Fail if Secure Connections Only mode is on and remote does not meet * key size requirements - MITM was checked in last step */ @@ -2651,42 +2651,42 @@ ble_sm_fail_rx(uint16_t conn_handle, struct os_mbuf **om, int ble_sm_incr_our_sign_counter(uint16_t conn_handle) { - struct ble_store_key_sec key_sec; - struct ble_store_value_sec value_sec; - struct ble_gap_conn_desc desc; - int rc; + struct ble_store_key_sec key_sec; + struct ble_store_value_sec value_sec; + struct ble_gap_conn_desc desc; + int rc; - rc = ble_gap_conn_find(conn_handle, &desc); - if (rc != 0) { - return rc; - } + rc = ble_gap_conn_find(conn_handle, &desc); + if (rc != 0) { + return rc; + } - memset(&key_sec, 0, sizeof key_sec); - key_sec.peer_addr = desc.peer_id_addr; + memset(&key_sec, 0, sizeof key_sec); + key_sec.peer_addr = desc.peer_id_addr; - rc = ble_store_read_our_sec(&key_sec, &value_sec); - if (rc != 0) { - return rc; - } - if (value_sec.csrk_present != 1) { - return BLE_HS_ENOENT; - } - if (value_sec.sign_counter == (uint32_t)0xffffffff) { - return BLE_HS_ENOMEM; - } + rc = ble_store_read_our_sec(&key_sec, &value_sec); + if (rc != 0) { + return rc; + } + if (value_sec.csrk_present != 1) { + return BLE_HS_ENOENT; + } + if (value_sec.sign_counter == (uint32_t)0xffffffff) { + return BLE_HS_ENOMEM; + } - rc = ble_store_delete_our_sec(&key_sec); - if (rc != 0) { - return rc; - } + rc = ble_store_delete_our_sec(&key_sec); + if (rc != 0) { + return rc; + } - value_sec.sign_counter += 1; - rc = ble_store_write_our_sec(&value_sec); - if (rc != 0) { - return rc; - } + value_sec.sign_counter += 1; + rc = ble_store_write_our_sec(&value_sec); + if (rc != 0) { + return rc; + } - return 0; + return 0; } /** @@ -2701,42 +2701,48 @@ ble_sm_incr_our_sign_counter(uint16_t conn_handle) int ble_sm_incr_peer_sign_counter(uint16_t conn_handle) { - struct ble_store_key_sec key_sec; - struct ble_store_value_sec value_sec; - struct ble_gap_conn_desc desc; - int rc; - - rc = ble_gap_conn_find(conn_handle, &desc); - if (rc != 0) { - return rc; - } - - memset(&key_sec, 0, sizeof key_sec); - key_sec.peer_addr = desc.peer_id_addr; - - rc = ble_store_read_peer_sec(&key_sec, &value_sec); - if (rc != 0) { - return rc; - } - if (value_sec.csrk_present != 1) { - return BLE_HS_ENOENT; - } - if (value_sec.sign_counter == (uint32_t)0xffffffff) { - return BLE_HS_ENOMEM; - } - - rc = ble_store_delete_peer_sec(&key_sec); - if (rc != 0) { - return rc; - } - - value_sec.sign_counter += 1; - rc = ble_store_write_peer_sec(&value_sec); - if (rc != 0) { - return rc; - } - - return 0; + struct ble_store_key_sec key_sec; + struct ble_store_value_sec value_sec; + struct ble_gap_conn_desc desc; + int rc; + + rc = ble_gap_conn_find(conn_handle, &desc); + if (rc != 0) { + return rc; + } + + memset(&key_sec, 0, sizeof key_sec); + key_sec.peer_addr = desc.peer_id_addr; + + rc = ble_store_read_peer_sec(&key_sec, &value_sec); + if (rc != 0) { + return rc; + } + if (value_sec.csrk_present != 1) { + return BLE_HS_ENOENT; + } + if (value_sec.sign_counter == (uint32_t)0xffffffff) { + return BLE_HS_ENOMEM; + } + + rc = ble_store_delete_peer_sec(&key_sec); + if (rc != 0) { + return rc; + } + + if (value_sec.irk_present == 1) { + ble_hs_pvcy_remove_entry(value_sec.peer_addr.type, value_sec.peer_addr.val); + // No need to check if the above command fails or passes + // Proceed with trying to write the new sign counter + } + + value_sec.sign_counter += 1; + rc = ble_store_write_peer_sec(&value_sec); + if (rc != 0) { + return rc; + } + + return 0; } /** diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_sm_alg.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_sm_alg.c index e0dc71c5..6e1533a5 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_sm_alg.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_sm_alg.c @@ -32,14 +32,12 @@ #if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS) #include "mbedtls/aes.h" -#if MYNEWT_VAL(BLE_SM_SC) #include "mbedtls/cipher.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" #include "mbedtls/cmac.h" #include "mbedtls/ecdh.h" #include "mbedtls/ecp.h" -#endif #else #include "tinycrypt/aes.h" @@ -240,16 +238,6 @@ done: return rc; } -#if MYNEWT_VAL(BLE_SM_SC) - -static void -ble_sm_alg_log_buf(const char *name, const uint8_t *buf, int len) -{ - BLE_HS_LOG(DEBUG, " %s=", name); - ble_hs_log_flat_buf(buf, len); - BLE_HS_LOG(DEBUG, "\n"); -} - /** * Cypher based Message Authentication Code (CMAC) with AES 128 bit * @@ -321,6 +309,16 @@ ble_sm_alg_aes_cmac(const uint8_t *key, const uint8_t *in, size_t len, } #endif +#if MYNEWT_VAL(BLE_SM_SC) + +static void +ble_sm_alg_log_buf(const char *name, const uint8_t *buf, int len) +{ + BLE_HS_LOG(DEBUG, " %s=", name); + ble_hs_log_flat_buf(buf, len); + BLE_HS_LOG(DEBUG, "\n"); +} + int ble_sm_alg_f4(const uint8_t *u, const uint8_t *v, const uint8_t *x, uint8_t z, uint8_t *out_enc_data) @@ -598,11 +596,11 @@ exit: } #else - if (uECC_valid_public_key(pk, &curve_secp256r1) < 0) { + if (uECC_valid_public_key(pk, uECC_secp256r1()) < 0) { return BLE_HS_EUNKNOWN; } - rc = uECC_shared_secret(pk, priv, dh, &curve_secp256r1); + rc = uECC_shared_secret(pk, priv, dh, uECC_secp256r1()); if (rc == TC_CRYPTO_FAIL) { return BLE_HS_EUNKNOWN; } @@ -711,7 +709,7 @@ ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) return BLE_HS_EUNKNOWN; } #else - if (uECC_make_key(pk, priv, &curve_secp256r1) != TC_CRYPTO_SUCCESS) { + if (uECC_make_key(pk, priv, uECC_secp256r1()) != TC_CRYPTO_SUCCESS) { return BLE_HS_EUNKNOWN; } #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_sm_cmd.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_sm_cmd.c index b84df1ec..a740dc3a 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_sm_cmd.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_sm_cmd.c @@ -29,18 +29,20 @@ void * ble_sm_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom) { struct ble_sm_hdr *hdr; + void *data; *txom = ble_hs_mbuf_l2cap_pkt(); if (*txom == NULL) { return NULL; } - if (os_mbuf_extend(*txom, sizeof(*hdr) + len) == NULL) { + data = os_mbuf_extend(*txom, sizeof(*hdr) + len); + if (data == NULL) { os_mbuf_free_chain(*txom); return NULL; } - hdr = (struct ble_sm_hdr *)(*txom)->om_data; + hdr = (struct ble_sm_hdr *)data; hdr->opcode = opcode; diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_store.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_store.c index d1cabfac..a407cd8f 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_store.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_store.c @@ -285,6 +285,42 @@ ble_store_delete_cccd(const struct ble_store_key_cccd *key) return rc; } +int +ble_store_read_csfc(const struct ble_store_key_csfc *key, + struct ble_store_value_csfc *out_value) +{ + union ble_store_value *store_value; + union ble_store_key *store_key; + int rc; + + store_key = (void *)key; + store_value = (void *)out_value; + rc = ble_store_read(BLE_STORE_OBJ_TYPE_CSFC, store_key, store_value); + return rc; +} + +int +ble_store_write_csfc(const struct ble_store_value_csfc *value) +{ + union ble_store_value *store_value; + int rc; + + store_value = (void *)value; + rc = ble_store_write(BLE_STORE_OBJ_TYPE_CSFC, store_value); + return rc; +} + +int +ble_store_delete_csfc(const struct ble_store_key_csfc *key) +{ + union ble_store_key *store_key; + int rc; + + store_key = (void *)key; + rc = ble_store_delete(BLE_STORE_OBJ_TYPE_CSFC, store_key); + return rc; +} + void ble_store_key_from_value_cccd(struct ble_store_key_cccd *out_key, const struct ble_store_value_cccd *value) @@ -436,6 +472,14 @@ ble_store_key_from_value_rpa_rec(struct ble_store_key_rpa_rec *out_key, out_key->idx = 0; } +void +ble_store_key_from_value_csfc(struct ble_store_key_csfc *out_key, + const struct ble_store_value_csfc *value) +{ + out_key->peer_addr = value->peer_addr; + out_key->idx = 0; +} + void ble_store_key_from_value(int obj_type, union ble_store_key *out_key, @@ -456,12 +500,17 @@ ble_store_key_from_value(int obj_type, break; #endif case BLE_STORE_OBJ_TYPE_PEER_ADDR: - ble_store_key_from_value_rpa_rec(&out_key->rpa_rec, &value->rpa_rec); - break; + ble_store_key_from_value_rpa_rec(&out_key->rpa_rec, &value->rpa_rec); + break; - case BLE_STORE_OBJ_TYPE_LOCAL_IRK: + case BLE_STORE_OBJ_TYPE_LOCAL_IRK: ble_store_key_from_value_local_irk(&out_key->local_irk, &value->local_irk); - break; + break; + + case BLE_STORE_OBJ_TYPE_CSFC: + ble_store_key_from_value_csfc(&out_key->csfc, &value->csfc); + break; + default: BLE_HS_DBG_ASSERT(0); @@ -506,6 +555,10 @@ ble_store_iterate(int obj_type, key.local_irk.addr = *BLE_ADDR_ANY; pidx = &key.local_irk.idx; break; + case BLE_STORE_OBJ_TYPE_CSFC: + key.csfc.peer_addr = *BLE_ADDR_ANY; + pidx = &key.csfc.idx; + break; default: BLE_HS_DBG_ASSERT(0); return BLE_HS_EINVAL; @@ -550,6 +603,7 @@ ble_store_clear(void) BLE_STORE_OBJ_TYPE_OUR_SEC, BLE_STORE_OBJ_TYPE_PEER_SEC, BLE_STORE_OBJ_TYPE_CCCD, + BLE_STORE_OBJ_TYPE_CSFC, BLE_STORE_OBJ_TYPE_PEER_ADDR, BLE_STORE_OBJ_TYPE_LOCAL_IRK, #if MYNEWT_VAL(ENC_ADV_DATA) diff --git a/lib/bt/host/nimble/nimble/nimble/host/src/ble_store_util.c b/lib/bt/host/nimble/nimble/nimble/host/src/ble_store_util.c index b1227755..837b8c8c 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/src/ble_store_util.c +++ b/lib/bt/host/nimble/nimble/nimble/host/src/ble_store_util.c @@ -154,6 +154,14 @@ ble_store_util_delete_peer(const ble_addr_t *peer_id_addr) return rc; } + memset(&key, 0, sizeof key); + key.csfc.peer_addr = *peer_id_addr; + + rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_CSFC, &key); + if (rc != 0) { + return rc; + } + #if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) struct ble_hs_dev_records *peer_rec = ble_rpa_find_peer_dev_rec(key.sec.peer_addr.val); @@ -346,6 +354,7 @@ ble_store_util_status_rr(struct ble_store_status_event *event, void *arg) case BLE_STORE_OBJ_TYPE_PEER_ADDR: return ble_gap_unpair_oldest_peer(); case BLE_STORE_OBJ_TYPE_CCCD: + case BLE_STORE_OBJ_TYPE_CSFC: /* Try unpairing oldest peer except current peer */ return ble_gap_unpair_oldest_except(&event->overflow.value->cccd.peer_addr); #if MYNEWT_VAL(ENC_ADV_DATA) diff --git a/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config.c b/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config.c index 770edfb0..cab63634 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config.c +++ b/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config.c @@ -49,6 +49,12 @@ struct ble_store_value_cccd int ble_store_config_num_cccds; +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) +struct ble_store_value_csfc + ble_store_config_csfcs[MYNEWT_VAL(BLE_STORE_MAX_CSFCS)]; +#endif +int ble_store_config_num_csfcs; + #if MYNEWT_VAL(ENC_ADV_DATA) struct ble_store_value_ead ble_store_config_eads[MYNEWT_VAL(BLE_STORE_MAX_EADS)]; @@ -302,7 +308,6 @@ ble_store_config_write_our_sec(const struct ble_store_value_sec *value_sec) } -#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) static int ble_store_config_delete_obj(void *values, int value_size, int idx, int *num_values) @@ -324,6 +329,7 @@ ble_store_config_delete_obj(void *values, int value_size, int idx, return 0; } +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) static int ble_store_config_delete_sec(const struct ble_store_key_sec *key_sec, struct ble_store_value_sec *value_secs, @@ -693,6 +699,7 @@ ble_store_config_write_ead(const struct ble_store_value_ead *value_ead) static int ble_store_config_find_local_irk(const struct ble_store_key_local_irk *key) { +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) struct ble_store_value_local_irk *local_irk; int skipped; int i; @@ -714,7 +721,7 @@ ble_store_config_find_local_irk(const struct ble_store_key_local_irk *key) return i; } - +#endif return -1; } @@ -763,6 +770,7 @@ ble_store_config_read_local_irk(const struct ble_store_key_local_irk *key_irk, static int ble_store_config_write_local_irk(const struct ble_store_value_local_irk *value_irk) { +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) struct ble_store_key_local_irk key_irk; int idx; int rc; @@ -789,6 +797,9 @@ ble_store_config_write_local_irk(const struct ble_store_value_local_irk *value_i } return 0; +#else + return BLE_HS_ENOTSUP; +#endif } @@ -872,6 +883,7 @@ ble_store_config_write_rpa_rec(const struct ble_store_value_rpa_rec *value_rpa_r static int ble_store_config_delete_rpa_rec(const struct ble_store_key_rpa_rec *key_rpa_rec) { +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) int idx; int rc; @@ -894,6 +906,127 @@ ble_store_config_delete_rpa_rec(const struct ble_store_key_rpa_rec *key_rpa_rec) } return 0; +#else + return BLE_HS_ENOENT; +#endif +} + +/***************************************************************************** + * $csfc * + *****************************************************************************/ + +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) +static int +ble_store_config_find_csfc(const struct ble_store_key_csfc *key, + const struct ble_store_value_csfc *value_csfc, + int num_value_csfc) +{ + const struct ble_store_value_csfc *cur; + int i; + + if (!ble_addr_cmp(&key->peer_addr, BLE_ADDR_ANY)) { + if (key->idx < num_value_csfc) { + return key->idx; + } + } else if (key->idx == 0) { + for (i = 0; i < num_value_csfc; i++) { + cur = &value_csfc[i]; + + if (!ble_addr_cmp(&cur->peer_addr, &key->peer_addr)) { + return i; + } + } + } + + return -1; +} +#endif + +static int +ble_store_config_delete_csfc(const struct ble_store_key_csfc *key_csfc) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) + int idx; + int rc; + + idx = ble_store_config_find_csfc(key_csfc, ble_store_config_csfcs, + ble_store_config_num_csfcs); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + rc = ble_store_config_delete_obj(ble_store_config_csfcs, + sizeof *ble_store_config_csfcs, + idx, &ble_store_config_num_csfcs); + + if (rc != 0) { + return rc; + } + + rc = ble_store_config_persist_csfcs(); + if (rc != 0) { + return rc; + } + + return 0; +#else + return BLE_HS_ENOENT; +#endif +} + +static int +ble_store_config_read_csfc(const struct ble_store_key_csfc *key_csfc, + struct ble_store_value_csfc *value_csfc) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) + int idx; + + idx = ble_store_config_find_csfc(key_csfc, ble_store_config_csfcs, + ble_store_config_num_csfcs); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + *value_csfc = ble_store_config_csfcs[idx]; + return 0; +#else + return BLE_HS_ENOENT; +#endif +} + +static int +ble_store_config_write_csfc(const struct ble_store_value_csfc *value_csfc) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) + struct ble_store_key_csfc key_csfc; + int idx; + int rc; + + ble_store_key_from_value_csfc(&key_csfc, value_csfc); + idx = ble_store_config_find_csfc(&key_csfc, ble_store_config_csfcs, + ble_store_config_num_csfcs); + if (idx == -1) { + if (ble_store_config_num_csfcs >= MYNEWT_VAL(BLE_STORE_MAX_CSFCS)) { + BLE_HS_LOG(DEBUG, "error persisting csfc; too many entries (%d)\n", + ble_store_config_num_csfcs); + return BLE_HS_ESTORE_CAP; + } + + idx = ble_store_config_num_csfcs; + ble_store_config_num_csfcs++; + } + + ble_store_config_csfcs[idx] = *value_csfc; + + rc = ble_store_config_persist_csfcs(); + if (rc != 0) { + return rc; + } + + return 0; +#else + return BLE_HS_ENOENT; +#endif } /***************************************************************************** @@ -938,6 +1071,10 @@ ble_store_config_read(int obj_type, const union ble_store_key *key, rc = ble_store_config_read_cccd(&key->cccd, &value->cccd); return rc; + case BLE_STORE_OBJ_TYPE_CSFC: + rc = ble_store_config_read_csfc(&key->csfc, &value->csfc); + return rc; + #if MYNEWT_VAL(ENC_ADV_DATA) case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA: rc = ble_store_config_read_ead(&key->ead, &value->ead); @@ -979,6 +1116,10 @@ ble_store_config_write(int obj_type, const union ble_store_value *val) rc = ble_store_config_write_cccd(&val->cccd); return rc; + case BLE_STORE_OBJ_TYPE_CSFC: + rc = ble_store_config_write_csfc(&val->csfc); + return rc; + #if MYNEWT_VAL(ENC_ADV_DATA) case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA: rc = ble_store_config_write_ead(&val->ead); @@ -1015,6 +1156,10 @@ ble_store_config_delete(int obj_type, const union ble_store_key *key) rc = ble_store_config_delete_cccd(&key->cccd); return rc; + case BLE_STORE_OBJ_TYPE_CSFC: + rc = ble_store_config_delete_csfc(&key->csfc); + return rc; + #if MYNEWT_VAL(ENC_ADV_DATA) case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA: rc = ble_store_config_delete_ead(&key->ead); @@ -1047,6 +1192,7 @@ ble_store_config_init(void) ble_store_config_num_our_secs = 0; ble_store_config_num_peer_secs = 0; ble_store_config_num_cccds = 0; + ble_store_config_num_csfcs = 0; #if MYNEWT_VAL(ENC_ADV_DATA) ble_store_config_num_eads = 0; #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config_conf.c b/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config_conf.c index 1300bc16..8d2d9051 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config_conf.c +++ b/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config_conf.c @@ -57,6 +57,12 @@ static struct conf_handler ble_store_config_conf_handler = { #define BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ \ (MYNEWT_VAL(BLE_STORE_MAX_CCCDS) * BLE_STORE_CONFIG_CCCD_ENCODE_SZ + 1) +#define BLE_STORE_CONFIG_CSFC_ENCODE_SZ \ + BASE64_ENCODE_SIZE(sizeof (struct ble_store_value_csfc)) + +#define BLE_STORE_CONFIG_CSFC_SET_ENCODE_SZ \ + (MYNEWT_VAL(BLE_STORE_MAX_CSFCS) * BLE_STORE_CONFIG_CSFC_ENCODE_SZ + 1) + #if MYNEWT_VAL(ENC_ADV_DATA) #define BLE_STORE_CONFIG_EAD_ENCODE_SZ \ BASE64_ENCODE_SIZE(sizeof (struct ble_store_value_ead)) @@ -127,6 +133,13 @@ ble_store_config_conf_set(int argc, char **argv, char *val) sizeof *ble_store_config_cccds, &ble_store_config_num_cccds); return rc; + } else if (strcmp(argv[0], "csfc") == 0) { + rc = ble_store_config_deserialize_arr( + val, + ble_store_config_csfcs, + sizeof *ble_store_config_csfcs, + &&ble_store_config_num_csfcs); + return rc; } #if MYNEWT_VAL(ENC_ADV_DATA) else if (strcmp(argv[0], "ead") == 0) { @@ -181,6 +194,13 @@ ble_store_config_conf_export(void (*func)(char *name, char *val), sizeof buf.cccd); func("ble_hs/cccd", buf.cccd); + ble_store_config_serialize_arr(ble_store_config_csfcs, + sizeof *ble_store_config_csfcs, + ble_store_config_num_csfcs, + buf.csfc, + sizeof buf.csfc); + func("ble_hs/csfc", buf.csfc); + #if MYNEWT_VAL(ENC_ADV_DATA) ble_store_config_serialize_arr(ble_store_config_eads, sizeof *ble_store_config_eads, @@ -264,6 +284,25 @@ ble_store_config_persist_cccds(void) return 0; } +int +ble_store_config_persist_csfcs(void) +{ + char buf[BLE_STORE_CONFIG_CSFC_SET_ENCODE_SZ]; + int rc; + + ble_store_config_serialize_arr(ble_store_config_csfcs, + sizeof *ble_store_config_csfcs, + ble_store_config_num_csfcs, + buf, + sizeof buf); + rc = conf_save_one("ble_hs/csfc", buf); + if (rc != 0) { + return BLE_HS_ESTORE_FAIL; + } + + return 0; +} + #if MYNEWT_VAL(ENC_ADV_DATA) int ble_store_config_persist_eads(void) diff --git a/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config_priv.h b/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config_priv.h index 581cefdc..a3dcc6aa 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config_priv.h +++ b/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_config_priv.h @@ -36,6 +36,10 @@ extern struct ble_store_value_cccd ble_store_config_cccds[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)]; extern int ble_store_config_num_cccds; +extern struct ble_store_value_csfc + ble_store_config_csfcs[MYNEWT_VAL(BLE_STORE_MAX_CSFCS)]; +extern int ble_store_config_num_csfcs; + #if MYNEWT_VAL(ENC_ADV_DATA) extern struct ble_store_value_ead ble_store_config_eads[MYNEWT_VAL(BLE_STORE_MAX_EADS)]; @@ -56,6 +60,7 @@ extern int ble_store_config_num_local_irks; int ble_store_config_persist_our_secs(void); int ble_store_config_persist_peer_secs(void); int ble_store_config_persist_cccds(void); +int ble_store_config_persist_csfcs(void); #if MYNEWT_VAL(BLE_STORE_MAX_BONDS) int ble_restore_our_sec_nvs(void); int ble_restore_peer_sec_nvs(void); @@ -72,6 +77,7 @@ void ble_store_config_conf_init(void); static inline int ble_store_config_persist_our_secs(void) { return 0; } static inline int ble_store_config_persist_peer_secs(void) { return 0; } static inline int ble_store_config_persist_cccds(void) { return 0; } +static inline int ble_store_config_persist_csfcs(void) { return 0; } #if MYNEWT_VAL(ENC_ADV_DATA) static inline int ble_store_config_persist_eads(void) { return 0; } #endif diff --git a/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c b/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c index 8ae391e4..4b0ade85 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c +++ b/lib/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c @@ -39,6 +39,7 @@ #define NIMBLE_NVS_PEER_SEC_KEY "peer_sec" #define NIMBLE_NVS_OUR_SEC_KEY "our_sec" #define NIMBLE_NVS_CCCD_SEC_KEY "cccd_sec" +#define NIMBLE_NVS_CSFC_SEC_KEY "csfc_sec" #define NIMBLE_NVS_PEER_RECORDS_KEY "p_dev_rec" #define NIMBLE_NVS_NAMESPACE "nimble_bond" @@ -66,7 +67,7 @@ get_nvs_key_string(int obj_type, int index, char *key_string) } else if (obj_type == BLE_STORE_OBJ_TYPE_OUR_SEC) { sprintf(key_string, "%s_%d", NIMBLE_NVS_OUR_SEC_KEY, index); #if MYNEWT_VAL(ENC_ADV_DATA) - } else if (obj_type == NIMBLE_NVS_EAD_SEC_KEY) { + } else if (obj_type == BLE_STORE_OBJ_TYPE_ENC_ADV_DATA) { sprintf(key_string, "%s_%d", NIMBLE_NVS_EAD_SEC_KEY, index); #endif } else if (obj_type == BLE_STORE_OBJ_TYPE_LOCAL_IRK) { @@ -74,8 +75,10 @@ get_nvs_key_string(int obj_type, int index, char *key_string) } else if (obj_type == BLE_STORE_OBJ_TYPE_PEER_ADDR){ sprintf(key_string, "%s_%d", NIMBLE_NVS_RPA_RECORDS_KEY, index); - }else { + } else if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) { sprintf(key_string, "%s_%d", NIMBLE_NVS_CCCD_SEC_KEY, index); + } else { + sprintf(key_string, "%s_%d", NIMBLE_NVS_CSFC_SEC_KEY, index); } } } @@ -110,8 +113,10 @@ get_nvs_max_obj_value(int obj_type) } else { if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) { return MYNEWT_VAL(BLE_STORE_MAX_CCCDS); + } else if (obj_type == BLE_STORE_OBJ_TYPE_CSFC) { + return MYNEWT_VAL(BLE_STORE_MAX_CSFCS); #if MYNEWT_VAL(ENC_ADV_DATA) - } else if (obj_type == BLE_STORE_OBJ_TYPE_EAD) { + } else if (obj_type == BLE_STORE_OBJ_TYPE_ENC_ADV_DATA) { return MYNEWT_VAL(BLE_STORE_MAX_EADS); #endif } else { @@ -176,8 +181,11 @@ get_nvs_db_value(int obj_type, char *key_string, union ble_store_value *val) if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) { err = nvs_get_blob(nimble_handle, key_string, &val->cccd, &required_size); + } else if (obj_type == BLE_STORE_OBJ_TYPE_CSFC) { + err = nvs_get_blob(nimble_handle, key_string, &val->csfc, + &required_size); #if MYNEWT_VAL(ENC_ADV_DATA) - } else if (obj_type == BLE_STORE_OBJ_TYPE_EAD) { + } else if (obj_type == BLE_STORE_OBJ_TYPE_ENC_ADV_DATA) { err = nvs_get_blob(nimble_handle, key_string, &val->ead, &required_size); #endif @@ -255,8 +263,11 @@ get_nvs_db_attribute(int obj_type, bool empty, void *value, int num_value) if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) { err = get_nvs_matching_index(&cur.sec, value, num_value, sizeof(struct ble_store_value_cccd)); + } else if (obj_type == BLE_STORE_OBJ_TYPE_CSFC) { + err = get_nvs_matching_index(&cur.csfc, value, num_value, + sizeof(struct ble_store_value_csfc)); #if MYNEWT_VAL(ENC_ADV_DATA) - } else if (obj_type == BLE_STORE_OBJ_TYPE_EAD) { + } else if (obj_type == BLE_STORE_OBJ_TYPE_ENC_ADV_DATA) { err = get_nvs_matching_index(&cur.sec, value, num_value, sizeof(struct ble_store_value_ead)); #endif @@ -392,8 +403,11 @@ ble_store_nvs_write(int obj_type, const union ble_store_value *val) if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) { return ble_nvs_write_key_value(key_string, &val->cccd, sizeof(struct ble_store_value_cccd)); + } else if (obj_type == BLE_STORE_OBJ_TYPE_CSFC) { + return ble_nvs_write_key_value(key_string, &val->csfc, sizeof(struct + ble_store_value_csfc)); #if MYNEWT_VAL(ENC_ADV_DATA) - } else if (obj_type == BLE_STORE_OBJ_TYPE_EAD) { + } else if (obj_type == BLE_STORE_OBJ_TYPE_ENC_ADV_DATA) { return ble_nvs_write_key_value(key_string, &val->ead, sizeof(struct ble_store_value_ead)); #endif @@ -489,8 +503,13 @@ populate_db_from_nvs(int obj_type, void *dst, int *db_num) memcpy(db_item, &cur.cccd, sizeof(struct ble_store_value_cccd)); db_item += sizeof(struct ble_store_value_cccd); (*db_num)++; + } else if (obj_type == BLE_STORE_OBJ_TYPE_CSFC) { + ESP_LOGD(TAG, "CSFC in RAM is filled up from NVS index = %d", i); + memcpy(db_item, &cur.csfc, sizeof(struct ble_store_value_csfc)); + db_item += sizeof(struct ble_store_value_csfc); + (*db_num)++; #if MYNEWT_VAL(ENC_ADV_DATA) - } if (obj_type == BLE_STORE_OBJ_TYPE_EAD) { + } else if (obj_type == BLE_STORE_OBJ_TYPE_ENC_ADV_DATA) { ESP_LOGD(TAG, "EAD in RAM is filled up from NVS index = %d", i); memcpy(db_item, &cur.ead, sizeof(struct ble_store_value_ead)); db_item += sizeof(struct ble_store_value_ead); @@ -581,8 +600,19 @@ ble_nvs_restore_sec_keys(void) ble_store_config_num_cccds); #endif +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) + err = populate_db_from_nvs(BLE_STORE_OBJ_TYPE_CSFC, ble_store_config_csfcs, + &ble_store_config_num_csfcs); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS operation failed for 'CSFC'"); + return err; + } + ESP_LOGD(TAG, "ble_store_config_csfcs restored %d bonds", + ble_store_config_num_csfcs); +#endif + #if MYNEWT_VAL(ENC_ADV_DATA) - err = populate_db_from_nvs(BLE_STORE_OBJ_TYPE_EAD, ble_store_config_eads, + err = populate_db_from_nvs(BLE_STORE_OBJ_TYPE_ENC_ADV_DATA, ble_store_config_eads, &ble_store_config_num_eads); if (err != ESP_OK) { ESP_LOGE(TAG, "NVS operation failed for 'EAD'"); @@ -667,6 +697,38 @@ int ble_store_config_persist_cccds(void) } #endif +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) +int ble_store_config_persist_csfcs(void) +{ + int nvs_count, nvs_idx; + union ble_store_value val; + + nvs_count = get_nvs_db_attribute(BLE_STORE_OBJ_TYPE_CSFC, 0, NULL, 0); + if (nvs_count == -1) { + ESP_LOGE(TAG, "NVS operation failed while persisting CSFC"); + return BLE_HS_ESTORE_FAIL; + } + + if (nvs_count < ble_store_config_num_csfcs) { + /* NVS db count less than RAM count, write operation */ + ESP_LOGD(TAG, "Persisting CSFC value in NVS..."); + val.csfc = ble_store_config_csfcs[ble_store_config_num_csfcs - 1]; + return ble_store_nvs_write(BLE_STORE_OBJ_TYPE_CSFC, &val); + } else if (nvs_count > ble_store_config_num_csfcs) { + /* NVS db count more than RAM count, delete operation */ + nvs_idx = get_nvs_db_attribute(BLE_STORE_OBJ_TYPE_CSFC, 0, + ble_store_config_csfcs, ble_store_config_num_csfcs); + if (nvs_idx == -1) { + ESP_LOGE(TAG, "NVS delete operation failed for CSFC"); + return BLE_HS_ESTORE_FAIL; + } + ESP_LOGD(TAG, "Deleting CSFC, nvs idx = %d", nvs_idx); + return ble_nvs_delete_value(BLE_STORE_OBJ_TYPE_CSFC, nvs_idx); + } + return 0; +} +#endif + #if MYNEWT_VAL(ENC_ADV_DATA) int ble_store_config_persist_eads(void) { @@ -693,7 +755,7 @@ int ble_store_config_persist_eads(void) return BLE_HS_ESTORE_FAIL; } ESP_LOGD(TAG, "Deleting EAD, nvs idx = %d", nvs_idx); - return ble_nvs_delete_value(BLE_STORE_OBJ_TYPE_EAD, nvs_idx); + return ble_nvs_delete_value(BLE_STORE_OBJ_TYPE_ENC_ADV_DATA, nvs_idx); } return 0; } diff --git a/lib/bt/host/nimble/nimble/nimble/host/store/ram/src/ble_store_ram.c b/lib/bt/host/nimble/nimble/nimble/host/store/ram/src/ble_store_ram.c index d587b8ac..2d7c3af1 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/store/ram/src/ble_store_ram.c +++ b/lib/bt/host/nimble/nimble/nimble/host/store/ram/src/ble_store_ram.c @@ -27,7 +27,6 @@ * use the store/config package. For a RAM-only BLE store, * use store/config and set BLE_STORE_CONFIG_PERSIST to 0. */ - #include #include @@ -36,6 +35,7 @@ #include "host/ble_hs.h" #include "store/ram/ble_store_ram.h" +#if !MYNEWT_VAL(BLE_USED_IN_IDF) #if MYNEWT_VAL(BLE_STORE_MAX_BONDS) static struct ble_store_value_sec ble_store_ram_our_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; @@ -57,6 +57,13 @@ static struct ble_store_value_cccd static int ble_store_ram_num_cccds; +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) +static struct ble_store_value_csfc + ble_store_ram_csfcs[MYNEWT_VAL(BLE_STORE_MAX_CSFCS)]; +#endif + +static int ble_store_ram_num_csfcs; + #if MYNEWT_VAL(ENC_ADV_DATA) static struct ble_store_value_ead ble_store_ram_eads[MYNEWT_VAL(BLE_STORE_MAX_EADS)]; @@ -184,7 +191,7 @@ ble_store_ram_write_our_sec(const struct ble_store_value_sec *value_sec) } -#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) || MYNEWT_VAL(BLE_STORE_MAX_CCCDS) static int ble_store_ram_delete_obj(void *values, int value_size, int idx, int *num_values) @@ -205,7 +212,9 @@ ble_store_ram_delete_obj(void *values, int value_size, int idx, return 0; } +#endif +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) static int ble_store_ram_delete_sec(const struct ble_store_key_sec *key_sec, struct ble_store_value_sec *value_secs, @@ -432,6 +441,111 @@ ble_store_ram_write_cccd(const struct ble_store_value_cccd *value_cccd) } +/***************************************************************************** + * $csfc * + *****************************************************************************/ + +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) +static int +ble_store_ram_find_csfc(const struct ble_store_key_csfc *key) +{ + struct ble_store_value_csfc *csfc; + int skipped; + int i; + + skipped = 0; + for (i = 0; i < ble_store_ram_num_csfcs; i++) { + csfc = ble_store_ram_csfcs + i; + + if (ble_addr_cmp(&key->peer_addr, BLE_ADDR_ANY)) { + if (ble_addr_cmp(&csfc->peer_addr, &key->peer_addr)) { + continue; + } + } + + if (key->idx > skipped) { + skipped++; + continue; + } + + return i; + } + + return -1; +} +#endif + +static int +ble_store_ram_delete_csfc(const struct ble_store_key_csfc *key_csfc) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) + int idx; + int rc; + + idx = ble_store_ram_find_csfc(key_csfc); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + rc = ble_store_ram_delete_obj(ble_store_ram_csfcs, + sizeof *ble_store_ram_csfcs, + idx, + &ble_store_ram_num_csfcs); + if (rc != 0) { + return rc; + } + return 0; +#else + return BLE_HS_ENOENT; +#endif +} + +static int +ble_store_ram_read_csfc(const struct ble_store_key_csfc *key_csfc, + struct ble_store_value_csfc *value_csfc) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) + int idx; + + idx = ble_store_ram_find_csfc(key_csfc); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + *value_csfc = ble_store_ram_csfcs[idx]; + + return 0; +#else + return BLE_HS_ENOENT; +#endif +} + +static int +ble_store_ram_write_csfc(const struct ble_store_value_csfc *value_csfc) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) + struct ble_store_key_csfc key_csfc; + int idx; + + ble_store_key_from_value_csfc(&key_csfc, value_csfc); + idx = ble_store_ram_find_csfc(&key_csfc); + if (idx == -1) { + if (ble_store_ram_num_csfcs >= MYNEWT_VAL(BLE_STORE_MAX_CSFCS)) { + BLE_HS_LOG(DEBUG, "error persisting csfc; too many entries (%d)\n", + ble_store_ram_num_csfcs); + return BLE_HS_ESTORE_CAP; + } + + idx = ble_store_ram_num_csfcs; + ble_store_ram_num_csfcs++; + } + + ble_store_ram_csfcs[idx] = *value_csfc; + return 0; +#else + return BLE_HS_ENOENT; +#endif +} /***************************************************************************** * $ead * @@ -567,6 +681,10 @@ ble_store_ram_read(int obj_type, const union ble_store_key *key, rc = ble_store_ram_read_cccd(&key->cccd, &value->cccd); return rc; + case BLE_STORE_OBJ_TYPE_CSFC: + rc = ble_store_ram_read_csfc(&key->csfc, &value->csfc); + return rc; + #if MYNEWT_VAL(ENC_ADV_DATA) case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA: rc = ble_store_ram_read_ead(&key->ead, &value->ead); @@ -602,6 +720,10 @@ ble_store_ram_write(int obj_type, const union ble_store_value *val) rc = ble_store_ram_write_cccd(&val->cccd); return rc; + case BLE_STORE_OBJ_TYPE_CSFC: + rc = ble_store_ram_write_csfc(&val->csfc); + return rc; + #if MYNEWT_VAL(ENC_ADV_DATA) case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA: rc = ble_store_ram_write_ead(&val->ead); @@ -631,6 +753,10 @@ ble_store_ram_delete(int obj_type, const union ble_store_key *key) rc = ble_store_ram_delete_cccd(&key->cccd); return rc; + case BLE_STORE_OBJ_TYPE_CSFC: + rc = ble_store_ram_delete_csfc(&key->csfc); + return rc; + #if MYNEWT_VAL(ENC_ADV_DATA) case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA: rc = ble_store_ram_delete_ead(&key->ead); @@ -656,7 +782,9 @@ ble_store_ram_init(void) ble_store_ram_num_our_secs = 0; ble_store_ram_num_peer_secs = 0; ble_store_ram_num_cccds = 0; + ble_store_ram_num_csfcs = 0; #if MYNEWT_VAL(ENC_ADV_DATA) ble_store_ram_num_eads = 0; #endif } +#endif //Not used in IDF diff --git a/lib/bt/host/nimble/nimble/nimble/host/syscfg.yml b/lib/bt/host/nimble/nimble/nimble/host/syscfg.yml index eb1abdf4..6694ee4c 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/syscfg.yml +++ b/lib/bt/host/nimble/nimble/nimble/host/syscfg.yml @@ -277,6 +277,10 @@ syscfg.defs: description: > Enables sending and receiving of GATT indications. (0/1) value: 1 + BLE_GATT_NOTIFY_MULTIPLE: + description: > + Enables sending and receiving of GATT multi handle notifications. + value: 1 # GATT options. BLE_GATT_READ_MAX_ATTRS: @@ -299,6 +303,22 @@ syscfg.defs: due to memory exhaustion. (0/1) Units are milliseconds. (0/1) value: 1000 + # Enhanced ATT bearer options + BLE_EATT_CHAN_NUM: + description: > + Maximum number of supported EATT channels (in total). If set to 0 + EATT support it disabled. + value: 0 + restrictions: + - BLE_GATT_NOTIFY_MULTIPLE + - BLE_L2CAP_ENHANCED_COC + - 'BLE_L2CAP_COC_MAX_NUM >= BLE_EATT_CHAN_NUM' + + BLE_EATT_MTU: + description: > + MTU used for EATT channels. + value: 128 + # Supported server ATT commands. (0/1) BLE_ATT_SVR_FIND_INFO: description: > @@ -357,6 +377,12 @@ syscfg.defs: Enables processing of incoming Handle Value Notification ATT commands. (0/1) value: 1 + BLE_ATT_SVR_NOTIFY_MULTI: + description: > + Enables processing of incoming Multi Handle Value Notification ATT + commands. (0/1) + value: MYNEWT_VAL_BLE_ATT_SVR_NOTIFY && (MYNEWT_VAL_BLE_VERSION >= 52) + BLE_ATT_SVR_INDICATE: description: > Enables processing of incoming Handle Value Indication ATT @@ -467,11 +493,22 @@ syscfg.defs: description: 'Minimum level for the BLE host log.' value: 1 + BLE_EATT_LOG_MOD: + description: 'Numeric module ID to use for BLE EATT log messages.' + value: 27 + BLE_EATT_LOG_LVL: + description: 'Minimum level for the BLE EATT log.' + value: 1 + syscfg.logs: BLE_HS_LOG: module: MYNEWT_VAL(BLE_HS_LOG_MOD) level: MYNEWT_VAL(BLE_HS_LOG_LVL) + BLE_EATT_LOG: + module: MYNEWT_VAL(BLE_EATT_LOG_MOD) + level: MYNEWT_VAL(BLE_EATT_LOG_LVL) + syscfg.vals.BLE_MESH: BLE_SM_SC: 1 diff --git a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_att_clt_test.c b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_att_clt_test.c index 0b6d55d3..35d2e235 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_att_clt_test.c +++ b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_att_clt_test.c @@ -67,9 +67,9 @@ ble_att_clt_test_tx_write_req_or_cmd(uint16_t conn_handle, uint16_t handle, om = ble_hs_test_util_om_from_flat(value, value_len); if (is_req) { - rc = ble_att_clt_tx_write_req(conn_handle, handle, om); + rc = ble_att_clt_tx_write_req(conn_handle, BLE_L2CAP_CID_ATT, handle, om); } else { - rc = ble_att_clt_tx_write_cmd(conn_handle, handle, om); + rc = ble_att_clt_tx_write_cmd(conn_handle, BLE_L2CAP_CID_ATT, handle, om); } TEST_ASSERT(rc == 0); } @@ -78,25 +78,35 @@ TEST_CASE_SELF(ble_att_clt_test_tx_find_info) { uint16_t conn_handle; int rc; + struct ble_hs_conn *conn; ble_hs_test_util_assert_mbufs_freed(NULL); conn_handle = ble_att_clt_test_misc_init(); + ble_hs_lock(); + conn = ble_hs_conn_find(conn_handle); + ble_hs_unlock(); /*** Success. */ - rc = ble_att_clt_tx_find_info(conn_handle, 1, 0xffff); + rc = ble_att_clt_tx_find_info(conn_handle, BLE_L2CAP_CID_ATT, 1, 0xffff); TEST_ASSERT(rc == 0); /*** Error: start handle of 0. */ - rc = ble_att_clt_tx_find_info(conn_handle, 0, 0xffff); + /** In unit tests we don't are not receiving response - procedure will + * not complete. Reset `client_att_busy` flag so new request can be sent + */ + conn->client_att_busy = false; + rc = ble_att_clt_tx_find_info(conn_handle, BLE_L2CAP_CID_ATT, 0, 0xffff); TEST_ASSERT(rc == BLE_HS_EINVAL); /*** Error: start handle greater than end handle. */ - rc = ble_att_clt_tx_find_info(conn_handle, 500, 499); + conn->client_att_busy = false; + rc = ble_att_clt_tx_find_info(conn_handle, BLE_L2CAP_CID_ATT, 500, 499); TEST_ASSERT(rc == BLE_HS_EINVAL); /*** Success; start and end handles equal. */ - rc = ble_att_clt_tx_find_info(conn_handle, 500, 500); + conn->client_att_busy = false; + rc = ble_att_clt_tx_find_info(conn_handle, BLE_L2CAP_CID_ATT, 500, 500); TEST_ASSERT(rc == 0); ble_hs_test_util_assert_mbufs_freed(NULL); @@ -175,9 +185,14 @@ ble_att_clt_test_case_tx_write_req_or_cmd(int is_req) uint16_t conn_handle; uint8_t value300[500] = { 0 }; uint8_t value5[5] = { 6, 7, 54, 34, 8 }; + struct ble_hs_conn *conn; conn_handle = ble_att_clt_test_misc_init(); + ble_hs_lock(); + conn = ble_hs_conn_find(conn_handle); + ble_hs_unlock(); + /*** 5-byte write. */ ble_att_clt_test_tx_write_req_or_cmd(conn_handle, 0x1234, value5, sizeof value5, is_req); @@ -185,6 +200,10 @@ ble_att_clt_test_case_tx_write_req_or_cmd(int is_req) is_req); /*** Overlong write; verify command truncated to ATT MTU. */ + /** In unit tests we are not receiving response - procedure will + * not complete. Reset `client_att_busy` flag so new request can be sent + */ + conn->client_att_busy = false; ble_att_clt_test_tx_write_req_or_cmd(conn_handle, 0xab83, value300, sizeof value300, is_req); ble_att_clt_test_misc_verify_tx_write(0xab83, value300, @@ -206,7 +225,7 @@ ble_att_clt_test_misc_prep_good(uint16_t handle, uint16_t offset, conn_handle = ble_att_clt_test_misc_init(); om = ble_hs_test_util_om_from_flat(attr_data, attr_data_len); - rc = ble_att_clt_tx_prep_write(conn_handle, handle, offset, om); + rc = ble_att_clt_tx_prep_write(conn_handle, BLE_L2CAP_CID_ATT, handle, offset, om); TEST_ASSERT(rc == 0); om = ble_hs_test_util_prev_tx_dequeue_pullup(); @@ -232,7 +251,7 @@ ble_att_clt_test_misc_exec_good(uint8_t flags) conn_handle = ble_att_clt_test_misc_init(); - rc = ble_att_clt_tx_exec_write(conn_handle, flags); + rc = ble_att_clt_tx_exec_write(conn_handle, BLE_L2CAP_CID_ATT, flags); TEST_ASSERT(rc == 0); om = ble_hs_test_util_prev_tx_dequeue_pullup(); @@ -256,7 +275,7 @@ ble_att_clt_test_misc_prep_bad(uint16_t handle, uint16_t offset, om = ble_hs_test_util_om_from_flat(attr_data, attr_data_len); - rc = ble_att_clt_tx_prep_write(conn_handle, handle, offset, om); + rc = ble_att_clt_tx_prep_write(conn_handle, BLE_L2CAP_CID_ATT, handle, offset, om); TEST_ASSERT(rc == status); } @@ -287,11 +306,11 @@ TEST_CASE_SELF(ble_att_clt_test_tx_read) conn_handle = ble_att_clt_test_misc_init(); /*** Success. */ - rc = ble_att_clt_tx_read(conn_handle, 1); + rc = ble_att_clt_tx_read(conn_handle, BLE_L2CAP_CID_ATT, 1); TEST_ASSERT(rc == 0); /*** Error: handle of 0. */ - rc = ble_att_clt_tx_read(conn_handle, 0); + rc = ble_att_clt_tx_read(conn_handle, BLE_L2CAP_CID_ATT, 0); TEST_ASSERT(rc == BLE_HS_EINVAL); ble_hs_test_util_assert_mbufs_freed(NULL); @@ -333,11 +352,11 @@ TEST_CASE_SELF(ble_att_clt_test_tx_read_blob) conn_handle = ble_att_clt_test_misc_init(); /*** Success. */ - rc = ble_att_clt_tx_read_blob(conn_handle, 1, 0); + rc = ble_att_clt_tx_read_blob(conn_handle, BLE_L2CAP_CID_ATT, 1, 0); TEST_ASSERT(rc == 0); /*** Error: handle of 0. */ - rc = ble_att_clt_tx_read_blob(conn_handle, 0, 0); + rc = ble_att_clt_tx_read_blob(conn_handle, BLE_L2CAP_CID_ATT, 0, 0); TEST_ASSERT(rc == BLE_HS_EINVAL); ble_hs_test_util_assert_mbufs_freed(NULL); @@ -380,7 +399,7 @@ TEST_CASE_SELF(ble_att_clt_test_tx_read_mult) conn_handle = ble_att_clt_test_misc_init(); /*** Success. */ - rc = ble_att_clt_tx_read_mult(conn_handle, ((uint16_t[]){ 1, 2 }), 2, false); + rc = ble_att_clt_tx_read_mult(conn_handle, BLE_L2CAP_CID_ATT, ((uint16_t[]){ 1, 2 }), 2, false); TEST_ASSERT(rc == 0); om = ble_hs_test_util_prev_tx_dequeue_pullup(); @@ -392,7 +411,7 @@ TEST_CASE_SELF(ble_att_clt_test_tx_read_mult) TEST_ASSERT(get_le16(om->om_data + BLE_ATT_READ_MULT_REQ_BASE_SZ + 2) == 2); /*** Error: no handles. */ - rc = ble_att_clt_tx_read_mult(conn_handle, NULL, 0, false); + rc = ble_att_clt_tx_read_mult(conn_handle, BLE_L2CAP_CID_ATT, NULL, 0, false); TEST_ASSERT(rc == BLE_HS_EINVAL); ble_hs_test_util_assert_mbufs_freed(NULL); @@ -501,14 +520,14 @@ TEST_CASE_SELF(ble_att_clt_test_tx_exec_write) uint16_t conn_handle; int rc; - conn_handle = ble_att_clt_test_misc_init(); /*** Success. */ ble_att_clt_test_misc_exec_good(BLE_ATT_EXEC_WRITE_F_CANCEL); ble_att_clt_test_misc_exec_good(BLE_ATT_EXEC_WRITE_F_EXECUTE); /*** Success: nonzero == execute. */ - rc = ble_att_clt_tx_exec_write(conn_handle, 0x02); + conn_handle = ble_att_clt_test_misc_init(); + rc = ble_att_clt_tx_exec_write(conn_handle, BLE_L2CAP_CID_ATT, 0x02); TEST_ASSERT(rc == 0); ble_hs_test_util_assert_mbufs_freed(NULL); diff --git a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_att_svr_test.c b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_att_svr_test.c index 60ab14b4..84394d6a 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_att_svr_test.c +++ b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_att_svr_test.c @@ -24,6 +24,7 @@ #include "nimble/hci_common.h" #include "ble_hs_test.h" #include "host/ble_uuid.h" +#include "host/ble_l2cap.h" #include "ble_hs_test_util.h" static uint8_t *ble_att_svr_test_attr_r_1; @@ -478,7 +479,7 @@ ble_att_svr_test_misc_verify_all_read_mult( } static void -ble_att_svr_test_misc_verify_tx_mtu_rsp(uint16_t conn_handle) +ble_att_svr_test_misc_verify_tx_mtu_rsp(uint16_t conn_handle, uint16_t cid) { struct ble_l2cap_chan *chan; struct ble_hs_conn *conn; @@ -487,7 +488,7 @@ ble_att_svr_test_misc_verify_tx_mtu_rsp(uint16_t conn_handle) ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, cid, &conn, &chan); assert(rc == 0); my_mtu = chan->my_mtu; @@ -644,7 +645,7 @@ ble_att_svr_test_misc_mtu_exchange(uint16_t my_mtu, uint16_t peer_sent, buf, sizeof buf); TEST_ASSERT(rc == 0); - ble_att_svr_test_misc_verify_tx_mtu_rsp(conn_handle); + ble_att_svr_test_misc_verify_tx_mtu_rsp(conn_handle, BLE_L2CAP_CID_ATT); ble_hs_lock(); rc = ble_hs_misc_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, @@ -1138,19 +1139,19 @@ TEST_CASE_SELF(ble_att_svr_test_find_info) conn_handle = ble_att_svr_test_misc_init(128); /*** Start handle of 0. */ - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 0, 0); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, 0, 0); TEST_ASSERT(rc != 0); ble_hs_test_util_verify_tx_err_rsp( BLE_ATT_OP_FIND_INFO_REQ, 0, BLE_ATT_ERR_INVALID_HANDLE); /*** Start handle > end handle. */ - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 101, 100); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, 101, 100); TEST_ASSERT(rc != 0); ble_hs_test_util_verify_tx_err_rsp( BLE_ATT_OP_FIND_INFO_REQ, 101, BLE_ATT_ERR_INVALID_HANDLE); /*** No attributes. */ - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 200, 300); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, 200, 300); TEST_ASSERT(rc != 0); ble_hs_test_util_verify_tx_err_rsp( BLE_ATT_OP_FIND_INFO_REQ, 200, BLE_ATT_ERR_ATTR_NOT_FOUND); @@ -1160,13 +1161,13 @@ TEST_CASE_SELF(ble_att_svr_test_find_info) ble_att_svr_test_misc_attr_fn_r_1, NULL); TEST_ASSERT(rc == 0); - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 200, 300); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, 200, 300); TEST_ASSERT(rc != 0); ble_hs_test_util_verify_tx_err_rsp( BLE_ATT_OP_FIND_INFO_REQ, 200, BLE_ATT_ERR_ATTR_NOT_FOUND); /*** One 128-bit entry. */ - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle1, handle1); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, handle1, handle1); TEST_ASSERT(rc == 0); ble_hs_test_util_verify_tx_find_info_rsp( ((struct ble_hs_test_util_att_info_entry[]) { { @@ -1181,7 +1182,7 @@ TEST_CASE_SELF(ble_att_svr_test_find_info) ble_att_svr_test_misc_attr_fn_r_1, NULL); TEST_ASSERT(rc == 0); - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle1, handle2); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, handle1, handle2); TEST_ASSERT(rc == 0); ble_hs_test_util_verify_tx_find_info_rsp( ((struct ble_hs_test_util_att_info_entry[]) { { @@ -1199,7 +1200,7 @@ TEST_CASE_SELF(ble_att_svr_test_find_info) ble_att_svr_test_misc_attr_fn_r_1, NULL); TEST_ASSERT(rc == 0); - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle1, handle3); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, handle1, handle3); TEST_ASSERT(rc == 0); ble_hs_test_util_verify_tx_find_info_rsp( ((struct ble_hs_test_util_att_info_entry[]) { { @@ -1213,7 +1214,7 @@ TEST_CASE_SELF(ble_att_svr_test_find_info) } })); /*** Remaining 16-bit entry requested. */ - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, handle3, handle3); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, handle3, handle3); TEST_ASSERT(rc == 0); ble_hs_test_util_verify_tx_find_info_rsp( ((struct ble_hs_test_util_att_info_entry[]) { { @@ -1936,13 +1937,13 @@ TEST_CASE_SELF(ble_att_svr_test_oom) TEST_ASSERT_FATAL(rc == 0); /* Ensure we were able to send a real response. */ - ble_att_svr_test_misc_verify_tx_mtu_rsp(conn_handle); + ble_att_svr_test_misc_verify_tx_mtu_rsp(conn_handle, BLE_L2CAP_CID_ATT); /*** Find information; always respond affirmatively, even when no mbufs. */ ble_hs_test_util_prev_tx_dequeue(); /* Receive a request. */ - rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, 1, 100); + rc = ble_hs_test_util_rx_att_find_info_req(conn_handle, BLE_L2CAP_CID_ATT, 1, 100); TEST_ASSERT_FATAL(rc == 0); /* Ensure we were able to send a real response. */ diff --git a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_conn_test.c b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_conn_test.c index 5cb94ce8..d74dd6fc 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_conn_test.c +++ b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_conn_test.c @@ -385,6 +385,7 @@ TEST_CASE_SELF(ble_gatt_conn_test_disconnect) uint16_t attr_handle; uint16_t offset = 0; int rc; + struct ble_hs_conn *conn; ble_gatt_conn_test_util_init(); @@ -405,65 +406,92 @@ TEST_CASE_SELF(ble_gatt_conn_test_disconnect) /*** Schedule some GATT procedures. */ /* Connection 1. */ mtu_arg.exp_conn_handle = 1; + ble_hs_lock(); + conn = ble_hs_conn_find(1); + ble_hs_unlock(); + + /** In unit tests we are not receiving response - procedure will + * not complete. Reset `client_att_busy` flag so new request can be sent + */ + conn->client_att_busy = false; ble_gattc_exchange_mtu(1, ble_gatt_conn_test_mtu_cb, &mtu_arg); disc_all_svcs_arg.exp_conn_handle = 1; + conn->client_att_busy = false; rc = ble_gattc_disc_all_svcs(1, ble_gatt_conn_test_disc_all_svcs_cb, &disc_all_svcs_arg); TEST_ASSERT_FATAL(rc == 0); disc_svc_uuid_arg.exp_conn_handle = 1; + conn->client_att_busy = false; rc = ble_gattc_disc_svc_by_uuid(1, BLE_UUID16_DECLARE(0x1111), ble_gatt_conn_test_disc_svc_uuid_cb, &disc_svc_uuid_arg); TEST_ASSERT_FATAL(rc == 0); find_inc_svcs_arg.exp_conn_handle = 1; + conn->client_att_busy = false; rc = ble_gattc_find_inc_svcs(1, 1, 0xffff, ble_gatt_conn_test_find_inc_svcs_cb, &find_inc_svcs_arg); TEST_ASSERT_FATAL(rc == 0); disc_all_chrs_arg.exp_conn_handle = 1; + conn->client_att_busy = false; rc = ble_gattc_disc_all_chrs(1, 1, 0xffff, ble_gatt_conn_test_disc_all_chrs_cb, &disc_all_chrs_arg); TEST_ASSERT_FATAL(rc == 0); /* Connection 2. */ + ble_hs_lock(); + conn = ble_hs_conn_find(2); + ble_hs_unlock(); + disc_all_dscs_arg.exp_conn_handle = 2; + conn->client_att_busy = false; rc = ble_gattc_disc_all_dscs(2, 3, 0xffff, ble_gatt_conn_test_disc_all_dscs_cb, &disc_all_dscs_arg); disc_chr_uuid_arg.exp_conn_handle = 2; + conn->client_att_busy = false; rc = ble_gattc_disc_chrs_by_uuid(2, 2, 0xffff, BLE_UUID16_DECLARE(0x2222), ble_gatt_conn_test_disc_chr_uuid_cb, &disc_chr_uuid_arg); read_arg.exp_conn_handle = 2; + conn->client_att_busy = false; rc = ble_gattc_read(2, BLE_GATT_BREAK_TEST_READ_ATTR_HANDLE, ble_gatt_conn_test_read_cb, &read_arg); TEST_ASSERT_FATAL(rc == 0); read_uuid_arg.exp_conn_handle = 2; + conn->client_att_busy = false; rc = ble_gattc_read_by_uuid(2, 1, 0xffff, BLE_UUID16_DECLARE(0x3333), ble_gatt_conn_test_read_uuid_cb, &read_uuid_arg); TEST_ASSERT_FATAL(rc == 0); read_long_arg.exp_conn_handle = 2; + conn->client_att_busy = false; rc = ble_gattc_read_long(2, BLE_GATT_BREAK_TEST_READ_ATTR_HANDLE, offset, ble_gatt_conn_test_read_long_cb, &read_long_arg); TEST_ASSERT_FATAL(rc == 0); /* Connection 3. */ + ble_hs_lock(); + conn = ble_hs_conn_find(3); + ble_hs_unlock(); + read_mult_arg.exp_conn_handle = 3; + conn->client_att_busy = false; rc = ble_gattc_read_mult(3, ((uint16_t[3]){5,6,7}), 3, ble_gatt_conn_test_read_mult_cb, &read_mult_arg); TEST_ASSERT_FATAL(rc == 0); write_arg.exp_conn_handle = 3; + conn->client_att_busy = false; rc = ble_hs_test_util_gatt_write_flat( 3, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE, ble_gatt_conn_test_write_value, sizeof ble_gatt_conn_test_write_value, @@ -471,6 +499,7 @@ TEST_CASE_SELF(ble_gatt_conn_test_disconnect) TEST_ASSERT_FATAL(rc == 0); write_long_arg.exp_conn_handle = 3; + conn->client_att_busy = false; rc = ble_hs_test_util_gatt_write_long_flat( 3, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE, ble_gatt_conn_test_write_value, sizeof ble_gatt_conn_test_write_value, @@ -481,10 +510,12 @@ TEST_CASE_SELF(ble_gatt_conn_test_disconnect) attr.offset = 0; attr.om = os_msys_get_pkthdr(0, 0); write_rel_arg.exp_conn_handle = 3; + conn->client_att_busy = false; rc = ble_gattc_write_reliable( 3, &attr, 1, ble_gatt_conn_test_write_rel_cb, &write_rel_arg); TEST_ASSERT_FATAL(rc == 0); + conn->client_att_busy = false; rc = ble_gatts_indicate(3, attr_handle); TEST_ASSERT_FATAL(rc == 0); @@ -528,6 +559,11 @@ TEST_CASE_SELF(ble_gatt_conn_test_disconnect) TEST_ASSERT(ble_gatt_conn_test_gap_event.type == 255); /* Connection 3. */ + /** This is required because of call ble_att_clt_tx_exec_write + * from ble_att_clt_tx_exec_write after broken connection - + * ble_gattc_fail_procs is called + */ + conn->client_att_busy = false; ble_gattc_connection_broken(3); TEST_ASSERT(mtu_arg.called == 1); TEST_ASSERT(disc_all_svcs_arg.called == 1); diff --git a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_disc_c_test.c b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_disc_c_test.c index e19db341..d0034889 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_disc_c_test.c +++ b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_disc_c_test.c @@ -25,6 +25,7 @@ #include "ble_hs_test.h" #include "host/ble_gatt.h" #include "host/ble_uuid.h" +#include "host/ble_l2cap.h" #include "ble_hs_test_util.h" struct ble_gatt_disc_c_test_char { @@ -50,8 +51,8 @@ ble_gatt_disc_c_test_init(void) } static int -ble_gatt_disc_c_test_misc_rx_rsp_once( - uint16_t conn_handle, struct ble_gatt_disc_c_test_char *chars) +ble_gatt_disc_c_test_misc_rx_rsp_once(uint16_t conn_handle, uint16_t cid, + struct ble_gatt_disc_c_test_char *chars) { struct ble_att_read_type_rsp rsp; uint8_t buf[1024]; @@ -86,14 +87,14 @@ ble_gatt_disc_c_test_misc_rx_rsp_once( if (chars[i].uuid->type == BLE_UUID_TYPE_16) { if (off + BLE_ATT_READ_TYPE_ADATA_SZ_16 > - ble_att_mtu(conn_handle)) { + ble_att_mtu_by_cid(conn_handle, cid)) { /* Can't fit any more entries. */ break; } } else { if (off + BLE_ATT_READ_TYPE_ADATA_SZ_128 > - ble_att_mtu(conn_handle)) { + ble_att_mtu_by_cid(conn_handle, cid)) { /* Can't fit any more entries. */ break; @@ -121,7 +122,7 @@ ble_gatt_disc_c_test_misc_rx_rsp_once( } static void -ble_gatt_disc_c_test_misc_rx_rsp(uint16_t conn_handle, +ble_gatt_disc_c_test_misc_rx_rsp(uint16_t conn_handle, uint16_t cid, uint16_t end_handle, struct ble_gatt_disc_c_test_char *chars) { @@ -130,7 +131,7 @@ ble_gatt_disc_c_test_misc_rx_rsp(uint16_t conn_handle, idx = 0; while (chars[idx].def_handle != 0) { - count = ble_gatt_disc_c_test_misc_rx_rsp_once(conn_handle, + count = ble_gatt_disc_c_test_misc_rx_rsp_once(conn_handle, cid, chars + idx); if (count == 0) { break; @@ -140,7 +141,8 @@ ble_gatt_disc_c_test_misc_rx_rsp(uint16_t conn_handle, if (chars[idx - 1].def_handle != end_handle) { /* Send the pending ATT Request. */ - ble_hs_test_util_rx_att_err_rsp(conn_handle, BLE_ATT_OP_READ_TYPE_REQ, + ble_hs_test_util_rx_att_err_rsp(conn_handle, cid, + BLE_ATT_OP_READ_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, chars[idx - 1].def_handle); } @@ -229,7 +231,7 @@ ble_gatt_disc_c_test_misc_all(uint16_t start_handle, uint16_t end_handle, ble_gatt_disc_c_test_misc_cb, &num_left); TEST_ASSERT(rc == 0); - ble_gatt_disc_c_test_misc_rx_rsp(2, end_handle, chars); + ble_gatt_disc_c_test_misc_rx_rsp(2, BLE_L2CAP_CID_ATT, end_handle, chars); ble_gatt_disc_c_test_misc_verify_chars(chars, stop_after); } @@ -252,7 +254,7 @@ ble_gatt_disc_c_test_misc_uuid(uint16_t start_handle, uint16_t end_handle, &stop_after); TEST_ASSERT(rc == 0); - ble_gatt_disc_c_test_misc_rx_rsp(2, end_handle, rsp_chars); + ble_gatt_disc_c_test_misc_rx_rsp(2, BLE_L2CAP_CID_ATT, end_handle, rsp_chars); ble_gatt_disc_c_test_misc_verify_chars(ret_chars, 0); } @@ -574,7 +576,7 @@ TEST_CASE_SELF(ble_gatt_disc_c_test_oom_all) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - num_chrs = ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs); + num_chrs = ble_gatt_disc_c_test_misc_rx_rsp_once(1, BLE_L2CAP_CID_ATT, chrs); /* Make sure there are still undiscovered characteristics. */ TEST_ASSERT_FATAL(num_chrs < sizeof chrs / sizeof chrs[0] - 1); @@ -598,7 +600,7 @@ TEST_CASE_SELF(ble_gatt_disc_c_test_oom_all) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs + num_chrs); + ble_gatt_disc_c_test_misc_rx_rsp_once(1, BLE_L2CAP_CID_ATT, chrs + num_chrs); /* Ensure no follow-up request got sent. It should not have gotten sent * due to mbuf exhaustion. @@ -617,7 +619,7 @@ TEST_CASE_SELF(ble_gatt_disc_c_test_oom_all) os_time_advance(ticks_until); ble_gattc_timer(); - ble_hs_test_util_rx_att_err_rsp(1, + ble_hs_test_util_rx_att_err_rsp(1, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, 1); @@ -663,7 +665,7 @@ TEST_CASE_SELF(ble_gatt_disc_c_test_oom_uuid) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - num_chrs = ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs); + num_chrs = ble_gatt_disc_c_test_misc_rx_rsp_once(1, BLE_L2CAP_CID_ATT, chrs); /* Make sure there are still undiscovered characteristics. */ TEST_ASSERT_FATAL(num_chrs < sizeof chrs / sizeof chrs[0] - 1); @@ -686,7 +688,7 @@ TEST_CASE_SELF(ble_gatt_disc_c_test_oom_uuid) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_disc_c_test_misc_rx_rsp_once(1, chrs + num_chrs); + ble_gatt_disc_c_test_misc_rx_rsp_once(1, BLE_L2CAP_CID_ATT, chrs + num_chrs); /* Ensure no follow-up request got sent. It should not have gotten sent * due to mbuf exhaustion. @@ -704,7 +706,7 @@ TEST_CASE_SELF(ble_gatt_disc_c_test_oom_uuid) os_time_advance(ticks_until); ble_gattc_timer(); - ble_hs_test_util_rx_att_err_rsp(1, + ble_hs_test_util_rx_att_err_rsp(1, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, 1); diff --git a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_disc_d_test.c b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_disc_d_test.c index e405c86f..acee2ef8 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_disc_d_test.c +++ b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_disc_d_test.c @@ -49,8 +49,8 @@ ble_gatt_disc_d_test_init(void) } static int -ble_gatt_disc_d_test_misc_rx_rsp_once( - uint16_t conn_handle, struct ble_gatt_disc_d_test_dsc *dscs) +ble_gatt_disc_d_test_misc_rx_rsp_once(uint16_t conn_handle, uint16_t cid, + struct ble_gatt_disc_d_test_dsc *dscs) { struct ble_att_find_info_rsp rsp; uint8_t buf[1024]; @@ -77,14 +77,14 @@ ble_gatt_disc_d_test_misc_rx_rsp_once( if (dscs[i].dsc_uuid.u.type == BLE_UUID_TYPE_16) { if (off + BLE_ATT_FIND_INFO_IDATA_16_SZ > - ble_att_mtu(conn_handle)) { + ble_att_mtu_by_cid(conn_handle, cid)) { /* Can't fit any more entries. */ break; } } else { if (off + BLE_ATT_FIND_INFO_IDATA_128_SZ > - ble_att_mtu(conn_handle)) { + ble_att_mtu_by_cid(conn_handle, cid)) { /* Can't fit any more entries. */ break; @@ -104,7 +104,7 @@ ble_gatt_disc_d_test_misc_rx_rsp_once( off += ble_uuid_length(&dscs[i].dsc_uuid.u); } - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, off); TEST_ASSERT(rc == 0); @@ -113,6 +113,7 @@ ble_gatt_disc_d_test_misc_rx_rsp_once( static void ble_gatt_disc_d_test_misc_rx_rsp(uint16_t conn_handle, + uint16_t cid, uint16_t end_handle, struct ble_gatt_disc_d_test_dsc *dscs) { @@ -121,7 +122,7 @@ ble_gatt_disc_d_test_misc_rx_rsp(uint16_t conn_handle, idx = 0; while (dscs[idx].chr_val_handle != 0) { - count = ble_gatt_disc_d_test_misc_rx_rsp_once(conn_handle, dscs + idx); + count = ble_gatt_disc_d_test_misc_rx_rsp_once(conn_handle, cid, dscs + idx); if (count == 0) { break; } @@ -130,7 +131,8 @@ ble_gatt_disc_d_test_misc_rx_rsp(uint16_t conn_handle, if (dscs[idx - 1].dsc_handle != end_handle) { /* Send the pending ATT Request. */ - ble_hs_test_util_rx_att_err_rsp(conn_handle, BLE_ATT_OP_FIND_INFO_REQ, + ble_hs_test_util_rx_att_err_rsp(conn_handle, cid, + BLE_ATT_OP_FIND_INFO_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, end_handle); } @@ -223,7 +225,7 @@ ble_gatt_disc_d_test_misc_all(uint16_t chr_val_handle, uint16_t end_handle, ble_gatt_disc_d_test_misc_cb, &num_left); TEST_ASSERT(rc == 0); - ble_gatt_disc_d_test_misc_rx_rsp(2, end_handle, dscs); + ble_gatt_disc_d_test_misc_rx_rsp(2, BLE_L2CAP_CID_ATT, end_handle, dscs); ble_gatt_disc_d_test_misc_verify_dscs(dscs, stop_after); } @@ -389,7 +391,7 @@ TEST_CASE_SELF(ble_gatt_disc_d_test_oom_all) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - num_dscs = ble_gatt_disc_d_test_misc_rx_rsp_once(1, dscs); + num_dscs = ble_gatt_disc_d_test_misc_rx_rsp_once(1, BLE_L2CAP_CID_ATT, dscs); /* Make sure there are still undiscovered services. */ TEST_ASSERT_FATAL(num_dscs < sizeof dscs / sizeof dscs[0] - 1); @@ -412,7 +414,7 @@ TEST_CASE_SELF(ble_gatt_disc_d_test_oom_all) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_disc_d_test_misc_rx_rsp_once(1, dscs + num_dscs); + ble_gatt_disc_d_test_misc_rx_rsp_once(1, BLE_L2CAP_CID_ATT, dscs + num_dscs); /* Ensure no follow-up request got sent. It should not have gotten sent * due to mbuf exhaustion. @@ -430,7 +432,7 @@ TEST_CASE_SELF(ble_gatt_disc_d_test_oom_all) os_time_advance(ticks_until); ble_gattc_timer(); - ble_hs_test_util_rx_att_err_rsp(1, + ble_hs_test_util_rx_att_err_rsp(1, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, 1); diff --git a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_disc_s_test.c b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_disc_s_test.c index 3e7a3026..87735f7d 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_disc_s_test.c +++ b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_disc_s_test.c @@ -56,8 +56,8 @@ ble_gatt_disc_s_test_misc_svc_length(struct ble_gatt_disc_s_test_svc *service) } static int -ble_gatt_disc_s_test_misc_rx_all_rsp_once( - uint16_t conn_handle, struct ble_gatt_disc_s_test_svc *services) +ble_gatt_disc_s_test_misc_rx_all_rsp_once(uint16_t conn_handle, uint16_t cid, + struct ble_gatt_disc_s_test_svc *services) { struct ble_att_read_group_type_rsp rsp; uint8_t buf[1024]; @@ -86,14 +86,14 @@ ble_gatt_disc_s_test_misc_rx_all_rsp_once( if (services[i].uuid->type == BLE_UUID_TYPE_16) { if (off + BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_16 > - ble_att_mtu(conn_handle)) { + ble_att_mtu_by_cid(conn_handle, cid)) { /* Can't fit any more entries. */ break; } } else { if (off + BLE_ATT_READ_GROUP_TYPE_ADATA_SZ_128 > - ble_att_mtu(conn_handle)) { + ble_att_mtu_by_cid(conn_handle,cid)) { /* Can't fit any more entries. */ break; @@ -110,7 +110,7 @@ ble_gatt_disc_s_test_misc_rx_all_rsp_once( off += ble_uuid_length(services[i].uuid); } - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, off); TEST_ASSERT(rc == 0); @@ -118,22 +118,22 @@ ble_gatt_disc_s_test_misc_rx_all_rsp_once( } static void -ble_gatt_disc_s_test_misc_rx_all_rsp( - uint16_t conn_handle, struct ble_gatt_disc_s_test_svc *services) +ble_gatt_disc_s_test_misc_rx_all_rsp(uint16_t conn_handle, uint16_t cid, + struct ble_gatt_disc_s_test_svc *services) { int count; int idx; idx = 0; while (services[idx].start_handle != 0) { - count = ble_gatt_disc_s_test_misc_rx_all_rsp_once(conn_handle, + count = ble_gatt_disc_s_test_misc_rx_all_rsp_once(conn_handle, cid, services + idx); idx += count; } if (services[idx - 1].end_handle != 0xffff) { /* Send the pending ATT Request. */ - ble_hs_test_util_rx_att_err_rsp(conn_handle, + ble_hs_test_util_rx_att_err_rsp(conn_handle, cid, BLE_ATT_OP_READ_GROUP_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, services[idx - 1].start_handle); @@ -141,8 +141,8 @@ ble_gatt_disc_s_test_misc_rx_all_rsp( } static int -ble_gatt_disc_s_test_misc_rx_uuid_rsp_once( - uint16_t conn_handle, struct ble_gatt_disc_s_test_svc *services) +ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(uint16_t conn_handle, uint16_t cid, + struct ble_gatt_disc_s_test_svc *services) { uint8_t buf[1024]; int off; @@ -160,7 +160,7 @@ ble_gatt_disc_s_test_misc_rx_uuid_rsp_once( } if (off + BLE_ATT_FIND_TYPE_VALUE_HINFO_BASE_SZ > - ble_att_mtu(conn_handle)) { + ble_att_mtu_by_cid(conn_handle, cid)) { /* Can't fit any more entries. */ break; @@ -173,7 +173,7 @@ ble_gatt_disc_s_test_misc_rx_uuid_rsp_once( off += 2; } - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, off); TEST_ASSERT(rc == 0); @@ -181,22 +181,22 @@ ble_gatt_disc_s_test_misc_rx_uuid_rsp_once( } static void -ble_gatt_disc_s_test_misc_rx_uuid_rsp( - uint16_t conn_handle, struct ble_gatt_disc_s_test_svc *services) +ble_gatt_disc_s_test_misc_rx_uuid_rsp(uint16_t conn_handle, uint16_t cid, + struct ble_gatt_disc_s_test_svc *services) { int count; int idx; idx = 0; while (services[idx].start_handle != 0) { - count = ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(conn_handle, + count = ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(conn_handle, cid, services + idx); idx += count; } if (services[idx - 1].end_handle != 0xffff) { /* Send the pending ATT Request. */ - ble_hs_test_util_rx_att_err_rsp(conn_handle, + ble_hs_test_util_rx_att_err_rsp(conn_handle, cid, BLE_ATT_OP_FIND_TYPE_VALUE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, services[idx - 1].start_handle); @@ -269,7 +269,7 @@ ble_gatt_disc_s_test_misc_good_all(struct ble_gatt_disc_s_test_svc *services) rc = ble_gattc_disc_all_svcs(2, ble_gatt_disc_s_test_misc_disc_cb, NULL); TEST_ASSERT(rc == 0); - ble_gatt_disc_s_test_misc_rx_all_rsp(2, services); + ble_gatt_disc_s_test_misc_rx_all_rsp(2, BLE_L2CAP_CID_ATT, services); ble_gatt_disc_s_test_misc_verify_services(services); } @@ -290,7 +290,7 @@ ble_gatt_disc_s_test_misc_good_uuid( ble_hs_test_util_verify_tx_disc_svc_uuid(services[0].uuid); - ble_gatt_disc_s_test_misc_rx_uuid_rsp(2, services); + ble_gatt_disc_s_test_misc_rx_uuid_rsp(2, BLE_L2CAP_CID_ATT, services); ble_gatt_disc_s_test_misc_verify_services(services); } @@ -425,7 +425,7 @@ TEST_CASE_SELF(ble_gatt_disc_s_test_oom_all) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - num_svcs = ble_gatt_disc_s_test_misc_rx_all_rsp_once(1, svcs); + num_svcs = ble_gatt_disc_s_test_misc_rx_all_rsp_once(1, BLE_L2CAP_CID_ATT, svcs); /* Make sure there are still undiscovered services. */ TEST_ASSERT_FATAL(num_svcs < sizeof svcs / sizeof svcs[0] - 1); @@ -448,7 +448,7 @@ TEST_CASE_SELF(ble_gatt_disc_s_test_oom_all) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_disc_s_test_misc_rx_all_rsp_once(1, svcs + num_svcs); + ble_gatt_disc_s_test_misc_rx_all_rsp_once(1, BLE_L2CAP_CID_ATT, svcs + num_svcs); /* Ensure no follow-up request got sent. It should not have gotten sent * due to mbuf exhaustion. @@ -465,7 +465,7 @@ TEST_CASE_SELF(ble_gatt_disc_s_test_oom_all) os_time_advance(ticks_until); ble_gattc_timer(); - ble_hs_test_util_rx_att_err_rsp(1, + ble_hs_test_util_rx_att_err_rsp(1, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_GROUP_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, 1); @@ -504,7 +504,7 @@ TEST_CASE_SELF(ble_gatt_disc_s_test_oom_uuid) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - num_svcs = ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(1, svcs); + num_svcs = ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(1, BLE_L2CAP_CID_ATT, svcs); /* Make sure there are still undiscovered services. */ TEST_ASSERT_FATAL(num_svcs < sizeof svcs / sizeof svcs[0] - 1); @@ -527,7 +527,7 @@ TEST_CASE_SELF(ble_gatt_disc_s_test_oom_uuid) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(1, svcs + num_svcs); + ble_gatt_disc_s_test_misc_rx_uuid_rsp_once(1, BLE_L2CAP_CID_ATT, svcs + num_svcs); /* Ensure no follow-up request got sent. It should not have gotten sent * due to mbuf exhaustion. @@ -545,7 +545,7 @@ TEST_CASE_SELF(ble_gatt_disc_s_test_oom_uuid) os_time_advance(ticks_until); ble_gattc_timer(); - ble_hs_test_util_rx_att_err_rsp(1, + ble_hs_test_util_rx_att_err_rsp(1, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_GROUP_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, 1); @@ -579,7 +579,7 @@ TEST_CASE_SELF(ble_gatt_disc_s_test_oom_timeout) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_disc_s_test_misc_rx_all_rsp_once(1, svcs); + ble_gatt_disc_s_test_misc_rx_all_rsp_once(1, BLE_L2CAP_CID_ATT, svcs); /* Keep trying to resume for 30 seconds, but never free any mbufs. Verify * procedure eventually times out. diff --git a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_find_s_test.c b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_find_s_test.c index 172bdd33..5f8075c9 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_find_s_test.c +++ b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_find_s_test.c @@ -90,8 +90,8 @@ ble_gatt_find_s_test_misc_verify_incs( } static int -ble_gatt_find_s_test_misc_rx_read_type( - uint16_t conn_handle, struct ble_gatt_find_s_test_entry *entries) +ble_gatt_find_s_test_misc_rx_read_type(uint16_t conn_handle, uint16_t cid, + struct ble_gatt_find_s_test_entry *entries) { struct ble_att_read_type_rsp rsp; uint8_t buf[1024]; @@ -134,14 +134,15 @@ ble_gatt_find_s_test_misc_rx_read_type( } if (i == 0) { - ble_hs_test_util_rx_att_err_rsp(conn_handle, BLE_ATT_OP_READ_TYPE_REQ, + ble_hs_test_util_rx_att_err_rsp(conn_handle, cid, + BLE_ATT_OP_READ_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, 0); return 0; } ble_att_read_type_rsp_write(buf + 0, BLE_ATT_READ_TYPE_RSP_BASE_SZ, &rsp); - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, off); TEST_ASSERT(rc == 0); @@ -149,7 +150,7 @@ ble_gatt_find_s_test_misc_rx_read_type( } static void -ble_gatt_find_s_test_misc_rx_read(uint16_t conn_handle, const ble_uuid_t *uuid) +ble_gatt_find_s_test_misc_rx_read(uint16_t conn_handle, uint16_t cid, const ble_uuid_t *uuid) { uint8_t buf[17]; int rc; @@ -159,7 +160,7 @@ ble_gatt_find_s_test_misc_rx_read(uint16_t conn_handle, const ble_uuid_t *uuid) buf[0] = BLE_ATT_OP_READ_RSP; ble_uuid_flat(uuid, buf + 1); - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, 17); TEST_ASSERT(rc == 0); } @@ -200,7 +201,7 @@ ble_gatt_find_s_test_misc_verify_tx_read(uint16_t handle) } static void -ble_gatt_find_s_test_misc_find_inc(uint16_t conn_handle, +ble_gatt_find_s_test_misc_find_inc(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, struct ble_gatt_find_s_test_entry *entries) { @@ -219,7 +220,7 @@ ble_gatt_find_s_test_misc_find_inc(uint16_t conn_handle, idx = 0; while (1) { ble_gatt_find_s_test_misc_verify_tx_read_type(cur_start, end_handle); - num_found = ble_gatt_find_s_test_misc_rx_read_type(conn_handle, + num_found = ble_gatt_find_s_test_misc_rx_read_type(conn_handle, cid, entries + idx); if (num_found == 0) { break; @@ -229,7 +230,7 @@ ble_gatt_find_s_test_misc_find_inc(uint16_t conn_handle, TEST_ASSERT(num_found == 1); ble_gatt_find_s_test_misc_verify_tx_read( entries[idx].start_handle); - ble_gatt_find_s_test_misc_rx_read(conn_handle, + ble_gatt_find_s_test_misc_rx_read(conn_handle, cid, entries[idx].uuid); } @@ -255,7 +256,7 @@ TEST_CASE_SELF(ble_gatt_find_s_test_1) ble_gatt_find_s_test_misc_init(); ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), NULL, NULL); - ble_gatt_find_s_test_misc_find_inc(2, 5, 10, + ble_gatt_find_s_test_misc_find_inc(2, BLE_L2CAP_CID_ATT, 5, 10, ((struct ble_gatt_find_s_test_entry[]) { { .inc_handle = 6, .start_handle = 35, @@ -275,7 +276,7 @@ TEST_CASE_SELF(ble_gatt_find_s_test_1) ble_gatt_find_s_test_misc_init(); ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), NULL, NULL); - ble_gatt_find_s_test_misc_find_inc(2, 34, 100, + ble_gatt_find_s_test_misc_find_inc(2, BLE_L2CAP_CID_ATT, 34, 100, ((struct ble_gatt_find_s_test_entry[]) { { .inc_handle = 36, .start_handle = 403, @@ -290,7 +291,7 @@ TEST_CASE_SELF(ble_gatt_find_s_test_1) ble_gatt_find_s_test_misc_init(); ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), NULL, NULL); - ble_gatt_find_s_test_misc_find_inc(2, 34, 100, + ble_gatt_find_s_test_misc_find_inc(2, BLE_L2CAP_CID_ATT, 34, 100, ((struct ble_gatt_find_s_test_entry[]) { { .inc_handle = 36, .start_handle = 403, @@ -310,7 +311,7 @@ TEST_CASE_SELF(ble_gatt_find_s_test_1) ble_gatt_find_s_test_misc_init(); ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), NULL, NULL); - ble_gatt_find_s_test_misc_find_inc(2, 1, 100, + ble_gatt_find_s_test_misc_find_inc(2, BLE_L2CAP_CID_ATT, 1, 100, ((struct ble_gatt_find_s_test_entry[]) { { .inc_handle = 36, .start_handle = 403, @@ -379,7 +380,7 @@ TEST_CASE_SELF(ble_gatt_find_s_test_oom) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_find_s_test_misc_rx_read_type(1, incs); + ble_gatt_find_s_test_misc_rx_read_type(1, BLE_L2CAP_CID_ATT, incs); /* Ensure no follow-up request got sent. It should not have gotten sent * due to mbuf exhaustion. @@ -402,11 +403,11 @@ TEST_CASE_SELF(ble_gatt_find_s_test_oom) * follow-up request, so there is always an mbuf available. */ /* XXX: Find a way to test this. */ - ble_gatt_find_s_test_misc_rx_read(1, incs[0].uuid); + ble_gatt_find_s_test_misc_rx_read(1, BLE_L2CAP_CID_ATT, incs[0].uuid); /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_find_s_test_misc_rx_read_type(1, incs + 1); + ble_gatt_find_s_test_misc_rx_read_type(1, BLE_L2CAP_CID_ATT, incs + 1); /* Verify the procedure succeeds after mbufs become available. */ rc = os_mbuf_free_chain(oms); @@ -414,9 +415,9 @@ TEST_CASE_SELF(ble_gatt_find_s_test_oom) os_time_advance(ticks_until); ble_gattc_timer(); - ble_gatt_find_s_test_misc_rx_read(1, incs[1].uuid); + ble_gatt_find_s_test_misc_rx_read(1, BLE_L2CAP_CID_ATT, incs[1].uuid); - ble_hs_test_util_rx_att_err_rsp(1, + ble_hs_test_util_rx_att_err_rsp(1, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, 1); diff --git a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_read_test.c b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_read_test.c index 572b0bf1..a22e5a55 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_read_test.c +++ b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_read_test.c @@ -160,7 +160,7 @@ ble_gatt_read_test_long_cb(uint16_t conn_handle, } static void -ble_gatt_read_test_misc_rx_rsp_good_raw(uint16_t conn_handle, +ble_gatt_read_test_misc_rx_rsp_good_raw(uint16_t conn_handle, uint16_t cid, uint8_t att_op, const void *data, int data_len) { @@ -174,27 +174,28 @@ ble_gatt_read_test_misc_rx_rsp_good_raw(uint16_t conn_handle, buf[0] = att_op; memcpy(buf + 1, data, data_len); - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, 1 + data_len); TEST_ASSERT(rc == 0); } static void -ble_gatt_read_test_misc_rx_rsp_good(uint16_t conn_handle, +ble_gatt_read_test_misc_rx_rsp_good(uint16_t conn_handle, uint16_t cid, struct ble_hs_test_util_flat_attr *attr) { - ble_gatt_read_test_misc_rx_rsp_good_raw(conn_handle, BLE_ATT_OP_READ_RSP, + ble_gatt_read_test_misc_rx_rsp_good_raw(conn_handle, cid, + BLE_ATT_OP_READ_RSP, attr->value, attr->value_len); } static void -ble_gatt_read_test_misc_rx_rsp_bad(uint16_t conn_handle, +ble_gatt_read_test_misc_rx_rsp_bad(uint16_t conn_handle, uint16_t cid, uint8_t att_error, uint16_t err_handle) { /* Send the pending ATT Read Request. */ - ble_hs_test_util_rx_att_err_rsp(conn_handle, BLE_ATT_OP_READ_REQ, + ble_hs_test_util_rx_att_err_rsp(conn_handle, cid, BLE_ATT_OP_READ_REQ, att_error, err_handle); } @@ -255,7 +256,7 @@ ble_gatt_read_test_misc_verify_good(struct ble_hs_test_util_flat_attr *attr) rc = ble_gattc_read(2, attr->handle, ble_gatt_read_test_cb, NULL); TEST_ASSERT_FATAL(rc == 0); - ble_gatt_read_test_misc_rx_rsp_good(2, attr); + ble_gatt_read_test_misc_rx_rsp_good(2, BLE_L2CAP_CID_ATT, attr); TEST_ASSERT(ble_gatt_read_test_num_attrs == 1); TEST_ASSERT(ble_gatt_read_test_attrs[0].conn_handle == 2); @@ -278,7 +279,7 @@ ble_gatt_read_test_misc_verify_bad(uint8_t att_status, rc = ble_gattc_read(2, attr->handle, ble_gatt_read_test_cb, NULL); TEST_ASSERT_FATAL(rc == 0); - ble_gatt_read_test_misc_rx_rsp_bad(2, att_status, attr->handle); + ble_gatt_read_test_misc_rx_rsp_bad(2, BLE_L2CAP_CID_ATT, att_status, attr->handle); TEST_ASSERT(ble_gatt_read_test_num_attrs == 0); TEST_ASSERT(ble_gatt_read_test_bad_conn_handle == 2); @@ -309,7 +310,8 @@ ble_gatt_read_test_misc_uuid_verify_good( while (1) { num_read = ble_gatt_read_test_misc_uuid_rx_rsp_good(2, attrs + idx); if (num_read == 0) { - ble_hs_test_util_rx_att_err_rsp(2, BLE_ATT_OP_READ_TYPE_REQ, + ble_hs_test_util_rx_att_err_rsp(2, BLE_L2CAP_CID_ATT, + BLE_ATT_OP_READ_TYPE_REQ, BLE_ATT_ERR_ATTR_NOT_FOUND, start_handle); break; @@ -369,7 +371,7 @@ ble_gatt_read_test_misc_long_verify_good( } else { att_op = BLE_ATT_OP_READ_BLOB_RSP; } - ble_gatt_read_test_misc_rx_rsp_good_raw(2, att_op, + ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_L2CAP_CID_ATT, att_op, attr->value + off, chunk_sz); rem_len -= chunk_sz; off += chunk_sz; @@ -401,7 +403,7 @@ ble_gatt_read_test_misc_long_verify_bad( ble_gatt_read_test_long_cb, NULL); TEST_ASSERT_FATAL(rc == 0); - ble_gatt_read_test_misc_rx_rsp_bad(2, att_status, attr->handle); + ble_gatt_read_test_misc_rx_rsp_bad(2, BLE_L2CAP_CID_ATT, att_status, attr->handle); TEST_ASSERT(ble_gatt_read_test_num_attrs == 0); TEST_ASSERT(ble_gatt_read_test_bad_conn_handle == 2); @@ -458,7 +460,7 @@ ble_gatt_read_test_misc_mult_verify_good( ble_gatt_read_test_cb, NULL); TEST_ASSERT_FATAL(rc == 0); - ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_MULT_RSP, + ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_MULT_RSP, expected_value, off); TEST_ASSERT(ble_gatt_read_test_complete); @@ -488,7 +490,7 @@ ble_gatt_read_test_misc_mult_verify_bad( ble_gatt_read_test_cb, NULL); TEST_ASSERT_FATAL(rc == 0); - ble_gatt_read_test_misc_rx_rsp_bad(2, att_status, err_handle); + ble_gatt_read_test_misc_rx_rsp_bad(2, BLE_L2CAP_CID_ATT, att_status, err_handle); TEST_ASSERT(ble_gatt_read_test_num_attrs == 0); TEST_ASSERT(ble_gatt_read_test_bad_conn_handle == 2); @@ -801,9 +803,9 @@ TEST_CASE_SELF(ble_gatt_read_test_concurrent) rc = ble_gattc_read(2, attrs[2].handle, ble_gatt_read_test_cb, NULL); TEST_ASSERT_FATAL(rc == 0); - ble_gatt_read_test_misc_rx_rsp_good(2, attrs + 0); - ble_gatt_read_test_misc_rx_rsp_good(2, attrs + 1); - ble_gatt_read_test_misc_rx_rsp_good(2, attrs + 2); + ble_gatt_read_test_misc_rx_rsp_good(2, BLE_L2CAP_CID_ATT, attrs + 0); + ble_gatt_read_test_misc_rx_rsp_good(2, BLE_L2CAP_CID_ATT, attrs + 1); + ble_gatt_read_test_misc_rx_rsp_good(2, BLE_L2CAP_CID_ATT, attrs + 2); TEST_ASSERT(ble_gatt_read_test_num_attrs == 3); @@ -852,8 +854,8 @@ TEST_CASE_SELF(ble_gatt_read_test_long_oom) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - chunk_sz = ble_att_mtu(2) - BLE_ATT_READ_RSP_BASE_SZ; - ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_RSP, + chunk_sz = ble_att_mtu_by_cid(2, BLE_L2CAP_CID_ATT) - BLE_ATT_READ_RSP_BASE_SZ; + ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_RSP, attr.value + off, chunk_sz); off += chunk_sz; @@ -875,8 +877,8 @@ TEST_CASE_SELF(ble_gatt_read_test_long_oom) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - chunk_sz = ble_att_mtu(2) - BLE_ATT_READ_RSP_BASE_SZ; - ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_RSP, + chunk_sz = ble_att_mtu_by_cid(2, BLE_L2CAP_CID_ATT) - BLE_ATT_READ_RSP_BASE_SZ; + ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_RSP, attr.value + off, chunk_sz); off += chunk_sz; @@ -897,7 +899,7 @@ TEST_CASE_SELF(ble_gatt_read_test_long_oom) ble_gattc_timer(); chunk_sz = attr.value_len - off; - ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_ATT_OP_READ_RSP, + ble_gatt_read_test_misc_rx_rsp_good_raw(2, BLE_L2CAP_CID_ATT, BLE_ATT_OP_READ_RSP, attr.value + off, chunk_sz); off += chunk_sz; diff --git a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_write_test.c b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_write_test.c index caa8e565..ea815c0d 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_write_test.c +++ b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_gatt_write_test.c @@ -87,8 +87,8 @@ ble_gatt_write_test_rx_rsp(uint16_t conn_handle) } static void -ble_gatt_write_test_rx_prep_rsp(uint16_t conn_handle, uint16_t attr_handle, - uint16_t offset, +ble_gatt_write_test_rx_prep_rsp(uint16_t conn_handle, uint16_t cid, + uint16_t attr_handle, uint16_t offset, const void *attr_data, uint16_t attr_data_len) { struct ble_att_prep_write_cmd rsp; @@ -102,19 +102,19 @@ ble_gatt_write_test_rx_prep_rsp(uint16_t conn_handle, uint16_t attr_handle, memcpy(buf + BLE_ATT_PREP_WRITE_CMD_BASE_SZ, attr_data, attr_data_len); rc = ble_hs_test_util_l2cap_rx_payload_flat( - conn_handle, BLE_L2CAP_CID_ATT, buf, + conn_handle, cid, buf, BLE_ATT_PREP_WRITE_CMD_BASE_SZ + attr_data_len); TEST_ASSERT(rc == 0); } static void -ble_gatt_write_test_rx_exec_rsp(uint16_t conn_handle) +ble_gatt_write_test_rx_exec_rsp(uint16_t conn_handle, uint16_t cid) { uint8_t op; int rc; op = BLE_ATT_OP_EXEC_WRITE_RSP; - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, &op, 1); TEST_ASSERT(rc == 0); } @@ -129,10 +129,10 @@ ble_gatt_write_test_misc_long_good(int attr_len) ble_gatt_write_test_init(); - ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), + ble_hs_test_util_create_conn(2, ((uint8_t[]) {2,3,4,5,6,7,8,9}), NULL, NULL); - mtu = ble_att_mtu(2); + mtu = ble_att_mtu_by_cid(2, BLE_L2CAP_CID_ATT); rc = ble_hs_test_util_gatt_write_long_flat( 2, 100, ble_gatt_write_test_attr_value, attr_len, @@ -152,7 +152,7 @@ ble_gatt_write_test_misc_long_good(int attr_len) /* Receive Prep Write response. */ ble_gatt_write_test_rx_prep_rsp( - 2, 100, off, ble_gatt_write_test_attr_value + off, len); + 2, BLE_L2CAP_CID_ATT, 100, off, ble_gatt_write_test_attr_value + off, len); /* Verify callback hasn't gotten called. */ TEST_ASSERT(!ble_gatt_write_test_cb_called); @@ -164,13 +164,13 @@ ble_gatt_write_test_misc_long_good(int attr_len) ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_EXECUTE); /* Receive Exec Write response. */ - ble_gatt_write_test_rx_exec_rsp(2); + ble_gatt_write_test_rx_exec_rsp(2, BLE_L2CAP_CID_ATT); /* Verify callback got called. */ TEST_ASSERT(ble_gatt_write_test_cb_called); } -typedef void ble_gatt_write_test_long_fail_fn(uint16_t conn_handle, +typedef void ble_gatt_write_test_long_fail_fn(uint16_t conn_handle, uint16_t cid, int off, int len); static void @@ -185,9 +185,9 @@ ble_gatt_write_test_misc_long_bad(int attr_len, ble_gatt_write_test_init(); - ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), + ble_hs_test_util_create_conn(2, ((uint8_t[]) {2,3,4,5,6,7,8,9}), NULL, NULL); - mtu = ble_att_mtu(2); + mtu = ble_att_mtu_by_cid(2, BLE_L2CAP_CID_ATT); rc = ble_hs_test_util_gatt_write_long_flat( 2, 100, ble_gatt_write_test_attr_value, attr_len, @@ -214,9 +214,9 @@ ble_gatt_write_test_misc_long_bad(int attr_len, } if (!fail_now) { ble_gatt_write_test_rx_prep_rsp( - 2, 100, off, ble_gatt_write_test_attr_value + off, len); + 2, BLE_L2CAP_CID_ATT, 100, off, ble_gatt_write_test_attr_value + off, len); } else { - cb(2, off, len); + cb(2, BLE_L2CAP_CID_ATT, off, len); break; } @@ -233,38 +233,38 @@ ble_gatt_write_test_misc_long_bad(int attr_len, } static void -ble_gatt_write_test_misc_long_fail_handle(uint16_t conn_handle, +ble_gatt_write_test_misc_long_fail_handle(uint16_t conn_handle, uint16_t cid, int off, int len) { ble_gatt_write_test_rx_prep_rsp( - conn_handle, 99, off, ble_gatt_write_test_attr_value + off, + conn_handle, cid, 99, off, ble_gatt_write_test_attr_value + off, len); } static void -ble_gatt_write_test_misc_long_fail_offset(uint16_t conn_handle, +ble_gatt_write_test_misc_long_fail_offset(uint16_t conn_handle, uint16_t cid, int off, int len) { ble_gatt_write_test_rx_prep_rsp( - conn_handle, 100, off + 1, ble_gatt_write_test_attr_value + off, + conn_handle, cid, 100, off + 1, ble_gatt_write_test_attr_value + off, len); } static void -ble_gatt_write_test_misc_long_fail_value(uint16_t conn_handle, +ble_gatt_write_test_misc_long_fail_value(uint16_t conn_handle, uint16_t cid, int off, int len) { ble_gatt_write_test_rx_prep_rsp( - conn_handle, 100, off, ble_gatt_write_test_attr_value + off + 1, + conn_handle, cid, 100, off, ble_gatt_write_test_attr_value + off + 1, len); } static void -ble_gatt_write_test_misc_long_fail_length(uint16_t conn_handle, +ble_gatt_write_test_misc_long_fail_length(uint16_t conn_handle, uint16_t cid, int off, int len) { ble_gatt_write_test_rx_prep_rsp( - conn_handle, 100, off, ble_gatt_write_test_attr_value + off, + conn_handle, cid, 100, off, ble_gatt_write_test_attr_value + off, len - 1); } @@ -313,9 +313,9 @@ ble_gatt_write_test_misc_reliable_good( flat_attrs + num_attrs); } - ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}), + ble_hs_test_util_create_conn(2, ((uint8_t[]) {2,3,4,5,6,7,8,9}), NULL, NULL); - mtu = ble_att_mtu(2); + mtu = ble_att_mtu_by_cid(2, BLE_L2CAP_CID_ATT); rc = ble_gattc_write_reliable(2, attrs, num_attrs, ble_gatt_write_test_reliable_cb_good, NULL); @@ -336,7 +336,7 @@ ble_gatt_write_test_misc_reliable_good( attr->value + off, len); /* Receive Prep Write response. */ - ble_gatt_write_test_rx_prep_rsp(2, attr->handle, off, + ble_gatt_write_test_rx_prep_rsp(2, BLE_L2CAP_CID_ATT, attr->handle, off, attr->value + off, len); /* Verify callback hasn't gotten called. */ @@ -353,7 +353,7 @@ ble_gatt_write_test_misc_reliable_good( ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_EXECUTE); /* Receive Exec Write response. */ - ble_gatt_write_test_rx_exec_rsp(2); + ble_gatt_write_test_rx_exec_rsp(2, BLE_L2CAP_CID_ATT); /* Verify callback got called. */ TEST_ASSERT(ble_gatt_write_test_cb_called); @@ -599,7 +599,7 @@ TEST_CASE_SELF(ble_gatt_write_test_long_queue_full) /* Receive Prep Write response. */ len = BLE_ATT_MTU_DFLT - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; ble_gatt_write_test_rx_prep_rsp( - 2, 100, off, ble_gatt_write_test_attr_value + off, len); + 2, BLE_L2CAP_CID_ATT, 100, off, ble_gatt_write_test_attr_value + off, len); /* Verify callback hasn't gotten called. */ TEST_ASSERT(!ble_gatt_write_test_cb_called); @@ -611,7 +611,8 @@ TEST_CASE_SELF(ble_gatt_write_test_long_queue_full) TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() != NULL); /* Receive queue full error. */ - ble_hs_test_util_rx_att_err_rsp(2, BLE_ATT_OP_PREP_WRITE_REQ, + ble_hs_test_util_rx_att_err_rsp(2, BLE_L2CAP_CID_ATT, + BLE_ATT_OP_PREP_WRITE_REQ, BLE_ATT_ERR_PREPARE_QUEUE_FULL, 100); /* Verify callback was called. */ @@ -654,14 +655,14 @@ TEST_CASE_SELF(ble_gatt_write_test_long_oom) ble_gatt_write_test_cb_good, NULL); TEST_ASSERT_FATAL(rc == 0); - chunk_sz = ble_att_mtu(2) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; + chunk_sz = ble_att_mtu_by_cid(2, BLE_L2CAP_CID_ATT) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; ble_hs_test_util_verify_tx_prep_write(attr.handle, off, attr.value + off, chunk_sz); /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_write_test_rx_prep_rsp(2, attr.handle, off, attr.value + off, + ble_gatt_write_test_rx_prep_rsp(2, BLE_L2CAP_CID_ATT, attr.handle, off, attr.value + off, chunk_sz); off += chunk_sz; @@ -688,7 +689,7 @@ TEST_CASE_SELF(ble_gatt_write_test_long_oom) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); ble_gatt_write_test_rx_prep_rsp( - 2, attr.handle, off, attr.value + off, chunk_sz); + 2, BLE_L2CAP_CID_ATT, attr.handle, off, attr.value + off, chunk_sz); off += chunk_sz; /* Ensure no follow-up request got sent. It should not have gotten sent @@ -711,7 +712,7 @@ TEST_CASE_SELF(ble_gatt_write_test_long_oom) ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_EXECUTE); /* Receive Exec Write response. */ - ble_gatt_write_test_rx_exec_rsp(2); + ble_gatt_write_test_rx_exec_rsp(2, BLE_L2CAP_CID_ATT); /* Verify callback got called. */ TEST_ASSERT(ble_gatt_write_test_cb_called); @@ -750,14 +751,14 @@ TEST_CASE_SELF(ble_gatt_write_test_reliable_oom) ble_gatt_write_test_reliable_cb_good, NULL); TEST_ASSERT_FATAL(rc == 0); - chunk_sz = ble_att_mtu(2) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; + chunk_sz = ble_att_mtu_by_cid(2, BLE_L2CAP_CID_ATT) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; ble_hs_test_util_verify_tx_prep_write(attr.handle, off, attr.value + off, chunk_sz); /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); - ble_gatt_write_test_rx_prep_rsp(2, attr.handle, off, attr.value + off, + ble_gatt_write_test_rx_prep_rsp(2, BLE_L2CAP_CID_ATT, attr.handle, off, attr.value + off, chunk_sz); off += chunk_sz; @@ -784,7 +785,7 @@ TEST_CASE_SELF(ble_gatt_write_test_reliable_oom) /* Exhaust the msys pool. Leave one mbuf for the forthcoming response. */ oms = ble_hs_test_util_mbuf_alloc_all_but(1); ble_gatt_write_test_rx_prep_rsp( - 2, attr.handle, off, attr.value + off, chunk_sz); + 2, BLE_L2CAP_CID_ATT, attr.handle, off, attr.value + off, chunk_sz); off += chunk_sz; /* Ensure no follow-up request got sent. It should not have gotten sent @@ -807,7 +808,7 @@ TEST_CASE_SELF(ble_gatt_write_test_reliable_oom) ble_hs_test_util_verify_tx_exec_write(BLE_ATT_EXEC_WRITE_F_EXECUTE); /* Receive Exec Write response. */ - ble_gatt_write_test_rx_exec_rsp(2); + ble_gatt_write_test_rx_exec_rsp(2, BLE_L2CAP_CID_ATT); /* Verify callback got called. */ TEST_ASSERT(ble_gatt_write_test_cb_called); diff --git a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_pvcy_test.c b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_pvcy_test.c index 79b93b83..7fd357d0 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_pvcy_test.c +++ b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_pvcy_test.c @@ -51,7 +51,7 @@ ble_hs_pvcy_test_util_all_gap_procs(int adv_status, int conn_status, int disc_status) { - struct ble_gap_disc_params disc_params; + struct ble_gap_disc_params disc_params = {0}; ble_addr_t peer_addr; int rc; @@ -338,7 +338,7 @@ TEST_CASE_SELF(ble_hs_pvcy_test_case_add_irk_adv) /*** Discovery active. */ TEST_CASE_SELF(ble_hs_pvcy_test_case_add_irk_disc) { - struct ble_gap_disc_params disc_params; + struct ble_gap_disc_params disc_params = {0}; int rc; ble_hs_pvcy_test_util_init(); @@ -407,7 +407,7 @@ TEST_CASE_SELF(ble_hs_pvcy_test_case_add_irk_conn) /*** Advertising and discovery active. */ TEST_CASE_SELF(ble_hs_pvcy_test_case_add_irk_adv_disc) { - struct ble_gap_disc_params disc_params; + struct ble_gap_disc_params disc_params = {0}; int rc; ble_hs_pvcy_test_util_init(); diff --git a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_test_util.c b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_test_util.c index c336ddf9..f5463b3e 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_test_util.c +++ b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_test_util.c @@ -741,7 +741,7 @@ ble_hs_test_util_set_att_mtu(uint16_t conn_handle, uint16_t mtu) ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, &conn, &chan); assert(rc == 0); chan->my_mtu = mtu; chan->peer_mtu = mtu; @@ -772,6 +772,7 @@ ble_hs_test_util_rx_att_mtu_cmd(uint16_t conn_handle, int is_req, uint16_t mtu) int ble_hs_test_util_rx_att_find_info_req(uint16_t conn_handle, + uint16_t cid, uint16_t start_handle, uint16_t end_handle) { @@ -784,7 +785,7 @@ ble_hs_test_util_rx_att_find_info_req(uint16_t conn_handle, ble_att_find_info_req_write(buf, sizeof buf, &req); - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, sizeof buf); return rc; @@ -1070,7 +1071,7 @@ ble_hs_test_util_rx_att_indicate_req(uint16_t conn_handle, } void -ble_hs_test_util_rx_att_err_rsp(uint16_t conn_handle, uint8_t req_op, +ble_hs_test_util_rx_att_err_rsp(uint16_t conn_handle, uint16_t cid, uint8_t req_op, uint8_t error_code, uint16_t err_handle) { struct ble_att_error_rsp rsp; @@ -1083,7 +1084,7 @@ ble_hs_test_util_rx_att_err_rsp(uint16_t conn_handle, uint8_t req_op, ble_att_error_rsp_write(buf, sizeof buf, &rsp); - rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT, + rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, cid, buf, sizeof buf); TEST_ASSERT(rc == 0); } diff --git a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_test_util.h b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_test_util.h index 7a0aa3eb..6d5d04c0 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_test_util.h +++ b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_test_util.h @@ -173,6 +173,7 @@ void ble_hs_test_util_set_att_mtu(uint16_t conn_handle, uint16_t mtu); int ble_hs_test_util_rx_att_mtu_cmd(uint16_t conn_handle, int is_req, uint16_t mtu); int ble_hs_test_util_rx_att_find_info_req(uint16_t conn_handle, + uint16_t cid, uint16_t start_handle, uint16_t end_handle); int ble_hs_test_util_rx_att_find_type_value_req(uint16_t conn_handle, @@ -228,8 +229,9 @@ int ble_hs_test_util_rx_att_indicate_req(uint16_t conn_handle, uint16_t attr_handle, void *attr_val, uint16_t attr_len); -void ble_hs_test_util_rx_att_err_rsp(uint16_t conn_handle, uint8_t req_op, - uint8_t error_code, uint16_t err_handle); +void ble_hs_test_util_rx_att_err_rsp(uint16_t conn_handle, uint16_t cid, + uint8_t req_op, uint8_t error_code, + uint16_t err_handle); void ble_hs_test_util_verify_tx_prep_write(uint16_t attr_handle, uint16_t offset, const void *data, int data_len); diff --git a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_test_util_hci.c b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_test_util_hci.c index e8054c2f..c27af143 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_test_util_hci.c +++ b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_hs_test_util_hci.c @@ -250,6 +250,19 @@ static const struct ble_hs_test_util_hci_ack hci_startup_seq[] = { .evt_params = { 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, .evt_params_len = 8, }, + { + .opcode = ble_hs_hci_util_opcode_join( + BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOC_SUPP_CMD), + .evt_params = { 0x20, 0x00, 0x80, 0x00, 0x00, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x28, 0x22, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0xf7, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x07, + 0xe0, 0x63, 0xe0, 0x04, 0x02, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .evt_params_len = 64 + }, { .opcode = ble_hs_hci_util_opcode_join( BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT), diff --git a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_os_test.c b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_os_test.c index 6588c679..1703a0cf 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_os_test.c +++ b/lib/bt/host/nimble/nimble/nimble/host/test/src/ble_os_test.c @@ -193,7 +193,7 @@ ble_os_disc_test_cb(struct ble_gap_event *event, void *arg) static void ble_os_disc_test_task_handler(void *arg) { - struct ble_gap_disc_params disc_params; + struct ble_gap_disc_params disc_params = {0}; int cb_called; int rc; diff --git a/lib/bt/host/nimble/nimble/nimble/host/test/syscfg.yml b/lib/bt/host/nimble/nimble/nimble/host/test/syscfg.yml index 031b6c8b..cfb3a817 100644 --- a/lib/bt/host/nimble/nimble/nimble/host/test/syscfg.yml +++ b/lib/bt/host/nimble/nimble/nimble/host/test/syscfg.yml @@ -30,3 +30,4 @@ syscfg.vals: BLE_VERSION: 52 BLE_L2CAP_ENHANCED_COC: 1 BLE_TRANSPORT_LL: custom + BLE_EATT_CHAN_NUM: 0 diff --git a/lib/bt/host/nimble/nimble/nimble/include/nimble/ble.h b/lib/bt/host/nimble/nimble/nimble/include/nimble/ble.h index 6979e945..e9a498d2 100644 --- a/lib/bt/host/nimble/nimble/nimble/include/nimble/ble.h +++ b/lib/bt/host/nimble/nimble/nimble/include/nimble/ble.h @@ -282,6 +282,7 @@ enum ble_error_codes #define BLE_ADDR_RANDOM (0x01) #define BLE_ADDR_PUBLIC_ID (0x02) #define BLE_ADDR_RANDOM_ID (0x03) +#define BLE_ADDR_ANONYMOUS (0xFF) #define BLE_ADDR_ANY (&(ble_addr_t) { 0, {0, 0, 0, 0, 0, 0} }) diff --git a/lib/bt/host/nimble/nimble/nimble/include/nimble/hci_common.h b/lib/bt/host/nimble/nimble/nimble/include/nimble/hci_common.h index 76a8b871..62ac9e8e 100644 --- a/lib/bt/host/nimble/nimble/nimble/include/nimble/hci_common.h +++ b/lib/bt/host/nimble/nimble/nimble/include/nimble/hci_common.h @@ -600,6 +600,7 @@ struct ble_hci_le_set_ext_adv_params_cp { uint8_t sid; uint8_t scan_req_notif; } __attribute__((packed)); + struct ble_hci_le_set_ext_adv_params_rp { int8_t tx_power; } __attribute__((packed)); @@ -714,6 +715,18 @@ struct ble_hci_le_ext_create_conn_cp { struct conn_params conn_params[0]; } __attribute__((packed)); +#define BLE_HCI_LE_EXT_CREATE_CONN_V2 (0x0085) +struct ble_hci_le_ext_create_conn_v2_cp { + uint8_t adv_handle; + uint8_t subevent; + uint8_t filter_policy; + uint8_t own_addr_type; + uint8_t peer_addr_type; + uint8_t peer_addr[6]; + uint8_t init_phy_mask; + struct conn_params conn_params[0]; +} __attribute__((packed)); + #define BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER 0x01 #define BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DISABLED 0x02 #define BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DUPLICATES 0x04 @@ -784,14 +797,88 @@ struct ble_hci_le_set_privacy_mode_cp { #define BLE_HCI_OCF_LE_RX_TEST_V3 (0x004F) #define BLE_HCI_OCF_LE_TX_TEST_V3 (0x0050) + #define BLE_HCI_OCF_LE_SET_CONNLESS_CTE_TX_PARAMS (0x0051) +struct ble_hci_le_set_connless_cte_tx_params_cp { + uint8_t adv_handle; + uint8_t cte_length; + uint8_t cte_type; + uint8_t cte_count; + uint8_t switching_pattern_len; + uint8_t switching_pattern[0]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_CONNLESS_CTE_TX_ENABLE (0x0052) +struct ble_hci_le_set_connless_cte_tx_enable_cp { + uint8_t adv_handle; + uint8_t cte_enable; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_CONNLESS_IQ_SAMPLING_ENABLE (0x0053) +struct ble_hci_le_set_connless_iq_sampling_enable_cp { + uint16_t sync_handle; + uint8_t sampling_enable; + uint8_t slot_durations; + uint8_t max_sampled_ctes; + uint8_t switching_pattern_len; + uint8_t antenna_ids[0]; +} __attribute__((packed)); + +struct ble_hci_le_set_connless_iq_sampling_enable_rp { + uint16_t sync_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_CONN_CTE_RX_PARAMS (0x0054) +struct ble_hci_le_set_conn_cte_rx_params_cp { + uint16_t conn_handle; + uint8_t sampling_enable; + uint8_t slot_durations; + uint8_t switching_pattern_len; + uint8_t antenna_ids[0]; +} __attribute__((packed)); +struct ble_hci_le_set_conn_cte_rx_params_rp { + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_CONN_CTE_TX_PARAMS (0x0055) +struct ble_hci_le_set_conn_cte_tx_params_cp { + uint16_t conn_handle; + uint8_t cte_types; + uint8_t switching_pattern_len; + uint8_t antenna_ids[0]; +} __attribute__((packed)); +struct ble_hci_le_set_conn_cte_tx_params_rp { + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_CONN_CTE_REQ_ENABLE (0x0056) +struct ble_gap_conn_cte_req_enable_cp { + uint16_t conn_handle; + uint8_t enable; + uint16_t cte_request_interval; + uint8_t requested_cte_length; + uint8_t requested_cte_type; +} __attribute__((packed)); +struct ble_gap_conn_cte_req_enable_rp { + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_CONN_CTE_RESP_ENABLE (0x0057) +struct ble_hci_le_set_conn_cte_rsp_enable_cp { + uint16_t conn_handle; + uint8_t enable; +} __attribute__((packed)); +struct ble_hci_le_set_conn_cte_rsp_enable_rp { + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_ANTENNA_INFO (0x0058) +struct ble_hci_le_rd_antenna_info_rp { + uint8_t switch_sampling_rates; + uint8_t num_antennae; + uint8_t max_switch_pattern_len; + uint8_t max_cte_len; +} __attribute__((packed)); #define BLE_HCI_OCF_LE_PERIODIC_ADV_RECEIVE_ENABLE (0x0059) struct ble_hci_le_periodic_adv_receive_enable_cp { @@ -1137,7 +1224,7 @@ struct ble_hci_le_set_transmit_power_report_enable_cp { uint8_t remote_enable; } __attribute__((packed)); -#define BLE_HCI_OCF_LE_SET_DATA_ADDR_CHANGE (0x007C) +#define BLE_HCI_OCF_LE_SET_DATA_ADDR_CHANGE (0x007C) struct ble_hci_le_set_data_addr_change_cp { uint8_t adv_handle; uint8_t change_reason; @@ -1157,10 +1244,68 @@ struct ble_hci_le_subrate_req_cp { uint16_t conn_handle; uint16_t subrate_min; uint16_t subrate_max; + uint16_t max_latency; uint16_t cont_num; uint16_t supervision_tmo; } __attribute__((packed)); +#define BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM_V2 (0x007F) +struct ble_hci_le_set_ext_adv_params_v2_cp { + struct ble_hci_le_set_ext_adv_params_cp cmd; + uint8_t pri_phy_opt; + uint8_t sec_phy_opt; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_SUBEV_DATA (0x0082) +struct periodic_adv_subevents { + uint8_t subevent; + uint8_t response_slot_start; + uint8_t response_slot_count; + uint8_t subevent_data_length; + uint8_t subevent_data[0]; +} __attribute__((packed)); + +struct ble_hci_le_set_periodic_adv_subev_data_cp { + uint8_t adv_handle; + uint8_t num_subevents; + struct periodic_adv_subevents subevents[0]; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_RESPONSE_DATA (0x0083) +struct ble_hci_le_set_periodic_adv_response_data { + uint16_t sync_handle; + uint16_t request_event; + uint8_t request_subevent; + uint8_t response_subevent; + uint8_t response_slot; + uint8_t response_data_length; + uint8_t response_data[0]; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_SYNC_SUBEVENT (0x0084) +struct ble_hci_le_set_periodic_adv_sync_subevent { + uint16_t sync_handle; + uint16_t periodic_adv_properties; + uint8_t num_subevents; + uint8_t subevents[0]; +} __attribute__((packed)); +struct ble_hci_le_set_periodic_adv_sync_subevent_rp { + uint16_t sync_handle; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS_V2 (0x0086) +struct ble_hci_le_set_periodic_adv_params_v2 { + uint8_t adv_handle; + uint16_t min_itvl; + uint16_t max_itvl; + uint16_t props; + uint8_t num_subevents; + uint8_t subevent_interval; + uint8_t response_slot_delay; + uint8_t response_slot_spacing; + uint8_t num_response_slots; +} __attribute__((packed)); + /* --- Vendor specific commands (OGF 0x003F) */ /* Read Random Static Address */ #define BLE_HCI_OCF_VS_RD_STATIC_ADDR (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0001)) @@ -1238,6 +1383,11 @@ struct ble_hci_vs_duplicate_exception_list_cp { #define BLE_HCI_OCF_VS_SET_CHAN_SELECT (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0112)) +#define BLE_HCI_OCF_VS_SET_EVT_MASK (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0116)) +struct ble_hci_vs_set_event_mask_cp { + uint32_t event_mask; +} __attribute__((packed)); + /* Command Specific Definitions */ /* --- Set controller to host flow control (OGF 0x03, OCF 0x0031) --- */ #define BLE_HCI_CTLR_TO_HOST_FC_OFF (0) @@ -1278,8 +1428,17 @@ struct ble_hci_vs_duplicate_exception_list_cp { #define BLE_HCI_ADV_PEER_ADDR_MAX (1) /* --- LE advertising channel tx power (OCF 0x0007) */ -#define BLE_HCI_ADV_CHAN_TXPWR_MIN (-20) -#define BLE_HCI_ADV_CHAN_TXPWR_MAX (10) +#if MYNEWT_VAL(BLE_VERSION) == 50 +#define BLE_HCI_ADV_CHAN_TXPWR_MIN (-20) +#define BLE_HCI_ADV_CHAN_TXPWR_MAX (10) +#elif MYNEWT_VAL(BLE_VERSION) == 51 +#define BLE_HCI_ADV_CHAN_TXPWR_MIN (-20) +#define BLE_HCI_ADV_CHAN_TXPWR_MAX (20) +#elif MYNEWT_VAL(BLE_VERSION) >= 52 +#define BLE_HCI_ADV_CHAN_TXPWR_MIN (-127) +#define BLE_HCI_ADV_CHAN_TXPWR_MAX (20) +#endif + /* --- LE set scan enable (OCF 0x000c) */ @@ -1392,7 +1551,11 @@ struct ble_hci_vs_duplicate_exception_list_cp { #define BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MIN (0x001b) #define BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MAX (0x00fb) #define BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MIN (0x0148) +#if BLE_50_FEATURE_SUPPORT #define BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MAX (0x4290) +#else +#define BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MAX (0x0848) +#endif /* --- LE read maximum default PHY (OCF 0x0030) */ #define BLE_HCI_LE_PHY_1M (1) @@ -1463,11 +1626,22 @@ struct ble_hci_vs_duplicate_exception_list_cp { #define BLE_HCI_PERIODIC_DATA_STATUS_COMPLETE 0x00 #define BLE_HCI_PERIODIC_DATA_STATUS_INCOMPLETE 0x01 #define BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED 0x02 +#define BLE_HCI_PERIODIC_DATA_STATUS_RX_FAILED 0xFF /* --- LE set privacy mode (OCF 0x004E) */ #define BLE_HCI_PRIVACY_NETWORK (0) #define BLE_HCI_PRIVACY_DEVICE (1) +/* --- LE set cte type (OCF 0x0051) */ +#define BLE_HCI_CTE_TYPE_AOA (0) +#define BLE_HCI_CTE_TYPE_AOD_1US (1) +#define BLE_HCI_CTE_TYPE_AOD_2US (2) + +/* --- LE set allow cte rsp types (OCF 0x0055) */ +#define BLE_HCI_CTE_RSP_ALLOW_AOA_MASK (0x01) +#define BLE_HCI_CTE_RSP_ALLOW_AOD_1US_MASK (0x02) +#define BLE_HCI_CTE_RSP_ALLOW_AOD_2US_MASK (0x04) + /* Event Codes */ #define BLE_HCI_EVCODE_INQUIRY_CMP (0x01) #define BLE_HCI_EVCODE_INQUIRY_RESULT (0x02) @@ -1638,6 +1812,8 @@ struct ble_hci_ev_vs_css_slot_changed { #define BLE_HCI_VS_SUBEV_ID_LLCP_TRACE (0x17) +#define BLE_HCI_VS_SUBEV_LE_SLEEP_WAKE_UP (0xC3) + /* LE sub-event codes */ #define BLE_HCI_LE_SUBEV_CONN_COMPLETE (0x01) struct ble_hci_ev_le_subev_conn_complete { @@ -1728,6 +1904,7 @@ struct ble_hci_ev_le_subev_gen_dhkey_complete { } __attribute__((packed)); #define BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE (0x0A) +#define BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE_V2 (0x29) struct ble_hci_ev_le_subev_enh_conn_complete { uint8_t subev_code; uint8_t status; @@ -1741,6 +1918,10 @@ struct ble_hci_ev_le_subev_enh_conn_complete { uint16_t conn_latency; uint16_t supervision_timeout; uint8_t mca; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + uint8_t adv_handle; + uint16_t sync_handle; +#endif } __attribute__((packed)); #define BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT (0x0B) @@ -1789,7 +1970,8 @@ struct ble_hci_ev_le_subev_ext_adv_rpt { struct ext_adv_report reports[0]; } __attribute__((packed)); -#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB (0x0E) +#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB (0x0E) +#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB_V2 (0x24) struct ble_hci_ev_le_subev_periodic_adv_sync_estab { uint8_t subev_code; uint8_t status; @@ -1800,15 +1982,41 @@ struct ble_hci_ev_le_subev_periodic_adv_sync_estab { uint8_t phy; uint16_t interval; uint8_t aca; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + uint8_t num_subevents; + uint8_t subevent_interval; + uint8_t response_slot_delay; + uint8_t response_slot_spacing; +#endif } __attribute__((packed)); #define BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT (0x0F) +#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT_V2 (0x25) struct ble_hci_ev_le_subev_periodic_adv_rpt { uint8_t subev_code; uint16_t sync_handle; int8_t tx_power; int8_t rssi; uint8_t cte_type; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + uint16_t event_counter; + uint8_t subevent; +#endif + uint8_t data_status; + uint8_t data_len; + uint8_t data[0]; +} __attribute__((packed)); + +struct ble_hci_ev_le_subev_periodic_adv_rpt_v2 { + uint8_t subev_code; + uint16_t sync_handle; + int8_t tx_power; + int8_t rssi; + uint8_t cte_type; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + uint16_t event_counter; + uint8_t subevent; +#endif // MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) uint8_t data_status; uint8_t data_len; uint8_t data[0]; @@ -1849,11 +2057,47 @@ struct ble_hci_ev_le_subev_chan_sel_alg { uint8_t csa; } __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_CONNLESS_IQ_RPT (0x15) +struct ble_hci_ev_le_subev_connless_iq_rpt { + uint8_t subev_code; + uint16_t sync_handle; + uint8_t channel_index; + int16_t rssi; + uint8_t rssi_antenna_id; + uint8_t cte_type; + uint8_t slot_durations; + uint8_t packet_status; + uint16_t periodic_event_counter; + uint8_t sample_count; + int8_t iq_samples[0]; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_CONN_IQ_RPT (0x16) +struct ble_hci_ev_le_subev_conn_iq_rpt { + uint8_t subev_code; + uint16_t conn_handle; + uint8_t rx_phy; + uint8_t data_channel_index; + int16_t rssi; + uint8_t rssi_antenna_id; + uint8_t cte_type; + uint8_t slot_durations; + uint8_t packet_status; + uint16_t conn_event_counter; + uint8_t sample_count; + int8_t iq_samples[0]; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_CTE_REQ_FAILED (0x17) +struct ble_hci_ev_le_subev_cte_req_failed { + uint8_t subev_code; + uint8_t status; + uint16_t conn_handle; +} __attribute__((packed)); -#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER (0x18) +#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER (0x18) +#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER_V2 (0x26) struct ble_hci_ev_le_subev_periodic_adv_sync_transfer { uint8_t subev_code; uint8_t status; @@ -1866,6 +2110,12 @@ struct ble_hci_ev_le_subev_periodic_adv_sync_transfer { uint8_t phy; uint16_t interval; uint8_t aca; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + uint8_t num_subevents; + uint8_t subevent_interval; + uint8_t response_slot_delay; + uint8_t response_slot_spacing; +#endif } __attribute__((packed)); #define BLE_HCI_LE_SUBEV_CIS_ESTABLISHED (0x19) @@ -2003,6 +2253,34 @@ struct ble_hci_ev_le_subev_subrate_change { uint16_t supervision_tmo; } __attribute__((packed)); +#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SUBEV_DATA_REQ (0x27) +struct ble_hci_ev_le_subev_periodic_adv_subev_data_req { + uint8_t subev_code; + uint8_t adv_handle; + uint8_t subevent_start; + uint8_t subevent_data_count; +} __attribute__((packed)); + +#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_RESP_REPORT (0x28) +struct periodic_adv_response { + int8_t tx_power; + int8_t rssi; + uint8_t cte_type; + uint8_t response_slot; + uint8_t data_status; + uint8_t data_length; + uint8_t data[0]; +} __attribute__((packed)); + +struct ble_hci_ev_le_subev_periodic_adv_resp_rep { + uint8_t subev_code; + uint8_t adv_handle; + uint8_t subevent; + uint8_t tx_status; + uint8_t num_responses; + struct periodic_adv_response responses[0]; +} __attribute__((packed)); + #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) // LE vendor hci event #define BLE_HCI_LE_SUBEV_DISCARD_REPORT_EVT 0XF0 diff --git a/lib/bt/host/nimble/nimble/nimble/include/nimble/nimble_opt_auto.h b/lib/bt/host/nimble/nimble/nimble/include/nimble/nimble_opt_auto.h index 6326abf5..8b3fde02 100644 --- a/lib/bt/host/nimble/nimble/nimble/include/nimble/nimble_opt_auto.h +++ b/lib/bt/host/nimble/nimble/nimble/include/nimble/nimble_opt_auto.h @@ -113,6 +113,10 @@ extern "C" { #define NIMBLE_BLE_ATT_CLT_INDICATE \ (MYNEWT_VAL(BLE_GATT_INDICATE)) +#undef NIMBLE_BLE_ATT_CLT_NOTIFY_MULT +#define NIMBLE_BLE_ATT_CLT_NOTIFY_MULT \ + (MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE)) + /** Security manager settings. */ #undef NIMBLE_BLE_SM diff --git a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/diag/pkg.yml b/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/diag/pkg.yml deleted file mode 100644 index 9b9ee83e..00000000 --- a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/diag/pkg.yml +++ /dev/null @@ -1,28 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/transport/dialog_cmac/cmac_driver/diag -pkg.description: Default diag configuration for CMAC -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - dialog - - da1469x - - cmac -pkg.apis: dialog_cmac_diag diff --git a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/diag/src/cmac_diag.c b/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/diag/src/cmac_diag.c deleted file mode 100644 index 83299038..00000000 --- a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/diag/src/cmac_diag.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "syscfg/syscfg.h" -#include "mcu/mcu.h" - -#if MYNEWT_VAL(BLE_CONTROLLER) -void -cmac_diag_setup_cmac(void) -{ - MCU_DIAG_MAP( 0, 4, DSER); - MCU_DIAG_MAP( 1, 6, CMAC_ON_ERROR); - MCU_DIAG_MAP( 2, 2, PHY_TX_EN); - MCU_DIAG_MAP( 3, 2, PHY_RX_EN); - MCU_DIAG_MAP( 4, 2, PHY_TXRX_DATA_COMB); - MCU_DIAG_MAP( 5, 2, PHY_TXRX_DATA_EN_COMB); - MCU_DIAG_MAP( 6, 5, EV1US_FRAME_START); - MCU_DIAG_MAP( 7, 5, EV_BS_START); - MCU_DIAG_MAP( 8, 5, EV1C_BS_STOP); - MCU_DIAG_MAP( 9, 5, EV1US_PHY_TO_IDLE); - MCU_DIAG_MAP(10, 9, CALLBACK_IRQ); - MCU_DIAG_MAP(11, 9, FIELD_IRQ); - MCU_DIAG_MAP(12, 9, FRAME_IRQ); - MCU_DIAG_MAP(13, 3, SLP_TIMER_ACTIVE); - MCU_DIAG_MAP(14, 4, SLEEPING); - MCU_DIAG_MAP(15, 8, LL_TIMER1_00); -} -#else -void -cmac_diag_setup_host(void) -{ - /* Setup pins for diagnostic signals */ - mcu_gpio_set_pin_function(42, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAG0); /* DIAG_0 @ P1.10 */ - mcu_gpio_set_pin_function(43, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAG1); /* DIAG_1 @ P1.11 */ - mcu_gpio_set_pin_function(44, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAG2); /* DIAG_2 @ P1.12 */ - mcu_gpio_set_pin_function(24, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_3 @ P0.24 */ - mcu_gpio_set_pin_function(21, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_4 @ P0.21 */ - mcu_gpio_set_pin_function(20, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_5 @ P0.20 */ - mcu_gpio_set_pin_function(19, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_6 @ P0.19 */ - mcu_gpio_set_pin_function(18, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_7 @ P0.18 */ - mcu_gpio_set_pin_function(31, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_8 @ P0.31 */ - mcu_gpio_set_pin_function(30, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_9 @ P0.30 */ - mcu_gpio_set_pin_function(29, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_10 @ P0.29 */ - mcu_gpio_set_pin_function(28, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_11 @ P0.28 */ - mcu_gpio_set_pin_function(27, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_12 @ P0.27 */ - mcu_gpio_set_pin_function(26, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_13 @ P0.26 */ - mcu_gpio_set_pin_function(38, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_14 @ P1.06 */ - mcu_gpio_set_pin_function(41, MCU_GPIO_MODE_OUTPUT, MCU_GPIO_FUNC_CMAC_DIAGX); /* DIAG_15 @ P1.09 */ -} -#endif diff --git a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_diag.h b/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_diag.h deleted file mode 100644 index dc6ee903..00000000 --- a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_diag.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef __MCU_CMAC_DIAG_H_ -#define __MCU_CMAC_DIAG_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -void cmac_diag_setup_host(void); -void cmac_diag_setup_cmac(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __MCU_CMAC_DIAG_H_ */ diff --git a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_host.h b/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_host.h deleted file mode 100644 index 50d86755..00000000 --- a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_host.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef __DA1469X_CMAC_V2_H_ -#define __DA1469X_CMAC_V2_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -void cmac_host_init(void); -void cmac_host_signal2cmac(void); -void cmac_host_rf_calibrate(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __DA1469X_CMAC_V2_H_ */ diff --git a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_shared.h b/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_shared.h deleted file mode 100644 index 887af258..00000000 --- a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/include/cmac_driver/cmac_shared.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef __MCU_CMAC_SHARED_H_ -#define __MCU_CMAC_SHARED_H_ - -#include -#include "syscfg/syscfg.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define CMAC_SHARED_MAGIC_CMAC (0x4C6C) /* "lL" */ -#define CMAC_SHARED_MAGIC_SYS (0x5368) /* "hS" */ - -#define CMAC_SHARED_F_SYS_LPCLK_AVAILABLE (0x0001) - -/* - * Simple circular buffer for storing random numbers generated by M33 - * Empty: cmr_in = cmr_out = 0; - * Full: cmr_in + 1 = cmr_out - * - * cmr_in: used by the M33 to add random numbers to the circular buffer. - * cmr_out: used by CMAC to retrieve random numbers - * - * NOTE: cmr_in and cmr_out are indices. - */ -#define CMAC_RAND_BUF_ELEMS (16) - -struct cmac_rand { - int cmr_active; - int cmr_in; - int cmr_out; - uint32_t cmr_buf[CMAC_RAND_BUF_ELEMS]; -}; - -struct cmac_mbox { - uint16_t rd_off; - uint16_t wr_off; -}; - -struct cmac_dcdc { - uint8_t enabled; - uint32_t v18; - uint32_t v18p; - uint32_t vdd; - uint32_t v14; - uint32_t ctrl1; -}; - -struct cmac_trim { - uint8_t rfcu_len; - uint8_t rfcu_mode1_len; - uint8_t rfcu_mode2_len; - uint8_t synth_len; - uint32_t rfcu[ MYNEWT_VAL(CMAC_TRIM_SIZE_RFCU) ]; - uint32_t rfcu_mode1[2]; - uint32_t rfcu_mode2[2]; - uint32_t synth[ MYNEWT_VAL(CMAC_TRIM_SIZE_SYNTH) ]; -}; - -#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE) -struct cmac_debug { - int8_t last_rx_rssi; - int8_t tx_power_override; - - uint32_t cal_res_1; - uint32_t cal_res_2; - uint32_t trim_val1_tx_1; - uint32_t trim_val1_tx_2; - uint32_t trim_val2_tx; - uint32_t trim_val2_rx; -}; -#endif - -#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE) -struct cmac_coredump { - uint32_t lr; - uint32_t pc; - uint32_t assert; - const char *assert_file; - uint32_t assert_line; - - uint32_t CM_STAT_REG; - uint32_t CM_LL_TIMER1_36_10_REG; - uint32_t CM_LL_TIMER1_9_0_REG; - uint32_t CM_ERROR_REG; - uint32_t CM_EXC_STAT_REG; -}; -#endif - -#define CMAC_PENDING_OP_LP_CLK 0x0001 -#define CMAC_PENDING_OP_RF_CAL 0x0002 - -struct cmac_shared_data { - uint16_t magic_cmac; - uint16_t magic_sys; - uint16_t pending_ops; - uint16_t lp_clock_freq; /* LP clock frequency */ - uint32_t xtal32m_settle_us;/* XTAL32M settling time */ - struct cmac_mbox mbox_s2c; /* SYS2CMAC mailbox */ - struct cmac_mbox mbox_c2s; /* CMAC2SYS mailbox */ - struct cmac_dcdc dcdc; /* DCDC settings */ - struct cmac_trim trim; /* Trim data */ - struct cmac_rand rand; /* Random numbers */ -#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE) - struct cmac_debug debug; /* Extra debug data */ -#endif -#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE) - struct cmac_coredump coredump; -#endif - - uint8_t mbox_s2c_buf[ MYNEWT_VAL(CMAC_MBOX_SIZE_S2C) ]; - uint8_t mbox_c2s_buf[ MYNEWT_VAL(CMAC_MBOX_SIZE_C2S) ]; -}; - -#if MYNEWT_VAL(BLE_CONTROLLER) -extern volatile struct cmac_shared_data g_cmac_shared_data; -#else -extern volatile struct cmac_shared_data *g_cmac_shared_data; -#endif - -/* cmac_mbox */ -typedef int (cmac_mbox_read_cb)(const void *data, uint16_t len); -typedef void (cmac_mbox_write_notif_cb)(void); -void cmac_mbox_set_read_cb(cmac_mbox_read_cb *cb); -void cmac_mbox_set_write_notif_cb(cmac_mbox_write_notif_cb *cb); -int cmac_mbox_has_data(void); -int cmac_mbox_read(void); -int cmac_mbox_write(const void *data, uint16_t len); - -/* cmac_rand */ -typedef void (*cmac_rand_isr_cb_t)(uint8_t rnum); -void cmac_rand_start(void); -void cmac_rand_stop(void); -void cmac_rand_read(void); -void cmac_rand_write(void); -void cmac_rand_chk_fill(void); -int cmac_rand_get_next(void); -int cmac_rand_is_active(void); -int cmac_rand_is_full(void); -void cmac_rand_fill(uint32_t *buf, int num_words); -void cmac_rand_set_isr_cb(cmac_rand_isr_cb_t cb); - -void cmac_shared_init(void); -void cmac_shared_sync(void); - -#if MYNEWT_VAL(BLE_CONTROLLER) -#define CMAC_SHARED_LOCK_VAL 0xc0000000 -#else -#define CMAC_SHARED_LOCK_VAL 0x40000000 -#endif - -static inline void -cmac_shared_lock(void) -{ - volatile uint32_t *bsr_set = (void *)0x50050074; - volatile uint32_t *bsr_stat = (void *)0x5005007c; - - while ((*bsr_stat & 0xc0000000) != CMAC_SHARED_LOCK_VAL) { - *bsr_set = CMAC_SHARED_LOCK_VAL; - } -} - -static inline void -cmac_shared_unlock(void) -{ - volatile uint32_t *bsr_reset = (void *)0x50050078; - - *bsr_reset = CMAC_SHARED_LOCK_VAL; -} - -#ifdef __cplusplus -} -#endif - -#endif /* __MCU_CMAC_SHARED_H_ */ diff --git a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/pkg.yml b/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/pkg.yml deleted file mode 100644 index 1fa003ab..00000000 --- a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/pkg.yml +++ /dev/null @@ -1,39 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -pkg.name: nimble/transport/dialog_cmac/cmac_driver -pkg.description: Driver for Dialog CMAC IPC -pkg.author: "Apache Mynewt " -pkg.homepage: "http://mynewt.apache.org/" -pkg.keywords: - - dialog - - da1469x - - cmac - -pkg.req_apis.CMAC_DEBUG_DIAG_ENABLE: - - dialog_cmac_diag - -pkg.ign_files.BLE_CONTROLLER: - - cmac_host.c - -pkg.post_link_cmds.BLE_CONTROLLER: - scripts/create_cmac_bin.sh: 100 - -pkg.pre_link_cmds.!BLE_CONTROLLER: - scripts/build_libcmac.sh: 100 diff --git a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/build_libcmac.sh b/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/build_libcmac.sh deleted file mode 100755 index bbc822aa..00000000 --- a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/build_libcmac.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -NEWT=${MYNEWT_NEWT_PATH} -OBJCOPY=${MYNEWT_OBJCOPY_PATH} -AR=${MYNEWT_AR_PATH} -LIBCMAC_A=${MYNEWT_USER_SRC_DIR}/libcmac.a - -export WORK_DIR=${MYNEWT_USER_WORK_DIR} -export BASENAME_ROM=cmac.rom -export BASENAME_RAM=cmac.ram - -if [ ${MYNEWT_VAL_CMAC_IMAGE_SINGLE} -eq 0 ]; then - # Create empty binary for ROM image (1 byte required for objcopy) - truncate -s 1 ${WORK_DIR}/${BASENAME_ROM}.bin - # Create fixed size RAM image - truncate -s ${MYNEWT_VAL_CMAC_IMAGE_RAM_SIZE} ${WORK_DIR}/${BASENAME_RAM}.bin -else - ${NEWT} build ${MYNEWT_VAL_CMAC_IMAGE_TARGET_NAME} -fi - -cd ${WORK_DIR} - -# Convert both binaries to objects and create archive to link -${OBJCOPY} -I binary -O elf32-littlearm -B armv8-m.main \ - --rename-section .data=.libcmac.rom ${BASENAME_ROM}.bin ${BASENAME_ROM}.o -${OBJCOPY} -I binary -O elf32-littlearm -B armv8-m.main \ - --rename-section .data=.libcmac.ram ${BASENAME_RAM}.bin ${BASENAME_RAM}.o -${AR} -rcs ${LIBCMAC_A} ${BASENAME_ROM}.o ${BASENAME_RAM}.o diff --git a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/create_cmac_bin.sh b/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/create_cmac_bin.sh deleted file mode 100755 index 954d0860..00000000 --- a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/scripts/create_cmac_bin.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -OBJCOPY=${MYNEWT_OBJCOPY_PATH} -ELF=${MYNEWT_APP_BIN_DIR}/blehci.elf - -cd ${WORK_DIR} - -# Strip .ram section from ROM image -${OBJCOPY} -R .ram -O binary ${ELF} ${BASENAME_ROM}.bin -# RAM image is the same as binary created by newt -cp ${ELF}.bin ${BASENAME_RAM}.bin - -# Create a copy of ROM image to flash to partition, if required -cp ${BASENAME_ROM}.bin ${ELF}.rom.bin diff --git a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_host.c b/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_host.c deleted file mode 100644 index cdb00060..00000000 --- a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_host.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include -#include -#include -#include "syscfg/syscfg.h" -#include "sysflash/sysflash.h" -#include "os/os.h" -#include "mcu/mcu.h" -#include "mcu/cmsis_nvic.h" -#include "mcu/da1469x_hal.h" -#include "mcu/da1469x_lpclk.h" -#include "mcu/da1469x_clock.h" -#include "mcu/da1469x_trimv.h" -#include "mcu/da1469x_pdc.h" -#include "cmac_driver/cmac_host.h" -#include "cmac_driver/cmac_shared.h" -#include "cmac_driver/cmac_diag.h" -#include "trng/trng.h" -#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE) -#include "console/console.h" -#endif - -/* CMAC data */ -extern char _binary_cmac_rom_bin_start[]; -extern char _binary_cmac_rom_bin_end; -extern char _binary_cmac_ram_bin_start[]; -extern char _binary_cmac_ram_bin_end; - -struct cmac_image_info { - uint32_t magic; - uint32_t size_rom; - uint32_t size_ram; - uint32_t offset_data; - uint32_t offset_shared; -}; - -/* PDC entry for waking up CMAC */ -static int8_t g_cmac_host_pdc_sys2cmac; -/* PDC entry for waking up M33 */ -static int8_t g_cmac_host_pdc_cmac2sys; - -static void cmac_host_rand_fill(struct os_event *ev); -static struct os_event g_cmac_host_rand_ev = { - .ev_cb = cmac_host_rand_fill -}; - -static void cmac_host_rand_chk_fill(void); - -#if MYNEWT_VAL_CHOICE(BLE_TRANSPORT_HS, uart) -static void cmac_host_error_w4flush(struct os_event *ev); -static struct os_event g_cmac_host_error_ev = { - .ev_cb = cmac_host_error_w4flush -}; -#endif - -static void -cmac2sys_isr(void) -{ -#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE) - volatile struct cmac_coredump *cd = &g_cmac_shared_data->coredump; - const char *assert_file; -#endif - - os_trace_isr_enter(); - - /* Clear CMAC2SYS interrupt */ - *(volatile uint32_t *)0x40002000 = 2; - - cmac_mbox_read(); - - if (*(volatile uint32_t *)0x40002000 & 0x1c00) { -#if MYNEWT_VAL(CMAC_DEBUG_COREDUMP_ENABLE) - console_blocking_mode(); - console_printf("CMAC error (0x%08lx)\n", *(volatile uint32_t *)0x40002000); - console_printf(" lr:0x%08lx pc:0x%08lx\n", cd->lr, cd->pc); - if (cd->assert) { - console_printf(" assert:0x%08lx\n", cd->assert); - if (cd->assert_file) { - /* Need to translate pointer from M0 code segment to M33 data */ - assert_file = cd->assert_file + MCU_MEM_SYSRAM_START_ADDRESS + - MEMCTRL->CMI_CODE_BASE_REG; - console_printf(" %s:%d\n", - assert_file, (unsigned)cd->assert_line); - } - } - console_printf(" 0x%08lx CM_ERROR_REG\n", cd->CM_ERROR_REG); - console_printf(" 0x%08lx CM_EXC_STAT_REG\n", cd->CM_EXC_STAT_REG); - console_printf(" 0x%08lx CM_LL_TIMER1_36_10_REG\n", cd->CM_LL_TIMER1_36_10_REG); - console_printf(" 0x%08lx CM_LL_TIMER1_9_0_REG\n", cd->CM_LL_TIMER1_9_0_REG); - - /* Spin if debugger is connected to CMAC to avoid resetting it */ - if (cd->CM_STAT_REG & 0x20) { - for (;;); - } -#endif - -#if MYNEWT_VAL_CHOICE(BLE_TRANSPORT_HS, uart) - NVIC_DisableIRQ(CMAC2SYS_IRQn); - /* Wait until UART is flushed and then assert */ - cmac_host_error_w4flush(NULL); - return; -#endif - - /* XXX CMAC is in error state, need to recover */ - assert(0); - return; - } - - cmac_host_rand_chk_fill(); - - os_trace_isr_exit(); -} - -static void -cmac_host_rand_fill(struct os_event *ev) -{ - size_t num_bytes; - struct trng_dev *trng; - uint32_t *rnum; - uint32_t rnums[CMAC_RAND_BUF_ELEMS]; - - /* Check if full */ - if (!cmac_rand_is_active() || cmac_rand_is_full()) { - return; - } - - assert(ev->ev_arg != NULL); - - /* Fill buffer with random numbers even though we may not use all of them */ - trng = ev->ev_arg; - rnum = &rnums[0]; - num_bytes = trng_read(trng, rnum, CMAC_RAND_BUF_ELEMS * sizeof(uint32_t)); - - cmac_rand_fill(rnum, num_bytes / 4); - cmac_host_signal2cmac(); -} - -static void -cmac_host_rand_chk_fill(void) -{ - if (cmac_rand_is_active() && !cmac_rand_is_full()) { - os_eventq_put(os_eventq_dflt_get(), &g_cmac_host_rand_ev); - } -} - -#if MYNEWT_VAL_CHOICE(BLE_TRANSPORT_HS, uart) -#if MYNEWT_VAL(BLE_TRANSPORT_UART_PORT) < 0 || MYNEWT_VAL(BLE_TRANSPORT_UART_PORT) > 2 -#error Invalid BLE_HCI_UART_PORT -#endif -static void -cmac_host_error_w4flush(struct os_event *ev) -{ - static UART_Type * const regs[] = { - (void *)UART, - (void *)UART2, - (void *)UART3 - }; - - if (!ev) { - /* Move to task context, we do not want to spin in interrupt */ - os_eventq_put(os_eventq_dflt_get(), &g_cmac_host_error_ev); - return; - } - - do { - cmac_mbox_read(); - while ((regs[MYNEWT_VAL(BLE_TRANSPORT_UART_PORT)]->UART_LSR_REG & - UART_UART_LSR_REG_UART_TEMT_Msk) == 0) { - /* Wait until both FIFO and shift registers are empty */ - } - } while (cmac_mbox_has_data()); - - /* Reset CMAC */ - CRG_TOP->CLK_RADIO_REG |= CRG_TOP_CLK_RADIO_REG_CMAC_SYNCH_RESET_Msk; - - assert(0); -} -#endif - -void -cmac_host_signal2cmac(void) -{ - da1469x_pdc_set(g_cmac_host_pdc_sys2cmac); -} - -static void -cmac_host_lpclk_cb(uint32_t freq) -{ - /* No need to wakeup CMAC if LP clock frequency did not change */ - if (g_cmac_shared_data->lp_clock_freq == freq) { - return; - } - - cmac_shared_lock(); - g_cmac_shared_data->lp_clock_freq = freq; - g_cmac_shared_data->pending_ops |= CMAC_PENDING_OP_LP_CLK; - cmac_shared_unlock(); - - cmac_host_signal2cmac(); -} - -#if MYNEWT_VAL(CMAC_DEBUG_HOST_PRINT_ENABLE) -static void -cmac_host_print_trim(const char *name, const uint32_t *tv, unsigned len) -{ - console_printf("[CMAC] Trim values for '%s'\n", name); - - while (len) { - console_printf(" 0x%08x = 0x%08x\n", (unsigned)tv[0], (unsigned)tv[1]); - len -= 2; - tv += 2; - } -} -#endif - -void -cmac_host_rf_calibrate(void) -{ - cmac_shared_lock(); - g_cmac_shared_data->pending_ops |= CMAC_PENDING_OP_RF_CAL; - cmac_shared_unlock(); - - cmac_host_signal2cmac(); -} - -void -cmac_host_init(void) -{ - struct trng_dev *trng; - struct cmac_image_info ii; - uint32_t cmac_rom_size; - uint32_t cmac_ram_size; -#if !MYNEWT_VAL(CMAC_IMAGE_SINGLE) - const struct flash_area *fa; - int rc; -#endif - struct cmac_trim *trim; - - /* Get trng os device */ - trng = (struct trng_dev *) os_dev_open("trng", OS_TIMEOUT_NEVER, NULL); - assert(trng); - g_cmac_host_rand_ev.ev_arg = trng; - -#if MYNEWT_VAL(CMAC_DEBUG_DIAG_ENABLE) - cmac_diag_setup_host(); -#endif - -#if MYNEWT_VAL(CMAC_DEBUG_SWD_ENABLE) - /* Enable CMAC debugger */ - CRG_TOP->SYS_CTRL_REG |= 0x40; /* CRG_TOP_SYS_CTRL_REG_CMAC_DEBUGGER_ENABLE_Msk */ -#endif - - /* - * Add PDC entry to wake up CMAC from M33 - * - * XXX if MCU_DEBUG_GPIO_DEEP_SLEEP is enabled on CMAC, this should also - * enable PD_COM so CMAC can access GPIOs after wake up - */ - g_cmac_host_pdc_sys2cmac = da1469x_pdc_add(MCU_PDC_TRIGGER_MAC_TIMER, - MCU_PDC_MASTER_CMAC, - MCU_PDC_EN_XTAL); - da1469x_pdc_set(g_cmac_host_pdc_sys2cmac); - da1469x_pdc_ack(g_cmac_host_pdc_sys2cmac); - - /* Add PDC entry to wake up M33 from CMAC, if does not exist yet */ - g_cmac_host_pdc_cmac2sys = da1469x_pdc_find(MCU_PDC_TRIGGER_COMBO, - MCU_PDC_MASTER_M33, 0); - if (g_cmac_host_pdc_cmac2sys < 0) { - g_cmac_host_pdc_cmac2sys = da1469x_pdc_add(MCU_PDC_TRIGGER_COMBO, - MCU_PDC_MASTER_M33, - MCU_PDC_EN_XTAL); - da1469x_pdc_set(g_cmac_host_pdc_cmac2sys); - da1469x_pdc_ack(g_cmac_host_pdc_cmac2sys); - } - - /* Setup CMAC2SYS interrupt */ - NVIC_SetVector(CMAC2SYS_IRQn, (uint32_t)cmac2sys_isr); - NVIC_SetPriority(CMAC2SYS_IRQn, MYNEWT_VAL(CMAC_CMAC2SYS_IRQ_PRIORITY)); - NVIC_DisableIRQ(CMAC2SYS_IRQn); - - /* Enable Radio LDO */ - CRG_TOP->POWER_CTRL_REG |= CRG_TOP_POWER_CTRL_REG_LDO_RADIO_ENABLE_Msk; - - /* Enable CMAC, but keep it in reset */ - CRG_TOP->CLK_RADIO_REG = (1 << CRG_TOP_CLK_RADIO_REG_RFCU_ENABLE_Pos) | - (1 << CRG_TOP_CLK_RADIO_REG_CMAC_SYNCH_RESET_Pos) | - (0 << CRG_TOP_CLK_RADIO_REG_CMAC_CLK_SEL_Pos) | - (1 << CRG_TOP_CLK_RADIO_REG_CMAC_CLK_ENABLE_Pos) | - (0 << CRG_TOP_CLK_RADIO_REG_CMAC_DIV_Pos); - - /* Calculate size of ROM and RAM area */ - cmac_rom_size = &_binary_cmac_rom_bin_end - &_binary_cmac_rom_bin_start[0]; - cmac_ram_size = &_binary_cmac_ram_bin_end - &_binary_cmac_ram_bin_start[0]; - - /* Load image header and check if image can be loaded */ -#if MYNEWT_VAL(CMAC_IMAGE_SINGLE) - memcpy(&ii, &_binary_cmac_rom_bin_start[128], sizeof(ii)); -#else - rc = flash_area_open(FLASH_AREA_IMAGE_1, &fa); - assert(rc == 0); - rc = flash_area_read(fa, 128, &ii, sizeof(ii)); - assert(rc == 0); -#endif - - assert(ii.magic == 0xC3ACC3AC); - assert(ii.size_rom == cmac_rom_size); - assert(ii.size_ram <= cmac_ram_size); - - /* Copy CMAC image to RAM */ -#if MYNEWT_VAL(CMAC_IMAGE_SINGLE) - memset(&_binary_cmac_ram_bin_start, 0xaa, cmac_ram_size); - memcpy(&_binary_cmac_ram_bin_start, &_binary_cmac_rom_bin_start, ii.size_rom); -#else - memset(&_binary_cmac_ram_bin_start, 0xaa, cmac_ram_size); - rc = flash_area_read(fa, 0, &_binary_cmac_ram_bin_start, ii.size_rom); - assert(rc == 0); -#endif - - /* Setup CMAC memory addresses */ - MEMCTRL->CMI_CODE_BASE_REG = (uint32_t)&_binary_cmac_ram_bin_start; - MEMCTRL->CMI_DATA_BASE_REG = MEMCTRL->CMI_CODE_BASE_REG + ii.offset_data; - MEMCTRL->CMI_SHARED_BASE_REG = MEMCTRL->CMI_CODE_BASE_REG + ii.offset_shared; - MEMCTRL->CMI_END_REG = MEMCTRL->CMI_CODE_BASE_REG + ii.size_ram - 1; - - /* Initialize shared memory */ - cmac_shared_init(); - - trim = (struct cmac_trim *)&g_cmac_shared_data->trim; - trim->rfcu_len = da1469x_trimv_group_read(6, trim->rfcu, ARRAY_SIZE(trim->rfcu)); - trim->rfcu_mode1_len = da1469x_trimv_group_read(8, trim->rfcu_mode1, ARRAY_SIZE(trim->rfcu_mode1)); - trim->rfcu_mode2_len = da1469x_trimv_group_read(10, trim->rfcu_mode2, ARRAY_SIZE(trim->rfcu_mode2)); - trim->synth_len = da1469x_trimv_group_read(7, trim->synth, ARRAY_SIZE(trim->synth)); - -#if MYNEWT_VAL(CMAC_DEBUG_HOST_PRINT_ENABLE) - cmac_host_print_trim("rfcu", trim->rfcu, trim->rfcu_len); - cmac_host_print_trim("rfcu_mode1", trim->rfcu_mode1, trim->rfcu_mode1_len); - cmac_host_print_trim("rfcu_mode2", trim->rfcu_mode2, trim->rfcu_mode2_len); - cmac_host_print_trim("synth", trim->synth, trim->synth_len); -#endif - - /* Release CMAC from reset and sync */ - CRG_TOP->CLK_RADIO_REG &= ~CRG_TOP_CLK_RADIO_REG_CMAC_SYNCH_RESET_Msk; - cmac_shared_sync(); - - da1469x_lpclk_register_cmac_cb(cmac_host_lpclk_cb); - -#if MYNEWT_VAL(CMAC_DEBUG_HOST_PRINT_ENABLE) && MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE) - /* Trim values are calculated on RF init, so are valid after synced with CMAC */ - console_printf("[CMAC] Calculated trim_val1: 1=0x%08x 2=0x%08x\n", - (unsigned)g_cmac_shared_data->debug.trim_val1_tx_1, - (unsigned)g_cmac_shared_data->debug.trim_val1_tx_2); - console_printf("[CMAC] Calculated trim_val2: tx=0x%08x rx=0x%08x\n", - (unsigned)g_cmac_shared_data->debug.trim_val2_tx, - (unsigned)g_cmac_shared_data->debug.trim_val2_rx); -#endif -} diff --git a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_mbox.c b/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_mbox.c deleted file mode 100644 index d2ee9ac9..00000000 --- a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_mbox.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include -#include -#include -#include -#include "syscfg/syscfg.h" -#include "mcu/mcu.h" -#include "os/os_arch.h" -#include "os/os.h" - -#ifndef min -#define min(_a, _b) ((_a) < (_b) ? (_a) : (_b)) -#endif - -static cmac_mbox_read_cb *g_cmac_mbox_read_cb; -static cmac_mbox_write_notif_cb *g_cmac_mbox_write_notif_cb; - -void -cmac_mbox_set_read_cb(cmac_mbox_read_cb *cb) -{ - g_cmac_mbox_read_cb = cb; -} - -void -cmac_mbox_set_write_notif_cb(cmac_mbox_write_notif_cb *cb) -{ - g_cmac_mbox_write_notif_cb = cb; -} - -int -cmac_mbox_has_data(void) -{ -#if MYNEWT_VAL(BLE_CONTROLLER) - volatile struct cmac_mbox *mbox = &g_cmac_shared_data.mbox_s2c; -#else - volatile struct cmac_mbox *mbox = &g_cmac_shared_data->mbox_c2s; -#endif - - return mbox->rd_off != mbox->wr_off; -} - -int -cmac_mbox_read(void) -{ -#if MYNEWT_VAL(BLE_CONTROLLER) - volatile struct cmac_mbox *mbox = &g_cmac_shared_data.mbox_s2c; - uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data.mbox_s2c_buf; - const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_S2C); -#else - volatile struct cmac_mbox *mbox = &g_cmac_shared_data->mbox_c2s; - uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data->mbox_c2s_buf; - const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_C2S); -#endif - uint16_t rd_off; - uint16_t wr_off; - uint16_t chunk; - int len = 0; - - if (!g_cmac_mbox_read_cb) { - return 0; - } - - do { - rd_off = mbox->rd_off; - wr_off = mbox->wr_off; - - if (rd_off <= wr_off) { - chunk = wr_off - rd_off; - } else { - chunk = mbox_size - rd_off; - } - - while (chunk) { - len = g_cmac_mbox_read_cb(&mbox_buf[rd_off], chunk); - if (len < 0) { - break; - } - - rd_off += len; - chunk -= len; - } - - mbox->rd_off = rd_off == mbox_size ? 0 : rd_off; - } while ((mbox->rd_off != mbox->wr_off) && (len >= 0)); - - return 0; -} - -int -cmac_mbox_write(const void *data, uint16_t len) -{ -#if MYNEWT_VAL(BLE_CONTROLLER) - volatile struct cmac_mbox *mbox = &g_cmac_shared_data.mbox_c2s; - uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data.mbox_c2s_buf; - const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_C2S); -#else - volatile struct cmac_mbox *mbox = &g_cmac_shared_data->mbox_s2c; - uint8_t *mbox_buf = (uint8_t *)&g_cmac_shared_data->mbox_s2c_buf; - const uint16_t mbox_size = MYNEWT_VAL(CMAC_MBOX_SIZE_S2C); -#endif - uint16_t rd_off; - uint16_t wr_off; - uint16_t max_wr; - uint16_t chunk; - - while (len) { - rd_off = mbox->rd_off; - wr_off = mbox->wr_off; - - /* - * Calculate maximum length to write, i.e. up to end of buffer or stop - * before rd_off to be able to detect full queue. - */ - if (rd_off > wr_off) { - /* - * |0|1|2|3|4|5|6|7| - * | | | |W| | |R| | - * `---^ - */ - max_wr = rd_off - wr_off - 1; - } else if (rd_off == 0) { - /* - * |0|1|2|3|4|5|6|7| - * |R| | |W| | | | | - * `-------^ - */ - max_wr = mbox_size - wr_off - 1; - } else { - /* - * |0|1|2|3|4|5|6|7| - * | |R| |W| | | | | - * `---------^ - */ - max_wr = mbox_size - wr_off; - } - - chunk = min(len, max_wr); - - if (chunk == 0) { - continue; - } - - memcpy(&mbox_buf[wr_off], data, chunk); - - wr_off += chunk; - mbox->wr_off = wr_off == mbox_size ? 0 : wr_off; - - g_cmac_mbox_write_notif_cb(); - - len -= chunk; - data = (uint8_t *)data + chunk; - } - - return 0; -} diff --git a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_rand.c b/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_rand.c deleted file mode 100644 index dbb93e92..00000000 --- a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_rand.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include -#include -#include -#include "syscfg/syscfg.h" -#include "mcu/mcu.h" -#include "os/os_arch.h" -#include "os/os.h" - -#if !MYNEWT_VAL(BLE_CONTROLLER) -int -cmac_rand_is_active(void) -{ - return g_cmac_shared_data->rand.cmr_active; -} - -int -cmac_rand_is_full(void) -{ - int next; - bool rc; - - next = cmac_rand_get_next(); - if (next == g_cmac_shared_data->rand.cmr_out) { - rc = 1; - } else { - rc = 0; - } - return rc; -} - -int -cmac_rand_get_next(void) -{ - int next; - - /* If active and not full, put event on queue to get random numbers */ - next = g_cmac_shared_data->rand.cmr_in + 1; - if (next == CMAC_RAND_BUF_ELEMS) { - next = 0; - } - return next; -} - -void -cmac_rand_fill(uint32_t *buf, int num_words) -{ - int next; - - /* XXX: if words is 0, is it possible we could get into a state - where we are waiting for random numbers but M33 does not know it - has to fill any? */ - - /* NOTE: we already know the buffer is not full first time through */ - next = g_cmac_shared_data->rand.cmr_in; - while (num_words) { - g_cmac_shared_data->rand.cmr_buf[next] = buf[0]; - next = cmac_rand_get_next(); - g_cmac_shared_data->rand.cmr_in = next; - next = cmac_rand_get_next(); - if (next == g_cmac_shared_data->rand.cmr_out) { - break; - } - --num_words; - ++buf; - } -} -#endif - -#if MYNEWT_VAL(BLE_CONTROLLER) -static cmac_rand_isr_cb_t g_cmac_rand_isr_cb; - -void -cmac_rand_set_isr_cb(cmac_rand_isr_cb_t cb) -{ - g_cmac_rand_isr_cb = cb; -} - -void -cmac_rand_start(void) -{ - g_cmac_shared_data.rand.cmr_active = 1; -} - -void -cmac_rand_stop(void) -{ - g_cmac_shared_data.rand.cmr_active = 0; -} - -/** - * cmac rnum read - * - * Called during the system to cmac isr to take random numbers - * from shared memory into the BLE stack. - */ -void -cmac_rand_read(void) -{ - uint8_t bytes_left; - uint32_t rnum; - - /* Just leave if no callback. */ - if (g_cmac_rand_isr_cb == NULL) { - return; - } - - bytes_left = 0; - while (g_cmac_shared_data.rand.cmr_active) { - if (bytes_left) { - --bytes_left; - rnum >>= 8; - } else if (g_cmac_shared_data.rand.cmr_out != g_cmac_shared_data.rand.cmr_in) { - bytes_left = 3; - rnum = g_cmac_shared_data.rand.cmr_buf[g_cmac_shared_data.rand.cmr_out]; - ++g_cmac_shared_data.rand.cmr_out; - if (g_cmac_shared_data.rand.cmr_out == CMAC_RAND_BUF_ELEMS) { - g_cmac_shared_data.rand.cmr_out = 0; - } - } else { - break; - } - (*g_cmac_rand_isr_cb)((uint8_t)rnum); - } -} -#endif diff --git a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_shared.c b/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_shared.c deleted file mode 100644 index cd7984af..00000000 --- a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/src/cmac_shared.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_CONTROLLER) && !MYNEWT_VAL(MCU_DEBUG_DSER_CMAC_SHARED) -#define MCU_DIAG_SER_DISABLE -#endif - -#include -#include -#include -#include "mcu/mcu.h" -#include -#include "os/os_arch.h" -#include "os/os.h" - -#ifndef min -#define min(_a, _b) ((_a) < (_b) ? (_a) : (_b)) -#endif - -#if MYNEWT_VAL(BLE_CONTROLLER) -volatile struct cmac_shared_data g_cmac_shared_data __attribute__((section(".shdata"))); -#else -volatile struct cmac_shared_data *g_cmac_shared_data; -#include "mcu/da1469x_clock.h" -#define MCU_DIAG_SER(_x) -#endif - -void -cmac_shared_init(void) -{ -#if !MYNEWT_VAL(BLE_CONTROLLER) - g_cmac_shared_data = (void *)(MCU_MEM_SYSRAM_START_ADDRESS + - MEMCTRL->CMI_SHARED_BASE_REG); - - memset((void *)g_cmac_shared_data, 0, sizeof(*g_cmac_shared_data)); - - g_cmac_shared_data->xtal32m_settle_us = MYNEWT_VAL(MCU_CLOCK_XTAL32M_SETTLE_TIME_US); - - g_cmac_shared_data->dcdc.enabled = DCDC->DCDC_CTRL1_REG & DCDC_DCDC_CTRL1_REG_DCDC_ENABLE_Msk; - if (g_cmac_shared_data->dcdc.enabled) { - g_cmac_shared_data->dcdc.v18 = DCDC->DCDC_V18_REG; - g_cmac_shared_data->dcdc.v18p = DCDC->DCDC_V18P_REG; - g_cmac_shared_data->dcdc.vdd = DCDC->DCDC_VDD_REG; - g_cmac_shared_data->dcdc.v14 = DCDC->DCDC_V14_REG; - g_cmac_shared_data->dcdc.ctrl1 = DCDC->DCDC_CTRL1_REG; - } - -#if MYNEWT_VAL(CMAC_DEBUG_DATA_ENABLE) - g_cmac_shared_data->debug.tx_power_override = INT8_MAX; -#endif -#endif -} - - -void -cmac_shared_sync(void) -{ - /* - * We need to guarantee proper order of initialization here, i.e. SYS has - * to wait until CMAC finished initialization as otherwise host may start - * sending HCI packets which will timeout as there is no one to read them. - */ -#if MYNEWT_VAL(BLE_CONTROLLER) - assert(g_cmac_shared_data.magic_cmac == 0); - - g_cmac_shared_data.magic_cmac = CMAC_SHARED_MAGIC_CMAC; - while (g_cmac_shared_data.magic_sys != CMAC_SHARED_MAGIC_SYS); - - NVIC_SetPriority(SYS2CMAC_IRQn, 3); - NVIC_EnableIRQ(SYS2CMAC_IRQn); -#else - assert(g_cmac_shared_data->magic_sys == 0); - - while (g_cmac_shared_data->magic_cmac != CMAC_SHARED_MAGIC_CMAC); - g_cmac_shared_data->magic_sys = CMAC_SHARED_MAGIC_SYS; - - NVIC_EnableIRQ(CMAC2SYS_IRQn); -#endif -} diff --git a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/syscfg.yml b/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/syscfg.yml deleted file mode 100644 index 6ff3b440..00000000 --- a/lib/bt/host/nimble/nimble/nimble/transport/dialog_cmac/cmac_driver/syscfg.yml +++ /dev/null @@ -1,104 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - CMAC_MBOX_SIZE_S2C: - description: > - Size of mailbox for SYS to CMAC data. The size - value should be power of 2 to allow for better - code optimization. - value: 128 - CMAC_MBOX_SIZE_C2S: - description: > - Size of mailbox for CMAC to SYS data. The size - value should be power of 2 to allow for better - code optimization. - value: 128 - - CMAC_TRIM_SIZE_RFCU: - description: > - Size of trim values for RFCU. This is maximum - number of trim values that can be read from - OTP and applied, all excessive values will be - discarded. - value: 10 - CMAC_TRIM_SIZE_SYNTH: - description: > - Size of trim values for RFCU. This is maximum - number of trim values that can be read from - OTP and applied, all excessive values will be - discarded. - value: 10 - - CMAC_DEBUG_SWD_ENABLE: - description: > - Enable CMAC SWD interface. - value: 0 - CMAC_DEBUG_DIAG_ENABLE: - description: > - Enable CMAC diagnostic lines. - value: 0 - CMAC_DEBUG_DATA_ENABLE: - description: > - Enable extra debugging data in shared segment. - value: 0 - CMAC_DEBUG_COREDUMP_ENABLE: - description: > - Enable dumping CMAC registers to shared segment - on fault. - value: 1 - CMAC_DEBUG_HOST_PRINT_ENABLE: - description: > - Enable some debug printouts to console from host side. - This will dump some settings during startup, useful to - check what is loaded to CMAC via shared data. - value: 0 - - CMAC_IMAGE_SINGLE: - description: > - When enable, CMAC binary is linked with application image - creating a single image build. See CMAC_IMAGE_TARGET_NAME. - When disabled, CMAC binary is built and flashed separately - to flash partition. See CMAC_IMAGE_PARTITION. - value: 1 - CMAC_IMAGE_TARGET_NAME: - description: > - Target name to build for CMAC binary for single image build. - value: "@apache-mynewt-nimble/targets/dialog_cmac" - CMAC_IMAGE_PARTITION: - description: > - Flash partition to load CMAC binary from if single image build - is disabled. - value: FLASH_AREA_IMAGE_1 - CMAC_IMAGE_RAM_SIZE: - description: > - Size of RAM area in bytes reserved for CMAC if single image - build is disabled. Unit suffix (K, M) is allowed. - Note: for single image build this setting is not applicable - since proper RAM area size is automatically calculated from - CMAC binary. - value: 128K - - CMAC_CMAC2SYS_IRQ_PRIORITY: - description: > - The priority of the CMAC2SYS IRQ. Default is 0, or highest - priority. - value: 0 - -syscfg.restrictions.!BLE_CONTROLLER: - - TRNG diff --git a/lib/bt/host/nimble/nimble/nimble/transport/esp_ipc/src/hci_esp_ipc.c b/lib/bt/host/nimble/nimble/nimble/transport/esp_ipc/src/hci_esp_ipc.c new file mode 100644 index 00000000..22f589a2 --- /dev/null +++ b/lib/bt/host/nimble/nimble/nimble/transport/esp_ipc/src/hci_esp_ipc.c @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include +#include +#include "os/os_mbuf.h" +#include "nimble/transport.h" +#include "esp_hci_transport.h" +#include "esp_hci_internal.h" + +static int +ble_transport_dummy_host_recv_cb(hci_trans_pkt_ind_t type, uint8_t *data, uint16_t len) +{ + /* Dummy function */ + return 0; +} + +static int +ble_transport_host_recv_cb(hci_trans_pkt_ind_t type, uint8_t *data, uint16_t len) +{ + int rc; + + if (type == HCI_ACL_IND) { + rc = ble_transport_to_hs_acl((struct os_mbuf *)data); + } else { + rc = ble_transport_to_hs_evt(data); + } + return rc; +} + +int +ble_transport_to_ll_cmd_impl(void *buf) +{ + return hci_transport_host_cmd_tx(buf, 0); +} + +int +ble_transport_to_ll_acl_impl(struct os_mbuf *om) +{ + return hci_transport_host_acl_tx((uint8_t *)om, 0); +} + +void +ble_transport_ll_init(void) +{ + hci_transport_host_callback_register(ble_transport_host_recv_cb); +} + +void +ble_transport_ll_deinit(void) +{ + hci_transport_host_callback_register(ble_transport_dummy_host_recv_cb); +} + +void * +ble_transport_alloc_cmd(void) +{ + return r_ble_hci_trans_buf_alloc(ESP_HCI_INTERNAL_BUF_CMD); +} + +void +ble_transport_free(void *buf) +{ + r_ble_hci_trans_buf_free(buf); +} diff --git a/lib/bt/host/nimble/nimble/nimble/transport/esp_ipc_legacy/src/hci_esp_ipc_legacy.c b/lib/bt/host/nimble/nimble/nimble/transport/esp_ipc_legacy/src/hci_esp_ipc_legacy.c new file mode 100644 index 00000000..323f4d75 --- /dev/null +++ b/lib/bt/host/nimble/nimble/nimble/transport/esp_ipc_legacy/src/hci_esp_ipc_legacy.c @@ -0,0 +1,39 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include +#include +#include "nimble/transport.h" +#include "esp_nimble_hci.h" + +/* This file is only used by ESP32, ESP32C3 and ESP32S3. */ +int +ble_transport_to_ll_cmd_impl(void *buf) +{ + return ble_hci_trans_hs_cmd_tx(buf); +} + +int +ble_transport_to_ll_acl_impl(struct os_mbuf *om) +{ + return ble_hci_trans_hs_acl_tx(om); +} + +void +ble_transport_ll_init(void) +{ + +} + +void +ble_transport_ll_deinit(void) +{ + +} + diff --git a/lib/bt/host/nimble/nimble/nimble/transport/include/nimble/transport.h b/lib/bt/host/nimble/nimble/nimble/transport/include/nimble/transport.h index b4ca3db2..dcdebcc0 100644 --- a/lib/bt/host/nimble/nimble/nimble/transport/include/nimble/transport.h +++ b/lib/bt/host/nimble/nimble/nimble/transport/include/nimble/transport.h @@ -76,154 +76,6 @@ void ble_transport_deinit(void); typedef int ble_hci_trans_rx_cmd_fn(uint8_t *cmd, void *arg); typedef int ble_hci_trans_rx_acl_fn(struct os_mbuf *om, void *arg); -#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED -#define ble_transport_alloc_cmd() ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD) -#define ble_transport_alloc_event(X) ble_hci_trans_buf_alloc(X ? BLE_HCI_TRANS_BUF_EVT_LO : BLE_HCI_TRANS_BUF_EVT_HI) -#define ble_transport_free ble_hci_trans_buf_free - -struct ble_hci_trans_funcs_t { - int(*_ble_hci_trans_hs_acl_tx)(struct os_mbuf *om); - int(*_ble_hci_trans_hs_cmd_tx)(uint8_t *cmd); - int(*_ble_hci_trans_ll_acl_tx)(struct os_mbuf *om); - int(*_ble_hci_trans_ll_evt_tx)(uint8_t *hci_ev); - int(*_ble_hci_trans_reset)(void); - int(*_ble_hci_trans_set_acl_free_cb)(os_mempool_put_fn *cb,void *arg); -}; - -extern struct ble_hci_trans_funcs_t *ble_hci_trans_funcs_ptr; - -/** - * Sends an HCI event from the controller to the host. - * - * @param cmd The HCI event to send. This buffer must be - * allocated via ble_hci_trans_buf_alloc(). - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_ll_evt_tx(uint8_t *hci_ev); -#define ble_hci_trans_ll_evt_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_evt_tx - -/** - * Sends ACL data from controller to host. - * - * @param om The ACL data packet to send. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_ll_acl_tx(struct os_mbuf *om); -#define ble_hci_trans_ll_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_acl_tx - -/** - * Sends an HCI command from the host to the controller. - * - * @param cmd The HCI command to send. This buffer must be - * allocated via ble_hci_trans_buf_alloc(). - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_hs_cmd_tx(uint8_t *cmd); -#define ble_hci_trans_hs_cmd_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_cmd_tx - -/** - * Sends ACL data from host to controller. - * - * @param om The ACL data packet to send. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_hs_acl_tx(struct os_mbuf *om); -#define ble_hci_trans_hs_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_acl_tx - -/** - * Allocates a flat buffer of the specified type. - * - * @param type The type of buffer to allocate; one of the - * BLE_HCI_TRANS_BUF_[...] constants. - * - * @return The allocated buffer on success; - * NULL on buffer exhaustion. - */ -extern uint8_t *r_ble_hci_trans_buf_alloc(int type); -#define ble_hci_trans_buf_alloc r_ble_hci_trans_buf_alloc - -/** - * Frees the specified flat buffer. The buffer must have been allocated via - * ble_hci_trans_buf_alloc(). - * - * @param buf The buffer to free. - */ -extern void r_ble_hci_trans_buf_free(uint8_t *buf); -#define ble_hci_trans_buf_free r_ble_hci_trans_buf_free - -/** - * Configures a callback to get executed whenever an ACL data packet is freed. - * The function is called immediately before the free occurs. - * - * @param cb The callback to configure. - * @param arg An optional argument to pass to the callback. - * - * @return 0 on success; - * BLE_ERR_UNSUPPORTED if the transport does not - * support this operation. - */ -extern int r_ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg); -#define ble_hci_trans_set_acl_free_cb ble_hci_trans_funcs_ptr->_ble_hci_trans_set_acl_free_cb - -/** - * Configures the HCI transport to operate with a controller. The transport - * will execute specified callbacks upon receiving HCI packets from the host. - * - * @param cmd_cb The callback to execute upon receiving an HCI - * command. - * @param cmd_arg Optional argument to pass to the command - * callback. - * @param acl_cb The callback to execute upon receiving ACL - * data. - * @param acl_arg Optional argument to pass to the ACL - * callback. - */ -extern void r_ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb, - void *cmd_arg, - ble_hci_trans_rx_acl_fn *acl_cb, - void *acl_arg); -#define ble_hci_trans_cfg_ll r_ble_hci_trans_cfg_ll - -/** - * Configures the HCI transport to operate with a host. The transport will - * execute specified callbacks upon receiving HCI packets from the controller. - * - * @param evt_cb The callback to execute upon receiving an HCI - * event. - * @param evt_arg Optional argument to pass to the event - * callback. - * @param acl_cb The callback to execute upon receiving ACL - * data. - * @param acl_arg Optional argument to pass to the ACL - * callback. - */ -extern void r_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb, - void *evt_arg, - ble_hci_trans_rx_acl_fn *acl_cb, - void *acl_arg); -#define ble_hci_trans_cfg_hs r_ble_hci_trans_cfg_hs - -/** - * Resets the HCI module to a clean state. Frees all buffers and reinitializes - * the underlying transport. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_reset(void); -#define ble_hci_trans_reset ble_hci_trans_funcs_ptr->_ble_hci_trans_reset - -void esp_ble_hci_trans_init(uint8_t); - -#else /** * Sends an HCI event from the controller to the host. * @@ -332,14 +184,13 @@ void esp_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb, * A BLE_ERR_[...] error code on failure. */ int esp_ble_hci_trans_reset(void); -#endif + struct os_mbuf; /* Initialization */ void ble_transport_init(void); /* Allocators for supported data types */ -#if !SOC_ESP_NIMBLE_CONTROLLER || !CONFIG_BT_CONTROLLER_ENABLED void *ble_transport_alloc_cmd(void); void *ble_transport_alloc_evt(int discardable); struct os_mbuf *ble_transport_alloc_acl_from_hs(void); @@ -349,18 +200,13 @@ struct os_mbuf *ble_transport_alloc_iso_from_ll(void); /* Generic deallocator for cmd/evt buffers */ void ble_transport_free(void *buf); -#endif /* Register put callback on acl_from_ll mbufs (for ll-hs flow control) */ int ble_transport_register_put_acl_from_ll_cb(os_mempool_put_fn *cb); -#if CONFIG_BT_CONTROLLER_ENABLED -#define ble_transport_to_ll_acl ble_hci_trans_hs_acl_tx -#define ble_transport_to_ll_cmd ble_hci_trans_hs_cmd_tx -#else + int ble_transport_to_ll_cmd(void *buf); int ble_transport_to_ll_acl(struct os_mbuf *om); -#endif /* Send data to hs/ll side */ int ble_transport_to_ll_iso(struct os_mbuf *om); diff --git a/lib/bt/host/nimble/nimble/nimble/transport/include/nimble/transport_impl.h b/lib/bt/host/nimble/nimble/nimble/transport/include/nimble/transport_impl.h index d5973378..1faec316 100644 --- a/lib/bt/host/nimble/nimble/nimble/transport/include/nimble/transport_impl.h +++ b/lib/bt/host/nimble/nimble/nimble/transport/include/nimble/transport_impl.h @@ -31,6 +31,8 @@ extern "C" { extern void ble_transport_ll_init(void); extern void ble_transport_hs_init(void); +extern void ble_transport_ll_deinit(void); + /* APIs to be implemented by HS/LL side of transports */ extern int ble_transport_to_ll_cmd_impl(void *buf); extern int ble_transport_to_ll_acl_impl(struct os_mbuf *om); diff --git a/lib/bt/host/nimble/nimble/nimble/transport/nrf5340/syscfg.yml b/lib/bt/host/nimble/nimble/nimble/transport/nrf5340/syscfg.yml deleted file mode 100644 index e8334f2a..00000000 --- a/lib/bt/host/nimble/nimble/nimble/transport/nrf5340/syscfg.yml +++ /dev/null @@ -1,20 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -syscfg.defs: - BLE_TRANSPORT_INT_FLOW_CTL: 1 diff --git a/lib/bt/host/nimble/nimble/nimble/transport/uart_ll/src/hci_uart.c b/lib/bt/host/nimble/nimble/nimble/transport/uart_ll/src/hci_uart.c index 95eae3f4..4cd9de3f 100644 --- a/lib/bt/host/nimble/nimble/nimble/transport/uart_ll/src/hci_uart.c +++ b/lib/bt/host/nimble/nimble/nimble/transport/uart_ll/src/hci_uart.c @@ -243,3 +243,13 @@ ble_transport_ll_init(void) STAILQ_INIT(&tx_q); } + +void +ble_transport_ll_deinit(void) +{ + memset(&hci_uart_h4sm, 0, sizeof(hci_uart_h4sm)); + + hal_uart_close(MYNEWT_VAL(BLE_TRANSPORT_UART_PORT)); + + hal_uart_deinit_cbs(); +} diff --git a/lib/bt/host/nimble/nimble/porting/examples/linux/include/logcfg/logcfg.h b/lib/bt/host/nimble/nimble/porting/examples/linux/include/logcfg/logcfg.h index 89af3530..9872da0b 100644 --- a/lib/bt/host/nimble/nimble/porting/examples/linux/include/logcfg/logcfg.h +++ b/lib/bt/host/nimble/nimble/porting/examples/linux/include/logcfg/logcfg.h @@ -8,6 +8,13 @@ #include "modlog/modlog.h" #include "log_common/log_common.h" +#define BLE_EATT_LOG_DEBUG(...) MODLOG_INFO(__VA_ARGS__) +#define BLE_EATT_LOG_INFO(...) MODLOG_INFO(22, __VA_ARGS__) +#define BLE_EATT_LOG_WARN(...) MODLOG_WARN(22, __VA_ARGS__) +#define BLE_EATT_LOG_ERROR(...) MODLOG_ERROR(22, __VA_ARGS__) +#define BLE_EATT_LOG_CRITICAL(...) MODLOG_CRITICAL(22, __VA_ARGS__) +#define BLE_EATT_LOG_DISABLED(...) MODLOG_DISABLED(22, __VA_ARGS__) + #define BLE_HS_LOG_DEBUG(...) IGNORE(__VA_ARGS__) #define BLE_HS_LOG_INFO(...) MODLOG_INFO(4, __VA_ARGS__) #define BLE_HS_LOG_WARN(...) MODLOG_WARN(4, __VA_ARGS__) diff --git a/lib/bt/host/nimble/nimble/porting/examples/linux/include/syscfg/syscfg.h b/lib/bt/host/nimble/nimble/porting/examples/linux/include/syscfg/syscfg.h index d089d7e6..d825fd01 100644 --- a/lib/bt/host/nimble/nimble/porting/examples/linux/include/syscfg/syscfg.h +++ b/lib/bt/host/nimble/nimble/porting/examples/linux/include/syscfg/syscfg.h @@ -535,6 +535,10 @@ #define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI (MYNEWT_VAL_BLE_ATT_SVR_NOTIFY && (MYNEWT_VAL_BLE_VERSION >= 52)) +#endif + #ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE #define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) #endif @@ -575,6 +579,22 @@ #define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) #endif +#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_LVL +#define MYNEWT_VAL_BLE_EATT_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_MOD +#define MYNEWT_VAL_BLE_EATT_LOG_MOD (27) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_MTU +#define MYNEWT_VAL_BLE_EATT_MTU (128) +#endif + #ifndef MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE #define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) #endif @@ -615,6 +635,10 @@ #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE +#define MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE (1) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif diff --git a/lib/bt/host/nimble/nimble/porting/examples/linux_blemesh/include/logcfg/logcfg.h b/lib/bt/host/nimble/nimble/porting/examples/linux_blemesh/include/logcfg/logcfg.h index 520c658c..99afa084 100644 --- a/lib/bt/host/nimble/nimble/porting/examples/linux_blemesh/include/logcfg/logcfg.h +++ b/lib/bt/host/nimble/nimble/porting/examples/linux_blemesh/include/logcfg/logcfg.h @@ -8,6 +8,13 @@ #include "modlog/modlog.h" #include "log_common/log_common.h" +#define BLE_EATT_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_EATT_LOG_INFO(...) MODLOG_INFO(22, __VA_ARGS__) +#define BLE_EATT_LOG_WARN(...) MODLOG_WARN(22, __VA_ARGS__) +#define BLE_EATT_LOG_ERROR(...) MODLOG_ERROR(22, __VA_ARGS__) +#define BLE_EATT_LOG_CRITICAL(...) MODLOG_CRITICAL(22, __VA_ARGS__) +#define BLE_EATT_LOG_DISABLED(...) MODLOG_DISABLED(22, __VA_ARGS__) + #define BLE_HS_LOG_DEBUG(...) IGNORE(__VA_ARGS__) #define BLE_HS_LOG_INFO(...) MODLOG_INFO(4, __VA_ARGS__) #define BLE_HS_LOG_WARN(...) MODLOG_WARN(4, __VA_ARGS__) diff --git a/lib/bt/host/nimble/nimble/porting/examples/linux_blemesh/include/syscfg/syscfg.h b/lib/bt/host/nimble/nimble/porting/examples/linux_blemesh/include/syscfg/syscfg.h index 1df8abaf..37742846 100644 --- a/lib/bt/host/nimble/nimble/porting/examples/linux_blemesh/include/syscfg/syscfg.h +++ b/lib/bt/host/nimble/nimble/porting/examples/linux_blemesh/include/syscfg/syscfg.h @@ -536,6 +536,10 @@ #define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI (MYNEWT_VAL_BLE_ATT_SVR_NOTIFY && (MYNEWT_VAL_BLE_VERSION >= 52)) +#endif + #ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE #define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) #endif @@ -576,6 +580,22 @@ #define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) #endif +#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_LVL +#define MYNEWT_VAL_BLE_EATT_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_MOD +#define MYNEWT_VAL_BLE_EATT_LOG_MOD (27) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_MTU +#define MYNEWT_VAL_BLE_EATT_MTU (128) +#endif + #ifndef MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE #define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) #endif @@ -616,6 +636,10 @@ #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE +#define MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE (1) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif diff --git a/lib/bt/host/nimble/nimble/porting/examples/nuttx/include/syscfg/syscfg.h b/lib/bt/host/nimble/nimble/porting/examples/nuttx/include/syscfg/syscfg.h index 51f8c44b..a51319c0 100644 --- a/lib/bt/host/nimble/nimble/porting/examples/nuttx/include/syscfg/syscfg.h +++ b/lib/bt/host/nimble/nimble/porting/examples/nuttx/include/syscfg/syscfg.h @@ -615,6 +615,10 @@ #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE +#define MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE (1) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif diff --git a/lib/bt/host/nimble/nimble/porting/nimble/include/hal/hal_uart.h b/lib/bt/host/nimble/nimble/porting/nimble/include/hal/hal_uart.h index 424d296e..8673c776 100644 --- a/lib/bt/host/nimble/nimble/porting/nimble/include/hal/hal_uart.h +++ b/lib/bt/host/nimble/nimble/porting/nimble/include/hal/hal_uart.h @@ -50,6 +50,11 @@ typedef int (*hal_uart_rx_char)(void *arg, uint8_t byte); int hal_uart_init_cbs(int uart, hal_uart_tx_char tx_func, hal_uart_tx_done tx_done, hal_uart_rx_char rx_func, void *arg); +/** + * De Initialize already registerd callbacks + */ +void hal_uart_deinit_cbs(void); + enum hal_uart_parity { /** No Parity */ HAL_UART_PARITY_NONE = 0, diff --git a/lib/bt/host/nimble/nimble/porting/nimble/include/logcfg/logcfg.h b/lib/bt/host/nimble/nimble/porting/nimble/include/logcfg/logcfg.h index f2f227c8..14633c52 100644 --- a/lib/bt/host/nimble/nimble/porting/nimble/include/logcfg/logcfg.h +++ b/lib/bt/host/nimble/nimble/porting/nimble/include/logcfg/logcfg.h @@ -166,4 +166,11 @@ #define DFLT_LOG_CRITICAL(...) MODLOG_CRITICAL(0, __VA_ARGS__) #define DFLT_LOG_DISABLED(...) MODLOG_DISABLED(0, __VA_ARGS__) +#define BLE_EATT_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_EATT_LOG_INFO(...) MODLOG_INFO(22, __VA_ARGS__) +#define BLE_EATT_LOG_WARN(...) MODLOG_WARN(22, __VA_ARGS__) +#define BLE_EATT_LOG_ERROR(...) MODLOG_ERROR(22, __VA_ARGS__) +#define BLE_EATT_LOG_CRITICAL(...) MODLOG_CRITICAL(22, __VA_ARGS__) +#define BLE_EATT_LOG_DISABLED(...) MODLOG_DISABLED(22, __VA_ARGS__) + #endif diff --git a/lib/bt/host/nimble/nimble/porting/nimble/include/os/os.h b/lib/bt/host/nimble/nimble/porting/nimble/include/os/os.h index ec495df9..64800956 100644 --- a/lib/bt/host/nimble/nimble/porting/nimble/include/os/os.h +++ b/lib/bt/host/nimble/nimble/porting/nimble/include/os/os.h @@ -30,14 +30,6 @@ extern "C" { #define static_assert _Static_assert #endif -#ifndef min -#define min(a, b) ((a)<(b)?(a):(b)) -#endif - -#ifndef max -#define max(a, b) ((a)>(b)?(a):(b)) -#endif - #include "syscfg/syscfg.h" #include "nimble/nimble_npl.h" diff --git a/lib/bt/host/nimble/nimble/porting/nimble/include/syscfg/syscfg.h b/lib/bt/host/nimble/nimble/porting/nimble/include/syscfg/syscfg.h index cc8a60b3..158f3846 100644 --- a/lib/bt/host/nimble/nimble/porting/nimble/include/syscfg/syscfg.h +++ b/lib/bt/host/nimble/nimble/porting/nimble/include/syscfg/syscfg.h @@ -538,6 +538,10 @@ #define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI (MYNEWT_VAL_BLE_ATT_SVR_NOTIFY && (MYNEWT_VAL_BLE_VERSION >= 52)) +#endif + #ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE #define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) #endif @@ -578,6 +582,22 @@ #define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) #endif +#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_LVL +#define MYNEWT_VAL_BLE_EATT_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_MOD +#define MYNEWT_VAL_BLE_EATT_LOG_MOD (27) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_MTU +#define MYNEWT_VAL_BLE_EATT_MTU (128) +#endif + #ifndef MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE #define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) #endif @@ -618,6 +638,10 @@ #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE +#define MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE (1) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif diff --git a/lib/bt/host/nimble/nimble/porting/nimble/src/hal_uart.c b/lib/bt/host/nimble/nimble/porting/nimble/src/hal_uart.c index 8a2a957e..89ef558f 100644 --- a/lib/bt/host/nimble/nimble/porting/nimble/src/hal_uart.c +++ b/lib/bt/host/nimble/nimble/porting/nimble/src/hal_uart.c @@ -43,6 +43,14 @@ int hal_uart_init_cbs(int uart_no, hal_uart_tx_char tx_func, return 0; } +void hal_uart_deinit_cbs(void) +{ + hci_uart.tx_char = NULL; + hci_uart.rx_char = NULL; + hci_uart.tx_done = NULL; + hci_uart.u_func_arg = NULL; +} + static void IRAM_ATTR hci_uart_rx_task(void *pvParameters) { uart_event_t event; diff --git a/lib/bt/host/nimble/nimble/porting/nimble/src/nimble_port.c b/lib/bt/host/nimble/nimble/porting/nimble/src/nimble_port.c index 87059f23..224ffde8 100644 --- a/lib/bt/host/nimble/nimble/porting/nimble/src/nimble_port.c +++ b/lib/bt/host/nimble/nimble/porting/nimble/src/nimble_port.c @@ -122,11 +122,10 @@ esp_err_t esp_nimble_init(void) os_msys_init(); #endif + + ble_transport_ll_init(); /* Initialize the host */ ble_transport_hs_init(); -#if CONFIG_BT_CONTROLLER_DISABLED && CONFIG_BT_NIMBLE_TRANSPORT_UART - ble_transport_ll_init(); -#endif return ESP_OK; } @@ -158,6 +157,12 @@ esp_err_t esp_nimble_deinit(void) #if !SOC_ESP_NIMBLE_CONTROLLER || !CONFIG_BT_CONTROLLER_ENABLED npl_freertos_funcs_deinit(); #endif + +#if !SOC_ESP_NIMBLE_CONTROLLER + npl_freertos_mempool_deinit(); +#endif + + ble_transport_ll_deinit(); return ESP_OK; } @@ -213,7 +218,7 @@ nimble_port_init(void) return ret; } -#if (BT_HCI_LOG_INCLUDED == TRUE) +#if MYNEWT_VAL(BT_HCI_LOG_INCLUDED) bt_hci_log_init(); #endif // (BT_HCI_LOG_INCLUDED == TRUE) diff --git a/lib/bt/host/nimble/nimble/porting/nimble/src/os_mbuf.c b/lib/bt/host/nimble/nimble/porting/nimble/src/os_mbuf.c index 8832fd2d..0a94ee40 100644 --- a/lib/bt/host/nimble/nimble/porting/nimble/src/os_mbuf.c +++ b/lib/bt/host/nimble/nimble/porting/nimble/src/os_mbuf.c @@ -35,6 +35,8 @@ #include "os/os.h" #include "os/os_trace_api.h" +#include "modlog/modlog.h" +#include "esp_log.h" #include #include @@ -59,6 +61,7 @@ STAILQ_HEAD(, os_mbuf_pool) g_msys_pool_list = STAILQ_HEAD_INITIALIZER(g_msys_pool_list); +static uint8_t log_count; int os_mqueue_init(struct os_mqueue *mq, ble_npl_event_fn *ev_cb, void *arg) @@ -186,6 +189,12 @@ os_msys_get(uint16_t dsize, uint16_t leadingspace) m = os_mbuf_get(pool, leadingspace); return (m); err: + log_count ++; + if ((log_count % 100) == 0) { + ESP_LOGI("ESP_LOG_INFO","_os_msys_find_pool failed (size %u)\n",dsize); + log_count = 0; + } + return (NULL); } @@ -205,6 +214,11 @@ os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len) m = os_mbuf_get_pkthdr(pool, user_hdr_len); return (m); err: + log_count ++; + if ((log_count % 100) == 0) { + ESP_LOGI("ESP_LOG_INFO","_os_msys_find_pool failed (size %u)\n",dsize); + log_count = 0; + } return (NULL); } diff --git a/lib/bt/host/nimble/nimble/porting/nimble/src/os_mempool.c b/lib/bt/host/nimble/nimble/porting/nimble/src/os_mempool.c index 79630bae..96b2992c 100644 --- a/lib/bt/host/nimble/nimble/porting/nimble/src/os_mempool.c +++ b/lib/bt/host/nimble/nimble/porting/nimble/src/os_mempool.c @@ -24,6 +24,7 @@ #include #include #include "syscfg/syscfg.h" +#include "modlog/modlog.h" #if !MYNEWT_VAL(OS_SYSVIEW_TRACE_MEMPOOL) #define OS_TRACE_DISABLE_FILE_API #endif diff --git a/lib/bt/host/nimble/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h b/lib/bt/host/nimble/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h index 4ac011f8..5bc86acb 100644 --- a/lib/bt/host/nimble/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h +++ b/lib/bt/host/nimble/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h @@ -48,6 +48,7 @@ void nimble_port_freertos_deinit(void); void npl_freertos_funcs_init(void); void npl_freertos_funcs_deinit(void); int npl_freertos_mempool_init(void); +void npl_freertos_mempool_deinit(void); struct npl_funcs_t * npl_freertos_funcs_get(void); #ifdef __cplusplus } diff --git a/lib/bt/host/nimble/nimble/porting/npl/freertos/src/npl_os_freertos.c b/lib/bt/host/nimble/nimble/porting/npl/freertos/src/npl_os_freertos.c index d72f0f6e..0a434e14 100644 --- a/lib/bt/host/nimble/nimble/porting/npl/freertos/src/npl_os_freertos.c +++ b/lib/bt/host/nimble/nimble/porting/npl/freertos/src/npl_os_freertos.c @@ -109,6 +109,17 @@ static const char *TAG = "Timer"; struct os_mempool ble_freertos_ev_pool; static os_membuf_t *ble_freertos_ev_buf = NULL; +#else + +struct os_mempool ble_freertos_ev_pool; +static os_membuf_t ble_freertos_ev_buf[ + OS_MEMPOOL_SIZE(BLE_TOTAL_EV_COUNT, sizeof (struct ble_npl_event_freertos)) +]; + +#endif + +#if CONFIG_BT_CONTROLLER_ENABLED + struct os_mempool ble_freertos_evq_pool; static os_membuf_t *ble_freertos_evq_buf = NULL; @@ -123,11 +134,6 @@ static os_membuf_t *ble_freertos_mutex_buf = NULL; #else -struct os_mempool ble_freertos_ev_pool; -static os_membuf_t ble_freertos_ev_buf[ - OS_MEMPOOL_SIZE(BLE_TOTAL_EV_COUNT, sizeof (struct ble_npl_event_freertos)) -]; - struct os_mempool ble_freertos_evq_pool; static os_membuf_t ble_freertos_evq_buf[ OS_MEMPOOL_SIZE(BLE_TOTAL_EVQ_COUNT, sizeof (struct ble_npl_eventq_freertos)) @@ -1148,6 +1154,9 @@ int npl_freertos_mempool_init(void) if(!ble_freertos_ev_buf) { goto _error; } +#endif + +#if CONFIG_BT_CONTROLLER_ENABLED ble_freertos_evq_buf = malloc(OS_MEMPOOL_SIZE(BLE_TOTAL_EVQ_COUNT, sizeof (struct ble_npl_eventq_freertos)) * sizeof(os_membuf_t)); if(!ble_freertos_evq_buf) { goto _error; @@ -1203,11 +1212,7 @@ int npl_freertos_mempool_init(void) } _error: -#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED - if(ble_freertos_ev_buf) { - free(ble_freertos_ev_buf); - ble_freertos_ev_buf = NULL; - } +#if CONFIG_BT_CONTROLLER_ENABLED if(ble_freertos_evq_buf) { free(ble_freertos_evq_buf); ble_freertos_evq_buf = NULL; @@ -1224,12 +1229,18 @@ _error: free(ble_freertos_mutex_buf); ble_freertos_mutex_buf = NULL; } +#endif + +#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED + if(ble_freertos_ev_buf) { + free(ble_freertos_ev_buf); + ble_freertos_ev_buf = NULL; + } return -1; -#else +#endif BLE_LL_ASSERT(rc == 0); return rc; -#endif } void npl_freertos_mempool_deinit(void) @@ -1239,6 +1250,9 @@ void npl_freertos_mempool_deinit(void) free(ble_freertos_ev_buf); ble_freertos_ev_buf = NULL; } +#endif + +#if CONFIG_BT_CONTROLLER_ENABLED if(ble_freertos_evq_buf) { free(ble_freertos_evq_buf); ble_freertos_evq_buf = NULL; diff --git a/lib/bt/host/nimble/nimble/porting/npl/riot/include/logcfg/logcfg.h b/lib/bt/host/nimble/nimble/porting/npl/riot/include/logcfg/logcfg.h index 89af3530..4fe2ee01 100644 --- a/lib/bt/host/nimble/nimble/porting/npl/riot/include/logcfg/logcfg.h +++ b/lib/bt/host/nimble/nimble/porting/npl/riot/include/logcfg/logcfg.h @@ -8,6 +8,13 @@ #include "modlog/modlog.h" #include "log_common/log_common.h" +#define BLE_EATT_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_EATT_LOG_INFO(...) MODLOG_INFO(22, __VA_ARGS__) +#define BLE_EATT_LOG_WARN(...) MODLOG_WARN(22, __VA_ARGS__) +#define BLE_EATT_LOG_ERROR(...) MODLOG_ERROR(22, __VA_ARGS__) +#define BLE_EATT_LOG_CRITICAL(...) MODLOG_CRITICAL(22, __VA_ARGS__) +#define BLE_EATT_LOG_DISABLED(...) MODLOG_DISABLED(22, __VA_ARGS__) + #define BLE_HS_LOG_DEBUG(...) IGNORE(__VA_ARGS__) #define BLE_HS_LOG_INFO(...) MODLOG_INFO(4, __VA_ARGS__) #define BLE_HS_LOG_WARN(...) MODLOG_WARN(4, __VA_ARGS__) diff --git a/lib/bt/host/nimble/nimble/porting/npl/riot/include/npl_syscfg/npl_sycfg.h b/lib/bt/host/nimble/nimble/porting/npl/riot/include/npl_syscfg/npl_sycfg.h deleted file mode 120000 index 53c55a90..00000000 --- a/lib/bt/host/nimble/nimble/porting/npl/riot/include/npl_syscfg/npl_sycfg.h +++ /dev/null @@ -1 +0,0 @@ -../syscfg/syscfg.h \ No newline at end of file diff --git a/lib/bt/host/nimble/nimble/porting/npl/riot/include/npl_syscfg/npl_sycfg.h b/lib/bt/host/nimble/nimble/porting/npl/riot/include/npl_syscfg/npl_sycfg.h new file mode 100644 index 00000000..a52b22c5 --- /dev/null +++ b/lib/bt/host/nimble/nimble/porting/npl/riot/include/npl_syscfg/npl_sycfg.h @@ -0,0 +1,1990 @@ +/** + * This file was generated by Apache newt version: 1.11.0-dev + */ + +#ifndef H_MYNEWT_SYSCFG_ +#define H_MYNEWT_SYSCFG_ + +/** + * This macro exists to ensure code includes this header when needed. If code + * checks the existence of a setting directly via ifdef without including this + * header, the setting macro will silently evaluate to 0. In contrast, an + * attempt to use these macros without including this header will result in a + * compiler error. + */ +#define MYNEWT_VAL(_name) MYNEWT_VAL_ ## _name +#define MYNEWT_VAL_CHOICE(_name, _val) MYNEWT_VAL_ ## _name ## __ ## _val + +#ifndef MYNEWT_VAL_HARDFLOAT +#define MYNEWT_VAL_HARDFLOAT (0) +#endif + +/*** @apache-mynewt-core/crypto/tinycrypt */ +#ifndef MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE +#define MYNEWT_VAL_TINYCRYPT_SYSINIT_STAGE (200) +#endif + +#ifndef MYNEWT_VAL_TINYCRYPT_UECC_RNG_TRNG_DEV_NAME +#define MYNEWT_VAL_TINYCRYPT_UECC_RNG_TRNG_DEV_NAME "trng" +#endif + +#ifndef MYNEWT_VAL_TINYCRYPT_UECC_RNG_USE_TRNG +#define MYNEWT_VAL_TINYCRYPT_UECC_RNG_USE_TRNG (0) +#endif + +/*** @apache-mynewt-core/hw/bsp/nordic_pca10056 */ +#ifndef MYNEWT_VAL_BSP_NRF52840 +#define MYNEWT_VAL_BSP_NRF52840 (1) +#endif + +#ifndef MYNEWT_VAL_SOFT_PWM +#define MYNEWT_VAL_SOFT_PWM (0) +#endif + +/*** @apache-mynewt-core/hw/hal */ +#ifndef MYNEWT_VAL_HAL_ENABLE_SOFTWARE_BREAKPOINTS +#define MYNEWT_VAL_HAL_ENABLE_SOFTWARE_BREAKPOINTS (1) +#endif + +#ifndef MYNEWT_VAL_HAL_FLASH_MAX_DEVICE_COUNT +#define MYNEWT_VAL_HAL_FLASH_MAX_DEVICE_COUNT (0) +#endif + +#ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ +#define MYNEWT_VAL_HAL_FLASH_VERIFY_BUF_SZ (16) +#endif + +#ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_ERASES +#define MYNEWT_VAL_HAL_FLASH_VERIFY_ERASES (0) +#endif + +#ifndef MYNEWT_VAL_HAL_FLASH_VERIFY_WRITES +#define MYNEWT_VAL_HAL_FLASH_VERIFY_WRITES (0) +#endif + +#ifndef MYNEWT_VAL_HAL_SBRK +#define MYNEWT_VAL_HAL_SBRK (1) +#endif + +#ifndef MYNEWT_VAL_HAL_SYSTEM_RESET_CB +#define MYNEWT_VAL_HAL_SYSTEM_RESET_CB (0) +#endif + +/*** @apache-mynewt-core/hw/mcu/nordic/nrf52xxx */ +#ifndef MYNEWT_VAL_ADC_0 +#define MYNEWT_VAL_ADC_0 (0) +#endif + +#ifndef MYNEWT_VAL_ADC_0_REFMV_0 +#define MYNEWT_VAL_ADC_0_REFMV_0 (0) +#endif + +#ifndef MYNEWT_VAL_CRYPTO +#define MYNEWT_VAL_CRYPTO (0) +#endif + +#ifndef MYNEWT_VAL_GPIO_AS_PIN_RESET +#define MYNEWT_VAL_GPIO_AS_PIN_RESET (0) +#endif + +#ifndef MYNEWT_VAL_I2C_0 +#define MYNEWT_VAL_I2C_0 (0) +#endif + +#ifndef MYNEWT_VAL_I2C_0_FREQ_KHZ +#define MYNEWT_VAL_I2C_0_FREQ_KHZ (100) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_I2C_0_PIN_SCL +#define MYNEWT_VAL_I2C_0_PIN_SCL (27) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_I2C_0_PIN_SDA +#define MYNEWT_VAL_I2C_0_PIN_SDA (26) +#endif + +#ifndef MYNEWT_VAL_I2C_1 +#define MYNEWT_VAL_I2C_1 (0) +#endif + +#ifndef MYNEWT_VAL_I2C_1_FREQ_KHZ +#define MYNEWT_VAL_I2C_1_FREQ_KHZ (100) +#endif + +#undef MYNEWT_VAL_I2C_1_PIN_SCL + +#undef MYNEWT_VAL_I2C_1_PIN_SDA + +#ifndef MYNEWT_VAL_MCU_BUS_DRIVER_I2C_USE_TWIM +#define MYNEWT_VAL_MCU_BUS_DRIVER_I2C_USE_TWIM (0) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_MCU_COMMON_STARTUP +#define MYNEWT_VAL_MCU_COMMON_STARTUP (1) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_MCU_DCDC_ENABLED +#define MYNEWT_VAL_MCU_DCDC_ENABLED (1) +#endif + +#ifndef MYNEWT_VAL_MCU_DEBUG_IGNORE_BKPT +#define MYNEWT_VAL_MCU_DEBUG_IGNORE_BKPT (0) +#endif + +#ifndef MYNEWT_VAL_MCU_FLASH_MIN_WRITE_SIZE +#define MYNEWT_VAL_MCU_FLASH_MIN_WRITE_SIZE (1) +#endif + +#ifndef MYNEWT_VAL_MCU_GPIO_USE_PORT_EVENT +#define MYNEWT_VAL_MCU_GPIO_USE_PORT_EVENT (0) +#endif + +#ifndef MYNEWT_VAL_MCU_HFCLK_SOURCE__HFINT +#define MYNEWT_VAL_MCU_HFCLK_SOURCE__HFINT (0) +#endif +#ifndef MYNEWT_VAL_MCU_HFCLK_SOURCE__HFXO +#define MYNEWT_VAL_MCU_HFCLK_SOURCE__HFXO (1) +#endif +#ifndef MYNEWT_VAL_MCU_HFCLK_SOURCE +#define MYNEWT_VAL_MCU_HFCLK_SOURCE (1) +#endif + +#ifndef MYNEWT_VAL_MCU_I2C_RECOVERY_DELAY_USEC +#define MYNEWT_VAL_MCU_I2C_RECOVERY_DELAY_USEC (100) +#endif + +#ifndef MYNEWT_VAL_MCU_ICACHE_ENABLED +#define MYNEWT_VAL_MCU_ICACHE_ENABLED (1) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_MCU_LFCLK_SOURCE__LFRC +#define MYNEWT_VAL_MCU_LFCLK_SOURCE__LFRC (0) +#endif +#ifndef MYNEWT_VAL_MCU_LFCLK_SOURCE__LFSYNTH +#define MYNEWT_VAL_MCU_LFCLK_SOURCE__LFSYNTH (0) +#endif +#ifndef MYNEWT_VAL_MCU_LFCLK_SOURCE__LFXO +#define MYNEWT_VAL_MCU_LFCLK_SOURCE__LFXO (1) +#endif +#ifndef MYNEWT_VAL_MCU_LFCLK_SOURCE +#define MYNEWT_VAL_MCU_LFCLK_SOURCE (1) +#endif + +#ifndef MYNEWT_VAL_MCU_NRF52832 +#define MYNEWT_VAL_MCU_NRF52832 (0) +#endif + +#ifndef MYNEWT_VAL_MCU_NRF52840 +#define MYNEWT_VAL_MCU_NRF52840 (0) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_MCU_TARGET__nRF52810 +#define MYNEWT_VAL_MCU_TARGET__nRF52810 (0) +#endif +#ifndef MYNEWT_VAL_MCU_TARGET__nRF52811 +#define MYNEWT_VAL_MCU_TARGET__nRF52811 (0) +#endif +#ifndef MYNEWT_VAL_MCU_TARGET__nRF52832 +#define MYNEWT_VAL_MCU_TARGET__nRF52832 (0) +#endif +#ifndef MYNEWT_VAL_MCU_TARGET__nRF52840 +#define MYNEWT_VAL_MCU_TARGET__nRF52840 (1) +#endif +#ifndef MYNEWT_VAL_MCU_TARGET +#define MYNEWT_VAL_MCU_TARGET (1) +#endif + +#ifndef MYNEWT_VAL_NFC_PINS_AS_GPIO +#define MYNEWT_VAL_NFC_PINS_AS_GPIO (1) +#endif + +#ifndef MYNEWT_VAL_PWM_0 +#define MYNEWT_VAL_PWM_0 (0) +#endif + +#ifndef MYNEWT_VAL_PWM_1 +#define MYNEWT_VAL_PWM_1 (0) +#endif + +#ifndef MYNEWT_VAL_PWM_2 +#define MYNEWT_VAL_PWM_2 (0) +#endif + +#ifndef MYNEWT_VAL_PWM_3 +#define MYNEWT_VAL_PWM_3 (0) +#endif + +#ifndef MYNEWT_VAL_QSPI_ADDRMODE +#define MYNEWT_VAL_QSPI_ADDRMODE (0) +#endif + +#ifndef MYNEWT_VAL_QSPI_DPMCONFIG +#define MYNEWT_VAL_QSPI_DPMCONFIG (0) +#endif + +#ifndef MYNEWT_VAL_QSPI_ENABLE +#define MYNEWT_VAL_QSPI_ENABLE (0) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_QSPI_FLASH_PAGE_SIZE +#define MYNEWT_VAL_QSPI_FLASH_PAGE_SIZE (256) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_QSPI_FLASH_SECTOR_COUNT +#define MYNEWT_VAL_QSPI_FLASH_SECTOR_COUNT (4096) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_QSPI_FLASH_SECTOR_SIZE +#define MYNEWT_VAL_QSPI_FLASH_SECTOR_SIZE (4096) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_QSPI_PIN_CS +#define MYNEWT_VAL_QSPI_PIN_CS (17) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_QSPI_PIN_DIO0 +#define MYNEWT_VAL_QSPI_PIN_DIO0 (20) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_QSPI_PIN_DIO1 +#define MYNEWT_VAL_QSPI_PIN_DIO1 (21) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_QSPI_PIN_DIO2 +#define MYNEWT_VAL_QSPI_PIN_DIO2 (22) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_QSPI_PIN_DIO3 +#define MYNEWT_VAL_QSPI_PIN_DIO3 (23) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_QSPI_PIN_SCK +#define MYNEWT_VAL_QSPI_PIN_SCK (19) +#endif + +#ifndef MYNEWT_VAL_QSPI_READOC +#define MYNEWT_VAL_QSPI_READOC (0) +#endif + +#ifndef MYNEWT_VAL_QSPI_SCK_DELAY +#define MYNEWT_VAL_QSPI_SCK_DELAY (0) +#endif + +#ifndef MYNEWT_VAL_QSPI_SCK_FREQ +#define MYNEWT_VAL_QSPI_SCK_FREQ (0) +#endif + +#ifndef MYNEWT_VAL_QSPI_SPI_MODE +#define MYNEWT_VAL_QSPI_SPI_MODE (0) +#endif + +#ifndef MYNEWT_VAL_QSPI_WRITEOC +#define MYNEWT_VAL_QSPI_WRITEOC (0) +#endif + +#ifndef MYNEWT_VAL_SPI_0_MASTER +#define MYNEWT_VAL_SPI_0_MASTER (0) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_SPI_0_MASTER_PIN_MISO +#define MYNEWT_VAL_SPI_0_MASTER_PIN_MISO (47) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_SPI_0_MASTER_PIN_MOSI +#define MYNEWT_VAL_SPI_0_MASTER_PIN_MOSI (46) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_SPI_0_MASTER_PIN_SCK +#define MYNEWT_VAL_SPI_0_MASTER_PIN_SCK (45) +#endif + +#ifndef MYNEWT_VAL_SPI_0_SLAVE +#define MYNEWT_VAL_SPI_0_SLAVE (0) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_SPI_0_SLAVE_PIN_MISO +#define MYNEWT_VAL_SPI_0_SLAVE_PIN_MISO (47) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_SPI_0_SLAVE_PIN_MOSI +#define MYNEWT_VAL_SPI_0_SLAVE_PIN_MOSI (46) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_SPI_0_SLAVE_PIN_SCK +#define MYNEWT_VAL_SPI_0_SLAVE_PIN_SCK (45) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_SPI_0_SLAVE_PIN_SS +#define MYNEWT_VAL_SPI_0_SLAVE_PIN_SS (44) +#endif + +#ifndef MYNEWT_VAL_SPI_1_MASTER +#define MYNEWT_VAL_SPI_1_MASTER (0) +#endif + +#undef MYNEWT_VAL_SPI_1_MASTER_PIN_MISO + +#undef MYNEWT_VAL_SPI_1_MASTER_PIN_MOSI + +#undef MYNEWT_VAL_SPI_1_MASTER_PIN_SCK + +#ifndef MYNEWT_VAL_SPI_1_SLAVE +#define MYNEWT_VAL_SPI_1_SLAVE (0) +#endif + +#undef MYNEWT_VAL_SPI_1_SLAVE_PIN_MISO + +#undef MYNEWT_VAL_SPI_1_SLAVE_PIN_MOSI + +#undef MYNEWT_VAL_SPI_1_SLAVE_PIN_SCK + +#undef MYNEWT_VAL_SPI_1_SLAVE_PIN_SS + +#ifndef MYNEWT_VAL_SPI_2_MASTER +#define MYNEWT_VAL_SPI_2_MASTER (0) +#endif + +#undef MYNEWT_VAL_SPI_2_MASTER_PIN_MISO + +#undef MYNEWT_VAL_SPI_2_MASTER_PIN_MOSI + +#undef MYNEWT_VAL_SPI_2_MASTER_PIN_SCK + +#ifndef MYNEWT_VAL_SPI_2_SLAVE +#define MYNEWT_VAL_SPI_2_SLAVE (0) +#endif + +#undef MYNEWT_VAL_SPI_2_SLAVE_PIN_MISO + +#undef MYNEWT_VAL_SPI_2_SLAVE_PIN_MOSI + +#undef MYNEWT_VAL_SPI_2_SLAVE_PIN_SCK + +#undef MYNEWT_VAL_SPI_2_SLAVE_PIN_SS + +#ifndef MYNEWT_VAL_SPI_3_MASTER +#define MYNEWT_VAL_SPI_3_MASTER (0) +#endif + +#undef MYNEWT_VAL_SPI_3_MASTER_PIN_MISO + +#undef MYNEWT_VAL_SPI_3_MASTER_PIN_MOSI + +#undef MYNEWT_VAL_SPI_3_MASTER_PIN_SCK + +#ifndef MYNEWT_VAL_TEMP +#define MYNEWT_VAL_TEMP (0) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_TIMER_0 +#define MYNEWT_VAL_TIMER_0 (0) +#endif + +#ifndef MYNEWT_VAL_TIMER_1 +#define MYNEWT_VAL_TIMER_1 (0) +#endif + +#ifndef MYNEWT_VAL_TIMER_2 +#define MYNEWT_VAL_TIMER_2 (0) +#endif + +#ifndef MYNEWT_VAL_TIMER_3 +#define MYNEWT_VAL_TIMER_3 (0) +#endif + +#ifndef MYNEWT_VAL_TIMER_4 +#define MYNEWT_VAL_TIMER_4 (0) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_TIMER_5 +#define MYNEWT_VAL_TIMER_5 (1) +#endif + +#ifndef MYNEWT_VAL_TRNG +#define MYNEWT_VAL_TRNG (0) +#endif + +#ifndef MYNEWT_VAL_UART_0 +#define MYNEWT_VAL_UART_0 (1) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_UART_0_PIN_CTS +#define MYNEWT_VAL_UART_0_PIN_CTS (7) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_UART_0_PIN_RTS +#define MYNEWT_VAL_UART_0_PIN_RTS (5) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_UART_0_PIN_RX +#define MYNEWT_VAL_UART_0_PIN_RX (8) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx) */ +#ifndef MYNEWT_VAL_UART_0_PIN_TX +#define MYNEWT_VAL_UART_0_PIN_TX (6) +#endif + +#ifndef MYNEWT_VAL_UART_1 +#define MYNEWT_VAL_UART_1 (0) +#endif + +#ifndef MYNEWT_VAL_UART_1_PIN_CTS +#define MYNEWT_VAL_UART_1_PIN_CTS (-1) +#endif + +#ifndef MYNEWT_VAL_UART_1_PIN_RTS +#define MYNEWT_VAL_UART_1_PIN_RTS (-1) +#endif + +#undef MYNEWT_VAL_UART_1_PIN_RX + +#undef MYNEWT_VAL_UART_1_PIN_TX + +#ifndef MYNEWT_VAL_XTAL_32768 +#define MYNEWT_VAL_XTAL_32768 (0) +#endif + +#ifndef MYNEWT_VAL_XTAL_32768_SYNTH +#define MYNEWT_VAL_XTAL_32768_SYNTH (0) +#endif + +#ifndef MYNEWT_VAL_XTAL_RC +#define MYNEWT_VAL_XTAL_RC (0) +#endif + +/*** @apache-mynewt-core/kernel/os */ +#ifndef MYNEWT_VAL_FLOAT_USER +#define MYNEWT_VAL_FLOAT_USER (0) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-core/kernel/os) */ +#ifndef MYNEWT_VAL_MSYS_1_BLOCK_COUNT +#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (5) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-core/kernel/os) */ +#ifndef MYNEWT_VAL_MSYS_1_BLOCK_SIZE +#define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (88) +#endif + +#ifndef MYNEWT_VAL_MSYS_1_SANITY_MIN_COUNT +#define MYNEWT_VAL_MSYS_1_SANITY_MIN_COUNT (0) +#endif + +#ifndef MYNEWT_VAL_MSYS_2_BLOCK_COUNT +#define MYNEWT_VAL_MSYS_2_BLOCK_COUNT (0) +#endif + +#ifndef MYNEWT_VAL_MSYS_2_BLOCK_SIZE +#define MYNEWT_VAL_MSYS_2_BLOCK_SIZE (0) +#endif + +#ifndef MYNEWT_VAL_MSYS_2_SANITY_MIN_COUNT +#define MYNEWT_VAL_MSYS_2_SANITY_MIN_COUNT (0) +#endif + +#ifndef MYNEWT_VAL_MSYS_SANITY_TIMEOUT +#define MYNEWT_VAL_MSYS_SANITY_TIMEOUT (60000) +#endif + +#ifndef MYNEWT_VAL_OS_ASSERT_CB +#define MYNEWT_VAL_OS_ASSERT_CB (0) +#endif + +#ifndef MYNEWT_VAL_OS_CLI +#define MYNEWT_VAL_OS_CLI (0) +#endif + +#ifndef MYNEWT_VAL_OS_COREDUMP +#define MYNEWT_VAL_OS_COREDUMP (0) +#endif + +#ifndef MYNEWT_VAL_OS_COREDUMP_CB +#define MYNEWT_VAL_OS_COREDUMP_CB (0) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/kernel/os) */ +#ifndef MYNEWT_VAL_OS_CPUTIME_FREQ +#define MYNEWT_VAL_OS_CPUTIME_FREQ (32768) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-core/kernel/os) */ +#ifndef MYNEWT_VAL_OS_CPUTIME_TIMER_NUM +#define MYNEWT_VAL_OS_CPUTIME_TIMER_NUM (5) +#endif + +#ifndef MYNEWT_VAL_OS_CRASH_FILE_LINE +#define MYNEWT_VAL_OS_CRASH_FILE_LINE (0) +#endif + +#ifndef MYNEWT_VAL_OS_CRASH_LOG +#define MYNEWT_VAL_OS_CRASH_LOG (0) +#endif + +#ifndef MYNEWT_VAL_OS_CRASH_RESTORE_REGS +#define MYNEWT_VAL_OS_CRASH_RESTORE_REGS (0) +#endif + +#ifndef MYNEWT_VAL_OS_CRASH_STACKTRACE +#define MYNEWT_VAL_OS_CRASH_STACKTRACE (0) +#endif + +#ifndef MYNEWT_VAL_OS_CTX_SW_STACK_CHECK +#define MYNEWT_VAL_OS_CTX_SW_STACK_CHECK (0) +#endif + +#ifndef MYNEWT_VAL_OS_CTX_SW_STACK_GUARD +#define MYNEWT_VAL_OS_CTX_SW_STACK_GUARD (4) +#endif + +#ifndef MYNEWT_VAL_OS_DEBUG_MODE +#define MYNEWT_VAL_OS_DEBUG_MODE (0) +#endif + +#ifndef MYNEWT_VAL_OS_EVENTQ_DEBUG +#define MYNEWT_VAL_OS_EVENTQ_DEBUG (0) +#endif + +#ifndef MYNEWT_VAL_OS_EVENTQ_MONITOR +#define MYNEWT_VAL_OS_EVENTQ_MONITOR (0) +#endif + +#ifndef MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MAX +#define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MAX (600000) +#endif + +#ifndef MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN +#define MYNEWT_VAL_OS_IDLE_TICKLESS_MS_MIN (100) +#endif + +#ifndef MYNEWT_VAL_OS_MAIN_STACK_SIZE +#define MYNEWT_VAL_OS_MAIN_STACK_SIZE (1024) +#endif + +#ifndef MYNEWT_VAL_OS_MAIN_TASK_PRIO +#define MYNEWT_VAL_OS_MAIN_TASK_PRIO (127) +#endif + +#ifndef MYNEWT_VAL_OS_MAIN_TASK_SANITY_ITVL_MS +#define MYNEWT_VAL_OS_MAIN_TASK_SANITY_ITVL_MS (0) +#endif + +#ifndef MYNEWT_VAL_OS_MEMPOOL_CHECK +#define MYNEWT_VAL_OS_MEMPOOL_CHECK (0) +#endif + +#ifndef MYNEWT_VAL_OS_MEMPOOL_GUARD +#define MYNEWT_VAL_OS_MEMPOOL_GUARD (0) +#endif + +#ifndef MYNEWT_VAL_OS_MEMPOOL_POISON +#define MYNEWT_VAL_OS_MEMPOOL_POISON (0) +#endif + +#ifndef MYNEWT_VAL_OS_SCHEDULING +#define MYNEWT_VAL_OS_SCHEDULING (1) +#endif + +#ifndef MYNEWT_VAL_OS_SYSINIT_STAGE +#define MYNEWT_VAL_OS_SYSINIT_STAGE (0) +#endif + +#ifndef MYNEWT_VAL_OS_SYSVIEW +#define MYNEWT_VAL_OS_SYSVIEW (0) +#endif + +#ifndef MYNEWT_VAL_OS_SYSVIEW_TRACE_CALLOUT +#define MYNEWT_VAL_OS_SYSVIEW_TRACE_CALLOUT (1) +#endif + +#ifndef MYNEWT_VAL_OS_SYSVIEW_TRACE_EVENTQ +#define MYNEWT_VAL_OS_SYSVIEW_TRACE_EVENTQ (1) +#endif + +#ifndef MYNEWT_VAL_OS_SYSVIEW_TRACE_MBUF +#define MYNEWT_VAL_OS_SYSVIEW_TRACE_MBUF (0) +#endif + +#ifndef MYNEWT_VAL_OS_SYSVIEW_TRACE_MEMPOOL +#define MYNEWT_VAL_OS_SYSVIEW_TRACE_MEMPOOL (0) +#endif + +#ifndef MYNEWT_VAL_OS_SYSVIEW_TRACE_MUTEX +#define MYNEWT_VAL_OS_SYSVIEW_TRACE_MUTEX (1) +#endif + +#ifndef MYNEWT_VAL_OS_SYSVIEW_TRACE_SEM +#define MYNEWT_VAL_OS_SYSVIEW_TRACE_SEM (1) +#endif + +#ifndef MYNEWT_VAL_OS_TASK_RUN_TIME_CPUTIME +#define MYNEWT_VAL_OS_TASK_RUN_TIME_CPUTIME (0) +#endif + +/* Overridden by @apache-mynewt-core/hw/mcu/nordic/nrf52xxx (defined by @apache-mynewt-core/kernel/os) */ +#ifndef MYNEWT_VAL_OS_TICKS_PER_SEC +#define MYNEWT_VAL_OS_TICKS_PER_SEC (128) +#endif + +#ifndef MYNEWT_VAL_OS_TIME_DEBUG +#define MYNEWT_VAL_OS_TIME_DEBUG (0) +#endif + +#ifndef MYNEWT_VAL_OS_WATCHDOG_MONITOR +#define MYNEWT_VAL_OS_WATCHDOG_MONITOR (0) +#endif + +#ifndef MYNEWT_VAL_SANITY_INTERVAL +#define MYNEWT_VAL_SANITY_INTERVAL (15000) +#endif + +#ifndef MYNEWT_VAL_WATCHDOG_INTERVAL +#define MYNEWT_VAL_WATCHDOG_INTERVAL (30000) +#endif + +/*** @apache-mynewt-core/libc/baselibc */ +#ifndef MYNEWT_VAL_BASELIBC_ASSERT_FILE_LINE +#define MYNEWT_VAL_BASELIBC_ASSERT_FILE_LINE (0) +#endif + +#ifndef MYNEWT_VAL_BASELIBC_EXECUTE_GLOBAL_CONSTRUCTORS +#define MYNEWT_VAL_BASELIBC_EXECUTE_GLOBAL_CONSTRUCTORS (1) +#endif + +#ifndef MYNEWT_VAL_BASELIBC_PRESENT +#define MYNEWT_VAL_BASELIBC_PRESENT (1) +#endif + +#ifndef MYNEWT_VAL_BASELIBC_THREAD_SAFE_HEAP_ALLOCATION +#define MYNEWT_VAL_BASELIBC_THREAD_SAFE_HEAP_ALLOCATION (0) +#endif + +/*** @apache-mynewt-core/sys/console/stub */ +#ifndef MYNEWT_VAL_CONSOLE_UART_BAUD +#define MYNEWT_VAL_CONSOLE_UART_BAUD (115200) +#endif + +#ifndef MYNEWT_VAL_CONSOLE_UART_DEV +#define MYNEWT_VAL_CONSOLE_UART_DEV "uart0" +#endif + +#ifndef MYNEWT_VAL_CONSOLE_UART_FLOW_CONTROL +#define MYNEWT_VAL_CONSOLE_UART_FLOW_CONTROL (UART_FLOW_CTL_NONE) +#endif + +/*** @apache-mynewt-core/sys/flash_map */ +#ifndef MYNEWT_VAL_FLASH_MAP_MAX_AREAS +#define MYNEWT_VAL_FLASH_MAP_MAX_AREAS (10) +#endif + +#ifndef MYNEWT_VAL_FLASH_MAP_SUPPORT_MFG +#define MYNEWT_VAL_FLASH_MAP_SUPPORT_MFG (0) +#endif + +#ifndef MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE +#define MYNEWT_VAL_FLASH_MAP_SYSINIT_STAGE (9) +#endif + +/*** @apache-mynewt-core/sys/log/common */ +#ifndef MYNEWT_VAL_DFLT_LOG_LVL +#define MYNEWT_VAL_DFLT_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_DFLT_LOG_MOD +#define MYNEWT_VAL_DFLT_LOG_MOD (0) +#endif + +#ifndef MYNEWT_VAL_LOG_GLOBAL_IDX +#define MYNEWT_VAL_LOG_GLOBAL_IDX (1) +#endif + +/*** @apache-mynewt-core/sys/log/modlog */ +#ifndef MYNEWT_VAL_MODLOG_CONSOLE_DFLT +#define MYNEWT_VAL_MODLOG_CONSOLE_DFLT (1) +#endif + +#ifndef MYNEWT_VAL_MODLOG_LOG_MACROS +#define MYNEWT_VAL_MODLOG_LOG_MACROS (0) +#endif + +#ifndef MYNEWT_VAL_MODLOG_MAX_MAPPINGS +#define MYNEWT_VAL_MODLOG_MAX_MAPPINGS (16) +#endif + +#ifndef MYNEWT_VAL_MODLOG_MAX_PRINTF_LEN +#define MYNEWT_VAL_MODLOG_MAX_PRINTF_LEN (128) +#endif + +#ifndef MYNEWT_VAL_MODLOG_SYSINIT_STAGE +#define MYNEWT_VAL_MODLOG_SYSINIT_STAGE (100) +#endif + +/*** @apache-mynewt-core/sys/log/stub */ +#ifndef MYNEWT_VAL_LOG_CONSOLE +#define MYNEWT_VAL_LOG_CONSOLE (1) +#endif + +#ifndef MYNEWT_VAL_LOG_FCB +#define MYNEWT_VAL_LOG_FCB (0) +#endif + +#ifndef MYNEWT_VAL_LOG_FCB_SLOT1 +#define MYNEWT_VAL_LOG_FCB_SLOT1 (0) +#endif + +#ifndef MYNEWT_VAL_LOG_LEVEL +#define MYNEWT_VAL_LOG_LEVEL (255) +#endif + +/*** @apache-mynewt-core/sys/sys */ +#ifndef MYNEWT_VAL_DEBUG_PANIC_ENABLED +#define MYNEWT_VAL_DEBUG_PANIC_ENABLED (1) +#endif + +/*** @apache-mynewt-core/sys/sysdown */ +#ifndef MYNEWT_VAL_SYSDOWN_CONSTRAIN_DOWN +#define MYNEWT_VAL_SYSDOWN_CONSTRAIN_DOWN (1) +#endif + +#ifndef MYNEWT_VAL_SYSDOWN_PANIC_FILE_LINE +#define MYNEWT_VAL_SYSDOWN_PANIC_FILE_LINE (0) +#endif + +#ifndef MYNEWT_VAL_SYSDOWN_PANIC_MESSAGE +#define MYNEWT_VAL_SYSDOWN_PANIC_MESSAGE (0) +#endif + +#ifndef MYNEWT_VAL_SYSDOWN_TIMEOUT_MS +#define MYNEWT_VAL_SYSDOWN_TIMEOUT_MS (10000) +#endif + +/*** @apache-mynewt-core/sys/sysinit */ +#ifndef MYNEWT_VAL_SYSINIT_CONSTRAIN_INIT +#define MYNEWT_VAL_SYSINIT_CONSTRAIN_INIT (1) +#endif + +#ifndef MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE +#define MYNEWT_VAL_SYSINIT_PANIC_FILE_LINE (0) +#endif + +#ifndef MYNEWT_VAL_SYSINIT_PANIC_MESSAGE +#define MYNEWT_VAL_SYSINIT_PANIC_MESSAGE (0) +#endif + +/*** @apache-mynewt-core/util/rwlock */ +#ifndef MYNEWT_VAL_RWLOCK_DEBUG +#define MYNEWT_VAL_RWLOCK_DEBUG (0) +#endif + +/*** @apache-mynewt-nimble/nimble */ +#ifndef MYNEWT_VAL_BLE_CONN_SUBRATING +#define MYNEWT_VAL_BLE_CONN_SUBRATING (0) +#endif + +#ifndef MYNEWT_VAL_BLE_EXT_ADV +#define MYNEWT_VAL_BLE_EXT_ADV (0) +#endif + +#ifndef MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE +#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31) +#endif + +#ifndef MYNEWT_VAL_ENC_ADV_DATA +#define MYNEWT_VAL_ENC_ADV_DATA (0) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble) */ +#ifndef MYNEWT_VAL_BLE_HCI_VS +#define MYNEWT_VAL_BLE_HCI_VS (1) +#endif + +#ifndef MYNEWT_VAL_BLE_HCI_VS_OCF_OFFSET +#define MYNEWT_VAL_BLE_HCI_VS_OCF_OFFSET (0) +#endif + +#ifndef MYNEWT_VAL_BLE_ISO +#define MYNEWT_VAL_BLE_ISO (0) +#endif + +#ifndef MYNEWT_VAL_BLE_ISO_TEST +#define MYNEWT_VAL_BLE_ISO_TEST (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MAX_CONNECTIONS +#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (1) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble) */ +#ifndef MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS +#define MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES +#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0) +#endif + +#ifndef MYNEWT_VAL_BLE_PERIODIC_ADV +#define MYNEWT_VAL_BLE_PERIODIC_ADV (0) +#endif + +#ifndef MYNEWT_VAL_BLE_PERIODIC_ADV_SYNC_TRANSFER +#define MYNEWT_VAL_BLE_PERIODIC_ADV_SYNC_TRANSFER (0) +#endif + +#ifndef MYNEWT_VAL_BLE_POWER_CONTROL +#define MYNEWT_VAL_BLE_POWER_CONTROL (0) +#endif + +#ifndef MYNEWT_VAL_BLE_ROLE_BROADCASTER +#define MYNEWT_VAL_BLE_ROLE_BROADCASTER (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ROLE_CENTRAL +#define MYNEWT_VAL_BLE_ROLE_CENTRAL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ROLE_OBSERVER +#define MYNEWT_VAL_BLE_ROLE_OBSERVER (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ROLE_PERIPHERAL +#define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_VERSION +#define MYNEWT_VAL_BLE_VERSION (50) +#endif + +#ifndef MYNEWT_VAL_BLE_WHITELIST +#define MYNEWT_VAL_BLE_WHITELIST (1) +#endif + +#ifndef MYNEWT_VAL_BLE_POWER_CONTROL +#define MYNEWT_VAL_BLE_POWER_CONTROL (0) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_BLOB_TRANSFER +#define MYNEWT_VAL_BLE_GATT_BLOB_TRANSFER (0) +#endif + +/*** @apache-mynewt-nimble/nimble/controller */ +#ifndef MYNEWT_VAL_BLE_CONTROLLER +#define MYNEWT_VAL_BLE_CONTROLLER (1) +#endif + +#ifndef MYNEWT_VAL_BLE_DEVICE +#define MYNEWT_VAL_BLE_DEVICE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_FEM_ANTENNA +#define MYNEWT_VAL_BLE_FEM_ANTENNA (0) +#endif + +/* Value copied from BLE_LL_LNA */ +#ifndef MYNEWT_VAL_BLE_FEM_LNA +#define MYNEWT_VAL_BLE_FEM_LNA (0) +#endif + +#ifndef MYNEWT_VAL_BLE_FEM_LNA_GAIN +#define MYNEWT_VAL_BLE_FEM_LNA_GAIN (0) +#endif + +#ifndef MYNEWT_VAL_BLE_FEM_LNA_GAIN_TUNABLE +#define MYNEWT_VAL_BLE_FEM_LNA_GAIN_TUNABLE (0) +#endif + +/* Value copied from BLE_LL_LNA_GPIO */ +#ifndef MYNEWT_VAL_BLE_FEM_LNA_GPIO +#define MYNEWT_VAL_BLE_FEM_LNA_GPIO (-1) +#endif + +/* Value copied from BLE_LL_LNA_TURN_ON_US */ +#ifndef MYNEWT_VAL_BLE_FEM_LNA_TURN_ON_US +#define MYNEWT_VAL_BLE_FEM_LNA_TURN_ON_US (1) +#endif + +/* Value copied from BLE_LL_PA */ +#ifndef MYNEWT_VAL_BLE_FEM_PA +#define MYNEWT_VAL_BLE_FEM_PA (0) +#endif + +#ifndef MYNEWT_VAL_BLE_FEM_PA_GAIN +#define MYNEWT_VAL_BLE_FEM_PA_GAIN (0) +#endif + +#ifndef MYNEWT_VAL_BLE_FEM_PA_GAIN_TUNABLE +#define MYNEWT_VAL_BLE_FEM_PA_GAIN_TUNABLE (0) +#endif + +/* Value copied from BLE_LL_PA_GPIO */ +#ifndef MYNEWT_VAL_BLE_FEM_PA_GPIO +#define MYNEWT_VAL_BLE_FEM_PA_GPIO (-1) +#endif + +/* Value copied from BLE_LL_PA_TURN_ON_US */ +#ifndef MYNEWT_VAL_BLE_FEM_PA_TURN_ON_US +#define MYNEWT_VAL_BLE_FEM_PA_TURN_ON_US (1) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */ +#ifndef MYNEWT_VAL_BLE_HW_WHITELIST_ENABLE +#define MYNEWT_VAL_BLE_HW_WHITELIST_ENABLE (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_ADD_STRICT_SCHED_PERIODS +#define MYNEWT_VAL_BLE_LL_ADD_STRICT_SCHED_PERIODS (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_CONN_PARAM_REQ +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_CONN_PARAM_REQ (MYNEWT_VAL_BLE_LL_ROLE_CENTRAL || MYNEWT_VAL_BLE_LL_ROLE_PERIPHERAL) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL (0) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */ +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_DATA_LEN_EXT +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_DATA_LEN_EXT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_2M_PHY +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_2M_PHY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CODED_PHY +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CODED_PHY (0) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */ +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CSA2 +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CSA2 (1) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */ +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_ENCRYPTION +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_ENCRYPTION (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_PING +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_PING (MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_ENCRYPTION) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE (0) +#endif + +/* Value copied from BLE_EXT_ADV */ +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_EXT_ADV +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_EXT_ADV (0) +#endif + +/* Value copied from BLE_ISO */ +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_ISO +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_ISO (0) +#endif + +/* Value copied from BLE_ISO_TEST */ +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_ISO_TEST +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_ISO_TEST (0) +#endif + +/* Value copied from BLE_PERIODIC_ADV */ +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV (0) +#endif + +/* Value copied from BLE_MAX_PERIODIC_SYNCS */ +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_CNT +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_CNT (0) +#endif + +/* Value copied from BLE_MAX_PERIODIC_SYNCS */ +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_LIST_CNT +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_LIST_CNT (0) +#endif + +/* Value copied from BLE_PERIODIC_ADV_SYNC_TRANSFER */ +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER (0) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */ +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_SCA_UPDATE +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_SCA_UPDATE (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_PERIPH_INIT_FEAT_XCHG +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_PERIPH_INIT_FEAT_XCHG (MYNEWT_VAL_BLE_LL_ROLE_CENTRAL || MYNEWT_VAL_BLE_LL_ROLE_PERIPHERAL) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_EVENT_END_MARGIN +#define MYNEWT_VAL_BLE_LL_CONN_EVENT_END_MARGIN (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_INIT_AUTO_DLE +#define MYNEWT_VAL_BLE_LL_CONN_INIT_AUTO_DLE (1) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */ +#ifndef MYNEWT_VAL_BLE_LL_CONN_INIT_MAX_TX_BYTES +#define MYNEWT_VAL_BLE_LL_CONN_INIT_MAX_TX_BYTES (MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_INIT_MIN_WIN_OFFSET +#define MYNEWT_VAL_BLE_LL_CONN_INIT_MIN_WIN_OFFSET (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_INIT_SLOTS +#define MYNEWT_VAL_BLE_LL_CONN_INIT_SLOTS (4) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_PHY_DEFAULT_PREF_MASK +#define MYNEWT_VAL_BLE_LL_CONN_PHY_DEFAULT_PREF_MASK (0x07) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_PHY_INIT_UPDATE +#define MYNEWT_VAL_BLE_LL_CONN_PHY_INIT_UPDATE (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_PHY_PREFER_2M +#define MYNEWT_VAL_BLE_LL_CONN_PHY_PREFER_2M (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_STRICT_SCHED +#define MYNEWT_VAL_BLE_LL_CONN_STRICT_SCHED (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_STRICT_SCHED_FIXED +#define MYNEWT_VAL_BLE_LL_CONN_STRICT_SCHED_FIXED (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_STRICT_SCHED_PERIOD_SLOTS +#define MYNEWT_VAL_BLE_LL_CONN_STRICT_SCHED_PERIOD_SLOTS (8) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_STRICT_SCHED_SLOT_US +#define MYNEWT_VAL_BLE_LL_CONN_STRICT_SCHED_SLOT_US (3750) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_DEBUG_GPIO_HCI_CMD +#define MYNEWT_VAL_BLE_LL_DEBUG_GPIO_HCI_CMD (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_DEBUG_GPIO_HCI_EV +#define MYNEWT_VAL_BLE_LL_DEBUG_GPIO_HCI_EV (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_DEBUG_GPIO_RFMGMT +#define MYNEWT_VAL_BLE_LL_DEBUG_GPIO_RFMGMT (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_DEBUG_GPIO_SCHED_ITEM +#define MYNEWT_VAL_BLE_LL_DEBUG_GPIO_SCHED_ITEM (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_DEBUG_GPIO_SCHED_RUN +#define MYNEWT_VAL_BLE_LL_DEBUG_GPIO_SCHED_RUN (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_DIRECT_TEST_MODE +#define MYNEWT_VAL_BLE_LL_DIRECT_TEST_MODE (0) +#endif + +/* Value copied from BLE_LL_DIRECT_TEST_MODE */ +#ifndef MYNEWT_VAL_BLE_LL_DTM +#define MYNEWT_VAL_BLE_LL_DTM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_DTM_EXTENSIONS +#define MYNEWT_VAL_BLE_LL_DTM_EXTENSIONS (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_EXT +#define MYNEWT_VAL_BLE_LL_EXT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_EXT_ADV_AUX_PTR_CNT +#define MYNEWT_VAL_BLE_LL_EXT_ADV_AUX_PTR_CNT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_HBD_FAKE_DUAL_MODE +#define MYNEWT_VAL_BLE_LL_HBD_FAKE_DUAL_MODE (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_HCI_LLCP_TRACE +#define MYNEWT_VAL_BLE_LL_HCI_LLCP_TRACE (0) +#endif + +/* Value copied from BLE_HCI_VS */ +#ifndef MYNEWT_VAL_BLE_LL_HCI_VS +#define MYNEWT_VAL_BLE_LL_HCI_VS (1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_HCI_VS_CONN_STRICT_SCHED +#define MYNEWT_VAL_BLE_LL_HCI_VS_CONN_STRICT_SCHED (0) +#endif + +/* Value copied from BLE_LL_VND_EVENT_ON_ASSERT */ +#ifndef MYNEWT_VAL_BLE_LL_HCI_VS_EVENT_ON_ASSERT +#define MYNEWT_VAL_BLE_LL_HCI_VS_EVENT_ON_ASSERT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_LNA +#define MYNEWT_VAL_BLE_LL_LNA (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_LNA_GPIO +#define MYNEWT_VAL_BLE_LL_LNA_GPIO (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_LNA_TURN_ON_US +#define MYNEWT_VAL_BLE_LL_LNA_TURN_ON_US (1) +#endif + +/* Value copied from BLE_LL_MFRG_ID */ +#ifndef MYNEWT_VAL_BLE_LL_MANUFACTURER_ID +#define MYNEWT_VAL_BLE_LL_MANUFACTURER_ID (0x0B65) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_MASTER_SCA +#define MYNEWT_VAL_BLE_LL_MASTER_SCA (4) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE +#define MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE (251) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_MFRG_ID +#define MYNEWT_VAL_BLE_LL_MFRG_ID (0x0B65) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_NUM_COMP_PKT_ITVL_MS +#define MYNEWT_VAL_BLE_LL_NUM_COMP_PKT_ITVL_MS (2000) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_NUM_SCAN_DUP_ADVS +#define MYNEWT_VAL_BLE_LL_NUM_SCAN_DUP_ADVS (8) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_NUM_SCAN_RSP_ADVS +#define MYNEWT_VAL_BLE_LL_NUM_SCAN_RSP_ADVS (8) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_OUR_SCA +#define MYNEWT_VAL_BLE_LL_OUR_SCA (60) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_PA +#define MYNEWT_VAL_BLE_LL_PA (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_PA_GPIO +#define MYNEWT_VAL_BLE_LL_PA_GPIO (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_PA_TURN_ON_US +#define MYNEWT_VAL_BLE_LL_PA_TURN_ON_US (1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_PRIO +#define MYNEWT_VAL_BLE_LL_PRIO (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_PUBLIC_DEV_ADDR +#define MYNEWT_VAL_BLE_LL_PUBLIC_DEV_ADDR (0x000000000000) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_RESOLV_LIST_SIZE +#define MYNEWT_VAL_BLE_LL_RESOLV_LIST_SIZE (4) +#endif + +/* Overridden by @apache-mynewt-core/hw/bsp/nordic_pca10056 (defined by @apache-mynewt-nimble/nimble/controller) */ +#ifndef MYNEWT_VAL_BLE_LL_RFMGMT_ENABLE_TIME +#define MYNEWT_VAL_BLE_LL_RFMGMT_ENABLE_TIME (1500) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_RNG_BUFSIZE +#define MYNEWT_VAL_BLE_LL_RNG_BUFSIZE (32) +#endif + +/* Value copied from BLE_ROLE_BROADCASTER */ +#ifndef MYNEWT_VAL_BLE_LL_ROLE_BROADCASTER +#define MYNEWT_VAL_BLE_LL_ROLE_BROADCASTER (1) +#endif + +/* Value copied from BLE_ROLE_CENTRAL */ +#ifndef MYNEWT_VAL_BLE_LL_ROLE_CENTRAL +#define MYNEWT_VAL_BLE_LL_ROLE_CENTRAL (1) +#endif + +/* Value copied from BLE_ROLE_OBSERVER */ +#ifndef MYNEWT_VAL_BLE_LL_ROLE_OBSERVER +#define MYNEWT_VAL_BLE_LL_ROLE_OBSERVER (1) +#endif + +/* Value copied from BLE_ROLE_PERIPHERAL */ +#ifndef MYNEWT_VAL_BLE_LL_ROLE_PERIPHERAL +#define MYNEWT_VAL_BLE_LL_ROLE_PERIPHERAL (1) +#endif + +/* Value copied from BLE_LL_OUR_SCA */ +#ifndef MYNEWT_VAL_BLE_LL_SCA +#define MYNEWT_VAL_BLE_LL_SCA (60) +#endif + +/* Value copied from BLE_LL_EXT_ADV_AUX_PTR_CNT */ +#ifndef MYNEWT_VAL_BLE_LL_SCAN_AUX_SEGMENT_CNT +#define MYNEWT_VAL_BLE_LL_SCAN_AUX_SEGMENT_CNT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY +#define MYNEWT_VAL_BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_SCHED_AUX_MAFS_DELAY +#define MYNEWT_VAL_BLE_LL_SCHED_AUX_MAFS_DELAY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_SCHED_SCAN_AUX_PDU_LEN +#define MYNEWT_VAL_BLE_LL_SCHED_SCAN_AUX_PDU_LEN (41) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_SCHED_SCAN_SYNC_PDU_LEN +#define MYNEWT_VAL_BLE_LL_SCHED_SCAN_SYNC_PDU_LEN (32) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_STACK_SIZE +#define MYNEWT_VAL_BLE_LL_STACK_SIZE (120) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_STRICT_CONN_SCHEDULING +#define MYNEWT_VAL_BLE_LL_STRICT_CONN_SCHEDULING (0) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */ +#ifndef MYNEWT_VAL_BLE_LL_SUPP_MAX_RX_BYTES +#define MYNEWT_VAL_BLE_LL_SUPP_MAX_RX_BYTES (MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */ +#ifndef MYNEWT_VAL_BLE_LL_SUPP_MAX_TX_BYTES +#define MYNEWT_VAL_BLE_LL_SUPP_MAX_TX_BYTES (MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_SYSINIT_STAGE +#define MYNEWT_VAL_BLE_LL_SYSINIT_STAGE (250) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_SYSVIEW +#define MYNEWT_VAL_BLE_LL_SYSVIEW (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_TX_PWR_DBM +#define MYNEWT_VAL_BLE_LL_TX_PWR_DBM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_TX_PWR_MAX_DBM +#define MYNEWT_VAL_BLE_LL_TX_PWR_MAX_DBM (20) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_USECS_PER_PERIOD +#define MYNEWT_VAL_BLE_LL_USECS_PER_PERIOD (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_VND_EVENT_ON_ASSERT +#define MYNEWT_VAL_BLE_LL_VND_EVENT_ON_ASSERT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_WHITELIST_SIZE +#define MYNEWT_VAL_BLE_LL_WHITELIST_SIZE (8) +#endif + +#ifndef MYNEWT_VAL_BLE_LP_CLOCK +#define MYNEWT_VAL_BLE_LP_CLOCK (1) +#endif + +#ifndef MYNEWT_VAL_BLE_NUM_COMP_PKT_RATE +#define MYNEWT_VAL_BLE_NUM_COMP_PKT_RATE ((2 * OS_TICKS_PER_SEC)) +#endif + +#ifndef MYNEWT_VAL_BLE_PUBLIC_DEV_ADDR +#define MYNEWT_VAL_BLE_PUBLIC_DEV_ADDR ((uint8_t[6]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +#endif + +#ifndef MYNEWT_VAL_BLE_XTAL_SETTLE_TIME +#define MYNEWT_VAL_BLE_XTAL_SETTLE_TIME (0) +#endif + +/*** @apache-mynewt-nimble/nimble/drivers/nrf5x */ +#ifndef MYNEWT_VAL_BLE_PHY_DBG_TIME_ADDRESS_END_PIN +#define MYNEWT_VAL_BLE_PHY_DBG_TIME_ADDRESS_END_PIN (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_PHY_DBG_TIME_TXRXEN_READY_PIN +#define MYNEWT_VAL_BLE_PHY_DBG_TIME_TXRXEN_READY_PIN (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_PHY_DBG_TIME_WFR_PIN +#define MYNEWT_VAL_BLE_PHY_DBG_TIME_WFR_PIN (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_PHY_NRF52_HEADERMASK_WORKAROUND +#define MYNEWT_VAL_BLE_PHY_NRF52_HEADERMASK_WORKAROUND (0) +#endif + +#ifndef MYNEWT_VAL_BLE_PHY_SYSVIEW +#define MYNEWT_VAL_BLE_PHY_SYSVIEW (0) +#endif + +#ifndef MYNEWT_VAL_BLE_PHY_UBLOX_BMD345_PUBLIC_ADDR +#define MYNEWT_VAL_BLE_PHY_UBLOX_BMD345_PUBLIC_ADDR (0) +#endif + +#ifndef MYNEWT_VAL_BLE_PHY_VARIABLE_TIFS +#define MYNEWT_VAL_BLE_PHY_VARIABLE_TIFS (0) +#endif + +/*** @apache-mynewt-nimble/nimble/host */ +#ifndef MYNEWT_VAL_BLE_ATT_PREFERRED_MTU +#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU (256) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO +#define MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_FIND_TYPE +#define MYNEWT_VAL_BLE_ATT_SVR_FIND_TYPE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_INDICATE +#define MYNEWT_VAL_BLE_ATT_SVR_INDICATE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES +#define MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES (64) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI (MYNEWT_VAL_BLE_ATT_SVR_NOTIFY && (MYNEWT_VAL_BLE_VERSION >= 52)) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE +#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE_TMO +#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE_TMO (30000) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ +#define MYNEWT_VAL_BLE_ATT_SVR_READ (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_BLOB +#define MYNEWT_VAL_BLE_ATT_SVR_READ_BLOB (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_GROUP_TYPE +#define MYNEWT_VAL_BLE_ATT_SVR_READ_GROUP_TYPE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_MULT +#define MYNEWT_VAL_BLE_ATT_SVR_READ_MULT (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE +#define MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_SIGNED_WRITE +#define MYNEWT_VAL_BLE_ATT_SVR_SIGNED_WRITE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_WRITE +#define MYNEWT_VAL_BLE_ATT_SVR_WRITE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP +#define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_LVL +#define MYNEWT_VAL_BLE_EATT_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_MOD +#define MYNEWT_VAL_BLE_EATT_LOG_MOD (27) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_MTU +#define MYNEWT_VAL_BLE_EATT_MTU (128) +#endif + +#ifndef MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE +#define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_DISC_ALL_CHRS +#define MYNEWT_VAL_BLE_GATT_DISC_ALL_CHRS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_DISC_ALL_DSCS +#define MYNEWT_VAL_BLE_GATT_DISC_ALL_DSCS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_DISC_ALL_SVCS +#define MYNEWT_VAL_BLE_GATT_DISC_ALL_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_DISC_CHR_UUID +#define MYNEWT_VAL_BLE_GATT_DISC_CHR_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_DISC_SVC_UUID +#define MYNEWT_VAL_BLE_GATT_DISC_SVC_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_FIND_INC_SVCS +#define MYNEWT_VAL_BLE_GATT_FIND_INC_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_INDICATE +#define MYNEWT_VAL_BLE_GATT_INDICATE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_MAX_PROCS +#define MYNEWT_VAL_BLE_GATT_MAX_PROCS (4) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY +#define MYNEWT_VAL_BLE_GATT_NOTIFY (1) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE +#define MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_READ +#define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_READ_LONG +#define MYNEWT_VAL_BLE_GATT_READ_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_READ_MAX_ATTRS +#define MYNEWT_VAL_BLE_GATT_READ_MAX_ATTRS (8) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_READ_MULT +#define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_READ_MULT_VAR +#define MYNEWT_VAL_BLE_GATT_READ_MULT_VAR (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_READ_UUID +#define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_RESUME_RATE +#define MYNEWT_VAL_BLE_GATT_RESUME_RATE (1000) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_SIGNED_WRITE +#define MYNEWT_VAL_BLE_GATT_SIGNED_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_WRITE +#define MYNEWT_VAL_BLE_GATT_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_WRITE_LONG +#define MYNEWT_VAL_BLE_GATT_WRITE_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_WRITE_MAX_ATTRS +#define MYNEWT_VAL_BLE_GATT_WRITE_MAX_ATTRS (4) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_WRITE_NO_RSP +#define MYNEWT_VAL_BLE_GATT_WRITE_NO_RSP (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_WRITE_RELIABLE +#define MYNEWT_VAL_BLE_GATT_WRITE_RELIABLE (MYNEWT_VAL_BLE_ROLE_CENTRAL) +#endif + +#ifndef MYNEWT_VAL_BLE_HOST +#define MYNEWT_VAL_BLE_HOST (1) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_AUTO_START +#define MYNEWT_VAL_BLE_HS_AUTO_START (1) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_DEBUG +#define MYNEWT_VAL_BLE_HS_DEBUG (0) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL (0) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL (1000) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH (2) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_LOG_LVL +#define MYNEWT_VAL_BLE_HS_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_LOG_MOD +#define MYNEWT_VAL_BLE_HS_LOG_MOD (4) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS +#define MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS (0) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_REQUIRE_OS +#define MYNEWT_VAL_BLE_HS_REQUIRE_OS (1) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_STOP_ON_SHUTDOWN +#define MYNEWT_VAL_BLE_HS_STOP_ON_SHUTDOWN (1) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_STOP_ON_SHUTDOWN_TIMEOUT +#define MYNEWT_VAL_BLE_HS_STOP_ON_SHUTDOWN_TIMEOUT (2000) +#endif + +#ifndef MYNEWT_VAL_BLE_HS_SYSINIT_STAGE +#define MYNEWT_VAL_BLE_HS_SYSINIT_STAGE (200) +#endif + +#ifndef MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM +#define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_L2CAP_COC_MPS +#define MYNEWT_VAL_BLE_L2CAP_COC_MPS (MYNEWT_VAL_MSYS_1_BLOCK_SIZE-8) +#endif + +#ifndef MYNEWT_VAL_BLE_L2CAP_COC_SDU_BUFF_COUNT +#define MYNEWT_VAL_BLE_L2CAP_COC_SDU_BUFF_COUNT (1) +#endif + +#ifndef MYNEWT_VAL_BLE_L2CAP_ENHANCED_COC +#define MYNEWT_VAL_BLE_L2CAP_ENHANCED_COC (0) +#endif + +#ifndef MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS +#define MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS (1) +#endif + +#ifndef MYNEWT_VAL_BLE_L2CAP_MAX_CHANS +#define MYNEWT_VAL_BLE_L2CAP_MAX_CHANS (3*MYNEWT_VAL_BLE_MAX_CONNECTIONS) +#endif + +#ifndef MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT +#define MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT (30000) +#endif + +#ifndef MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS +#define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH +#define MYNEWT_VAL_BLE_MESH (0) +#endif + +#ifndef MYNEWT_VAL_BLE_RPA_TIMEOUT +#define MYNEWT_VAL_BLE_RPA_TIMEOUT (300) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_BONDING +#define MYNEWT_VAL_BLE_SM_BONDING (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_IO_CAP +#define MYNEWT_VAL_BLE_SM_IO_CAP (BLE_HS_IO_NO_INPUT_OUTPUT) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_KEYPRESS +#define MYNEWT_VAL_BLE_SM_KEYPRESS (0) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/host) */ +#ifndef MYNEWT_VAL_BLE_SM_LEGACY +#define MYNEWT_VAL_BLE_SM_LEGACY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_LVL +#define MYNEWT_VAL_BLE_SM_LVL (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_MAX_PROCS +#define MYNEWT_VAL_BLE_SM_MAX_PROCS (1) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_MITM +#define MYNEWT_VAL_BLE_SM_MITM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG +#define MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_OUR_KEY_DIST +#define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (0) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/host) */ +#ifndef MYNEWT_VAL_BLE_SM_SC +#define MYNEWT_VAL_BLE_SM_SC (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS +#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_SC_ONLY +#define MYNEWT_VAL_BLE_SM_SC_ONLY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST +#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0) +#endif + +#ifndef MYNEWT_VAL_BLE_STORE_MAX_BONDS +#define MYNEWT_VAL_BLE_STORE_MAX_BONDS (3) +#endif + +#ifndef MYNEWT_VAL_BLE_STORE_MAX_CCCDS +#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8) +#endif + +#ifdef CONFIG_BT_NIMBLE_MAX_EADS +#define MYNEWT_VAL_BLE_STORE_MAX_EADS CONFIG_BT_NIMBLE_MAX_EADS +#endif + +/*** @apache-mynewt-nimble/nimble/host/services/gap */ +#ifndef MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE +#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM +#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION +#define MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME "nimble" +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH (31) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_SLAVE_LATENCY +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SLAVE_LATENCY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_SUPERVISION_TMO +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SUPERVISION_TMO (0) +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_SYSINIT_STAGE +#define MYNEWT_VAL_BLE_SVC_GAP_SYSINIT_STAGE (301) +#endif + +/*** @apache-mynewt-nimble/nimble/host/services/gatt */ +#ifndef MYNEWT_VAL_BLE_SVC_GATT_SYSINIT_STAGE +#define MYNEWT_VAL_BLE_SVC_GATT_SYSINIT_STAGE (302) +#endif + +/*** @apache-mynewt-nimble/nimble/transport */ +#undef MYNEWT_VAL_BLE_ACL_BUF_COUNT + +#undef MYNEWT_VAL_BLE_ACL_BUF_SIZE + +#undef MYNEWT_VAL_BLE_HCI_BRIDGE + +#undef MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE + +#undef MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT + +#undef MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT + +#undef MYNEWT_VAL_BLE_HCI_TRANSPORT + +#ifndef MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE +#define MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE (128) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_RTT +#define MYNEWT_VAL_BLE_MONITOR_RTT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED +#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME +#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME "btmonitor" +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE +#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE (256) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_UART +#define MYNEWT_VAL_BLE_MONITOR_UART (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE +#define MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE (1000000) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE +#define MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE (64) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_UART_DEV +#define MYNEWT_VAL_BLE_MONITOR_UART_DEV "uart0" +#endif + +#ifndef MYNEWT_VAL_BLE_TRANSPORT +#define MYNEWT_VAL_BLE_TRANSPORT (1) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/transport) */ +#ifndef MYNEWT_VAL_BLE_TRANSPORT_ACL_COUNT +#define MYNEWT_VAL_BLE_TRANSPORT_ACL_COUNT (24) +#endif + +/* Value copied from BLE_TRANSPORT_ACL_COUNT */ +#ifndef MYNEWT_VAL_BLE_TRANSPORT_ACL_FROM_HS_COUNT +#define MYNEWT_VAL_BLE_TRANSPORT_ACL_FROM_HS_COUNT (24) +#endif + +/* Value copied from BLE_TRANSPORT_ACL_COUNT */ +#ifndef MYNEWT_VAL_BLE_TRANSPORT_ACL_FROM_LL_COUNT +#define MYNEWT_VAL_BLE_TRANSPORT_ACL_FROM_LL_COUNT (24) +#endif + +#ifndef MYNEWT_VAL_BLE_TRANSPORT_ACL_SIZE +#define MYNEWT_VAL_BLE_TRANSPORT_ACL_SIZE (251) +#endif + +/* Overridden by @apache-mynewt-nimble/porting/targets/riot (defined by @apache-mynewt-nimble/nimble/transport) */ +#ifndef MYNEWT_VAL_BLE_TRANSPORT_EVT_COUNT +#define MYNEWT_VAL_BLE_TRANSPORT_EVT_COUNT (2) +#endif + +#ifndef MYNEWT_VAL_BLE_TRANSPORT_EVT_DISCARDABLE_COUNT +#define MYNEWT_VAL_BLE_TRANSPORT_EVT_DISCARDABLE_COUNT (16) +#endif + +#ifndef MYNEWT_VAL_BLE_TRANSPORT_EVT_SIZE +#define MYNEWT_VAL_BLE_TRANSPORT_EVT_SIZE (70) +#endif + +#ifndef MYNEWT_VAL_BLE_TRANSPORT_HS__cdc +#define MYNEWT_VAL_BLE_TRANSPORT_HS__cdc (0) +#endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_HS__custom +#define MYNEWT_VAL_BLE_TRANSPORT_HS__custom (0) +#endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_HS__dialog_cmac +#define MYNEWT_VAL_BLE_TRANSPORT_HS__dialog_cmac (0) +#endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_HS__native +#define MYNEWT_VAL_BLE_TRANSPORT_HS__native (1) +#endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_HS__nrf5340 +#define MYNEWT_VAL_BLE_TRANSPORT_HS__nrf5340 (0) +#endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_HS__uart +#define MYNEWT_VAL_BLE_TRANSPORT_HS__uart (0) +#endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_HS__usb +#define MYNEWT_VAL_BLE_TRANSPORT_HS__usb (0) +#endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_HS +#define MYNEWT_VAL_BLE_TRANSPORT_HS (1) +#endif + +#ifndef MYNEWT_VAL_BLE_TRANSPORT_LL__apollo3 +#define MYNEWT_VAL_BLE_TRANSPORT_LL__apollo3 (0) +#endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_LL__custom +#define MYNEWT_VAL_BLE_TRANSPORT_LL__custom (0) +#endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_LL__dialog_cmac +#define MYNEWT_VAL_BLE_TRANSPORT_LL__dialog_cmac (0) +#endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_LL__emspi +#define MYNEWT_VAL_BLE_TRANSPORT_LL__emspi (0) +#endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_LL__native +#define MYNEWT_VAL_BLE_TRANSPORT_LL__native (1) +#endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_LL__nrf5340 +#define MYNEWT_VAL_BLE_TRANSPORT_LL__nrf5340 (0) +#endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_LL__socket +#define MYNEWT_VAL_BLE_TRANSPORT_LL__socket (0) +#endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_LL +#define MYNEWT_VAL_BLE_TRANSPORT_LL (1) +#endif + +/*** newt */ +#ifndef MYNEWT_VAL_APP_NAME +#define MYNEWT_VAL_APP_NAME "dummy_app" +#endif + +#ifndef MYNEWT_VAL_APP_dummy_app +#define MYNEWT_VAL_APP_dummy_app (1) +#endif + +#ifndef MYNEWT_VAL_ARCH_NAME +#define MYNEWT_VAL_ARCH_NAME "cortex_m4" +#endif + +#ifndef MYNEWT_VAL_ARCH_cortex_m4 +#define MYNEWT_VAL_ARCH_cortex_m4 (1) +#endif + +#ifndef MYNEWT_VAL_BSP_NAME +#define MYNEWT_VAL_BSP_NAME "nordic_pca10056" +#endif + +#ifndef MYNEWT_VAL_BSP_nordic_pca10056 +#define MYNEWT_VAL_BSP_nordic_pca10056 (1) +#endif + +#ifndef MYNEWT_VAL_NEWT_FEATURE_LOGCFG +#define MYNEWT_VAL_NEWT_FEATURE_LOGCFG (1) +#endif + +#ifndef MYNEWT_VAL_NEWT_FEATURE_SYSDOWN +#define MYNEWT_VAL_NEWT_FEATURE_SYSDOWN (1) +#endif + +#ifndef MYNEWT_VAL_TARGET_NAME +#define MYNEWT_VAL_TARGET_NAME "riot" +#endif + +#ifndef MYNEWT_VAL_TARGET_riot +#define MYNEWT_VAL_TARGET_riot (1) +#endif + +/*** Included packages */ +#define MYNEWT_PKG_apache_mynewt_core__compiler_arm_none_eabi_m4 1 +#define MYNEWT_PKG_apache_mynewt_core__crypto_tinycrypt 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_bsp_nordic_pca10056 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_cmsis_core 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_drivers_uart 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_drivers_uart_uart_hal 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_hal 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_mcu_nordic 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_mcu_nordic_nrf52xxx 1 +#define MYNEWT_PKG_apache_mynewt_core__kernel_os 1 +#define MYNEWT_PKG_apache_mynewt_core__libc_baselibc 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_console_stub 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_defs 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_flash_map 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_log_common 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_log_modlog 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_log_stub 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_stats_stub 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_sys 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_sysdown 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_sysinit 1 +#define MYNEWT_PKG_apache_mynewt_core__util_mem 1 +#define MYNEWT_PKG_apache_mynewt_core__util_rwlock 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_controller 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_drivers_nrf5x 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_host 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_host_services_gap 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_host_services_gatt 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_transport 1 +#define MYNEWT_PKG_apache_mynewt_nimble__porting_npl_mynewt 1 +#define MYNEWT_PKG_apache_mynewt_nimble__porting_targets_dummy_app 1 +#define MYNEWT_PKG_apache_mynewt_nimble__porting_targets_riot 1 + +#endif diff --git a/lib/bt/host/nimble/nimble/porting/npl/riot/include/syscfg/syscfg.h b/lib/bt/host/nimble/nimble/porting/npl/riot/include/syscfg/syscfg.h index c90322ea..a52b22c5 100644 --- a/lib/bt/host/nimble/nimble/porting/npl/riot/include/syscfg/syscfg.h +++ b/lib/bt/host/nimble/nimble/porting/npl/riot/include/syscfg/syscfg.h @@ -1406,6 +1406,10 @@ #define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI (MYNEWT_VAL_BLE_ATT_SVR_NOTIFY && (MYNEWT_VAL_BLE_VERSION >= 52)) +#endif + #ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE #define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) #endif @@ -1446,6 +1450,22 @@ #define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) #endif +#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_LVL +#define MYNEWT_VAL_BLE_EATT_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_MOD +#define MYNEWT_VAL_BLE_EATT_LOG_MOD (27) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_MTU +#define MYNEWT_VAL_BLE_EATT_MTU (128) +#endif + #ifndef MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE #define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) #endif @@ -1486,6 +1506,10 @@ #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE +#define MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE (1) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif diff --git a/lib/bt/host/nimble/nimble/sbom.yml b/lib/bt/host/nimble/nimble/sbom.yml index 214758da..c1eb6d63 100644 --- a/lib/bt/host/nimble/nimble/sbom.yml +++ b/lib/bt/host/nimble/nimble/sbom.yml @@ -1,5 +1,5 @@ name: 'Apache Mynewt Nimble' -version: '1.5.0' +version: '1.6.0' supplier: 'Organization: Espressif Systems (Shanghai) CO LTD' originator: 'Organization: The Apache Software Foundation' description: An open-source Bluetooth 5.1 stack with additional features and patches from Espressif. diff --git a/lib/bt/host/nimble/port/include/esp_nimble_cfg.h b/lib/bt/host/nimble/port/include/esp_nimble_cfg.h index d2fa3338..6c80ae75 100644 --- a/lib/bt/host/nimble/port/include/esp_nimble_cfg.h +++ b/lib/bt/host/nimble/port/include/esp_nimble_cfg.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -98,6 +98,14 @@ #define MYNEWT_VAL_BLE_EXT_ADV (CONFIG_BT_NIMBLE_EXT_ADV) #endif +#ifndef MYNEWT_VAL_BLE_EXT_ADV_V2 +#ifdef CONFIG_BT_NIMBLE_EXT_ADV_V2 +#define MYNEWT_VAL_BLE_EXT_ADV_V2 (CONFIG_BT_NIMBLE_EXT_ADV_V2) +#else +#define MYNEWT_VAL_BLE_EXT_ADV_V2 (0) +#endif +#endif + #ifndef CONFIG_BT_NIMBLE_EXT_ADV_MAX_SIZE #define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31) #else @@ -129,11 +137,27 @@ #define MYNEWT_VAL_BLE_MAX_PERIODIC_ADVERTISER_LIST (CONFIG_BT_NIMBLE_MAX_PERIODIC_ADVERTISER_LIST) #endif +#ifndef MYNEWT_VAL_BLE_INCL_SVC_DISCOVERY +#ifdef CONFIG_BT_NIMBLE_INCL_SVC_DISCOVERY +#define MYNEWT_VAL_BLE_INCL_SVC_DISCOVERY (CONFIG_BT_NIMBLE_INCL_SVC_DISCOVERY) +#else +#define MYNEWT_VAL_BLE_INCL_SVC_DISCOVERY (0) +#endif +#endif + #ifndef CONFIG_BT_NIMBLE_GATT_CACHING #define MYNEWT_VAL_BLE_GATT_CACHING (0) #else #define MYNEWT_VAL_BLE_GATT_CACHING (CONFIG_BT_NIMBLE_GATT_CACHING) +#ifndef MYNEWT_VAL_BLE_GATT_CACHING_INCLUDE_SERVICES +#ifdef CONFIG_BT_NIMBLE_GATT_CACHING_INCLUDE_SERVICES +#define MYNEWT_VAL_BLE_GATT_CACHING_INCLUDE_SERVICES (CONFIG_BT_NIMBLE_GATT_CACHING_INCLUDE_SERVICES) +#else +#define MYNEWT_VAL_BLE_GATT_CACHING_INCLUDE_SERVICES (0) +#endif +#endif + #ifdef CONFIG_BT_NIMBLE_GATT_CACHING_MAX_CONNS #define MYNEWT_VAL_BLE_GATT_CACHING_MAX_CONNS (CONFIG_BT_NIMBLE_GATT_CACHING_MAX_CONNS) #else @@ -146,6 +170,14 @@ #define MYNEWT_VAL_BLE_GATT_CACHING_MAX_SVCS (0) #endif +#ifndef MYNEWT_VAL_BLE_GATT_CACHING_MAX_INCL_SVCS +#ifdef CONFIG_BT_NIMBLE_GATT_CACHING_MAX_INCL_SVCS +#define MYNEWT_VAL_BLE_GATT_CACHING_MAX_INCL_SVCS (CONFIG_BT_NIMBLE_GATT_CACHING_MAX_INCL_SVCS) +#else +#define MYNEWT_VAL_BLE_GATT_CACHING_MAX_INCL_SVCS (0) +#endif +#endif + #ifdef CONFIG_BT_NIMBLE_GATT_CACHING_MAX_CHRS #define MYNEWT_VAL_BLE_GATT_CACHING_MAX_CHRS (CONFIG_BT_NIMBLE_GATT_CACHING_MAX_CHRS) #else @@ -158,6 +190,16 @@ #define MYNEWT_VAL_BLE_GATT_CACHING_MAX_DSCS (0) #endif +#ifdef CONFIG_BT_NIMBLE_GATT_CACHING_DISABLE_AUTO +#define MYNEWT_VAL_BLE_GATT_CACHING_DISABLE_AUTO (CONFIG_BT_NIMBLE_GATT_CACHING_DISABLE_AUTO) +#else +#define MYNEWT_VAL_BLE_GATT_CACHING_DISABLE_AUTO (0) +#endif + +#endif + +#ifndef MYNEWT_VAL_BLE_GATT_CSFC_SIZE +#define MYNEWT_VAL_BLE_GATT_CSFC_SIZE (1) #endif #ifndef CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES @@ -202,6 +244,18 @@ #define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif +#ifndef CONFIG_BT_NIMBLE_GATT_CLIENT +#define MYNEWT_VAL_BLE_GATTC (0) +#else +#define MYNEWT_VAL_BLE_GATTC (CONFIG_BT_NIMBLE_GATT_CLIENT) +#endif + +#ifndef CONFIG_BT_NIMBLE_GATT_SERVER +#define MYNEWT_VAL_BLE_GATTS (0) +#else +#define MYNEWT_VAL_BLE_GATTS (CONFIG_BT_NIMBLE_GATT_SERVER) +#endif + #ifndef MYNEWT_VAL_BLE_WHITELIST #define MYNEWT_VAL_BLE_WHITELIST (1) #endif @@ -234,7 +288,7 @@ #endif #ifndef MYNEWT_VAL_BLE_VERSION -#define MYNEWT_VAL_BLE_VERSION (50) +#define MYNEWT_VAL_BLE_VERSION (54) #endif #ifndef MYNEWT_VAL_BLE_LL_ADD_STRICT_SCHED_PERIODS @@ -511,6 +565,12 @@ #define MYNEWT_VAL_BLE_L2CAP_COC_SDU_BUFF_COUNT CONFIG_BT_NIMBLE_L2CAP_COC_SDU_BUFF_COUNT #endif +#if CONFIG_BT_NIMBLE_L2CAP_ENHANCED_COC || CONFIG_BT_NIMBLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_L2CAP_ENHANCED_COC (1) +#else +#define MYNEWT_VAL_BLE_L2CAP_ENHANCED_COC (0) +#endif + #ifndef MYNEWT_VAL_BLE_DYNAMIC_SERVICE #ifdef CONFIG_BT_NIMBLE_DYNAMIC_SERVICE #define MYNEWT_VAL_BLE_DYNAMIC_SERVICE CONFIG_BT_NIMBLE_DYNAMIC_SERVICE @@ -536,13 +596,17 @@ #endif #ifndef MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES -#define MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES (64) +#define MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES CONFIG_BT_NIMBLE_ATT_MAX_PREP_ENTRIES #endif #ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY #define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI (1) +#endif + #ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE #define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) #endif @@ -567,6 +631,10 @@ #define MYNEWT_VAL_BLE_ATT_SVR_READ_MULT (1) #endif +#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_MULT_VAR +#define MYNEWT_VAL_BLE_ATT_SVR_READ_MULT_VAR (1) +#endif + #ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE #define MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE (1) #endif @@ -583,6 +651,49 @@ #define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) #endif +#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (CONFIG_BT_NIMBLE_EATT_CHAN_NUM) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_LVL +#define MYNEWT_VAL_BLE_EATT_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_MOD +#define MYNEWT_VAL_BLE_EATT_LOG_MOD (27) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_MTU +#define MYNEWT_VAL_BLE_EATT_MTU (128) +#endif + +#ifndef MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES + +#if MYNEWT_VAL_BLE_GATT_CACHING +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_ROBUST_CACHING (1) +#else +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_ROBUST_CACHING (0) +#endif //MYNEWT_VAL_BLE_GATT_CACHING + +#if CONFIG_BT_NIMBLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_EATT (2) +#else +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_EATT (0) +#endif //CONFIG_BT_NIMBLE_EATT_CHAN_NUM + +#if MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_NOTIFY_MULTI (4) +#else +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_NOTIFY_MULTI (0) +#endif //MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI + +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES ( \ + MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_ROBUST_CACHING | \ + MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_EATT | \ + MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_NOTIFY_MULTI \ + ) +#endif //MYNEWT_VAL_CLIENT_SUPPORTED_FEATURES + #ifndef MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE #define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) #endif @@ -623,6 +734,10 @@ #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE +#define MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE (1) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif @@ -749,11 +864,15 @@ #define MYNEWT_VAL_BLE_HS_SYSINIT_STAGE (200) #endif +#if CONFIG_BT_NIMBLE_EATT_CHAN_NUM > CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM +#define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM (CONFIG_BT_NIMBLE_EATT_CHAN_NUM) +#else #ifndef CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM #define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM (2) #else #define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM -#endif +#endif //CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM +#endif //CONFIG_BT_NIMBLE_EATT_CHAN_NUM #ifndef MYNEWT_VAL_BLE_L2CAP_COC_MPS #define MYNEWT_VAL_BLE_L2CAP_COC_MPS (MYNEWT_VAL_MSYS_1_BLOCK_SIZE-8) @@ -771,7 +890,11 @@ #define MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT (30000) #endif -#ifndef MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS +#if CONFIG_BT_NIMBLE_EATT_CHAN_NUM > CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM +#define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (CONFIG_BT_NIMBLE_EATT_CHAN_NUM) +#elif CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM +#define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM) +#else #define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (1) #endif @@ -885,13 +1008,25 @@ #endif #ifndef MYNEWT_VAL_BLE_SM_SC_ONLY +#ifdef CONFIG_BT_NIMBLE_SM_SC_ONLY +#define MYNEWT_VAL_BLE_SM_SC_ONLY (CONFIG_BT_NIMBLE_SM_SC_ONLY) +#else #define MYNEWT_VAL_BLE_SM_SC_ONLY (0) #endif +#endif #ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST #define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0) #endif +#ifndef MYNEWT_VAL_BLE_SMP_ID_RESET +#ifdef CONFIG_BT_NIMBLE_SMP_ID_RESET +#define MYNEWT_VAL_BLE_SMP_ID_RESET CONFIG_BT_NIMBLE_SMP_ID_RESET +#else +#define MYNEWT_VAL_BLE_SMP_ID_RESET (0) +#endif +#endif + #ifndef MYNEWT_VAL_BLE_CRYPTO_STACK_MBEDTLS #define MYNEWT_VAL_BLE_CRYPTO_STACK_MBEDTLS (CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS) #endif @@ -904,6 +1039,10 @@ #define MYNEWT_VAL_BLE_STORE_MAX_CCCDS CONFIG_BT_NIMBLE_MAX_CCCDS #endif +#ifndef MYNEWT_VAL_BLE_STORE_MAX_CSFCS +#define MYNEWT_VAL_BLE_STORE_MAX_CSFCS CONFIG_BT_NIMBLE_MAX_BONDS +#endif + #ifdef CONFIG_BT_NIMBLE_MAX_EADS #define MYNEWT_VAL_BLE_STORE_MAX_EADS CONFIG_BT_NIMBLE_MAX_EADS #endif @@ -948,7 +1087,7 @@ /*** nimble/host/services/bas */ #ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE -#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE (1) +#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE (CONFIG_BT_NIMBLE_SVC_BAS_BATTERY_LEVEL_NOTIFY) #endif #ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM @@ -1548,7 +1687,7 @@ /*** @apache-mynewt-nimble/nimble/host/services/bas */ #ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE -#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE (1) +#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE (CONFIG_BT_NIMBLE_SVC_BAS_BATTERY_LEVEL_NOTIFY) #endif #ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM @@ -1565,29 +1704,34 @@ #endif #ifndef MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT -#define MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT (NULL) +#define MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT ("0000") #endif /* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */ -#ifndef MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM +#if CONFIG_BT_NIMBLE_SVC_DIS_FIRMWARE_REVISION +#define MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM (0) +#else #define MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM (-1) #endif #ifndef MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT -#define MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT (NULL) +#define MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT ("0000") #endif /* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */ -#ifndef MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM +#if CONFIG_BT_NIMBLE_SVC_DIS_HARDWARE_REVISION +#define MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM (0) +#else #define MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM (-1) #endif #ifndef MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT -#define MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT (NULL) +#define MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT ("espressif") #endif -/* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */ -#ifndef MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM +#if CONFIG_BT_NIMBLE_SVC_DIS_MANUFACTURER_NAME +#define MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM (0) +#else #define MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM (-1) #endif @@ -1600,20 +1744,24 @@ #endif #ifndef MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT -#define MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT (NULL) +#define MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT ("0000") #endif /* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */ -#ifndef MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM +#if CONFIG_BT_NIMBLE_SVC_DIS_SERIAL_NUMBER +#define MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM (0) +#else #define MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM (-1) #endif #ifndef MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT -#define MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT (NULL) +#define MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT ("0000") #endif /* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */ -#ifndef MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM +#if CONFIG_BT_NIMBLE_SVC_DIS_SOFTWARE_REVISION +#define MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM (0) +#else #define MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM (-1) #endif @@ -1622,23 +1770,31 @@ #endif #ifndef MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_DEFAULT -#define MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_DEFAULT (NULL) +#define MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_DEFAULT ("00000000") #endif /* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */ -#ifndef MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_READ_PERM +#if CONFIG_BT_NIMBLE_SVC_DIS_SYSTEM_ID +#define MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_READ_PERM (0) +#else #define MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_READ_PERM (-1) #endif #ifndef MYNEWT_VAL_BLE_SVC_DIS_PNP_ID_DEFAULT -#define MYNEWT_VAL_BLE_SVC_DIS_PNP_ID_DEFAULT (NULL) +#define MYNEWT_VAL_BLE_SVC_DIS_PNP_ID_DEFAULT ("000000") #endif /* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */ -#ifndef MYNEWT_VAL_BLE_SVC_DIS_PNP_ID_READ_PERM +#if CONFIG_BT_NIMBLE_SVC_DIS_PNP_ID +#define MYNEWT_VAL_BLE_SVC_DIS_PNP_ID_READ_PERM (0) +#else #define MYNEWT_VAL_BLE_SVC_DIS_PNP_ID_READ_PERM (-1) #endif +#ifndef MYNEWT_VAL_BLE_SVC_DIS_INCLUDED +#define MYNEWT_VAL_BLE_SVC_DIS_INCLUDED (CONFIG_BT_NIMBLE_SVC_DIS_INCLUDED) +#endif + /*** @apache-mynewt-nimble/nimble/host/services/gap */ #ifndef MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE #define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE @@ -1701,6 +1857,16 @@ CONFIG_BT_NIMBLE_SVC_GAP_PPCP_SUPERVISION_TMO #endif +#ifndef MYNEWT_VAL_BLE_SVC_GAP_GATT_SECURITY_LEVEL +#define MYNEWT_VAL_BLE_SVC_GAP_GATT_SECURITY_LEVEL \ + CONFIG_BT_NIMBLE_SVC_GAP_GATT_SECURITY_LEVEL +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_RPA_ONLY +#define MYNEWT_VAL_BLE_SVC_GAP_RPA_ONLY \ + CONFIG_BT_NIMBLE_SVC_GAP_RPA_ONLY +#endif + /*** nimble/transport */ #ifndef MYNEWT_VAL_BLE_HCI_TRANSPORT_EMSPI #define MYNEWT_VAL_BLE_HCI_TRANSPORT_EMSPI (0) @@ -1816,7 +1982,7 @@ #ifdef CONFIG_BT_NIMBLE_HOST_QUEUE_CONG_CHECK #define MYNEWT_VAL_BLE_QUEUE_CONG_CHECK CONFIG_BT_NIMBLE_HOST_QUEUE_CONG_CHECK #else -#define MYNEWT_VAL_BLE_QUEUE_CONG_CHECK FALSE +#define MYNEWT_VAL_BLE_QUEUE_CONG_CHECK (0) #endif #endif @@ -1828,6 +1994,38 @@ #endif #endif +#ifndef MYNEWT_VAL_BLE_AOA_AOD +#ifdef CONFIG_BT_NIMBLE_AOA_AOD +#define MYNEWT_VAL_BLE_AOA_AOD CONFIG_BT_NIMBLE_AOA_AOD +#else +#define MYNEWT_VAL_BLE_AOA_AOD (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_GATTC_PROC_PREEMPTION_PROTECT +#ifdef CONFIG_BT_NIMBLE_GATTC_PROC_PREEMPTION_PROTECT +#define MYNEWT_VAL_BLE_GATTC_PROC_PREEMPTION_PROTECT CONFIG_BT_NIMBLE_GATTC_PROC_PREEMPTION_PROTECT +#else +#define MYNEWT_VAL_BLE_GATTC_PROC_PREEMPTION_PROTECT (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_HOST_ALLOW_CONNECT_WITH_SCAN +#ifdef CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN +#define MYNEWT_VAL_BLE_HOST_ALLOW_CONNECT_WITH_SCAN CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN +#else +#define MYNEWT_VAL_BLE_HOST_ALLOW_CONNECT_WITH_SCAN (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BT_HCI_LOG_INCLUDED +#ifdef CONFIG_BT_HCI_LOG_DEBUG_EN +#define MYNEWT_VAL_BT_HCI_LOG_INCLUDED CONFIG_BT_HCI_LOG_DEBUG_EN +#else +#define MYNEWT_VAL_BT_HCI_LOG_INCLUDED (0) +#endif +#endif + #if CONFIG_BT_CONTROLLER_DISABLED && CONFIG_BT_NIMBLE_TRANSPORT_UART #ifndef MYNEWT_VAL_BLE_TRANSPORT_UART_PORT #define MYNEWT_VAL_BLE_TRANSPORT_UART_PORT CONFIG_BT_NIMBLE_TRANSPORT_UART_PORT @@ -1862,4 +2060,32 @@ #endif #endif +#ifndef MYNEWT_VAL_BLE_PERIODIC_ADV_WITH_RESPONSES +#ifdef CONFIG_BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES +#define MYNEWT_VAL_BLE_PERIODIC_ADV_WITH_RESPONSES (CONFIG_BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES) +#else +#define MYNEWT_VAL_BLE_PERIODIC_ADV_WITH_RESPONSES (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_HANDLE_REPEAT_PAIRING_DELETION +#ifdef CONFIG_BT_NIMBLE_HANDLE_REPEAT_PAIRING_DELETION +#define MYNEWT_VAL_BLE_HANDLE_REPEAT_PAIRING_DELETION (CONFIG_BT_NIMBLE_HANDLE_REPEAT_PAIRING_DELETION) +#else +#define MYNEWT_VAL_BLE_HANDLE_REPEAT_PAIRING_DELETION (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_ERR_CHECK +#ifdef CONFIG_BT_NIMBLE_PRINT_ERR_NAME +#define MYNEWT_VAL_BLE_ERR_CHECK CONFIG_BT_NIMBLE_PRINT_ERR_NAME +#else +#define MYNEWT_VAL_BLE_ERR_CHECK (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_USED_IN_IDF +#define MYNEWT_VAL_BLE_USED_IN_IDF (1) +#endif + #endif diff --git a/lib/bt/include/esp32/include/esp_bt.h b/lib/bt/include/esp32/include/esp_bt.h index b31ce276..0e9b5fd1 100644 --- a/lib/bt/include/esp32/include/esp_bt.h +++ b/lib/bt/include/esp32/include/esp_bt.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -50,38 +50,44 @@ extern "C" { #endif //CONFIG_BT_ENABLED -#define ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL 0x20240315 +/** +* @brief Internal use only +* +* @note Please do not modify this value +*/ +#define ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL 0x20250318 /** - * @brief Bluetooth mode for controller enable/disable + * @brief Bluetooth Controller mode */ typedef enum { - ESP_BT_MODE_IDLE = 0x00, /*!< Bluetooth is not running */ - ESP_BT_MODE_BLE = 0x01, /*!< Run BLE mode */ - ESP_BT_MODE_CLASSIC_BT = 0x02, /*!< Run Classic BT mode */ - ESP_BT_MODE_BTDM = 0x03, /*!< Run dual mode */ + ESP_BT_MODE_IDLE = 0x00, /*!< Bluetooth is not operating. */ + ESP_BT_MODE_BLE = 0x01, /*!< Bluetooth is operating in BLE mode. */ + ESP_BT_MODE_CLASSIC_BT = 0x02, /*!< Bluetooth is operating in Classic Bluetooth mode. */ + ESP_BT_MODE_BTDM = 0x03, /*!< Bluetooth is operating in Dual mode. */ } esp_bt_mode_t; /** - * @brief BLE sleep clock accuracy(SCA), values for ble_sca field in esp_bt_controller_config_t, - * currently only ESP_BLE_SCA_500PPM and ESP_BLE_SCA_250PPM are supported + * @brief BLE sleep clock accuracy (SCA) + * + * @note Currently only ESP_BLE_SCA_500PPM and ESP_BLE_SCA_250PPM are supported. */ -enum { - ESP_BLE_SCA_500PPM = 0, /*!< BLE SCA at 500ppm */ - ESP_BLE_SCA_250PPM, /*!< BLE SCA at 250ppm */ - ESP_BLE_SCA_150PPM, /*!< BLE SCA at 150ppm */ - ESP_BLE_SCA_100PPM, /*!< BLE SCA at 100ppm */ - ESP_BLE_SCA_75PPM, /*!< BLE SCA at 75ppm */ - ESP_BLE_SCA_50PPM, /*!< BLE SCA at 50ppm */ - ESP_BLE_SCA_30PPM, /*!< BLE SCA at 30ppm */ - ESP_BLE_SCA_20PPM, /*!< BLE SCA at 20ppm */ -}; +typedef enum { + ESP_BLE_SCA_500PPM = 0, /*!< BLE SCA at 500 ppm */ + ESP_BLE_SCA_250PPM, /*!< BLE SCA at 250 ppm */ + ESP_BLE_SCA_150PPM, /*!< BLE SCA at 150 ppm */ + ESP_BLE_SCA_100PPM, /*!< BLE SCA at 100 ppm */ + ESP_BLE_SCA_75PPM, /*!< BLE SCA at 75 ppm */ + ESP_BLE_SCA_50PPM, /*!< BLE SCA at 50 ppm */ + ESP_BLE_SCA_30PPM, /*!< BLE SCA at 30 ppm */ + ESP_BLE_SCA_20PPM, /*!< BLE SCA at 20 ppm */ +} esp_ble_sca_t; #ifdef CONFIG_BT_ENABLED /* While scanning, if the free memory value in controller is less than SCAN_SEND_ADV_RESERVED_SIZE, -the adv packet will be discarded until the memory is restored. */ +the advertising packet will be discarded until the memory is restored. */ #define SCAN_SEND_ADV_RESERVED_SIZE 1000 -/* enable controller log debug when adv lost */ +/* enable controller log debug when the advertising packet gets lost */ #define CONTROLLER_ADV_LOST_DEBUG_BIT (0<<0) #ifdef CONFIG_BTDM_CTRL_HCI_UART_NO @@ -102,7 +108,7 @@ the adv packet will be discarded until the memory is restored. */ #define SCAN_DUPLICATE_TYPE_VALUE 0 #endif -/* normal adv cache size */ +/* normal advertising cache size */ #ifdef CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE #define NORMAL_SCAN_DUPLICATE_CACHE_SIZE CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE #else @@ -173,6 +179,51 @@ the adv packet will be discarded until the memory is restored. */ #define BTDM_CTRL_SCAN_BACKOFF_UPPERLIMITMAX 0 #endif +#ifdef CONFIG_BTDM_BLE_LLCP_CONN_UPDATE +#define BTDM_BLE_LLCP_CONN_UPDATE (1<<0) +#else +#define BTDM_BLE_LLCP_CONN_UPDATE (0<<0) +#endif + +#ifdef CONFIG_BTDM_BLE_LLCP_CHAN_MAP_UPDATE +#define BTDM_BLE_LLCP_CHAN_MAP_UPDATE (1<<1) +#else +#define BTDM_BLE_LLCP_CHAN_MAP_UPDATE (0<<1) +#endif + +#define BTDM_BLE_LLCP_DISC_FLAG (BTDM_BLE_LLCP_CONN_UPDATE | BTDM_BLE_LLCP_CHAN_MAP_UPDATE) + +#ifdef CONFIG_BTDM_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS +#define BTDM_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS_ENABLED CONFIG_BTDM_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS +#else +#define BTDM_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS_ENABLED 0 +#endif + +#if defined(CONFIG_BTDM_BLE_CHAN_ASS_EN) +#define BTDM_BLE_CHAN_ASS_EN (CONFIG_BTDM_BLE_CHAN_ASS_EN) +#else +#define BTDM_BLE_CHAN_ASS_EN (0) +#endif + +#if CONFIG_BTDM_CTRL_CONTROLLER_DEBUG_MODE_1 +#define BTDM_CTRL_CONTROLLER_DEBUG_MODE_1 (1 << 1) +#else +#define BTDM_CTRL_CONTROLLER_DEBUG_MODE_1 0 +#endif + +#ifndef BTDM_CTRL_CONTROLLER_DEBUG_FLAG +#define BTDM_CTRL_CONTROLLER_DEBUG_FLAG (BTDM_CTRL_CONTROLLER_DEBUG_MODE_1 | CONTROLLER_ADV_LOST_DEBUG_BIT) +#endif + +#if defined(CONFIG_BTDM_BLE_PING_EN) +#define BTDM_BLE_PING_EN (CONFIG_BTDM_BLE_PING_EN) +#else +#define BTDM_BLE_PING_EN (0) +#endif + +/** +* @brief Default Bluetooth Controller configuration +*/ #define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \ .controller_task_stack_size = ESP_TASK_BT_CONTROLLER_STACK, \ .controller_task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \ @@ -183,7 +234,7 @@ the adv packet will be discarded until the memory is restored. */ .normal_adv_size = NORMAL_SCAN_DUPLICATE_CACHE_SIZE, \ .mesh_adv_size = MESH_DUPLICATE_SCAN_CACHE_SIZE, \ .send_adv_reserved_size = SCAN_SEND_ADV_RESERVED_SIZE, \ - .controller_debug_flag = CONTROLLER_ADV_LOST_DEBUG_BIT, \ + .controller_debug_flag = BTDM_CTRL_CONTROLLER_DEBUG_FLAG, \ .mode = BTDM_CONTROLLER_MODE_EFF, \ .ble_max_conn = CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF, \ .bt_max_acl_conn = CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF, \ @@ -194,112 +245,158 @@ the adv packet will be discarded until the memory is restored. */ .ble_sca = CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF, \ .pcm_role = CONFIG_BTDM_CTRL_PCM_ROLE_EFF, \ .pcm_polar = CONFIG_BTDM_CTRL_PCM_POLAR_EFF, \ + .pcm_fsyncshp = CONFIG_BTDM_CTRL_PCM_FSYNCSHP_EFF, \ .hli = BTDM_CTRL_HLI, \ + .enc_key_sz_min = CONFIG_BTDM_CTRL_BR_EDR_MIN_ENC_KEY_SZ_DFT_EFF, \ .dup_list_refresh_period = SCAN_DUPL_CACHE_REFRESH_PERIOD, \ .ble_scan_backoff = BTDM_CTRL_SCAN_BACKOFF_UPPERLIMITMAX, \ + .ble_llcp_disc_flag = BTDM_BLE_LLCP_DISC_FLAG, \ + .ble_aa_check = BTDM_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS_ENABLED, \ + .ble_chan_ass_en = BTDM_BLE_CHAN_ASS_EN, \ + .ble_ping_en = BTDM_BLE_PING_EN, \ .magic = ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL, \ } #else +/** +* @brief Default Bluetooth Controller configuration +*/ #define BT_CONTROLLER_INIT_CONFIG_DEFAULT() {0}; ESP_STATIC_ASSERT(0, "please enable bluetooth in menuconfig to use esp_bt.h"); #endif /** - * @brief Controller config options, depend on config mask. - * Config mask indicate which functions enabled, this means - * some options or parameters of some functions enabled by config mask. + * @brief Bluetooth Controller config options + * @note + * 1. For parameters configurable through menuconfig, it is recommended to adjust them via the menuconfig interface. Please refer to menuconfig for details on the range and default values. + * 2. It is not recommended to modify the values for parameters which are not configurable through menuconfig. */ typedef struct { - /* - * Following parameters can be configured runtime, when call esp_bt_controller_init() - */ - uint16_t controller_task_stack_size; /*!< Bluetooth controller task stack size */ - uint8_t controller_task_prio; /*!< Bluetooth controller task priority */ - uint8_t hci_uart_no; /*!< If use UART1/2 as HCI IO interface, indicate UART number */ - uint32_t hci_uart_baudrate; /*!< If use UART1/2 as HCI IO interface, indicate UART baudrate */ - uint8_t scan_duplicate_mode; /*!< scan duplicate mode */ - uint8_t scan_duplicate_type; /*!< scan duplicate type */ - uint16_t normal_adv_size; /*!< Normal adv size for scan duplicate */ - uint16_t mesh_adv_size; /*!< Mesh adv size for scan duplicate */ - uint16_t send_adv_reserved_size; /*!< Controller minimum memory value */ - uint32_t controller_debug_flag; /*!< Controller debug log flag */ - uint8_t mode; /*!< Controller mode: BR/EDR, BLE or Dual Mode */ - uint8_t ble_max_conn; /*!< BLE maximum connection numbers */ - uint8_t bt_max_acl_conn; /*!< BR/EDR maximum ACL connection numbers */ - uint8_t bt_sco_datapath; /*!< SCO data path, i.e. HCI or PCM module */ - bool auto_latency; /*!< BLE auto latency, used to enhance classic BT performance */ - bool bt_legacy_auth_vs_evt; /*!< BR/EDR Legacy auth complete event required to protect from BIAS attack */ - /* - * Following parameters can not be configured runtime when call esp_bt_controller_init() - * It will be overwrite with a constant value which in menuconfig or from a macro. - * So, do not modify the value when esp_bt_controller_init() - */ - uint8_t bt_max_sync_conn; /*!< BR/EDR maximum ACL connection numbers. Effective in menuconfig */ - uint8_t ble_sca; /*!< BLE low power crystal accuracy index */ - uint8_t pcm_role; /*!< PCM role (master & slave)*/ - uint8_t pcm_polar; /*!< PCM polar trig (falling clk edge & rising clk edge) */ - bool hli; /*!< Using high level interrupt or not */ - uint16_t dup_list_refresh_period; /*!< Duplicate scan list refresh period */ - bool ble_scan_backoff; /*!< BLE scan backoff */ + uint16_t controller_task_stack_size; /*!< Bluetooth Controller task stack size in bytes */ + uint8_t controller_task_prio; /*!< Bluetooth Controller task priority */ + uint8_t hci_uart_no; /*!< UART number as HCI I/O interface. Configurable in menuconfig. + - 1 - URAT 1 (default) + - 2 - URAT 2 */ + uint32_t hci_uart_baudrate; /*!< UART baudrate. Configurable in menuconfig. + - Range: 115200 - 921600 + - Default: 921600 */ + uint8_t scan_duplicate_mode; /*!< Scan duplicate filtering mode. Configurable in menuconfig. + - 0 - Normal scan duplicate filtering mode (default) + - 1 - Special scan duplicate filtering mode for BLE Mesh */ + uint8_t scan_duplicate_type; /*!< Scan duplicate filtering type. If `scan_duplicate_mode` is set to 1, this parameter will be ignored. Configurable in menuconfig. + - 0 - Filter scan duplicates by device address only (default) + - 1 - Filter scan duplicates by advertising data only, even if they originate from different devices. + - 2 - Filter scan duplicated by device address and advertising data. */ + uint16_t normal_adv_size; /*!< Maximum number of devices in scan duplicate filtering list. Configurable in menuconfig + - Range: 10 - 1000 + - Default: 100 */ + uint16_t mesh_adv_size; /*!< Maximum number of Mesh advertising packets in scan duplicate filtering list. Configurable in menuconfig + - Range: 10 - 1000 + - Default: 100 */ + uint16_t send_adv_reserved_size; /*!< Controller minimum memory value in bytes. Internal use only */ + uint32_t controller_debug_flag; /*!< Controller debug log flag. Internal use only */ + uint8_t mode; /*!< Controller mode. Configurable in menuconfig + - 1 - BLE mode + - 2 - Classic Bluetooth mode + - 3 - Dual mode + - 4 - Others: Invalid */ + uint8_t ble_max_conn; /*!< Maximum number of BLE connections. Configurable in menuconfig + - Range: 1 - 9 + - Default: 3 */ + uint8_t bt_max_acl_conn; /*!< Maximum number of BR/EDR ACL connections. Configurable in menuconfig + - Range: 1 - 7 + - Default: 2 */ + uint8_t bt_sco_datapath; /*!< SCO data path. Configurable in menuconfig + - 0 - HCI module (default) + - 1 - PCM module */ + bool auto_latency; /*!< True if BLE auto latency is enabled, used to enhance Classic Bluetooth performance in the Dual mode; false otherwise (default). Configurable in menuconfig */ + bool bt_legacy_auth_vs_evt; /*!< True if BR/EDR Legacy Authentication Vendor Specific Event is enabled (default in the classic bluetooth or Dual mode), which is required to protect from BIAS attack; false otherwise. Configurable in menuconfig */ + uint8_t bt_max_sync_conn; /*!< Maximum number of BR/EDR synchronous connections. Configurable in menuconfig + - Range: 0 - 3 + - Default: 0 */ + uint8_t ble_sca; /*!< BLE low power crystal accuracy index. Configurable in menuconfig + - 0 - `BTDM_BLE_DEFAULT_SCA_500PPM` + - 1 - `BTDM_BLE_DEFAULT_SCA_250PPM` (default) */ + uint8_t pcm_role; /*!< PCM role. Configurable in menuconfig + - 0 - PCM master (default) + - 1 - PCM slave (default) */ + uint8_t pcm_polar; /*!< PCM polarity (falling clk edge & rising clk edge). Configurable in menuconfig + - 0 - Falling Edge (default) + - 1 - Rising Edge */ + uint8_t pcm_fsyncshp; /*!< Physical shape of the PCM Frame Synchronization signal. Configurable in menuconfig + - 0 - Stereo Mode (default) + - 1 - Mono Mode 1 + - 2 - Mono Mode 2 */ + bool hli; /*!< True if using high-level (level 4) interrupt (default); false otherwise. Configurable in menuconfig */ + uint8_t enc_key_sz_min; /*!< Minimum size of the encryption key + - Range: 7 - 16 + - Default: 7 */ + uint16_t dup_list_refresh_period; /*!< Scan duplicate filtering list refresh period in seconds. Configurable in menuconfig + - Range: 0 - 100 seconds + - Default: 0 second */ + bool ble_scan_backoff; /*!< True if BLE scan backoff is enabled; false otherwise (default). Configurable in menuconfig */ + uint8_t ble_llcp_disc_flag; /*!< Flag indicating whether the Controller disconnects after Instant Passed (0x28) error occurs. Configurable in menuconfig. + - The Controller does not disconnect after Instant Passed (0x28) by default. */ + bool ble_aa_check; /*!< True if adds a verification step for the Access Address within the `CONNECT_IND` PDU; false otherwise (default). Configurable in menuconfig */ + uint8_t ble_chan_ass_en; /*!< True if BLE channel assessment is enabled (default), false otherwise. Configurable in menuconfig */ + uint8_t ble_ping_en; /*!< True if BLE ping procedure is enabled (default), false otherwise. Configurable in menuconfig */ uint32_t magic; /*!< Magic number */ } esp_bt_controller_config_t; /** - * @brief Bluetooth controller enable/disable/initialised/de-initialised status + * @brief Bluetooth Controller status */ typedef enum { - ESP_BT_CONTROLLER_STATUS_IDLE = 0, - ESP_BT_CONTROLLER_STATUS_INITED, - ESP_BT_CONTROLLER_STATUS_ENABLED, - ESP_BT_CONTROLLER_STATUS_NUM, + ESP_BT_CONTROLLER_STATUS_IDLE = 0, /*!< The Controller is not initialized or has been de-initialized. */ + ESP_BT_CONTROLLER_STATUS_INITED, /*!< The Controller has been initialized, but not enabled or has been disabled. */ + ESP_BT_CONTROLLER_STATUS_ENABLED, /*!< The Controller has been initialized and enabled. */ + ESP_BT_CONTROLLER_STATUS_NUM, /*!< Number of Controller statuses */ } esp_bt_controller_status_t; /** - * @brief BLE tx power type - * ESP_BLE_PWR_TYPE_CONN_HDL0-8: for each connection, and only be set after connection completed. - * when disconnect, the correspond TX power is not effected. - * ESP_BLE_PWR_TYPE_ADV : for advertising/scan response. - * ESP_BLE_PWR_TYPE_SCAN : for scan. - * ESP_BLE_PWR_TYPE_DEFAULT : if each connection's TX power is not set, it will use this default value. - * if neither in scan mode nor in adv mode, it will use this default value. - * If none of power type is set, system will use ESP_PWR_LVL_P3 as default for ADV/SCAN/CONN0-9. + * @brief BLE TX power type + * @note + * 1. The connection TX power can only be set after the connection is established. + * After disconnecting, the corresponding TX power will not be affected. + * 2. `ESP_BLE_PWR_TYPE_DEFAULT` can be used to set the TX power for power types that have not been set before. + * It will not affect the TX power values which have been set for the ADV/SCAN/CONN0-8 power types. + * 3. If none of power type is set, the system will use `ESP_PWR_LVL_P3` as default for all power types. */ typedef enum { - ESP_BLE_PWR_TYPE_CONN_HDL0 = 0, /*!< For connection handle 0 */ - ESP_BLE_PWR_TYPE_CONN_HDL1 = 1, /*!< For connection handle 1 */ - ESP_BLE_PWR_TYPE_CONN_HDL2 = 2, /*!< For connection handle 2 */ - ESP_BLE_PWR_TYPE_CONN_HDL3 = 3, /*!< For connection handle 3 */ - ESP_BLE_PWR_TYPE_CONN_HDL4 = 4, /*!< For connection handle 4 */ - ESP_BLE_PWR_TYPE_CONN_HDL5 = 5, /*!< For connection handle 5 */ - ESP_BLE_PWR_TYPE_CONN_HDL6 = 6, /*!< For connection handle 6 */ - ESP_BLE_PWR_TYPE_CONN_HDL7 = 7, /*!< For connection handle 7 */ - ESP_BLE_PWR_TYPE_CONN_HDL8 = 8, /*!< For connection handle 8 */ - ESP_BLE_PWR_TYPE_ADV = 9, /*!< For advertising */ - ESP_BLE_PWR_TYPE_SCAN = 10, /*!< For scan */ - ESP_BLE_PWR_TYPE_DEFAULT = 11, /*!< For default, if not set other, it will use default value */ - ESP_BLE_PWR_TYPE_NUM = 12, /*!< TYPE numbers */ + ESP_BLE_PWR_TYPE_CONN_HDL0 = 0, /*!< TX power for connection handle 0 */ + ESP_BLE_PWR_TYPE_CONN_HDL1 = 1, /*!< TX power for connection handle 1 */ + ESP_BLE_PWR_TYPE_CONN_HDL2 = 2, /*!< TX power for connection handle 2 */ + ESP_BLE_PWR_TYPE_CONN_HDL3 = 3, /*!< TX power for connection handle 3 */ + ESP_BLE_PWR_TYPE_CONN_HDL4 = 4, /*!< TX power for connection handle 4 */ + ESP_BLE_PWR_TYPE_CONN_HDL5 = 5, /*!< TX power for connection handle 5 */ + ESP_BLE_PWR_TYPE_CONN_HDL6 = 6, /*!< TX power for connection handle 6 */ + ESP_BLE_PWR_TYPE_CONN_HDL7 = 7, /*!< TX power for connection handle 7 */ + ESP_BLE_PWR_TYPE_CONN_HDL8 = 8, /*!< TX power for connection handle 8 */ + ESP_BLE_PWR_TYPE_ADV = 9, /*!< TX power for advertising */ + ESP_BLE_PWR_TYPE_SCAN = 10, /*!< TX power for scan */ + ESP_BLE_PWR_TYPE_DEFAULT = 11, /*!< Default TX power type, which can be used to set the TX power for power types that have not been set before.*/ + ESP_BLE_PWR_TYPE_NUM = 12, /*!< Number of types */ } esp_ble_power_type_t; /** - * @brief Bluetooth TX power level(index), it's just a index corresponding to power(dbm). + * @brief Bluetooth TX power level (index). Each index corresponds to a specific power value in dBm. */ typedef enum { - ESP_PWR_LVL_N12 = 0, /*!< Corresponding to -12dbm */ - ESP_PWR_LVL_N9 = 1, /*!< Corresponding to -9dbm */ - ESP_PWR_LVL_N6 = 2, /*!< Corresponding to -6dbm */ - ESP_PWR_LVL_N3 = 3, /*!< Corresponding to -3dbm */ - ESP_PWR_LVL_N0 = 4, /*!< Corresponding to 0dbm */ - ESP_PWR_LVL_P3 = 5, /*!< Corresponding to +3dbm */ - ESP_PWR_LVL_P6 = 6, /*!< Corresponding to +6dbm */ - ESP_PWR_LVL_P9 = 7, /*!< Corresponding to +9dbm */ - ESP_PWR_LVL_N14 = ESP_PWR_LVL_N12, /*!< Backward compatibility! Setting to -14dbm will actually result to -12dbm */ - ESP_PWR_LVL_N11 = ESP_PWR_LVL_N9, /*!< Backward compatibility! Setting to -11dbm will actually result to -9dbm */ - ESP_PWR_LVL_N8 = ESP_PWR_LVL_N6, /*!< Backward compatibility! Setting to -8dbm will actually result to -6dbm */ - ESP_PWR_LVL_N5 = ESP_PWR_LVL_N3, /*!< Backward compatibility! Setting to -5dbm will actually result to -3dbm */ - ESP_PWR_LVL_N2 = ESP_PWR_LVL_N0, /*!< Backward compatibility! Setting to -2dbm will actually result to 0dbm */ - ESP_PWR_LVL_P1 = ESP_PWR_LVL_P3, /*!< Backward compatibility! Setting to +1dbm will actually result to +3dbm */ - ESP_PWR_LVL_P4 = ESP_PWR_LVL_P6, /*!< Backward compatibility! Setting to +4dbm will actually result to +6dbm */ - ESP_PWR_LVL_P7 = ESP_PWR_LVL_P9, /*!< Backward compatibility! Setting to +7dbm will actually result to +9dbm */ + ESP_PWR_LVL_N12 = 0, /*!< Corresponding to -12 dBm */ + ESP_PWR_LVL_N9 = 1, /*!< Corresponding to -9 dBm */ + ESP_PWR_LVL_N6 = 2, /*!< Corresponding to -6 dBm */ + ESP_PWR_LVL_N3 = 3, /*!< Corresponding to -3 dBm */ + ESP_PWR_LVL_N0 = 4, /*!< Corresponding to 0 dBm */ + ESP_PWR_LVL_P3 = 5, /*!< Corresponding to +3 dBm */ + ESP_PWR_LVL_P6 = 6, /*!< Corresponding to +6 dBm */ + ESP_PWR_LVL_P9 = 7, /*!< Corresponding to +9 dBm */ + ESP_PWR_LVL_N14 = ESP_PWR_LVL_N12, /*!< Backward compatibility! Setting to -14 dBm will actually result in -12 dBm */ + ESP_PWR_LVL_N11 = ESP_PWR_LVL_N9, /*!< Backward compatibility! Setting to -11 dBm will actually result in -9 dBm */ + ESP_PWR_LVL_N8 = ESP_PWR_LVL_N6, /*!< Backward compatibility! Setting to -8 dBm will actually result in -6 dBm */ + ESP_PWR_LVL_N5 = ESP_PWR_LVL_N3, /*!< Backward compatibility! Setting to -5 dBm will actually result in -3 dBm */ + ESP_PWR_LVL_N2 = ESP_PWR_LVL_N0, /*!< Backward compatibility! Setting to -2 dBm will actually result in 0 dBm */ + ESP_PWR_LVL_P1 = ESP_PWR_LVL_P3, /*!< Backward compatibility! Setting to +1 dBm will actually result in +3 dBm */ + ESP_PWR_LVL_P4 = ESP_PWR_LVL_P6, /*!< Backward compatibility! Setting to +4 dBm will actually result in +6 dBm */ + ESP_PWR_LVL_P7 = ESP_PWR_LVL_P9, /*!< Backward compatibility! Setting to +7 dBm will actually result in +9 dBm */ } esp_power_level_t; /** @@ -311,245 +408,334 @@ typedef enum { } esp_sco_data_path_t; /** - * @brief Set BLE TX power - * Connection Tx power should only be set after connection created. - * @param power_type : The type of which tx power, could set Advertising/Connection/Default and etc - * @param power_level: Power level(index) corresponding to absolute value(dbm) - * @return ESP_OK - success, other - failed - */ -esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_t power_level); - -/** - * @brief Get BLE TX power - * Connection Tx power should only be get after connection created. - * @param power_type : The type of which tx power, could set Advertising/Connection/Default and etc - * @return >= 0 - Power level, < 0 - Invalid - */ -esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type); - -/** - * @brief Set BR/EDR TX power - * BR/EDR power control will use the power in range of minimum value and maximum value. - * The power level will effect the global BR/EDR TX power, such inquire, page, connection and so on. - * Please call the function after esp_bt_controller_enable and before any function which cause RF do TX. - * So you can call the function before doing discovery, profile init and so on. - * For example, if you want BR/EDR use the new TX power to do inquire, you should call - * this function before inquire. Another word, If call this function when BR/EDR is in inquire(ING), - * please do inquire again after call this function. - * Default minimum power level is ESP_PWR_LVL_N0, and maximum power level is ESP_PWR_LVL_P3. - * @param min_power_level: The minimum power level - * @param max_power_level: The maximum power level - * @return ESP_OK - success, other - failed - */ -esp_err_t esp_bredr_tx_power_set(esp_power_level_t min_power_level, esp_power_level_t max_power_level); - -/** - * @brief Get BR/EDR TX power - * If the argument is not NULL, then store the corresponding value. - * @param min_power_level: The minimum power level - * @param max_power_level: The maximum power level - * @return ESP_OK - success, other - failed - */ -esp_err_t esp_bredr_tx_power_get(esp_power_level_t *min_power_level, esp_power_level_t *max_power_level); - -/** - * @brief Set default SCO data path - * Should be called after controller is enabled, and before (e)SCO link is established - * @param data_path: SCO data path - * @return ESP_OK - success, other - failed + * @brief Bluetooth sleep clock */ -esp_err_t esp_bredr_sco_datapath_set(esp_sco_data_path_t data_path); +typedef enum { + ESP_BT_SLEEP_CLOCK_NONE = 0, /*!< Sleep clock not configured */ + ESP_BT_SLEEP_CLOCK_MAIN_XTAL = 1, /*!< SoC main crystal */ + ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL = 2, /*!< External 32.768kHz crystal/oscillator */ +} esp_bt_sleep_clock_t; /** - * @brief Initialize BT controller to allocate task and other resource. - * This function should be called only once, before any other BT functions are called. - * @param cfg: Initial configuration of BT controller. Different from previous version, there's a mode and some - * connection configuration in "cfg" to configure controller work mode and allocate the resource which is needed. - * @return ESP_OK - success, other - failed + * @brief Initialize the Bluetooth Controller to allocate tasks and other resources + * + * @note This function should be called only once, before any other Bluetooth functions. + * + * @param[in] cfg Initial Bluetooth Controller configuration + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state + * - ESP_ERR_INVALID_ARG: Invalid arguments + * - ESP_ERR_NO_MEM: Out of memory */ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg); /** - * @brief De-initialize BT controller to free resource and delete task. - * You should stop advertising and scanning, as well as - * disconnect all existing connections before de-initializing BT controller. + * @brief De-initialize Bluetooth Controller to free resources and delete tasks * - * This function should be called only once, after any other BT functions are called. - * @return ESP_OK - success, other - failed + * @note + * 1. You should stop advertising and scanning, and disconnect all existing connections before de-initializing Bluetooth Controller. + * 2. This function should be called after `esp_bt_controller_disable` if the Controller was enabled before. + * 3. This function should be called only once, after any other Bluetooth functions. + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state */ esp_err_t esp_bt_controller_deinit(void); /** - * @brief Enable BT controller. - * Due to a known issue, you cannot call esp_bt_controller_enable() a second time - * to change the controller mode dynamically. To change controller mode, call - * esp_bt_controller_disable() and then call esp_bt_controller_enable() with the new mode. - * @param mode : the mode(BLE/BT/BTDM) to enable. For compatible of API, retain this argument. This mode must be - * equal as the mode in "cfg" of esp_bt_controller_init(). - * @return ESP_OK - success, other - failed + * @brief Enable Bluetooth Controller + * + * @note + * 1. Bluetooth Controller cannot be enabled in `ESP_BT_CONTROLLER_STATUS_IDLE` status. It has to be initialized first. + * 2. Due to a known issue, you cannot call `esp_bt_controller_enable()` for the second time + * to change the Controller mode dynamically. To change the Controller mode, call + * `esp_bt_controller_disable()` and then call `esp_bt_controller_enable()` with the new mode. + * + * @param[in] mode The Bluetooth Controller mode (BLE/Classic Bluetooth/BTDM) to enable + * + * For API compatibility, retain this argument. This mode must match the mode specified in the `cfg` of `esp_bt_controller_init()`. + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state + * - ESP_ERR_INVALID_ARG: Invalid arguments */ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode); /** - * @brief Disable BT controller - * @return ESP_OK - success, other - failed + * @brief Disable Bluetooth Controller + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state */ esp_err_t esp_bt_controller_disable(void); /** - * @brief Get BT controller is initialised/de-initialised/enabled/disabled - * @return status value + * @brief Get Bluetooth Controller status + * + * @return + * - ESP_BT_CONTROLLER_STATUS_IDLE: The Controller is not initialized or has been de-initialized. + * - ESP_BT_CONTROLLER_STATUS_INITED: The Controller has been initialized, but not enabled or has been disabled. + * - ESP_BT_CONTROLLER_STATUS_ENABLED: The Controller has been initialized and enabled. */ esp_bt_controller_status_t esp_bt_controller_get_status(void); -/** @brief esp_vhci_host_callback - * used for vhci call host function to notify what host need to do +/** + * @brief Release the Controller memory as per the mode + * + * This function releases the BSS, data and other sections of the Controller to heap. The total size is about 70 KB. + * + * @note + * 1. This function is optional and should be called only if you want to free up memory for other components. + * 2. This function should only be called when the Controller is in `ESP_BT_CONTROLLER_STATUS_IDLE` status. + * 3. Once Bluetooth Controller memory is released, the process cannot be reversed. This means you cannot use the Bluetooth Controller mode that you have released using this function. + * 4. If your firmware will upgrade the Bluetooth Controller mode later (such as switching from BLE to Classic Bluetooth or from disabled to enabled), then do not call this function. + * + * If you never intend to use Bluetooth in a current boot-up cycle, calling `esp_bt_controller_mem_release(ESP_BT_MODE_BTDM)` could release the BSS and data consumed by both Classic Bluetooth and BLE Controller to heap. + * + * If you intend to use BLE only, calling `esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT)` could release the BSS and data consumed by Classic Bluetooth Controller. You can then continue using BLE. + * + * If you intend to use Classic Bluetooth only, calling `esp_bt_controller_mem_release(ESP_BT_MODE_BLE)` could release the BSS and data consumed by BLE Controller. You can then continue using Classic Bluetooth. + * + * + * @param[in] mode The Bluetooth Controller mode + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state + * - ESP_ERR_NOT_FOUND: Requested resource not found */ -typedef struct esp_vhci_host_callback { - void (*notify_host_send_available)(void); /*!< callback used to notify that the host can send packet to controller */ - int (*notify_host_recv)(uint8_t *data, uint16_t len); /*!< callback used to notify that the controller has a packet to send to the host*/ -} esp_vhci_host_callback_t; +esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode); -/** @brief esp_vhci_host_check_send_available - * used for check actively if the host can send packet to controller or not. - * @return true for ready to send, false means cannot send packet +/** @brief Release the Controller memory, BSS and data section of the Classic Bluetooth/BLE Host stack as per the mode + * + * @note + * 1. This function is optional and should be called only if you want to free up memory for other components. + * 2. This function should only be called when the Controller is in `ESP_BT_CONTROLLER_STATUS_IDLE` status. + * 3. Once Bluetooth Controller memory is released, the process cannot be reversed. This means you cannot use the Bluetooth Controller mode that you have released using this function. + * 4. If your firmware will upgrade the Bluetooth Controller mode later (such as switching from BLE to Classic Bluetooth or from disabled to enabled), then do not call this function. + * + * This function first releases Controller memory by internally calling `esp_bt_controller_mem_release()`, then releases Host memory. + * + * If you never intend to use Bluetooth in a current boot-up cycle, calling `esp_bt_mem_release(ESP_BT_MODE_BTDM)` could release the BSS and data consumed by both Classic Bluetooth and BLE stack to heap. + * + * If you intend to use BLE only, calling `esp_bt_mem_release(ESP_BT_MODE_CLASSIC_BT)` could release the BSS and data consumed by Classic Bluetooth. You can then continue using BLE. + * + * If you intend to use Classic Bluetooth only, calling `esp_bt_mem_release(ESP_BT_MODE_BLE)` could release the BSS and data consumed by BLE. You can then continue using Classic Bluetooth. + * + * For example, if you only use Bluetooth for setting the Wi-Fi configuration, and do not use Bluetooth in the rest of the product operation, + * after receiving the Wi-Fi configuration, you can disable/de-init Bluetooth and release its memory. + * Below is the sequence of APIs to be called for such scenarios: + * + * esp_bluedroid_disable(); + * esp_bluedroid_deinit(); + * esp_bt_controller_disable(); + * esp_bt_controller_deinit(); + * esp_bt_mem_release(ESP_BT_MODE_BTDM); + * + * @param[in] mode The Bluetooth Controller mode + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state + * - ESP_ERR_NOT_FOUND: Requested resource not found */ -bool esp_vhci_host_check_send_available(void); +esp_err_t esp_bt_mem_release(esp_bt_mode_t mode); -/** @brief esp_vhci_host_send_packet - * host send packet to controller +/** + * @brief Enable Bluetooth modem sleep + * + * There are currently two options for Bluetooth modem sleep: ORIG mode and EVED mode. The latter is intended for BLE only. + * The modem sleep mode could be configured in menuconfig. * - * Should not call this function from within a critical section - * or when the scheduler is suspended. + * In ORIG mode, if there is no event to process, the Bluetooth Controller will periodically switch off some components and pause operation, then wake up according to the scheduled interval and resume work. + * It can also wakeup earlier upon external request using function `esp_bt_controller_wakeup_request()`. * - * @param data the packet point - * @param len the packet length + * @note This function shall not be invoked before `esp_bt_controller_enable()`. + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state + * - ESP_ERR_NOT_SUPPORTED: Operation or feature not supported */ -void esp_vhci_host_send_packet(uint8_t *data, uint16_t len); +esp_err_t esp_bt_sleep_enable(void); -/** @brief esp_vhci_host_register_callback - * register the vhci reference callback - * struct defined by vhci_host_callback structure. - * @param callback esp_vhci_host_callback type variable - * @return ESP_OK - success, ESP_FAIL - failed +/** + * @brief Disable Bluetooth modem sleep + * + * @note + * 1. Bluetooth Controller will not be allowed to enter modem sleep after calling this function. + * 2. In ORIG modem sleep mode, calling this function may not immediately wake up the Controller if it is currently dormant. + * In this case, `esp_bt_controller_wakeup_request()` can be used to shorten the wake-up time. + * 3. This function shall not be invoked before `esp_bt_controller_enable()`. + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state + * - ESP_ERR_NOT_SUPPORTED: The modem sleep mode is not supported */ -esp_err_t esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback); +esp_err_t esp_bt_sleep_disable(void); -/** @brief esp_bt_controller_mem_release - * release the controller memory as per the mode +/** + * @brief Set BLE TX power * - * This function releases the BSS, data and other sections of the controller to heap. The total size is about 70k bytes. + * @note Connection TX power should only be set after the connection is established. * - * esp_bt_controller_mem_release(mode) should be called only before esp_bt_controller_init() - * or after esp_bt_controller_deinit(). + * @param[in] power_type The type of TX power. It could be Advertising, Connection, Default, etc. + * @param[in] power_level Power level (index) corresponding to the absolute value (dBm) * - * Note that once BT controller memory is released, the process cannot be reversed. It means you cannot use the bluetooth - * mode which you have released by this function. + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: Invalid argument + */ +esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_t power_level); + +/** + * @brief Get BLE TX power * - * If your firmware will later upgrade the Bluetooth controller mode (BLE -> BT Classic or disabled -> enabled) - * then do not call this function. + * @note Connection TX power should only be retrieved after the connection is established. * - * If the app calls esp_bt_controller_enable(ESP_BT_MODE_BLE) to use BLE only then it is safe to call - * esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT) at initialization time to free unused BT Classic memory. + * @param[in] power_type The type of TX power. It could be Advertising/Connection/Default and etc. * - * If the mode is ESP_BT_MODE_BTDM, then it may be useful to call API esp_bt_mem_release(ESP_BT_MODE_BTDM) instead, - * which internally calls esp_bt_controller_mem_release(ESP_BT_MODE_BTDM) and additionally releases the BSS and data - * consumed by the BT/BLE host stack to heap. For more details about usage please refer to the documentation of - * esp_bt_mem_release() function + * @return + * - Power level * - * @param mode : the mode want to release memory - * @return ESP_OK - success, other - failed */ -esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode); +esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type); -/** @brief esp_bt_mem_release - * release controller memory and BSS and data section of the BT/BLE host stack as per the mode - * - * This function first releases controller memory by internally calling esp_bt_controller_mem_release(). - * Additionally, if the mode is set to ESP_BT_MODE_BTDM, it also releases the BSS and data consumed by the BT/BLE host stack to heap +/** + * @brief Manually clear the BLE scan duplicate list * - * Note that once BT memory is released, the process cannot be reversed. It means you cannot use the bluetooth - * mode which you have released by this function. + * @note + * 1. This function name is incorrectly spelled, it will be fixed in release 5.x version. + * 2. The scan duplicate list will be automatically cleared when the maximum amount of devices in the filter is reached. + * The amount of devices in the filter can be configured in menuconfig. * - * If your firmware will later upgrade the Bluetooth controller mode (BLE -> BT Classic or disabled -> enabled) - * then do not call this function. + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state + */ +esp_err_t esp_ble_scan_duplicate_list_flush(void); +esp_err_t esp_ble_scan_dupilcate_list_flush(void); + +/** + * @brief Set BR/EDR TX power * - * If you never intend to use bluetooth in a current boot-up cycle, you can call esp_bt_mem_release(ESP_BT_MODE_BTDM) - * before esp_bt_controller_init or after esp_bt_controller_deinit. + * BR/EDR power control will use the power within the range of minimum value and maximum value. + * The power level will affect the global BR/EDR TX power for operations such as inquiry, page, and connection. * - * For example, if a user only uses bluetooth for setting the WiFi configuration, and does not use bluetooth in the rest of the product operation". - * In such cases, after receiving the WiFi configuration, you can disable/deinit bluetooth and release its memory. - * Below is the sequence of APIs to be called for such scenarios: + * @note + * 1. Please call this function after `esp_bt_controller_enable()` and before any functions that cause RF transmission, + * such as performing discovery, profile initialization, and so on. + * 2. For BR/EDR to use the new TX power for inquiry, call this function before starting an inquiry. + * If BR/EDR is already inquiring, restart the inquiry after calling this function. * - * esp_bluedroid_disable(); - * esp_bluedroid_deinit(); - * esp_bt_controller_disable(); - * esp_bt_controller_deinit(); - * esp_bt_mem_release(ESP_BT_MODE_BTDM); + * @param[in] min_power_level The minimum power level. The default value is `ESP_PWR_LVL_N0`. + * @param[in] max_power_level The maximum power level. The default value is `ESP_PWR_LVL_P3`. * - * @note In case of NimBLE host, to release BSS and data memory to heap, the mode needs to be - * set to ESP_BT_MODE_BTDM as controller is dual mode. - * @param mode : the mode whose memory is to be released - * @return ESP_OK - success, other - failed + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state */ -esp_err_t esp_bt_mem_release(esp_bt_mode_t mode); +esp_err_t esp_bredr_tx_power_set(esp_power_level_t min_power_level, esp_power_level_t max_power_level); /** - * @brief enable bluetooth to enter modem sleep + * @brief Get BR/EDR TX power * - * Note that this function shall not be invoked before esp_bt_controller_enable() + * The corresponding power levels will be stored into the arguments. * - * There are currently two options for bluetooth modem sleep, one is ORIG mode, and another is EVED Mode. EVED Mode is intended for BLE only. + * @param[out] min_power_level Pointer to store the minimum power level + * @param[out] max_power_level The maximum power level * - * For ORIG mode: - * Bluetooth modem sleep is enabled in controller start up by default if CONFIG_CTRL_BTDM_MODEM_SLEEP is set and "ORIG mode" is selected. In ORIG modem sleep mode, bluetooth controller will switch off some components and pause to work every now and then, if there is no event to process; and wakeup according to the scheduled interval and resume the work. It can also wakeup earlier upon external request using function "esp_bt_controller_wakeup_request". + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: Invalid argument + */ +esp_err_t esp_bredr_tx_power_get(esp_power_level_t *min_power_level, esp_power_level_t *max_power_level); + +/** + * @brief Set BR/EDR default SCO data path + * + * @note This function should be called after the Controller is enabled, and before (e)SCO link is established. + * + * @param[in] data_path SCO data path * * @return - * - ESP_OK : success - * - other : failed + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state */ -esp_err_t esp_bt_sleep_enable(void); +esp_err_t esp_bredr_sco_datapath_set(esp_sco_data_path_t data_path); +/** + * @brief Virtual HCI (VHCI) callback functions to notify the Host on the next operation + */ +typedef struct esp_vhci_host_callback { + void (*notify_host_send_available)(void); /*!< Callback to notify the Host that the Controller is ready to receive the HCI data */ + int (*notify_host_recv)(uint8_t *data, uint16_t len); /*!< Callback to notify the Host that the Controller has the HCI data to send */ +} esp_vhci_host_callback_t; /** - * @brief disable bluetooth modem sleep - * - * Note that this function shall not be invoked before esp_bt_controller_enable() + * @brief Check whether the Controller is ready to receive the HCI data from the Host * - * If esp_bt_sleep_disable() is called, bluetooth controller will not be allowed to enter modem sleep; + * If the return value is True, the Host can send the HCI data to the Controller. * - * If ORIG modem sleep mode is in use, if this function is called, bluetooth controller may not immediately wake up if it is dormant then. - * In this case, esp_bt_controller_wakeup_request() can be used to shorten the time for wakeup. + * @note This function should be called before each `esp_vhci_host_send_packet()`. * * @return - * - ESP_OK : success - * - other : failed + * True if the Controller is ready to receive the HCI data; false otherwise */ -esp_err_t esp_bt_sleep_disable(void); +bool esp_vhci_host_check_send_available(void); /** - * @brief Manually clear scan duplicate list + * @brief Send the HCI data to the Controller * - * Note that scan duplicate list will be automatically cleared when the maximum amount of device in the filter is reached - * the amount of device in the filter can be configured in menuconfig. + * @note + * 1. This function shall not be called within a critical section or when the scheduler is suspended. + * 2. This function should be called only if `esp_vhci_host_check_send_available()` returns True. + * + * @param[in] data Pointer to the HCI data + * @param[in] len The HCI data length + */ +void esp_vhci_host_send_packet(uint8_t *data, uint16_t len); + +/** + * @brief Register the VHCI callback functions defined in `esp_vhci_host_callback` structure * - * @note This function name is incorrectly spelled, it will be fixed in release 5.x version. + * @param[in] callback `esp_vhci_host_callback` type variable * * @return - * - ESP_OK : success - * - other : failed + * - ESP_OK: Success + * - ESP_FAIL: Failure */ -esp_err_t esp_ble_scan_dupilcate_list_flush(void); +esp_err_t esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback); /** - * @brief bt Wi-Fi power domain power on + * @brief Get the Bluetooth module sleep clock source. + * + * @note This function should be called after `esp_bt_controller_init()` + * + * @return + * - Clock source used in Bluetooth low power mode */ -void esp_wifi_bt_power_domain_on(void); +esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void); /** - * @brief bt Wi-Fi power domain power off + * @brief Set the Bluetooth module sleep clock source. + * + * @note This function should be called before `esp_bt_controller_init()` + * + * @param[in] lpclk Bluetooth sleep clock source + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: Invalid argument */ -void esp_wifi_bt_power_domain_off(void); +esp_err_t esp_bt_set_lpclk_src(esp_bt_sleep_clock_t lpclk); #ifdef __cplusplus } diff --git a/lib/bt/include/esp32/include/esp_bt_vs.h b/lib/bt/include/esp32/include/esp_bt_vs.h new file mode 100644 index 00000000..e8472ab5 --- /dev/null +++ b/lib/bt/include/esp32/include/esp_bt_vs.h @@ -0,0 +1,252 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// +// @brief HCI VS Commands for Espressif's Bluetooth Host +// +// @note The following vendor-specific HCI commands are exclusively for Espressif's Bluetooth Host (Bluedroid Host or NimBLE Host). +// If you are using a different host or HCI UART, these commands will not be enabled, unless the init function is called from the application. +// Note, these functions as well as these additional vendor-specific HCI commands are intended for Espressif's Bluetooth Host use only. +// Application developers should not call the init functions in their applications. +// + +/** + * @brief Test vendor HCI feature (OCF: 0x0081) + * + * The Controller return the value in command + * + * @note The init function is `bt_stack_enableEchoVsCmd(true)` + */ +#define ESP_BT_VS_COMMON_ECHO_OCF (0x0081) + +/** +* @brief echo test cmd parameters +*/ +struct bt_hci_vs_common_echo { + uint8_t echo; /*!< echo data */ +}; + +/** + * @brief Set/Clear coexistence status (OCF: 0x0082) + * + * @note The init function is `bt_stack_enableCoexVsCmd(true)` + */ +#define ESP_BT_VS_SET_COEX_STATUS_OCF (0x0082) +/** +* @brief Set/Clear coexistence status cmd parameters +*/ +struct bt_hci_vs_set_coex_status { + uint8_t type; /*!< WIFI, BLE or BT */ + uint8_t op; /*!< clear or set status */ + uint8_t status; /*!< WIFI, BLE or BT status */ +}; + +/** + * @brief Config scanning duplicate exceptional list (OCF: 0x0108) + * + * @note The init function is `advFilter_stack_enableDupExcListCmd(true)` + */ +#define ESP_BT_VS_CONFIG_DUP_EXC_LIST_OCF (0x0108) +/** +* @brief Update exception list cmd parameters +*/ +struct bt_hci_vs_update_exc_list { + uint8_t subcode; /*!< Add, remove or clear exception list */ + uint32_t type; /*!< device type */ + uint8_t device_info[6]; /*!< device information */ +}; + +/** + * @brief Enable/disable advertising report flow control (OCF: 0x0109) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_SET_ADV_REPORT_FLOW_CTRL_OCF (0x0109) + +/** +* @brief Init ADV flow control cmd parameters +*/ +struct bt_hci_vs_init_adv_flow_ctrl { + uint8_t enable; /*!< Enable ADV flow control */ + uint16_t num; /*!< ADV buffer maximum value */ + uint16_t adv_lost_threshold; /*!< ADV lost event triggered threshold */ +}; + +/** + * @brief Update the number of advertising report flow control (OCF: 0x010A) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_UPD_ADV_REPORT_FLOW_CTRL_NUM_OCF (0x010a) +/** +* @brief Update ADV flow control cmd parameters +*/ +struct bt_hci_vs_update_adv_flow_ctrl { + uint16_t num; /*!< The number of ADV report processed */ +}; + +/** + * @brief Clear legacy advertising (same as HCI_LE_Clear_Advertising_Sets) (OCF: 0x010C) + * + * @note The init function is `adv_stack_enableClearLegacyAdvVsCmd(true)` + */ +#define ESP_BT_VS_CLR_LEGACY_ADV_OCF (0x010c) +/** +* @brief Clear legacy ADV cmd parameters +*/ +struct bt_hci_vs_ble_clr_legacy_adv { + // no parameters +}; + +/** + * @brief Set Classic Bluetooth minimum encryption key size (OCF: 0x0182) + * + * @note The init function is `bt_stack_enableSecCtrlVsCmd(true)` + */ +#define ESP_BT_VS_SET_MIN_ENC_KEY_SIZE_OCF (0x0182) +/** +* @brief Set bt minimum encryption key size cmd parameters +*/ +struct bt_hci_vs_set_min_enc_key_size { + uint8_t size; /*!< the minimum encryption key size */ +}; + +// +// @brief HCI VS Events for Espressif's Bluetooth Host +// +// @note The following HCI VS events are exclusively for Espressif's Bluetooth Host (ESP-Bluedroid Host or ESP-NimBLE Host). +// If you are using a non-ESP host or HCI UART, these events will remain disabled unless the initialization function is explicitly called from the application. +// Note, these init functions as well as these additional HCI VS events are intended for Espressif's Bluetooth Host use only. +// Application developers **should not** call the init functions in their applications. +// + +/** + * @brief BLE advertising report lost event for flow control (EVTCODE: 0x3E, SUBCODE: 0xF0) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_LE_ADV_LOST_EVT_SUBCODE (0xF0) +/** +* @brief ADV lost event parameters +*/ +struct bt_hci_vs_le_adv_lost_evt { + uint32_t nb_lost; /*!< The number of ADV report discarded */ +}; + +/** + * @brief This event indicates legacy authentication is completed by remote device (EVTCODE: 0xFF, SUBCODE: 0x03) + * + * @note The init function is `bt_stack_enableSecCtrlVsCmd(true)` + */ +#define ESP_BT_VS_LEGACY_REM_AUTH_EVT_SUBCODE (0x03) +/** +* @brief legacy remote auth event parameters +*/ +struct bt_hci_vs_legacy_rem_auth_evt { + uint16_t conhdl; /*!< connection handle */ +}; + +// +// @brief HCI VS Commands for Espressif's Internal-Use Debugging +// +// @note The following HCI VS debugging commands are implemented in Bluetooth controller pre-compiled libraries. +// These commands are not linked into the application binary, unless the specific enabling function is called from the application. +// They are intended for Espressif's internal use only. Application developers **should not** call the specific enabling function in their applications. +// + +// +// @brief OCF for vendor specific BLE internal test command +// +// @note The init function is `esp_ble_internalTestFeaturesEnable(true)` +// +#define ESP_BT_VS_CFG_TEST_RELATED_OCF (0x0113) + #define ESP_BT_VS_CFG_TEST_ENABLE_SUBCMD (0X00) + #define ESP_BT_VS_CFG_TEST_ENABLE_ADV_DELAY_SUBCMD (0X01) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_FOREVER_SUBCMD (0X04) + #define ESP_BT_VS_CFG_TEST_SET_EXPECTED_PEER_SUBCMD (0X05) + #define ESP_BT_VS_CFG_TEST_GET_ADV_TXED_CNT_SUBCMD (0X06) + #define ESP_BT_VS_CFG_TEST_GET_SCAN_RXED_CNT_SUBCMD (0X07) + #define ESP_BT_VS_CFG_TEST_SET_TXPWR_LVL_SUBCMD (0X08) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_LVL_SUBCMD (0X09) + #define ESP_BT_VS_CFG_TEST_CLEAR_RAND_ADDR_SUBCMD (0X11) + #define ESP_BT_VS_CFG_TEST_GET_MAX_TXPWR_SUBCMD (0X12) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_RANGE_SUBCMD (0X13) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_AA_SUBCMD (0X14) + #define ESP_BT_VS_CFG_TEST_SET_ADV_AA_SUBCMD (0X15) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_CHAN_SUBCMD (0X16) + #define ESP_BT_VS_CFG_TEST_GET_CTRL_STATUS_SUBCMD (0X1a) + #define ESP_BT_VS_CFG_TEST_GET_CTRL_COMPILE_VER_SUBCMD (0X24) + #define ESP_BT_VS_CFG_TEST_RELATED_SUBCMD_MAX (0Xff) + +/** + * @note The init function is `bt_stack_enablePktCtrlVsCmd(true)` + */ +#define ESP_BT_VS_WR_DM1_ENABLE_OCF (0x0181) + +/** + * @note The init function is `bt_stack_enableClkCtrlVsCmd(true)` + */ +#define ESP_BT_VS_CLK_UPDATE_OCF (0x0183) + +/** + * @note The init function is `bt_stack_enableAfhVsCmd(true)` + */ +#define ESP_BT_VS_SET_AFH_OCF (0x0187) + +/** + * @note The init function is `bt_stack_enableBasicVsCmd(true)` + */ +#define ESP_BT_VS_SET_EVT_MASK_OCF (0x0188) + +/** + * @note The init function is `bt_stack_enableAfhVsCmd(true)` + */ +#define ESP_BT_VS_SET_AFH_REPORTING_MODE_OCF (0x0189) + +/** + * @note The init function is `bt_stack_enableAfhVsCmd(true)` + */ +#define ESP_BT_VS_MASK_RMT_CHANNEL_CLASSIFICATION_OCF (0x018a) + +/** + * @note The init function is `bt_stack_enableRateCtrlVsCmd(true)` + */ +#define ESP_BT_VS_WR_AUTO_RATE_INIT_OCF (0x018b) + +// +// @brief HCI VS Events for Espressif's Internal-Use Debugging +// +// @note The following HCI VS debugging events are implemented in Bluetooth controller pre-compiled libraries. +// These events are not linked into the application binary, unless the specific enabling function is called from the application. +// Application developers **should not** call the specific enabling function in their applications. +// + +/** + * @note The init function is `bt_stack_enableAfhVsCmd(true)` + */ +#define ESP_BT_VS_AFH_CHG_EVT_SUBCODE (0x05) + +/** + * @note The init function is `bt_stack_enableAfhVsCmd(true)` + */ +#define ESP_BT_VS_CH_CLASSIFICATION_EVT_SUBCODE (0x06) + +/** + * @note The init function is `bt_stack_enableAfhVsCmd(true)` + */ +#define ESP_BT_VS_CH_CLASSIFICATION_REPORTING_MODE_EVT_SUBCODE (0x07) + +#ifdef __cplusplus +} +#endif diff --git a/lib/bt/include/esp32c2/include/esp_bt.h b/lib/bt/include/esp32c2/include/esp_bt.h index ee1bede7..de161b08 100644 --- a/lib/bt/include/esp32c2/include/esp_bt.h +++ b/lib/bt/include/esp32c2/include/esp_bt.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,6 +16,7 @@ #include "nimble/nimble_npl.h" #include "../../../../controller/esp32c2/esp_bt_cfg.h" #include "hal/efuse_hal.h" +#include "esp_private/esp_modem_clock.h" #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART #include "driver/uart.h" @@ -72,26 +73,26 @@ typedef enum { } esp_ble_power_type_t; /** - * @brief Bluetooth TX power level(index), it's just a index corresponding to power(dbm). + * @brief Bluetooth TX power level(index), it's just a index corresponding to power(dBm). */ typedef enum { - ESP_PWR_LVL_N24 = 0, /*!< Corresponding to -24dbm */ - ESP_PWR_LVL_N21 = 1, /*!< Corresponding to -21dbm */ - ESP_PWR_LVL_N18 = 2, /*!< Corresponding to -18dbm */ - ESP_PWR_LVL_N15 = 3, /*!< Corresponding to -15dbm */ - ESP_PWR_LVL_N12 = 4, /*!< Corresponding to -12dbm */ - ESP_PWR_LVL_N9 = 5, /*!< Corresponding to -9dbm */ - ESP_PWR_LVL_N6 = 6, /*!< Corresponding to -6dbm */ - ESP_PWR_LVL_N3 = 7, /*!< Corresponding to -3dbm */ - ESP_PWR_LVL_N0 = 8, /*!< Corresponding to 0dbm */ - ESP_PWR_LVL_P3 = 9, /*!< Corresponding to +3dbm */ - ESP_PWR_LVL_P6 = 10, /*!< Corresponding to +6dbm */ - ESP_PWR_LVL_P9 = 11, /*!< Corresponding to +9dbm */ - ESP_PWR_LVL_P12 = 12, /*!< Corresponding to +12dbm */ - ESP_PWR_LVL_P15 = 13, /*!< Corresponding to +15dbm */ - ESP_PWR_LVL_P18 = 14, /*!< Corresponding to +18dbm */ - ESP_PWR_LVL_P20 = 15, /*!< Corresponding to +20dbm */ - ESP_PWR_LVL_P21 = 15, /*!< Corresponding to +20dbm, this enum variable has been deprecated */ + ESP_PWR_LVL_N24 = 0, /*!< Corresponding to -24 dBm */ + ESP_PWR_LVL_N21 = 1, /*!< Corresponding to -21 dBm */ + ESP_PWR_LVL_N18 = 2, /*!< Corresponding to -18 dBm */ + ESP_PWR_LVL_N15 = 3, /*!< Corresponding to -15 dBm */ + ESP_PWR_LVL_N12 = 4, /*!< Corresponding to -12 dBm */ + ESP_PWR_LVL_N9 = 5, /*!< Corresponding to -9 dBm */ + ESP_PWR_LVL_N6 = 6, /*!< Corresponding to -6 dBm */ + ESP_PWR_LVL_N3 = 7, /*!< Corresponding to -3 dBm */ + ESP_PWR_LVL_N0 = 8, /*!< Corresponding to 0 dBm */ + ESP_PWR_LVL_P3 = 9, /*!< Corresponding to +3 dBm */ + ESP_PWR_LVL_P6 = 10, /*!< Corresponding to +6 dBm */ + ESP_PWR_LVL_P9 = 11, /*!< Corresponding to +9 dBm */ + ESP_PWR_LVL_P12 = 12, /*!< Corresponding to +12 dBm */ + ESP_PWR_LVL_P15 = 13, /*!< Corresponding to +15 dBm */ + ESP_PWR_LVL_P18 = 14, /*!< Corresponding to +18 dBm */ + ESP_PWR_LVL_P20 = 15, /*!< Corresponding to +20 dBm */ + ESP_PWR_LVL_P21 = 15, /*!< Corresponding to +20 dBm, this enum variable has been deprecated */ ESP_PWR_LVL_INVALID = 0xFF, /*!< Indicates an invalid value */ } esp_power_level_t; @@ -127,7 +128,7 @@ typedef struct { * @brief Set BLE TX power * Connection Tx power should only be set after connection created. * @param power_type : The type of which tx power, could set Advertising/Connection/Default and etc - * @param power_level: Power level(index) corresponding to absolute value(dbm) + * @param power_level: Power level(index) corresponding to absolute value(dBm) * @return ESP_OK - success, other - failed */ esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_t power_level); @@ -145,7 +146,7 @@ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type); * Connection Tx power should only be set after connection created. * @param power_type : The enhanced type of which tx power, could set Advertising/Connection/Default and etc * @param handle : The handle of Advertising or Connection and the value 0 for other enhanced power types. - * @param power_level: Power level(index) corresponding to absolute value(dbm) + * @param power_level: Power level(index) corresponding to absolute value(dBm) * @return ESP_OK - success, other - failed */ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle, esp_power_level_t power_level); @@ -166,7 +167,7 @@ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t po */ uint8_t esp_ble_get_chip_rev_version(void); -#define CONFIG_VERSION 0x20231124 +#define CONFIG_VERSION 0x20250310 #define CONFIG_MAGIC 0x5A5AA5A5 /** @@ -226,6 +227,11 @@ typedef struct { uint8_t version_num; /*!< Version number */ uint8_t ignore_wl_for_direct_adv; /*!< Ignore the white list for directed advertising */ uint8_t csa2_select; /*!< Select CSA#2 */ + uint8_t ble_aa_check; /*!< True if adds a verification step for the Access Address within the CONNECT_IND PDU; false otherwise. Configurable in menuconfig */ + uint8_t ble_llcp_disc_flag; /*!< Flag indicating whether the Controller disconnects after Instant Passed (0x28) error occurs. Configurable in menuconfig. + - The Controller does not disconnect after Instant Passed (0x28) by default. */ + uint16_t scan_backoff_upperlimitmax; /*!< The value of upperlimitmax is 2^n, The maximum value is 256 */ + uint8_t vhci_enabled; /*!< VHCI mode is enabled */ uint32_t config_magic; /*!< Configuration magic value */ } esp_bt_controller_config_t; @@ -262,13 +268,6 @@ typedef struct { .controller_run_cpu = 0, \ .enable_qa_test = RUN_QA_TEST, \ .enable_bqb_test = RUN_BQB_TEST, \ - .enable_uart_hci = HCI_UART_EN, \ - .ble_hci_uart_port = DEFAULT_BT_LE_HCI_UART_PORT, \ - .ble_hci_uart_baud = DEFAULT_BT_LE_HCI_UART_BAUD, \ - .ble_hci_uart_data_bits = DEFAULT_BT_LE_HCI_UART_DATA_BITS, \ - .ble_hci_uart_stop_bits = DEFAULT_BT_LE_HCI_UART_STOP_BITS, \ - .ble_hci_uart_flow_ctrl = DEFAULT_BT_LE_HCI_UART_FLOW_CTRL, \ - .ble_hci_uart_uart_parity = DEFAULT_BT_LE_HCI_UART_PARITY, \ .enable_tx_cca = DEFAULT_BT_LE_TX_CCA_ENABLED, \ .cca_rssi_thresh = 256 - DEFAULT_BT_LE_CCA_RSSI_THRESH, \ .sleep_en = NIMBLE_SLEEP_ENABLE, \ @@ -279,6 +278,10 @@ typedef struct { .version_num = esp_ble_get_chip_rev_version(), \ .ignore_wl_for_direct_adv = 0, \ .csa2_select = DEFAULT_BT_LE_50_FEATURE_SUPPORT, \ + .ble_aa_check = DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS, \ + .ble_llcp_disc_flag = BT_LE_CTRL_LLCP_DISC_FLAG, \ + .scan_backoff_upperlimitmax = BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX, \ + .vhci_enabled = DEFAULT_BT_LE_VHCI_ENABLED, \ .config_magic = CONFIG_MAGIC, \ } @@ -435,6 +438,14 @@ extern int esp_ble_hw_get_static_addr(esp_ble_addr_t *addr); void esp_ble_controller_log_dump_all(bool output); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +modem_clock_lpclk_src_t esp_bt_get_lpclk_src(void); + +void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src); + +uint32_t esp_bt_get_lpclk_freq(void); + +void esp_bt_set_lpclk_freq(uint32_t clk_freq); + #ifdef __cplusplus } #endif diff --git a/lib/bt/include/esp32c2/include/esp_bt_vs.h b/lib/bt/include/esp32c2/include/esp_bt_vs.h new file mode 100644 index 00000000..1010073b --- /dev/null +++ b/lib/bt/include/esp32c2/include/esp_bt_vs.h @@ -0,0 +1,214 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +// @brief HCI VS Commands for Espressif's Bluetooth Host +// +// @note The following vendor-specific HCI commands are exclusively for Espressif's Bluetooth Host (ESP-Bluedroid Host or ESP-NimBLE Host). +// If you are using a non-ESP host or HCI UART, these commands will remain disabled unless the initialization function is explicitly called from the application. +// Note, these init functions as well as these additional HCI VS commands are intended for Espressif's Bluetooth Host use only. +// Application developers **should not** call the init functions in their applications. +// + +/** + * @brief Enable/disable advertising report flow control (OCF: 0x0109) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_SET_ADV_REPORT_FLOW_CTRL_OCF (0x0109) +/** +* @brief Init ADV flow control cmd parameters +*/ +struct bt_hci_vs_init_adv_flow_ctrl { + uint8_t enable; /*!< Enable ADV flow control */ + uint16_t num; /*!< ADV buffer maximum value */ + uint16_t adv_lost_threshold; /*!< ADV lost event triggered threshold */ +}; + +/** + * @brief Update the number of advertising report in ADV flow control (OCF: 0x010A) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_UPD_ADV_REPORT_FLOW_CTRL_NUM_OCF (0x010a) +/** +* @brief Update ADV flow control cmd parameters +*/ +struct bt_hci_vs_update_adv_flow_ctrl { + uint16_t num; /*!< The number of ADV report processed */ +}; + +/** + * @brief Clear legacy advertising (same as HCI_LE_Clear_Advertising_Sets) (OCF: 0x010C) + * + * @note The init function is `adv_stack_enableClearLegacyAdvVsCmd(true)` + */ +#define ESP_BT_VS_CLR_LEGACY_ADV_OCF (0x010c) +/** +* @brief Clear legacy ADV cmd parameters +*/ +struct bt_hci_vs_ble_clr_legacy_adv { + // no parameters +}; + +/** + * @brief Enable/disable channel selection algorithm #2 (OCF: 0x0112) + * + * @note The init function is `chanSel_stack_enableSetCsaVsCmd(true)` + */ +#define ESP_BT_VS_ENABLE_CSA2_OCF (0x0112) +/** +* @brief Enable/disable channel selection algorithm #2 cmd parameters +*/ +struct bt_hci_vs_ble_csa_enable { + uint8_t csa2_select; /*!< Select CSA2 */ +}; + +/** + * @brief Set BLE vendor events mask (OCF: 0x0116) + * + * @note The init function is `hci_stack_enableSetVsEvtMaskVsCmd(true)` + */ +#define ESP_BT_VS_SET_LE_VENDOR_EVTS_MASK_OCF (0x0116) +/** +* @brief Set BLE vendor events mask cmd parameters +*/ +struct bt_hci_vs_ble_set_vs_evts_mask { + uint32_t evt_masks; /*!< BLE vendor events Mask */ +}; + +// @brief HCI VS Events for Espressif's Bluetooth Host +// +// @note The following HCI VS events are exclusively for Espressif's Bluetooth Host (ESP-Bluedroid Host or ESP-NimBLE Host). +// If you are using a non-ESP host or HCI UART, these events will remain disabled unless the initialization function is explicitly called from the application. +// Note, these init functions as well as these additional HCI VS events are intended for Espressif's Bluetooth Host use only. +// Application developers **should not** call the init functions in their applications. +// + +/** + * @brief BLE Scan/Connect Request, Aux Connect Response received event (EVTCODE: 0xFF, SUBCODE: 0xC0) + * + * @note The init function is `adv_stack_enableScanReqRxdVsEvent(true)` + */ +#define ESP_BT_VS_LE_CONN_SCAN_REQ_RXED_EVT_SUBCODE (0xC0) +/** +* @brief BLE Scan/Connect Request, Aux Connect Response received event parameters +*/ +struct bt_hci_vs_le_conn_scan_req_rxed_evt { + uint8_t evt_type; /*!< Event type; 0: SCAN_REQ; 1: CONN_IND */ + uint8_t handle; /*!< Advertisement handle */ + uint8_t peer_addr_type; /*!< Peer address type */ + uint8_t peer_addr[6]; /*!< Peer address */ +}; + +/** + * @brief BLE Channel Map Update Completion event (EVTCODE: 0xFF, SUBCODE: 0xC1) + * + * @note The init function is `conn_stack_enableChanMapUpdCompVsEvent(true)` + */ +#define ESP_BT_VS_LE_CHAN_UPDATE_COMP_EVT_SUBCODE (0xC1) +/** +* @brief BLE Channel Map Update Completion event parameters +*/ +struct bt_hci_vs_le_chan_update_comp_evt { + uint8_t status; /*!< Controller error code */ + uint16_t handle; /*!< Connection handle */ + uint8_t ch_map[5]; /*!< Updated channel map */ +}; + +/** + * @brief BLE Wakeup From Sleep event (EVTCODE: 0xFF, SUBCODE: 0xC3) + * + * @note The init function is `sleep_stack_enableWakeupVsEvent(true)` + */ +#define ESP_BT_VS_LE_SLEEP_WAKEUP_EVT_SUBCODE (0xC3) +/** +* @brief BLE wakeup event parameters +*/ +struct bt_hci_vs_le_sleep_wakeup_evt { + // no parameters +}; + +/** + * @brief BLE advertising report lost event for flow control (EVTCODE: 0x3E, SUBCODE: 0xF0) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_LE_ADV_LOST_EVT_SUBCODE (0xF0) +/** +* @brief ADV lost event parameters +*/ +struct bt_hci_vs_le_adv_lost_evt { + uint32_t nb_lost; /*!< The number of ADV report discarded */ +}; + +// +// @brief HCI VS Commands for Espressif's Internal-Use Debugging +// +// @note The following HCI VS debugging commands are implemented in Bluetooth controller pre-compiled libraries. +// These commands are not linked into the application binary, unless the function `esp_ble_internalTestFeaturesEnable(true)`is called from the application. +// They are intended for Espressif's internal use only. Application developers **should not** call `esp_ble_internalTestFeaturesEnable(true)` in their applications. +// + +#define ESP_BT_VS_CFG_TEST_RELATED_OCF (0x0113) + #define ESP_BT_VS_CFG_TEST_ENABLE_SUBCMD (0X00) + #define ESP_BT_VS_CFG_TEST_ENABLE_ADV_DELAY_SUBCMD (0X01) + #define ESP_BT_VS_CFG_TEST_SET_PREF_CODED_SUBCMD (0X02) + #define ESP_BT_VS_CFG_TEST_SET_DEFAULT_PRIV_MODE_SUBCMD (0X03) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_FOREVER_SUBCMD (0X04) + #define ESP_BT_VS_CFG_TEST_SET_EXPECTED_PEER_SUBCMD (0X05) + #define ESP_BT_VS_CFG_TEST_GET_ADV_TXED_CNT_SUBCMD (0X06) + #define ESP_BT_VS_CFG_TEST_GET_SCAN_RXED_CNT_SUBCMD (0X07) + #define ESP_BT_VS_CFG_TEST_SET_TXPWR_LVL_SUBCMD (0X08) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_LVL_SUBCMD (0X09) + #define ESP_BT_VS_CFG_TEST_SET_TXPWR_LVL_ENH_SUBCMD (0X0a) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_LVL_ENH_SUBCMD (0X0b) + #define ESP_BT_VS_CFG_TEST_IGNORE_WL_FOR_DIR_ADV_SUBCMD (0X0c) + #define ESP_BT_VS_CFG_TEST_GET_ADV_RXED_RSSI_SUBCMD (0X0d) + #define ESP_BT_VS_CFG_TEST_ENABLE_CCA_SUBCMD (0X0e) + #define ESP_BT_VS_CFG_TEST_SET_CCA_WIN_SUBCMD (0X0f) + #define ESP_BT_VS_CFG_TEST_READ_CCA_DATA_SUBCM (0X10) + #define ESP_BT_VS_CFG_TEST_CLEAR_RAND_ADDR_SUBCMD (0X11) + #define ESP_BT_VS_CFG_TEST_GET_MAX_TXPWR_SUBCMD (0X12) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_RANGE_SUBCMD (0X13) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_AA_SUBCMD (0X14) + #define ESP_BT_VS_CFG_TEST_SET_ADV_AA_SUBCMD (0X15) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_CHAN_SUBCMD (0X16) + #define ESP_BT_VS_CFG_TEST_SKIP_LIGHT_SLEEP_CHECK_SUBCMD (0X17) + #define ESP_BT_VS_CFG_TEST_SET_WAKEUP_OVERHEAD_SUBCMD (0X18) + #define ESP_BT_VS_CFG_TEST_GET_ADV_MIN_ITVL_SUBCMD (0X19) + #define ESP_BT_VS_CFG_TEST_GET_CTRL_STATUS_SUBCMD (0X1a) + #define ESP_BT_VS_CFG_TEST_ENABLE_RECODE_RX_STATE_SUBCMD (0X1f) + #define ESP_BT_VS_CFG_TEST_GET_RECODE_CNT_SUBCMD (0X20) + #define ESP_BT_VS_CFG_TEST_CLR_RECODE_CNT_SUBCMD (0X21) + #define ESP_BT_VS_CFG_TEST_GET_CTRL_COMPILE_VER_SUBCMD (0X24) + #define ESP_BT_VS_CFG_TEST_SET_AUX_ADV_OFFSET_SUBCMD (0X25) + #define ESP_BT_VS_CFG_TEST_GET_BACKOFF_UPLIMIT_SUBCMD (0X2d) + #define ESP_BT_VS_CFG_TEST_GET_RXED_ADV_ADI_SUBCMD (0X2f) + #define ESP_BT_VS_CFG_TEST_SET_RX_SENS_THRESH_SUBCMD (0X31) + #define ESP_BT_VS_CFG_TEST_SET_AGC_MAX_GAIN_SUBCMD (0X39) + #define ESP_BT_VS_CFG_TEST_RELATED_SUBCMD_MAX (0Xff) + +// +// @brief HCI VS Events for Espressif's Internal-Use Debugging +// +// @note The following HCI VS debugging events are implemented in Bluetooth controller pre-compiled libraries. +// These events are not linked into the application binary, unless the function `esp_ble_internalTestFeaturesEnable(true)`is called from the application. +// Application developers **should not** call `esp_ble_internalTestFeaturesEnable(true)` in their applications. +// + + +#ifdef __cplusplus +} +#endif diff --git a/lib/bt/include/esp32c3/include/esp_bt.h b/lib/bt/include/esp32c3/include/esp_bt.h index 8beb1d17..86c902fc 100644 --- a/lib/bt/include/esp32c3/include/esp_bt.h +++ b/lib/bt/include/esp32c3/include/esp_bt.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,50 +18,76 @@ extern "C" { #endif +/** +* @brief Internal use only +* +* @note Please do not modify this value +*/ #define ESP_BT_CTRL_CONFIG_MAGIC_VAL 0x5A5AA5A5 -#define ESP_BT_CTRL_CONFIG_VERSION 0x02404010 +/** +* @brief Internal use only +* +* @note Please do not modify this value +*/ +#define ESP_BT_CTRL_CONFIG_VERSION 0x02505080 + +/** +* @brief Internal use only +* +* @note Please do not modify this value +*/ #define ESP_BT_HCI_TL_MAGIC_VALUE 0xfadebead + +/** +* @brief Internal use only +* +* @note Please do not modify this value +*/ #define ESP_BT_HCI_TL_VERSION 0x00010000 /** - * @brief Bluetooth mode for controller enable/disable + * @brief Bluetooth Controller mode */ typedef enum { - ESP_BT_MODE_IDLE = 0x00, /*!< Bluetooth is not running */ - ESP_BT_MODE_BLE = 0x01, /*!< Run BLE mode */ - ESP_BT_MODE_CLASSIC_BT = 0x02, /*!< Run Classic BT mode */ - ESP_BT_MODE_BTDM = 0x03, /*!< Run dual mode */ + ESP_BT_MODE_IDLE = 0x00, /*!< Bluetooth is not operating. */ + ESP_BT_MODE_BLE = 0x01, /*!< Bluetooth is operating in BLE mode. */ + ESP_BT_MODE_CLASSIC_BT = 0x02, /*!< Unsupported mode */ + ESP_BT_MODE_BTDM = 0x03, /*!< Unsupported mode */ } esp_bt_mode_t; /** - * @brief Type of controller HCI transport layer + * @brief BLE Controller HCI transport layer type */ typedef enum { ESP_BT_CTRL_HCI_TL_UART = 0, /*!< HCI UART h4 transport layer */ - ESP_BT_CTRL_HCI_TL_VHCI = 1, /*!< VHCI interface */ + ESP_BT_CTRL_HCI_TL_VHCI = 1, /*!< Virtual HCI interface */ } esp_bt_ctrl_hci_tl_t; /** - * @brief type of BLE connection event length computation + * @brief BLE connection event length computation type */ typedef enum { ESP_BLE_CE_LEN_TYPE_ORIG = 0, /*!< original */ - ESP_BLE_CE_LEN_TYPE_CE = 1, /*!< use CE_LEN parameter from HCI commands */ + ESP_BLE_CE_LEN_TYPE_CE = 1, /*!< use `CE_LEN` parameter from HCI commands */ ESP_BLE_CE_LEN_TYPE_SD = 1, /*!< Espressif vendor defined */ } esp_ble_ce_len_t; /** - * @brief Bluetooth sleep mode + * @brief Bluetooth modem sleep mode */ typedef enum { - ESP_BT_SLEEP_MODE_NONE = 0, /*!< Bluetooth sleep mode disabled */ - ESP_BT_SLEEP_MODE_1 = 1, /*!< Bluetooth sleep mode 1 */ + ESP_BT_SLEEP_MODE_NONE = 0, /*!< Disable modem sleep */ + ESP_BT_SLEEP_MODE_1 = 1, /*!< Enable modem sleep */ } esp_bt_sleep_mode_t; /** - * @brief Bluetooth sleep clock + * @brief Bluetooth modem sleep clock source + * + * @note If the modem sleep mode is enabled, `ESP_BT_SLEEP_CLOCK_MAIN_XTAL` is the default option and + * `ESP_BT_SLEEP_CLOCK_NONE` will become an invalid option. */ + typedef enum { ESP_BT_SLEEP_CLOCK_NONE = 0, /*!< Sleep clock not configured */ ESP_BT_SLEEP_CLOCK_MAIN_XTAL = 1, /*!< SoC main crystal */ @@ -71,25 +97,25 @@ typedef enum { } esp_bt_sleep_clock_t; /** - * @brief antenna index used for bluetooth + * @brief Bluetooth antenna index */ enum { - ESP_BT_ANT_IDX_0 = 0, /*!< anntena NO 0 */ - ESP_BT_ANT_IDX_1 = 1, /*!< anntena NO 1 */ + ESP_BT_ANT_IDX_0 = 0, /*!< Antenna NO 0 */ + ESP_BT_ANT_IDX_1 = 1, /*!< Antenna NO 1 */ }; /** - * @brief Maximum Tx/Rx time limit on Coded-PHY connection + * @brief Enable / disable the maximum TX/RX time limit for Coded-PHY connections in coexistence with Wi-Fi scenarios */ enum { ESP_BT_COEX_PHY_CODED_TX_RX_TIME_LIMIT_FORCE_DISABLE = 0, /*!< Disable the limit */ - ESP_BT_COEX_PHY_CODED_TX_RX_TIME_LIMIT_FORCE_ENABLE, /*!< Always Enable the limit */ + ESP_BT_COEX_PHY_CODED_TX_RX_TIME_LIMIT_FORCE_ENABLE, /*!< Enable the limit */ }; -#define ESP_BT_HCI_TL_STATUS_OK (0) /*!< HCI_TL Tx/Rx operation status OK */ +#define ESP_BT_HCI_TL_STATUS_OK (0) /*!< HCI_TL TX/RX operation status OK */ /** - * @brief callback function for HCI Transport Layer send/receive operations + * @brief Callback function for HCI Transport Layer send/receive operations */ typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status); @@ -217,6 +243,93 @@ typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status); #define BLE_HW_TARGET_CODE_CHIP_ECO0 (0x02010000) #endif +#ifdef CONFIG_BT_CTRL_BLE_LLCP_CONN_UPDATE +#define BT_CTRL_BLE_LLCP_CONN_UPDATE (1<<0) +#else +#define BT_CTRL_BLE_LLCP_CONN_UPDATE (0<<0) +#endif + +#ifdef CONFIG_BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE +#define BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE (1<<1) +#else +#define BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE (0<<1) +#endif + +#ifdef CONFIG_BT_CTRL_BLE_LLCP_PHY_UPDATE +#define BT_CTRL_BLE_LLCP_PHY_UPDATE (1<<2) +#else +#define BT_CTRL_BLE_LLCP_PHY_UPDATE (0<<2) +#endif + +#define BT_CTRL_BLE_LLCP_DISC_FLAG (BT_CTRL_BLE_LLCP_CONN_UPDATE | BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE | BT_CTRL_BLE_LLCP_PHY_UPDATE) +#if defined(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY) +#define BT_CTRL_RUN_IN_FLASH_ONLY CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY +#else +#define BT_CTRL_RUN_IN_FLASH_ONLY (0) +#endif + + + +#if defined(CONFIG_BT_CTRL_DTM_ENABLE) +#define BT_CTRL_DTM_ENABLE CONFIG_BT_CTRL_DTM_ENABLE +#else +#define BT_CTRL_DTM_ENABLE (0) +#endif + +#if defined(CONFIG_BT_CTRL_BLE_MASTER) +#define BT_CTRL_BLE_MASTER CONFIG_BT_CTRL_BLE_MASTER +#else +#define BT_CTRL_BLE_MASTER (0) +#endif + +#if defined(CONFIG_BT_CTRL_BLE_TEST) +#define BT_CTRL_BLE_TEST CONFIG_BT_CTRL_BLE_TEST +#else +#define BT_CTRL_BLE_TEST (0) +#endif + +#if defined (CONFIG_BT_CTRL_BLE_SECURITY_ENABLE) +#define BLE_SECURITY_ENABLE (CONFIG_BT_CTRL_BLE_SECURITY_ENABLE) +#else +#define BLE_SECURITY_ENABLE (0) +#endif + +#if defined (CONFIG_BT_CTRL_BLE_SCAN) +#define BT_CTRL_BLE_SCAN CONFIG_BT_CTRL_BLE_SCAN +#else +#define BT_CTRL_BLE_SCAN (0) +#endif + +#if defined (CONFIG_BT_CTRL_BLE_ADV) +#define BT_CTRL_BLE_ADV CONFIG_BT_CTRL_BLE_ADV +#else +#define BT_CTRL_BLE_ADV (0) +#endif + +#ifdef CONFIG_BT_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS +#define BLE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS_ENABLED CONFIG_BT_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS +#else +#define BLE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS_ENABLED 0 +#endif + +#if defined(CONFIG_BT_CTRL_LE_LOG_EN) +#define BT_BLE_LOG_EN CONFIG_BT_CTRL_LE_LOG_EN +#else +#define BT_BLE_LOG_EN (0) +#endif + +#if defined(CONFIG_BT_CTRL_LE_LOG_MODE_EN) +#define BLE_LOG_MODE_EN CONFIG_BT_CTRL_LE_LOG_MODE_EN +#else +#define BLE_LOG_MODE_EN (0) +#endif + +#if defined(CONFIG_BT_CTRL_LE_LOG_LEVEL) +#define BLE_LOG_LEVEL CONFIG_BT_CTRL_LE_LOG_LEVEL +#else +#define BLE_LOG_LEVEL (0) +#endif + #define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \ .magic = ESP_BT_CTRL_CONFIG_MAGIC_VAL, \ .version = ESP_BT_CTRL_CONFIG_VERSION, \ @@ -255,6 +368,17 @@ typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status); .ble_data_lenth_zero_aux = BT_BLE_ADV_DATA_LENGTH_ZERO_AUX, \ .ble_chan_ass_en = BT_CTRL_CHAN_ASS_EN, \ .ble_ping_en = BT_CTRL_LE_PING_EN, \ + .ble_llcp_disc_flag = BT_CTRL_BLE_LLCP_DISC_FLAG, \ + .run_in_flash = BT_CTRL_RUN_IN_FLASH_ONLY, \ + .dtm_en = BT_CTRL_DTM_ENABLE, \ + .enc_en = BLE_SECURITY_ENABLE, \ + .qa_test = BT_CTRL_BLE_TEST, \ + .connect_en = BT_CTRL_BLE_MASTER, \ + .scan_en = BT_CTRL_BLE_SCAN, \ + .ble_aa_check = BLE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS_ENABLED, \ + .ble_log_mode_en = BLE_LOG_MODE_EN, \ + .ble_log_level = BLE_LOG_LEVEL, \ + .adv_en = BT_CTRL_BLE_ADV, \ } #else @@ -263,7 +387,8 @@ typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status); /** * @brief Controller HCI transport layer function structure - * This structure shall be registered when HCI transport layer is UART + * + * @note This structure must be registered when HCI transport layer is UART */ typedef struct { uint32_t _magic; /*!< Magic number */ @@ -279,351 +404,528 @@ typedef struct { } esp_bt_hci_tl_t; /** - * @brief Controller config options, depend on config mask. - * Config mask indicate which functions enabled, this means - * some options or parameters of some functions enabled by config mask. + * @brief Bluetooth Controller config options + * @note + * 1. For parameters configurable through menuconfig, it is recommended to adjust them via the menuconfig interface. Please refer to menuconfig for details on the range and default values. + * 2. It is not recommended to modify the values for parameters which are not configurable through menuconfig. */ typedef struct { - /* - * Following parameters can not be configured runtime when call esp_bt_controller_init() - * They will be overwritten by constant values from menuconfig options or from macros. - * So, do not modify the value when esp_bt_controller_init() - */ uint32_t magic; /*!< Magic number */ uint32_t version; /*!< version number of the defined structure */ - /* - * Following parameters can be configured runtime, when call esp_bt_controller_init() - */ - uint16_t controller_task_stack_size; /*!< Bluetooth controller task stack size */ - uint8_t controller_task_prio; /*!< Bluetooth controller task priority */ - uint8_t controller_task_run_cpu; /*!< CPU num that Bluetooth controller task runs on */ - uint8_t bluetooth_mode; /*!< Controller mode: BR/EDR, BLE or Dual Mode */ - uint8_t ble_max_act; /*!< BLE maximum number of air activities */ - uint8_t sleep_mode; /*!< controller sleep mode */ - uint8_t sleep_clock; /*!< controller sleep clock */ - uint8_t ble_st_acl_tx_buf_nb; /*!< controller static ACL TX BUFFER number */ - uint8_t ble_hw_cca_check; /*!< controller hardware triggered CCA check */ - uint16_t ble_adv_dup_filt_max; /*!< maximum number of duplicate scan filter */ - bool coex_param_en; /*!< deprecated */ - uint8_t ce_len_type; /*!< connection event length computation method */ - bool coex_use_hooks; /*!< deprecated */ - uint8_t hci_tl_type; /*!< HCI transport layer, UART, VHCI, etc */ - esp_bt_hci_tl_t *hci_tl_funcs; /*!< hci transport functions used, must be set when hci_tl_type is UART */ - uint8_t txant_dft; /*!< default Tx antenna */ - uint8_t rxant_dft; /*!< default Rx antenna */ - uint8_t txpwr_dft; /*!< default Tx power */ + uint16_t controller_task_stack_size; /*!< Bluetooth Controller task stack size in bytes */ + uint8_t controller_task_prio; /*!< Bluetooth Controller task priority */ + uint8_t controller_task_run_cpu; /*!< CPU number that Bluetooth Controller task runs on. Configurable in menuconfig. + - 0 - CPU 0 (default) + - 1 - CPU 1 */ + uint8_t bluetooth_mode; /*!< BLE mode */ + uint8_t ble_max_act; /*!< The maximum number of BLE instance. Configurable in menuconfig. + - Range: 1 - 10 + - Default: 6 */ + uint8_t sleep_mode; /*!< Modem sleep mode. Configurable in menuconfig. + - 0 - Disable (default) + - 1 - Enable */ + uint8_t sleep_clock; /*!< Modem sleep clock source. Configurable in menuconfig. */ + uint8_t ble_st_acl_tx_buf_nb; /*!< Static ACL TX buffer numbers. Configurable in menuconfig. + - Range: 0 - 12 + - Default: 0 */ + uint8_t ble_hw_cca_check; /*!< Deprecated */ + uint16_t ble_adv_dup_filt_max; /*!< The maximum number of extended duplicate scan filter. Configurable in menuconfig. + - Range: 1 - 500 + - Default: 30 */ + bool coex_param_en; /*!< Deprecated */ + uint8_t ce_len_type; /*!< Connection event length determination method. Configurable in menuconfig. + - 0 - Original (default) + - 1 - use `CE_LEN` parameter from HCI commands + - 2 - Espressif vendor defined method */ + bool coex_use_hooks; /*!< Deprecated */ + uint8_t hci_tl_type; /*!< HCI transport layer type. Configurable in menuconfig. + - 0 - URAT + - 1 - Virtual HCI (default) */ + esp_bt_hci_tl_t *hci_tl_funcs; /*!< HCI transport functions used. It must be set when `hci_tl_type` is UART. */ + uint8_t txant_dft; /*!< Default TX antenna. Configurable in menuconfig. + - 0 - Antenna 0 (default) + - 1 - Antenna 1 */ + uint8_t rxant_dft; /*!< Default RX antenna. Configurable in menuconfig. + - 0 - Antenna 0 (default) + - 1 - Antenna 1 */ + uint8_t txpwr_dft; /*!< Default TX power. Please refer to `esp_power_level_t` for supported power level. Configurable in menuconfig. + - Default : `ESP_PWR_LVL_P9` +9 dBm. */ uint32_t cfg_mask; /*!< Configuration mask to set specific options */ - uint8_t scan_duplicate_mode; /*!< scan duplicate mode */ - uint8_t scan_duplicate_type; /*!< scan duplicate type */ - uint16_t normal_adv_size; /*!< Normal adv size for scan duplicate */ - uint16_t mesh_adv_size; /*!< Mesh adv size for scan duplicate */ - uint8_t coex_phy_coded_tx_rx_time_limit; /*!< limit on max tx/rx time in case of connection using CODED-PHY with Wi-Fi coexistence */ - uint32_t hw_target_code; /*!< hardware target */ - uint8_t slave_ce_len_min; /*!< slave minimum ce length*/ - uint8_t hw_recorrect_en; /*!< Hardware re-correction enabled */ - uint8_t cca_thresh; /*!< cca threshold*/ - uint16_t scan_backoff_upperlimitmax; /*!< scan backoff upperlimitmax value */ - uint16_t dup_list_refresh_period; /*!< duplicate scan list refresh time */ - bool ble_50_feat_supp; /*!< BLE 5.0 feature support */ - uint8_t ble_cca_mode; /*!< BLE CCA mode */ - uint8_t ble_data_lenth_zero_aux; /*!< Config ext adv aux option */ - uint8_t ble_chan_ass_en; /*!< BLE channel assessment enable */ - uint8_t ble_ping_en; /*!< BLE ping procedure enable */ + uint8_t scan_duplicate_mode; /*!< Scan duplicate filtering mode. Configurable in menuconfig. + - 0 - Normal scan duplicate filtering mode (default) + - 1 - Special scan duplicate filtering mode for BLE Mesh */ + uint8_t scan_duplicate_type; /*!< Scan duplicate filtering type. If `scan_duplicate_mode` is set to 1, this parameter will be ignored. Configurable in menuconfig. + - 0 - Filter scan duplicates by device address only (default) + - 1 - Filter scan duplicates by advertising data only, even if they originate from different devices. + - 2 - Filter scan duplicated by device address and advertising data. */ + uint16_t normal_adv_size; /*!< Maximum number of devices in scan duplicate filtering list. Configurable in menuconfig. + - Range: 10 - 1000 + - Default: 100 */ + uint16_t mesh_adv_size; /*!< Maximum number of Mesh advertising packets in scan duplicate filtering list. Configurable in menuconfig. + - Range: 10 - 1000 + - Default: 100 */ + uint8_t coex_phy_coded_tx_rx_time_limit; /*!< Enable / disable the maximum TX/RX time limit for Coded-PHY connections in coexistence with Wi-Fi scenarios. Configurable in menuconfig. + - 0 - Disable (default) + - 1 - Enable */ + uint32_t hw_target_code; /*!< Hardware target. Internal use only. Please do not modify this value. */ + uint8_t slave_ce_len_min; /*!< Slave minimum connection event length: 5 slots. Please do not modify this value. */ + uint8_t hw_recorrect_en; /*!< Enable / disable uncoded phy / coded phy hardware re-correction. Configurable in menuconfig. */ + uint8_t cca_thresh; /*!< Absolute value of hardware-triggered CCA threshold. The CCA threshold is always negative. + If the channel assessment result exceeds the CCA threshold (e.g. -75 dBm), indicating the channel is busy, + the hardware will not transmit packets on that channel. Configurable in menuconfig. + - Range: 20 dBm - 100 dBm + - Default: 75 dBm */ + uint16_t scan_backoff_upperlimitmax; /*!< Enable / disable active scan backoff. Configurable in menuconfig. + - 0 - Disable (default) + - 1 - Enable */ + uint16_t dup_list_refresh_period; /*!< Scan duplicate filtering list refresh period in seconds. Configurable in menuconfig + - Range: 0 - 100 seconds + - Default: 0 second */ + bool ble_50_feat_supp; /*!< True if BLE 5.0 features are enabled; false otherwise. This option depends on whether the Host enable the 5.0 features. */ + uint8_t ble_cca_mode; /*!< BLE CCA mode. Configurable in menuconfig + - 0 - Disable (default) + - 1 - Hardware-triggered CCA + - 2 - Software-based CCA (experimental) */ + uint8_t ble_data_lenth_zero_aux; /*!< Enable / disable auxiliary packets when the extended ADV data length is zero. Configurable in menuconfig. + - 0 - Disable (default) + - 1 - Enable */ + uint8_t ble_chan_ass_en; /*!< Enable / disable BLE channel assessment. Configurable in menuconfig. + - 0 - Disable + - 1 - Enable (default) */ + uint8_t ble_ping_en; /*!< Enable / disable BLE ping procedure. Configurable in menuconfig. + - 0 - Disable + - 1 - Enable (default) */ + uint8_t ble_llcp_disc_flag; /*!< Flag indicating whether the Controller disconnects after Instant Passed (0x28) error occurs. Configurable in menuconfig. + - The Controller does not disconnect after Instant Passed (0x28) by default. */ + bool run_in_flash; /*!< True if the Controller code is in flash (flash model); false otherwise (default). Configurable in menuconfig. */ + bool dtm_en; /*!< True if the DTM feature is enabled; false otherwise (default). Configurable in menuconfig. */ + bool enc_en; /*!< True if the encryption feature is enabled (default); false otherwise. Configurable in menuconfig. */ + bool qa_test; /*!< True if the QA test feature is enabled; false otherwise (default). Configurable in menuconfig.*/ + bool connect_en; /*!< True if the connection feature is enabled (default); false otherwise. Configurable in menuconfig.*/ + bool scan_en; /*!< True if the scan feature is enabled (default); false otherwise. Configurable in menuconfig.*/ + bool ble_aa_check; /*!< True if adds a verification step for the Access Address within the CONNECT_IND PDU; false otherwise. Configurable in menuconfig */ + uint32_t ble_log_mode_en; /*!< BLE log mode enable */ + uint8_t ble_log_level; /*!< BLE log level */ + bool adv_en; /*!< True if the ADV feature is enabled (default); false otherwise. Configurable in menuconfig.*/ } esp_bt_controller_config_t; /** - * @brief Bluetooth controller enable/disable/initialised/de-initialised status + * @brief Bluetooth Controller status */ typedef enum { - ESP_BT_CONTROLLER_STATUS_IDLE = 0, - ESP_BT_CONTROLLER_STATUS_INITED, - ESP_BT_CONTROLLER_STATUS_ENABLED, - ESP_BT_CONTROLLER_STATUS_NUM, + ESP_BT_CONTROLLER_STATUS_IDLE = 0, /*!< The Controller is not initialized or has been de-initialized. */ + ESP_BT_CONTROLLER_STATUS_INITED, /*!< The Controller has been initialized, but not enabled or has been disabled. */ + ESP_BT_CONTROLLER_STATUS_ENABLED, /*!< The Controller has been initialized and enabled. */ + ESP_BT_CONTROLLER_STATUS_NUM, /*!< Number of Controller statuses */ } esp_bt_controller_status_t; /** - * @brief BLE tx power type - * ESP_BLE_PWR_TYPE_CONN_HDL0-8: for each connection, and only be set after connection completed. - * when disconnect, the correspond TX power is not effected. - * ESP_BLE_PWR_TYPE_ADV : for advertising/scan response. - * ESP_BLE_PWR_TYPE_SCAN : for scan. - * ESP_BLE_PWR_TYPE_DEFAULT : if each connection's TX power is not set, it will use this default value. - * if neither in scan mode nor in adv mode, it will use this default value. - * If none of power type is set, system will use ESP_PWR_LVL_P3 as default for ADV/SCAN/CONN0-9. + * @brief BLE TX power type + * + * This TX power type is used for the API `esp_ble_tx_power_set()` and `esp_ble_tx_power_get()`. + * + * @note + * 1. The connection TX power can only be set after the connection is established. + * After disconnecting, the corresponding TX power will not be affected. + * 2. `ESP_BLE_PWR_TYPE_DEFAULT` can be used to set the TX power for power types that have not been set before. + * It will not affect the TX power values which have been set for the ADV/SCAN/CONN0-8 power types. + * 3. If none of power type is set, the system will use `ESP_PWR_LVL_P3` as default for all power types. */ typedef enum { - ESP_BLE_PWR_TYPE_CONN_HDL0 = 0, /*!< For connection handle 0 */ - ESP_BLE_PWR_TYPE_CONN_HDL1 = 1, /*!< For connection handle 1 */ - ESP_BLE_PWR_TYPE_CONN_HDL2 = 2, /*!< For connection handle 2 */ - ESP_BLE_PWR_TYPE_CONN_HDL3 = 3, /*!< For connection handle 3 */ - ESP_BLE_PWR_TYPE_CONN_HDL4 = 4, /*!< For connection handle 4 */ - ESP_BLE_PWR_TYPE_CONN_HDL5 = 5, /*!< For connection handle 5 */ - ESP_BLE_PWR_TYPE_CONN_HDL6 = 6, /*!< For connection handle 6 */ - ESP_BLE_PWR_TYPE_CONN_HDL7 = 7, /*!< For connection handle 7 */ - ESP_BLE_PWR_TYPE_CONN_HDL8 = 8, /*!< For connection handle 8 */ - ESP_BLE_PWR_TYPE_ADV = 9, /*!< For advertising */ - ESP_BLE_PWR_TYPE_SCAN = 10, /*!< For scan */ - ESP_BLE_PWR_TYPE_DEFAULT = 11, /*!< For default, if not set other, it will use default value */ - ESP_BLE_PWR_TYPE_NUM = 12, /*!< TYPE numbers */ + ESP_BLE_PWR_TYPE_CONN_HDL0 = 0, /*!< TX power for Connection state handle 0 */ + ESP_BLE_PWR_TYPE_CONN_HDL1 = 1, /*!< TX power for Connection state handle 1 */ + ESP_BLE_PWR_TYPE_CONN_HDL2 = 2, /*!< TX power for Connection state handle 2 */ + ESP_BLE_PWR_TYPE_CONN_HDL3 = 3, /*!< TX power for Connection state handle 3 */ + ESP_BLE_PWR_TYPE_CONN_HDL4 = 4, /*!< TX power for Connection state handle 4 */ + ESP_BLE_PWR_TYPE_CONN_HDL5 = 5, /*!< TX power for Connection state handle 5 */ + ESP_BLE_PWR_TYPE_CONN_HDL6 = 6, /*!< TX power for Connection state handle 6 */ + ESP_BLE_PWR_TYPE_CONN_HDL7 = 7, /*!< TX power for Connection state handle 7 */ + ESP_BLE_PWR_TYPE_CONN_HDL8 = 8, /*!< TX power for Connection state handle 8 */ + ESP_BLE_PWR_TYPE_ADV = 9, /*!< TX power for Advertising state*/ + ESP_BLE_PWR_TYPE_SCAN = 10, /*!< TX power for Scanning state */ + ESP_BLE_PWR_TYPE_DEFAULT = 11, /*!< TX power for states that have not been set before */ + ESP_BLE_PWR_TYPE_NUM = 12, /*!< Reserved */ } esp_ble_power_type_t; /** - * @brief Bluetooth TX power level(index), it's just a index corresponding to power(dbm). + * @brief The enhanced type of which TX power, could set Advertising/Connection/Default and etc. + * + * This TX power type is used for the API `esp_ble_tx_power_set_enhanced()` and `esp_ble_tx_power_get_enhanced()`. + * + * @note + * 1. The connection TX power can only be set after the connection is established. + * After disconnecting, the corresponding TX power will not be affected. + * 2. `ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT` can be used to set the TX power for power types that have not been set before. + * It will not affect the TX power values which have been set for the ADV/SCAN/INIT/CONN power types. + * 3. If none of power type is set, the system will use `ESP_PWR_LVL_P3` as default for all power types. */ typedef enum { - ESP_PWR_LVL_N24 = 0, /*!< Corresponding to -24dbm */ - ESP_PWR_LVL_N21 = 1, /*!< Corresponding to -21dbm */ - ESP_PWR_LVL_N18 = 2, /*!< Corresponding to -18dbm */ - ESP_PWR_LVL_N15 = 3, /*!< Corresponding to -15dbm */ - ESP_PWR_LVL_N12 = 4, /*!< Corresponding to -12dbm */ - ESP_PWR_LVL_N9 = 5, /*!< Corresponding to -9dbm */ - ESP_PWR_LVL_N6 = 6, /*!< Corresponding to -6dbm */ - ESP_PWR_LVL_N3 = 7, /*!< Corresponding to -3dbm */ - ESP_PWR_LVL_N0 = 8, /*!< Corresponding to 0dbm */ - ESP_PWR_LVL_P3 = 9, /*!< Corresponding to +3dbm */ - ESP_PWR_LVL_P6 = 10, /*!< Corresponding to +6dbm */ - ESP_PWR_LVL_P9 = 11, /*!< Corresponding to +9dbm */ - ESP_PWR_LVL_P12 = 12, /*!< Corresponding to +12dbm */ - ESP_PWR_LVL_P15 = 13, /*!< Corresponding to +15dbm */ - ESP_PWR_LVL_P18 = 14, /*!< Corresponding to +18dbm */ - ESP_PWR_LVL_P21 = 15, /*!< Corresponding to +21dbm */ - ESP_PWR_LVL_INVALID = 0xFF, /*!< Indicates an invalid value */ -} esp_power_level_t; + ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT = 0, /*!< TX power for states that have not been set before */ + ESP_BLE_ENHANCED_PWR_TYPE_ADV, /*!< TX power for Advertising state */ + ESP_BLE_ENHANCED_PWR_TYPE_SCAN, /*!< TX power for Scanning state */ + ESP_BLE_ENHANCED_PWR_TYPE_INIT, /*!< TX power for Initiating state */ + ESP_BLE_ENHANCED_PWR_TYPE_CONN, /*!< TX power for Connection state */ + ESP_BLE_ENHANCED_PWR_TYPE_MAX, /*!< Reserved */ +} esp_ble_enhanced_power_type_t; /** - * @brief Set BLE TX power - * Connection Tx power should only be set after connection created. - * @param power_type : The type of which tx power, could set Advertising/Connection/Default and etc - * @param power_level: Power level(index) corresponding to absolute value(dbm) - * @return ESP_OK - success, other - failed + * @brief Bluetooth TX power level (index). Each index corresponds to a specific power value in dBm. */ -esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_t power_level); - -/** - * @brief Get BLE TX power - * Connection Tx power should only be get after connection created. - * @param power_type : The type of which tx power, could set Advertising/Connection/Default and etc - * @return >= 0 - Power level, < 0 - Invalid - */ -esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type); +typedef enum { + ESP_PWR_LVL_N24 = 0, /*!< Corresponding to -24 dBm */ + ESP_PWR_LVL_N21 = 1, /*!< Corresponding to -21 dBm */ + ESP_PWR_LVL_N18 = 2, /*!< Corresponding to -18 dBm */ + ESP_PWR_LVL_N15 = 3, /*!< Corresponding to -15 dBm */ + ESP_PWR_LVL_N12 = 4, /*!< Corresponding to -12 dBm */ + ESP_PWR_LVL_N9 = 5, /*!< Corresponding to -9 dBm */ + ESP_PWR_LVL_N6 = 6, /*!< Corresponding to -6 dBm */ + ESP_PWR_LVL_N3 = 7, /*!< Corresponding to -3 dBm */ + ESP_PWR_LVL_N0 = 8, /*!< Corresponding to 0 dBm */ + ESP_PWR_LVL_P3 = 9, /*!< Corresponding to +3 dBm */ + ESP_PWR_LVL_P6 = 10, /*!< Corresponding to +6 dBm */ + ESP_PWR_LVL_P9 = 11, /*!< Corresponding to +9 dBm */ + ESP_PWR_LVL_P12 = 12, /*!< Corresponding to +12 dBm */ + ESP_PWR_LVL_P15 = 13, /*!< Corresponding to +15 dBm */ + ESP_PWR_LVL_P18 = 14, /*!< Corresponding to +18 dBm */ + ESP_PWR_LVL_P20 = 15, /*!< Corresponding to +20 dBm */ + ESP_PWR_LVL_P21 = 15, /*!< Deprecated */ + ESP_PWR_LVL_INVALID = 0xFF, /*!< Indicates an invalid value */ +} esp_power_level_t; /** - * @brief Initialize BT controller to allocate task and other resource. - * This function should be called only once, before any other BT functions are called. - * @param cfg: Initial configuration of BT controller. Different from previous version, there's a mode and some - * connection configuration in "cfg" to configure controller work mode and allocate the resource which is needed. - * @return ESP_OK - success, other - failed + * @brief Initialize the Bluetooth Controller to allocate tasks and other resources + * + * @note This function should be called only once, before any other Bluetooth functions. + * + * @param[in] cfg Initial Bluetooth Controller configuration + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state + * - ESP_ERR_NOT_SUPPORTED: Invalid Bluetooth Controller mode + * - ESP_ERR_INVALID_ARG: Invalid arguments + * - ESP_ERR_NO_MEM: Out of memory + * - ESP_FAIL: Failure due to other reasons + * */ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg); /** - * @brief De-initialize BT controller to free resource and delete task. - * You should stop advertising and scanning, as well as - * disconnect all existing connections before de-initializing BT controller. + * @brief De-initialize Bluetooth Controller to free resources and delete tasks + * + * @note + * 1. You should make sure that the Controller is in idle state before de-initializing it. + * 2. This function should be called only once, after any other Bluetooth functions. * - * This function should be called only once, after any other BT functions are called. - * This function is not whole completed, esp_bt_controller_init cannot called after this function. - * @return ESP_OK - success, other - failed + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: Invalid arguments + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state + * - ESP_ERR_NO_MEM: Out of memory */ esp_err_t esp_bt_controller_deinit(void); /** - * @brief Enable BT controller. - * Due to a known issue, you cannot call esp_bt_controller_enable() a second time - * to change the controller mode dynamically. To change controller mode, call - * esp_bt_controller_disable() and then call esp_bt_controller_enable() with the new mode. - * @param mode : the mode(BLE/BT/BTDM) to enable. For compatible of API, retain this argument. This mode must be - * equal as the mode in "cfg" of esp_bt_controller_init(). - * @return ESP_OK - success, other - failed + * @brief Enable Bluetooth Controller + * + * @note + * 1. Bluetooth Controller cannot be enabled in `ESP_BT_CONTROLLER_STATUS_IDLE` status. It has to be initialized first. + * 2. Due to a known issue, you cannot call `esp_bt_controller_enable()` for the second time + * to change the Controller mode dynamically. To change the Controller mode, call + * `esp_bt_controller_disable()` and then call `esp_bt_controller_enable()` with the new mode. + * + * @param[in] mode The Bluetooth Controller mode to enable + * + * For API compatibility, retain this argument. This mode must match the mode specified in the `cfg` of `esp_bt_controller_init()`. + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state + * - ESP_ERR_INVALID_ARG: Invalid arguments */ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode); /** - * @brief Disable BT controller - * @return ESP_OK - success, other - failed + * @brief Disable Bluetooth Controller + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state */ esp_err_t esp_bt_controller_disable(void); /** - * @brief Get BT controller is initialised/de-initialised/enabled/disabled - * @return status value - */ -esp_bt_controller_status_t esp_bt_controller_get_status(void); - -uint16_t esp_bt_get_tx_buf_num(void); - -/** @brief esp_vhci_host_callback - * used for vhci call host function to notify what host need to do - */ -typedef struct esp_vhci_host_callback { - void (*notify_host_send_available)(void); /*!< callback used to notify that the host can send packet to controller */ - int (*notify_host_recv)(uint8_t *data, uint16_t len); /*!< callback used to notify that the controller has a packet to send to the host*/ -} esp_vhci_host_callback_t; - -/** @brief esp_vhci_host_check_send_available - * used for check actively if the host can send packet to controller or not. - * @return true for ready to send, false means cannot send packet - */ -bool esp_vhci_host_check_send_available(void); - -/** @brief esp_vhci_host_send_packet - * host send packet to controller + * @brief Get Bluetooth Controller status * - * Should not call this function from within a critical section - * or when the scheduler is suspended. - * - * @param data the packet point - * @param len the packet length - */ -void esp_vhci_host_send_packet(uint8_t *data, uint16_t len); - -/** @brief esp_vhci_host_register_callback - * register the vhci reference callback - * struct defined by vhci_host_callback structure. - * @param callback esp_vhci_host_callback type variable - * @return ESP_OK - success, ESP_FAIL - failed + * @return + * - ESP_BT_CONTROLLER_STATUS_IDLE: The Controller is not initialized or has been de-initialized. + * - ESP_BT_CONTROLLER_STATUS_INITED: The Controller has been initialized, but not enabled or has been disabled. + * - ESP_BT_CONTROLLER_STATUS_ENABLED: The Controller has been initialized and enabled. */ -esp_err_t esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback); +esp_bt_controller_status_t esp_bt_controller_get_status(void); -/** @brief esp_bt_controller_mem_release - * release the controller memory as per the mode - * - * This function releases the BSS, data and other sections of the controller to heap. The total size is about 70k bytes. +/** + * @brief Release the Controller memory as per the mode * - * esp_bt_controller_mem_release(mode) should be called only before esp_bt_controller_init() - * or after esp_bt_controller_deinit(). + * This function releases the BSS, data and other sections of the Controller to heap. The total size is about 70 KB. * - * Note that once BT controller memory is released, the process cannot be reversed. It means you cannot use the bluetooth - * mode which you have released by this function. + * @note + * 1. This function is optional and should be called only if you want to free up memory for other components. + * 2. This function should only be called when the Controller is in `ESP_BT_CONTROLLER_STATUS_IDLE` status. + * 3. Once Bluetooth Controller memory is released, the process cannot be reversed. This means you cannot use the Bluetooth Controller mode that you have released using this function. + * 4. If your firmware will upgrade the Bluetooth Controller mode later (such as from disabled to enabled), then do not call this function. * - * If your firmware will later upgrade the Bluetooth controller mode (BLE -> BT Classic or disabled -> enabled) - * then do not call this function. + * If you never intend to use Bluetooth in a current boot-up cycle, calling `esp_bt_controller_mem_release(ESP_BT_MODE_BLE)` could release the BSS and data consumed by BLE Controller to heap. * - * If the app calls esp_bt_controller_enable(ESP_BT_MODE_BLE) to use BLE only then it is safe to call - * esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT) at initialization time to free unused BT Classic memory. * - * If the mode is ESP_BT_MODE_BTDM, then it may be useful to call API esp_bt_mem_release(ESP_BT_MODE_BTDM) instead, - * which internally calls esp_bt_controller_mem_release(ESP_BT_MODE_BTDM) and additionally releases the BSS and data - * consumed by the BT/BLE host stack to heap. For more details about usage please refer to the documentation of - * esp_bt_mem_release() function + * @param[in] mode The Bluetooth Controller mode * - * @param mode : the mode want to release memory - * @return ESP_OK - success, other - failed + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state + * - ESP_ERR_NOT_FOUND: Requested resource not found */ esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode); -/** @brief esp_bt_mem_release - * release controller memory and BSS and data section of the BT/BLE host stack as per the mode - * - * This function first releases controller memory by internally calling esp_bt_controller_mem_release(). - * Additionally, if the mode is set to ESP_BT_MODE_BTDM, it also releases the BSS and data consumed by the BT/BLE host stack to heap +/** @brief Release the Controller memory, BSS and data section of the BLE Host stack as per the mode * - * Note that once BT memory is released, the process cannot be reversed. It means you cannot use the bluetooth - * mode which you have released by this function. + * @note + * 1. This function is optional and should be called only if you want to free up memory for other components. + * 2. This function should only be called when the Controller is in `ESP_BT_CONTROLLER_STATUS_IDLE` status. + * 3. Once Bluetooth Controller memory is released, the process cannot be reversed. This means you cannot use the Bluetooth Controller mode that you have released using this function. + * 4. If your firmware will upgrade the Bluetooth Controller mode later (such as from disabled to enabled), then do not call this function. * - * If your firmware will later upgrade the Bluetooth controller mode (BLE -> BT Classic or disabled -> enabled) - * then do not call this function. + * This function first releases Controller memory by internally calling `esp_bt_controller_mem_release()`, then releases Host memory. * - * If you never intend to use bluetooth in a current boot-up cycle, you can call esp_bt_mem_release(ESP_BT_MODE_BTDM) - * before esp_bt_controller_init or after esp_bt_controller_deinit. + * If you never intend to use Bluetooth in a current boot-up cycle, calling `esp_bt_mem_release(ESP_BT_MODE_BLE)` could release the BSS and data consumed by BLE stack to heap. * - * For example, if a user only uses bluetooth for setting the WiFi configuration, and does not use bluetooth in the rest of the product operation". - * In such cases, after receiving the WiFi configuration, you can disable/deinit bluetooth and release its memory. + * For example, if you only use Bluetooth for setting the Wi-Fi configuration, and do not use Bluetooth in the rest of the product operation, + * after receiving the Wi-Fi configuration, you can disable/de-init Bluetooth and release its memory. * Below is the sequence of APIs to be called for such scenarios: * - * esp_bluedroid_disable(); - * esp_bluedroid_deinit(); - * esp_bt_controller_disable(); - * esp_bt_controller_deinit(); - * esp_bt_mem_release(ESP_BT_MODE_BTDM); + * esp_bluedroid_disable(); + * esp_bluedroid_deinit(); + * esp_bt_controller_disable(); + * esp_bt_controller_deinit(); + * esp_bt_mem_release(ESP_BT_MODE_BLE); * - * @param mode : the mode whose memory is to be released - * @return ESP_OK - success, other - failed + * @param[in] mode The Bluetooth Controller mode + * + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state + * - ESP_ERR_NOT_FOUND: Requested resource not found */ esp_err_t esp_bt_mem_release(esp_bt_mode_t mode); /** - * @brief enable bluetooth to enter modem sleep + * @brief Enable Bluetooth modem sleep * - * Note that this function shall not be invoked before esp_bt_controller_enable() + * There are currently two options for Bluetooth modem sleep: ORIG mode and EVED mode. The latter is intended for BLE only. + * The modem sleep mode could be configured in menuconfig. * - * There are currently two options for bluetooth modem sleep, one is ORIG mode, and another is EVED Mode. EVED Mode is intended for BLE only. + * In ORIG mode, if there is no event to process, the Bluetooth Controller will periodically switch off some components and pause operation, then wake up according to the scheduled interval and resume work. + * It can also wakeup earlier upon external request using function `esp_bt_controller_wakeup_request()`. * - * For ORIG mode: - * Bluetooth modem sleep is enabled in controller start up by default if CONFIG_BTDM_CONTROLLER_MODEM_SLEEP is set and "ORIG mode" is selected. In ORIG modem sleep mode, bluetooth controller will switch off some components and pause to work every now and then, if there is no event to process; and wakeup according to the scheduled interval and resume the work. It can also wakeup earlier upon external request using function "esp_bt_controller_wakeup_request". + * @note This function shall not be invoked before `esp_bt_controller_enable()`. * * @return - * - ESP_OK : success - * - other : failed + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state + * - ESP_ERR_NOT_SUPPORTED: Operation or feature not supported */ esp_err_t esp_bt_sleep_enable(void); - /** - * @brief disable bluetooth modem sleep + * @brief Disable Bluetooth modem sleep * - * Note that this function shall not be invoked before esp_bt_controller_enable() - * - * If esp_bt_sleep_disable() is called, bluetooth controller will not be allowed to enter modem sleep; - * - * If ORIG modem sleep mode is in use, if this function is called, bluetooth controller may not immediately wake up if it is dormant then. - * In this case, esp_bt_controller_wakeup_request() can be used to shorten the time for wakeup. + * @note + * 1. Bluetooth Controller will not be allowed to enter modem sleep after calling this function. + * 2. In ORIG modem sleep mode, calling this function may not immediately wake up the Controller if it is currently dormant. + * In this case, `esp_bt_controller_wakeup_request()` can be used to shorten the wake-up time. + * 3. This function shall not be invoked before `esp_bt_controller_enable()`. * * @return - * - ESP_OK : success - * - other : failed + * - ESP_OK: Success + * - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state + * - ESP_ERR_NOT_SUPPORTED: Operation or feature not supported */ esp_err_t esp_bt_sleep_disable(void); /** - * @brief to check whether bluetooth controller is sleeping at the instant, if modem sleep is enabled + * @brief Get the Bluetooth sleep clock source. * - * Note that this function shall not be invoked before esp_bt_controller_enable() - * This function is supposed to be used ORIG mode of modem sleep + * @note This function shall not be invoked before `esp_bt_controller_init()`. * - * @return true if in modem sleep state, false otherwise + * @return clock source used in Bluetooth low power mode */ -bool esp_bt_controller_is_sleeping(void); +esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void); /** - * @brief request controller to wakeup from sleeping state during sleep mode + * @brief Check if the Bluetooth Controller is currently in sleep mode when modem sleep is enabled. * - * Note that this function shall not be invoked before esp_bt_controller_enable() - * Note that this function is supposed to be used ORIG mode of modem sleep - * Note that after this request, bluetooth controller may again enter sleep as long as the modem sleep is enabled + * @note + * 1. This function shall not be invoked before `esp_bt_controller_enable()`. + * 2. This function is supposed to be used ORIG mode of modem sleep. + * + * @return + * - True if the Controller is in modem sleep state; false otherwise. + */ +bool esp_bt_controller_is_sleeping(void); + +/** + * @brief Request the Controller to wakeup from sleeping state during sleep mode * * Profiling shows that it takes several milliseconds to wakeup from modem sleep after this request. + * * Generally it takes longer if 32kHz XTAL is used than the main XTAL, due to the lower frequency of the former as the bluetooth low power clock source. + * + * @note + * 1. This function shall not be invoked before `esp_bt_controller_enable()`. + * 2. This function is supposed to be used ORIG mode of modem sleep. + * 3. After this request, the Bluetooth Controller can re-enter sleep as long as modem sleep remains enabled. */ void esp_bt_controller_wakeup_request(void); /** - * @brief notify bluetooth controller task to process the event upon Tx or Rx done + * @brief Set BLE TX power for the specified power type + * + * It is recommended to use `esp_ble_tx_power_set_enhanced` to set TX power for individual advertising and connection handle. + * + * @note Connection TX power should only be set after the connection is established. + * + * @param[in] power_type The type of TX power. It could be Advertising, Connection, or Default. + * @param[in] power_level Power level (index) corresponding to the absolute value (dBm) + * + * @return + * - ESP_OK: Success + * - ESP_ERR_NOT_SUPPORTED: Invalid TX power type + * - ESP_FAIL: Failure due to other reasons + */ +esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_t power_level); + +/** + * @brief Get BLE TX power of the specified power type + * + * It is recommended to use `esp_ble_tx_power_get_enhanced` to get TX power of individual advertising and connection handle. + * + * @note + * 1. Connection TX power should only be retrieved after the connection is established. + * 2. If an invalid power type is provided, this API returns `ESP_PWR_LVL_INVALID`. + * + * @param[in] power_type The type of TX power. It could be Advertising/Connection/Default and etc. + * + * @return + * - Power level + * + */ +esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type); + +/** + * @brief Set BLE TX power for the specified Advertising or Connection handle + * + * For the TX power type: `ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT`, `ESP_BLE_ENHANCED_PWR_TYPE_SCAN`, `ESP_BLE_ENHANCED_PWR_TYPE_INIT`, + * this API will ignore the input handle number, and set 0 internally. + * + * For the TX power type: `ESP_BLE_ENHANCED_PWR_TYPE_ADV` and `ESP_BLE_ENHANCED_PWR_TYPE_CONN`, + * this API will set the TX power for the target handle. + * + * @note + * 1. Connection TX power should only be set after connection created. + * + * @param[in] power_type The type of TX power + * @param[in] handle The handle of Advertising or Connection + * @param[in] power_level Power level (index) corresponding to absolute value (dBm) + * + * @return + * - ESP_OK: Success + * - ESP_ERR_NOT_SUPPORTED: Invalid TX power type + * - ESP_FAIL: Failure due to other reasons + */ +esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle, esp_power_level_t power_level); + +/** + * @brief Get BLE TX power of the specified Advertising or Connection handle + * + * For the TX power type: `ESP_BLE_ENHANCED_PWR_TYPE_DEFAULT`, `ESP_BLE_ENHANCED_PWR_TYPE_SCAN`, `ESP_BLE_ENHANCED_PWR_TYPE_INIT`, + * this API will ignore the input handle number. + * + * For the TX power type: `ESP_BLE_ENHANCED_PWR_TYPE_ADV` and `ESP_BLE_ENHANCED_PWR_TYPE_CONN`, + * this API will return the TX power of the target handle. * - * Note that this function shall not be invoked before esp_bt_controller_enable() - * This function can be called in both ISR and non-ISR context + * @note + * 1. Connection Tx power should only be get after connection created. + * 2. If an invalid power type is provided, this API returns `ESP_PWR_LVL_INVALID`. + * + * @param[in] power_type The type of TX power + * @param[in] handle The handle of Advertising or Connection and the value 0 for other enhanced power types + * + * @return Power level + */ +esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle); + +/** + * @brief Notify Bluetooth Controller task to process the event upon TX or RX done * + * @note + * 1. This function shall not be invoked before `esp_bt_controller_enable()`. + * 2. This function can be called in both ISR and non-ISR context. + * 3. This function ignored the passed `event` value currently */ int esp_bt_h4tl_eif_io_event_notify(int event); /** - * @brief bt Wi-Fi power domain power on + * @brief Virtual HCI (VHCI) callback functions to notify the Host on the next operation */ -void esp_wifi_bt_power_domain_on(void); +typedef struct esp_vhci_host_callback { + void (*notify_host_send_available)(void); /*!< callback used to notify that the Host can send the HCI data to Controller */ + int (*notify_host_recv)(uint8_t *data, uint16_t len); /*!< callback used to notify that the Controller has the HCI data to send to the Host */ +} esp_vhci_host_callback_t; /** - * @brief bt Wi-Fi power domain power off + * @brief Check whether the Controller is ready to receive the HCI data + * + * If the return value is True, the Host can send the HCI data to the Controller. + * + * @note This function should be called before each `esp_vhci_host_send_packet()`. + * + * @return + * True if the Controller is ready to receive the HCI data; false otherwise. */ -void esp_wifi_bt_power_domain_off(void); +bool esp_vhci_host_check_send_available(void); /** - * @brief Get the Bluetooth module sleep clock source. + * @brief Send the HCI data to the Controller * - * Note that this function shall not be invoked before esp_bt_controller_init() + * @note + * 1. This function shall not be called within a critical section or when the scheduler is suspended. + * 2. This function should be called only if `esp_vhci_host_check_send_available` returns True. * - * @return clock source used in Bluetooth low power mode + * @param[in] data Pointer to the HCI data + * @param[in] len The HCI data length */ -esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void); +void esp_vhci_host_send_packet(uint8_t *data, uint16_t len); + +/** + * @brief Register the VHCI callback functions defined in `esp_vhci_host_callback` structure. + * + * @param[in] callback `esp_vhci_host_callback` type variable + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Failure + */ +esp_err_t esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback); + +/** + * @brief Select buffers +*/ +typedef enum { + ESP_BLE_LOG_BUF_HCI = 0x02, + ESP_BLE_LOG_BUF_CONTROLLER = 0x05, +} esp_ble_log_buf_t; + +void esp_ble_controller_log_dump_all(bool output); #ifdef __cplusplus } diff --git a/lib/bt/include/esp32c3/include/esp_bt_vs.h b/lib/bt/include/esp32c3/include/esp_bt_vs.h new file mode 100644 index 00000000..78d926eb --- /dev/null +++ b/lib/bt/include/esp32c3/include/esp_bt_vs.h @@ -0,0 +1,175 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +// @brief HCI VS Commands for Espressif's Bluetooth Host +// +// @note The following vendor-specific HCI commands are exclusively for Espressif's Bluetooth Host (ESP-Bluedroid Host or ESP-NimBLE Host). +// If you are using a non-ESP host or HCI UART, these commands will remain disabled unless the initialization function is explicitly called from the application. +// Note, these init functions as well as these additional HCI VS commands are intended for Espressif's Bluetooth Host use only. +// Application developers **should not** call the init functions in their applications. +// + +/** + * @brief Test vendor HCI feature (OCF: 0x0081) + * + * The Controller returns the value in command. + * + * @note The init function is `bt_stack_enableEchoVsCmd(true)` + */ +#define ESP_BT_VS_COMMON_ECHO_OCF (0x0081) +/** +* @brief echo test cmd parameters +*/ +struct bt_hci_vs_common_echo { + uint8_t echo; /*!< echo data */ +}; + +/** + * @brief Config scanning duplicate exceptional list (OCF: 0x0108) + * + * @note The init function is `advFilter_stack_eanbleDupExcListCmd(true)` + */ +#define ESP_BT_VS_CONFIG_DUP_EXC_LIST_OCF (0x0108) +/** +* @brief Update exception list cmd parameters +*/ +struct bt_hci_vs_update_exc_list { + uint8_t subcode; /*!< Add, remove or clear exception list */ + uint32_t type; /*!< device type */ + uint8_t device_info[6]; /*!< device information */ +}; + +/** + * @brief Enable/disable advertising report flow control (OCF: 0x0109) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_SET_ADV_REPORT_FLOW_CTRL_OCF (0x0109) +/** +* @brief Init ADV flow control cmd parameters +*/ +struct bt_hci_vs_init_adv_flow_ctrl { + uint8_t enable; /*!< Enable ADV flow control */ + uint16_t num; /*!< ADV buffer maximum value */ + uint16_t adv_lost_threshold; /*!< ADV lost event triggered threshold */ +}; + +/** + * @brief Update the number of advertising report in ADV flow control (OCF: 0x010A) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_UPD_ADV_REPORT_FLOW_CTRL_NUM_OCF (0x010a) +/** +* @brief Update ADV flow control cmd parameters +*/ +struct bt_hci_vs_update_adv_flow_ctrl { + uint16_t num; /*!< The number of ADV report processed */ +}; + +/** + * @brief Clear legacy advertising (same as HCI_LE_Clear_Advertising_Sets) (OCF: 0x010C) + * + * @note The init function is `adv_stack_enableClearLegacyAdvVsCmd(true)` + */ +#define ESP_BT_VS_CLR_LEGACY_ADV_OCF (0x010c) +/** +* @brief Clear legacy ADV cmd parameters +*/ +struct bt_hci_vs_ble_clr_legacy_adv { + // no parameters +}; + +/** + * @brief Enable/disable channel selection algorithm #2 (OCF: 0x0112) + * + * @note The init function is `chanSel_stack_enableSetCsaVsCmd(true)` + */ +#define ESP_BT_VS_ENABLE_CSA2_OCF (0x0112) +/** +* @brief Enable/disable channel selection algorithm #2 cmd parameters +*/ +struct bt_hci_vs_ble_csa_enable { + uint8_t csa2_select; /*!< Select CSA2 */ +}; + +// @brief HCI VS Events for Espressif's Bluetooth Host +// +// @note The following HCI VS events are exclusively for Espressif's Bluetooth Host (ESP-Bluedroid Host or ESP-NimBLE Host). +// If you are using a non-ESP host or HCI UART, these events will remain disabled unless the initialization function is explicitly called from the application. +// Note, these init functions as well as these additional HCI VS events are intended for Espressif's Bluetooth Host use only. +// Application developers **should not** call the init functions in their applications. +// + +/** + * @brief BLE advertising report lost event for flow control (EVTCODE: 0x3E, SUBCODE: 0xF0) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_LE_ADV_LOST_EVT_SUBCODE (0xF0) +/** +* @brief ADV lost event parameters +*/ +struct bt_hci_vs_le_adv_lost_evt { + uint32_t nb_lost; /*!< The number of ADV report discarded */ +}; + +// +// @brief HCI VS Commands for Espressif's Internal-Use Debugging +// +// @note The following HCI VS debugging commands are implemented in Bluetooth controller pre-compiled libraries. +// These commands are not linked into the application binary, unless the function `esp_ble_internalTestFeaturesEnable(true)`is called from the application. +// They are intended for Espressif's internal use only. Application developers **should not** call `esp_ble_internalTestFeaturesEnable(true)` in their applications. +// + +#define ESP_BT_VS_CFG_TEST_RELATED_OCF (0x0113) + #define ESP_BT_VS_CFG_TEST_ENABLE_SUBCMD (0X00) + #define ESP_BT_VS_CFG_TEST_ENABLE_ADV_DELAY_SUBCMD (0X01) + #define ESP_BT_VS_CFG_TEST_SET_PREF_CODED_SUBCMD (0X02) + #define ESP_BT_VS_CFG_TEST_SET_DEFAULT_PRIV_MODE_SUBCMD (0X03) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_FOREVER_SUBCMD (0X04) + #define ESP_BT_VS_CFG_TEST_SET_EXPECTED_PEER_SUBCMD (0X05) + #define ESP_BT_VS_CFG_TEST_GET_ADV_TXED_CNT_SUBCMD (0X06) + #define ESP_BT_VS_CFG_TEST_GET_SCAN_RXED_CNT_SUBCMD (0X07) + #define ESP_BT_VS_CFG_TEST_SET_TXPWR_LVL_SUBCMD (0X08) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_LVL_SUBCMD (0X09) + #define ESP_BT_VS_CFG_TEST_SET_TXPWR_LVL_ENH_SUBCMD (0X0a) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_LVL_ENH_SUBCMD (0X0b) + #define ESP_BT_VS_CFG_TEST_ENABLE_CCA_SUBCMD (0X0e) + #define ESP_BT_VS_CFG_TEST_CLEAR_RAND_ADDR_SUBCMD (0X11) + #define ESP_BT_VS_CFG_TEST_GET_MAX_TXPWR_SUBCMD (0X12) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_RANGE_SUBCMD (0X13) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_AA_SUBCMD (0X14) + #define ESP_BT_VS_CFG_TEST_SET_ADV_AA_SUBCMD (0X15) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_CHAN_SUBCMD (0X16) + #define ESP_BT_VS_CFG_TEST_GET_CTRL_STATUS_SUBCMD (0X1a) + #define ESP_BT_VS_CFG_TEST_GET_CTRL_COMPILE_VER_SUBCMD (0X24) + #define ESP_BT_VS_CFG_TEST_SET_AUX_ADV_OFFSET_SUBCMD (0X25) + #define ESP_BT_VS_CFG_TEST_SET_AUX_OFFSET_THRESHOLD_SUBCMD (0X2b) + #define ESP_BT_VS_CFG_TEST_SET_RX_SENS_THRESH_SUBCMD (0X31) + #define ESP_BT_VS_CFG_TEST_SET_AGC_MAX_GAIN_SUBCMD (0X39) + #define ESP_BT_VS_CFG_TEST_RELATED_SUBCMD_MAX (0Xff) + +// +// @brief HCI VS Events for Espressif's Internal-Use Debugging +// +// @note The following HCI VS debugging events are implemented in Bluetooth controller pre-compiled libraries. +// These events are not linked into the application binary, unless the function `esp_ble_internalTestFeaturesEnable(true)`is called from the application. +// Application developers **should not** call `esp_ble_internalTestFeaturesEnable(true)` in their applications. +// + +#ifdef __cplusplus +} +#endif diff --git a/lib/bt/include/esp32c5/include/esp_bt.h b/lib/bt/include/esp32c5/include/esp_bt.h index 1a7cd646..91b1da30 100644 --- a/lib/bt/include/esp32c5/include/esp_bt.h +++ b/lib/bt/include/esp32c5/include/esp_bt.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,6 +16,7 @@ #include "nimble/nimble_npl.h" #include "../../../../controller/esp32c5/esp_bt_cfg.h" #include "hal/efuse_hal.h" +#include "esp_private/esp_modem_clock.h" #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART #include "driver/uart.h" @@ -75,6 +76,9 @@ typedef enum { * @brief Bluetooth TX power level(index), it's just a index corresponding to power(dbm). */ typedef enum { + ESP_PWR_LVL_N24 = 0, /*!< Corresponding to -24dbm */ + ESP_PWR_LVL_N21 = 1, /*!< Corresponding to -21dbm */ + ESP_PWR_LVL_N18 = 2, /*!< Corresponding to -18dbm */ ESP_PWR_LVL_N15 = 3, /*!< Corresponding to -15dbm */ ESP_PWR_LVL_N12 = 4, /*!< Corresponding to -12dbm */ ESP_PWR_LVL_N9 = 5, /*!< Corresponding to -9dbm */ @@ -155,7 +159,7 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type */ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle); -#define CONFIG_VERSION 0x20231124 +#define CONFIG_VERSION 0x20250526 #define CONFIG_MAGIC 0x5A5AA5A5 /** @@ -196,13 +200,6 @@ typedef struct { uint8_t controller_run_cpu; /*!< CPU core on which the controller runs */ uint8_t enable_qa_test; /*!< Enable quality assurance (QA) testing */ uint8_t enable_bqb_test; /*!< Enable Bluetooth Qualification Test (BQB) testing */ - uint8_t enable_uart_hci; /*!< Enable UART HCI (Host Controller Interface) */ - uint8_t ble_hci_uart_port; /*!< UART port number for Bluetooth HCI */ - uint32_t ble_hci_uart_baud; /*!< Baud rate for Bluetooth HCI UART */ - uint8_t ble_hci_uart_data_bits; /*!< Number of data bits for Bluetooth HCI UART */ - uint8_t ble_hci_uart_stop_bits; /*!< Number of stop bits for Bluetooth HCI UART */ - uint8_t ble_hci_uart_flow_ctrl; /*!< Flow control settings for Bluetooth HCI UART */ - uint8_t ble_hci_uart_uart_parity; /*!< Parity settings for Bluetooth HCI UART */ uint8_t enable_tx_cca; /*!< Enable Transmit Clear Channel Assessment (TX CCA) */ uint8_t cca_rssi_thresh; /*!< RSSI threshold for Transmit Clear Channel Assessment (CCA) */ uint8_t sleep_en; /*!< Enable sleep mode */ @@ -216,6 +213,25 @@ typedef struct { uint8_t ignore_wl_for_direct_adv; /*!< Ignore the whitelist for direct advertising */ uint8_t enable_pcl; /*!< Enable power control */ uint8_t csa2_select; /*!< Select CSA#2*/ + uint8_t enable_csr; /*!< Enable CSR */ + uint8_t ble_aa_check; /*!< True if adds a verification step for the Access Address within the CONNECT_IND PDU; false otherwise. Configurable in menuconfig */ + uint8_t ble_llcp_disc_flag; /*!< Flag indicating whether the Controller disconnects after Instant Passed (0x28) error occurs. Configurable in menuconfig. + - The Controller does not disconnect after Instant Passed (0x28) by default. */ + uint16_t scan_backoff_upperlimitmax; /*!< The value of upperlimitmax is 2^n, The maximum value is 256 */ + uint8_t ble_chan_ass_en; /*!< Enable / disable BLE channel assessment. Configurable in menuconfig. + - 0 - Disable + - 1 - Enable (default) */ + uint8_t ble_data_lenth_zero_aux; /*!< Enable / disable auxiliary packets when the extended ADV data length is zero. Configurable in menuconfig. + - 0 - Disable (default) + - 1 - Enable */ + uint8_t vhci_enabled; /*!< VHCI mode is enabled */ + uint8_t ptr_check_enabled; /*!< Enable boundary check for internal memory. */ + uint8_t ble_adv_tx_options; /*!< The options for Extended advertising sending. */ + uint8_t skip_unnecessary_checks_en; /*!< The option to skip non-fatal state checks and perform extra handling for fatal checks. */ + uint8_t fast_conn_data_tx_en; /*!< The option for fast transmission of connection data + - 0 - Disable + - 1 - Enable (default) */ + int8_t ch39_txpwr; /*!< BLE transmit power (in dBm) used for BLE advertising on channel 39. */ uint32_t config_magic; /*!< Magic number for configuration validation */ } esp_bt_controller_config_t; @@ -252,13 +268,6 @@ typedef struct { .controller_run_cpu = 0, \ .enable_qa_test = RUN_QA_TEST, \ .enable_bqb_test = RUN_BQB_TEST, \ - .enable_uart_hci = HCI_UART_EN, \ - .ble_hci_uart_port = DEFAULT_BT_LE_HCI_UART_PORT, \ - .ble_hci_uart_baud = DEFAULT_BT_LE_HCI_UART_BAUD, \ - .ble_hci_uart_data_bits = DEFAULT_BT_LE_HCI_UART_DATA_BITS, \ - .ble_hci_uart_stop_bits = DEFAULT_BT_LE_HCI_UART_STOP_BITS, \ - .ble_hci_uart_flow_ctrl = DEFAULT_BT_LE_HCI_UART_FLOW_CTRL, \ - .ble_hci_uart_uart_parity = DEFAULT_BT_LE_HCI_UART_PARITY, \ .enable_tx_cca = DEFAULT_BT_LE_TX_CCA_ENABLED, \ .cca_rssi_thresh = 256 - DEFAULT_BT_LE_CCA_RSSI_THRESH, \ .sleep_en = NIMBLE_SLEEP_ENABLE, \ @@ -270,6 +279,18 @@ typedef struct { .ignore_wl_for_direct_adv = 0, \ .enable_pcl = DEFAULT_BT_LE_POWER_CONTROL_ENABLED, \ .csa2_select = DEFAULT_BT_LE_50_FEATURE_SUPPORT, \ + .enable_csr = 0, \ + .ble_aa_check = DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS, \ + .ble_llcp_disc_flag = BT_LE_CTRL_LLCP_DISC_FLAG, \ + .scan_backoff_upperlimitmax = BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX, \ + .ble_chan_ass_en = DEFAULT_BT_LE_CTRL_CHAN_ASS_EN, \ + .ble_data_lenth_zero_aux = DEFAULT_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX, \ + .vhci_enabled = DEFAULT_BT_LE_VHCI_ENABLED, \ + .ptr_check_enabled = DEFAULT_BT_LE_PTR_CHECK_ENABLED, \ + .ble_adv_tx_options = 0, \ + .skip_unnecessary_checks_en = 0, \ + .fast_conn_data_tx_en = DEFAULT_BT_LE_CTRL_FAST_CONN_DATA_TX_EN, \ + .ch39_txpwr = BLE_LL_TX_PWR_DBM_N, \ .config_magic = CONFIG_MAGIC, \ } @@ -426,6 +447,14 @@ extern int esp_ble_hw_get_static_addr(esp_ble_addr_t *addr); void esp_ble_controller_log_dump_all(bool output); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +modem_clock_lpclk_src_t esp_bt_get_lpclk_src(void); + +void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src); + +uint32_t esp_bt_get_lpclk_freq(void); + +void esp_bt_set_lpclk_freq(uint32_t clk_freq); + #ifdef __cplusplus } #endif diff --git a/lib/bt/include/esp32c5/include/esp_bt_vs.h b/lib/bt/include/esp32c5/include/esp_bt_vs.h new file mode 100644 index 00000000..3cbed925 --- /dev/null +++ b/lib/bt/include/esp32c5/include/esp_bt_vs.h @@ -0,0 +1,360 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +// @brief HCI VS Commands for Espressif's Bluetooth Host +// +// @note The following vendor-specific HCI commands are exclusively for Espressif's Bluetooth Host (ESP-Bluedroid Host or ESP-NimBLE Host). +// If you are using a non-ESP host or HCI UART, these commands will remain disabled unless the initialization function is explicitly called from the application. +// Note, these init functions as well as these additional HCI VS commands are intended for Espressif's Bluetooth Host use only. +// Application developers **should not** call the init functions in their applications. +// + +/** + * @brief Config scanning duplicate exceptional list (OCF: 0x0108) + * + * @note The init function is `advFilter_stack_eanbleDupExcListCmd(true)` + */ +#define ESP_BT_VS_CONFIG_DUP_EXC_LIST_OCF (0x0108) +/** +* @brief Update exception list cmd parameters +*/ +struct bt_hci_vs_update_exc_list { + uint8_t subcode; /*!< Add, remove or clear exception list */ + uint32_t type; /*!< device type */ + uint8_t device_info[6]; /*!< device information */ +}; + +/** + * @brief Enable/disable advertising report flow control (OCF: 0x0109) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_SET_ADV_REPORT_FLOW_CTRL_OCF (0x0109) +/** +* @brief Init ADV flow control cmd parameters +*/ +struct bt_hci_vs_init_adv_flow_ctrl { + uint8_t enable; /*!< Enable ADV flow control */ + uint16_t num; /*!< ADV buffer maximum value */ + uint16_t adv_lost_threshold; /*!< ADV lost event triggered threshold */ +}; + +/** + * @brief Update the number of advertising report in ADV flow control (OCF: 0x010A) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_UPD_ADV_REPORT_FLOW_CTRL_NUM_OCF (0x010a) +/** +* @brief Update ADV flow control cmd parameters +*/ +struct bt_hci_vs_update_adv_flow_ctrl { + uint16_t num; /*!< The number of ADV report processed */ +}; + +/** + * @brief Clear legacy advertising (same as HCI_LE_Clear_Advertising_Sets) (OCF: 0x010C) + * + * @note The init function is `adv_stack_enableClearLegacyAdvVsCmd(true)` + */ +#define ESP_BT_VS_CLR_LEGACY_ADV_OCF (0x010c) +/** +* @brief Clear legacy ADV cmd parameters +*/ +struct bt_hci_vs_ble_clr_legacy_adv { + // no parameters +}; + +/** + * @brief Set parameters of duplicate list (OCF: 0x010D) + * + * @note The init function is `advFilter_stack_eanbleDupExcListCmd(true)` + */ +#define ESP_BT_VS_SET_DUP_LIST_PARAMS_OCF (0x010d) +/** +* @brief Set duplicate list cmd parameters +*/ +struct bt_hci_vs_ble_set_dup_params { + uint8_t dup_mode; /*!< Duplicate mode */ + uint8_t dup_ad_type; /*!< Duplicate data type */ + uint16_t ring_list_max_num; /*!< Duplicate list size */ +}; + +/** + * @brief Enable/disable duplicate and exception list (OCF: 0x010E) + * + * @note The init function is `advFilter_stack_eanbleDupExcListCmd(true)` + */ +#define ESP_BT_VS_ENABLE_DUP_EXC_LIST_OCF (0x010e) +/** +* @brief Enable duplicate and exception list cmd parameters +*/ +struct bt_hci_vs_ble_enable_dup_exc { + uint8_t enable; /*!< Enable or disable */ + uint8_t ring_list_reset; /*!< Reset list */ +}; + +/** + * @brief Enable optimization of multiple connections (OCF: 0x010F) + * + * @note The init function is `arr_stack_enableMultiConnVsCmd(true)` + */ +#define ESP_BT_VS_ENABLE_ARRANGEMENT_OCF (0x010f) +/** +* @brief Multiple connections optimization cmd parameters +*/ +struct bt_hci_vs_ble_enable_arrangement { + uint32_t common_factor; /*!< The greatest common factor of connection interval */ + uint8_t enable; /*!< Enable or disable */ +}; + +/** + * @brief Set scheduling length for a certain role (OCF: 0x0110) + * + * @note The init function is `arr_stack_enableMultiConnVsCmd(true)` + */ +#define ESP_BT_VS_SET_SCHED_ROLE_LEN_OCF (0x0110) +/** +* @brief Scheduling length cmd parameters +*/ +struct bt_hci_vs_ble_set_sched_role_len { + uint8_t role; /*!< BLE role; 0: central; 1: peripheral */ + uint32_t len; /*!< Length is us */ +}; + +/** + * @brief Set RSSI threshold for automatic power control (OCF: 0x0111) + * + * @note The init function is `pcl_stack_enableSetRssiThreshVsCmd(true)` + */ +#define ESP_BT_VS_SET_PCL_RSSI_THRESH_OCF (0x0111) +/** +* @brief PCL RSSI threshold cmd parameters +*/ +struct bt_hci_vs_ble_set_pcl_rssi_thresh { + uint16_t conn_handle; /*!< Connection handle */ + uint8_t rssi_thresh_min_1M; /*!< Lower limit for 1M */ + uint8_t rssi_thresh_max_1M; /*!< Upper limit for 1M */ + uint8_t rssi_thresh_min_2M; /*!< Lower limit for 2M */ + uint8_t rssi_thresh_max_2M; /*!< Upper limit for 2M */ + uint8_t rssi_thresh_min_s2coded; /*!< Lower limit for s2 coded */ + uint8_t rssi_thresh_max_s2coded; /*!< Upper limit for s2 coded */ + uint8_t rssi_thresh_min_s8coded; /*!< Lower limit for s8 coded */ + uint8_t rssi_thresh_max_s8coded; /*!< Upper limit for s8 coded */ +}; + +/** + * @brief Enable/disable channel selection algorithm #2 (OCF: 0x0112) + * + * @note The init function is `chanSel_stack_enableSetCsaVsCmd(true)` + */ +#define ESP_BT_VS_ENABLE_CSA2_OCF (0x0112) +/** +* @brief Enable/disable channel selection algorithm #2 cmd parameters +*/ +struct bt_hci_vs_ble_csa_enable { + uint8_t csa2_select; /*!< Select CSA2 */ +}; + +/** + * @brief Set parameters of controller logs (OCF: 0x0114) + * + * @note The init function is `log_stack_enableLogsRelatedVsCmd(true)` + */ +#define ESP_BT_VS_SET_LOG_PARAMS_OCF (0x0114) +/** +* @brief Controller logs cmd parameters +*/ +struct bt_hci_vs_ble_log_params { + uint8_t type; /*!< Operation type */ + uint32_t output_enable; /*!< Enable/disable output */ + uint8_t buffer_optoin /*!< Select log buffers */ +}; + +/** + * @brief Set BLE vendor events mask (OCF: 0x0116) + * + * @note The init function is `hci_stack_enableSetVsEvtMaskVsCmd(true)` + */ +#define ESP_BT_VS_SET_LE_VENDOR_EVTS_MASK_OCF (0x0116) +/** +* @brief Set BLE vendor events mask cmd parameters +*/ +struct bt_hci_vs_ble_set_vs_evts_mask { + uint32_t evt_masks; /*!< BLE vendor events Mask */ +}; + +/** + * @brief Set peer sleep clock accuracy to a constant value (OCF: 0x0118) + * + * @note The init function is `winWiden_stack_enableSetConstPeerScaVsCmd(true)` + */ +#define ESP_BT_VS_SET_CONST_PEER_SCA_OCF (0x0118) +/** +* @brief Peer constant SCA cmd parameters +*/ +struct bt_hci_vs_ble_set_const_peer_sca { + uint16_t peer_sca; /*!< Peer SCA */ +}; + +// @brief HCI VS Events for Espressif's Bluetooth Host +// +// @note The following HCI VS events are exclusively for Espressif's Bluetooth Host (ESP-Bluedroid Host or ESP-NimBLE Host). +// If you are using a non-ESP host or HCI UART, these events will remain disabled unless the initialization function is explicitly called from the application. +// Note, these init functions as well as these additional HCI VS events are intended for Espressif's Bluetooth Host use only. +// Application developers **should not** call the init functions in their applications. +// + +/** + * @brief BLE Scan/Connect Request, Aux Connect Response received event (EVTCODE: 0xFF, SUBCODE: 0xC0) + * + * @note The init function is `adv_stack_enableScanReqRxdVsEvent(true)` + */ +#define ESP_BT_VS_LE_CONN_SCAN_REQ_RXED_EVT_SUBCODE (0xC0) +/** +* @brief BLE Scan/Connect Request, Aux Connect Response received event parameters +*/ +struct bt_hci_vs_le_conn_scan_req_rxed_evt { + uint8_t evt_type; /*!< Event type; 0: SCAN_REQ; 1: CONN_IND */ + uint8_t handle; /*!< Advertisement handle */ + uint8_t peer_addr_type; /*!< Peer address type */ + uint8_t peer_addr[6]; /*!< Peer address */ +}; + +/** + * @brief BLE Channel Map Update Completion event (EVTCODE: 0xFF, SUBCODE: 0xC1) + * + * @note The init function is `conn_stack_enableChanMapUpdCompVsEvent(true)` + */ +#define ESP_BT_VS_LE_CHAN_UPDATE_COMP_EVT_SUBCODE (0xC1) +/** +* @brief BLE Channel Map Update Completion event parameters +*/ +struct bt_hci_vs_le_chan_update_comp_evt { + uint8_t status; /*!< Controller error code */ + uint16_t handle; /*!< Connection handle */ + uint8_t ch_map[5]; /*!< Updated channel map */ +}; + +/** + * @brief BLE Wakeup From Sleep event (EVTCODE: 0xFF, SUBCODE: 0xC3) + * + * @note The init function is `sleep_stack_enableWakeupVsEvent(true)` + */ +#define ESP_BT_VS_LE_SLEEP_WAKEUP_EVT_SUBCODE (0xC3) +/** +* @brief BLE wakeup event parameters +*/ +struct bt_hci_vs_le_sleep_wakeup_evt { + // no parameters +}; + +/** + * @brief BLE advertising report lost event for flow control (EVTCODE: 0x3E, SUBCODE: 0xF0) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_LE_ADV_LOST_EVT_SUBCODE (0xF0) +/** +* @brief ADV lost event parameters +*/ +struct bt_hci_vs_le_adv_lost_evt { + uint32_t nb_lost; /*!< The number of ADV report discarded */ +}; + +// +// @brief HCI VS Commands for Espressif's Internal-Use Debugging +// +// @note The following HCI VS debugging commands are implemented in Bluetooth controller pre-compiled libraries. +// These commands are not linked into the application binary, unless the function `esp_ble_internalTestFeaturesEnable(true)`is called from the application. +// They are intended for Espressif's internal use only. Application developers **should not** call `esp_ble_internalTestFeaturesEnable(true)` in their applications. +// + +#define ESP_BT_VS_CFG_TEST_RELATED_OCF (0x0113) + #define ESP_BT_VS_CFG_TEST_ENABLE_SUBCMD (0X00) + #define ESP_BT_VS_CFG_TEST_ENABLE_ADV_DELAY_SUBCMD (0X01) + #define ESP_BT_VS_CFG_TEST_SET_PREF_CODED_SUBCMD (0X02) + #define ESP_BT_VS_CFG_TEST_SET_DEFAULT_PRIV_MODE_SUBCMD (0X03) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_FOREVER_SUBCMD (0X04) + #define ESP_BT_VS_CFG_TEST_SET_EXPECTED_PEER_SUBCMD (0X05) + #define ESP_BT_VS_CFG_TEST_GET_ADV_TXED_CNT_SUBCMD (0X06) + #define ESP_BT_VS_CFG_TEST_GET_SCAN_RXED_CNT_SUBCMD (0X07) + #define ESP_BT_VS_CFG_TEST_SET_TXPWR_LVL_SUBCMD (0X08) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_LVL_SUBCMD (0X09) + #define ESP_BT_VS_CFG_TEST_SET_TXPWR_LVL_ENH_SUBCMD (0X0a) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_LVL_ENH_SUBCMD (0X0b) + #define ESP_BT_VS_CFG_TEST_IGNORE_WL_FOR_DIR_ADV_SUBCMD (0X0c) + #define ESP_BT_VS_CFG_TEST_GET_ADV_RXED_RSSI_SUBCMD (0X0d) + #define ESP_BT_VS_CFG_TEST_ENABLE_CCA_SUBCMD (0X0e) + #define ESP_BT_VS_CFG_TEST_SET_CCA_WIN_SUBCMD (0X0f) + #define ESP_BT_VS_CFG_TEST_READ_CCA_DATA_SUBCM (0X10) + #define ESP_BT_VS_CFG_TEST_CLEAR_RAND_ADDR_SUBCMD (0X11) + #define ESP_BT_VS_CFG_TEST_GET_MAX_TXPWR_SUBCMD (0X12) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_RANGE_SUBCMD (0X13) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_AA_SUBCMD (0X14) + #define ESP_BT_VS_CFG_TEST_SET_ADV_AA_SUBCMD (0X15) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_CHAN_SUBCMD (0X16) + #define ESP_BT_VS_CFG_TEST_SKIP_LIGHT_SLEEP_CHECK_SUBCMD (0X17) + #define ESP_BT_VS_CFG_TEST_SET_WAKEUP_OVERHEAD_SUBCMD (0X18) + #define ESP_BT_VS_CFG_TEST_GET_ADV_MIN_ITVL_SUBCMD (0X19) + #define ESP_BT_VS_CFG_TEST_GET_CTRL_STATUS_SUBCMD (0X1a) + #define ESP_BT_VS_CFG_TEST_SET_CONN_PHY_TXPWR_SUBCMD (0X1b) + #define ESP_BT_VS_CFG_TEST_GET_CONN_PHY_TXPWR_SUBCMD (0X1c) + #define ESP_BT_VS_CFG_TEST_GET_RXBUF_EMPTY_CNT_SUBCMD (0X1d) + #define ESP_BT_VS_CFG_TEST_RESTART_SUBCMD (0X1e) + #define ESP_BT_VS_CFG_TEST_ENABLE_RECODE_RX_STATE_SUBCMD (0X1f) + #define ESP_BT_VS_CFG_TEST_GET_RECODE_CNT_SUBCMD (0X20) + #define ESP_BT_VS_CFG_TEST_CLR_RECODE_CNT_SUBCMD (0X21) + #define ESP_BT_VS_CFG_TEST_GET_CTRL_COMPILE_VER_SUBCMD (0X24) + #define ESP_BT_VS_CFG_TEST_SET_AUX_ADV_OFFSET_SUBCMD (0X25) + #define ESP_BT_VS_CFG_TEST_INIT_FLEXIBLE_MODE_SUBCMD (0X26) + #define ESP_BT_VS_CFG_TEST_ENABLE_FLEXIBLE_MODE_SUBCMD (0X27) + #define ESP_BT_VS_CFG_TEST_SET_FLEXIBLE_CONN_ERR_SUBCMD (0X28) + #define ESP_BT_VS_CFG_TEST_SET_FLEXIBLE_ADV_ERR_SUBCMD (0X29) + #define ESP_BT_VS_CFG_TEST_SET_FLEXIBLE_SCAN_ERR_SUBCMD (0X2a) + #define ESP_BT_VS_CFG_TEST_GET_TXED_CRCERR_SUBCMD (0X2c) + #define ESP_BT_VS_CFG_TEST_GET_BACKOFF_UPLIMIT_SUBCMD (0X2d) + #define ESP_BT_VS_CFG_TEST_GET_RXED_ADV_ADI_SUBCMD (0X2f) + #define ESP_BT_VS_CFG_TEST_SET_SCH_RAND_MODE_SUBCMD (0X30) + #define ESP_BT_VS_CFG_TEST_SET_RX_SENS_THRESH_SUBCMD (0X31) + #define ESP_BT_VS_CFG_TEST_CHECK_MSYS_BUF_SUBCMD (0X32) + #define ESP_BT_VS_CFG_TEST_UPDATE_BLE_TIMER_SUBCMD (0X33) + #define ESP_BT_VS_CFG_TEST_UPDATE_BLE_RTC_SUBCMD (0X34) + #define ESP_BT_VS_CFG_TEST_SET_LOCKED_MEM_NUM_SUBCMD (0X35) + #define ESP_BT_VS_CFG_TEST_ALLOW_MEM_ALLOC_SUBCMD (0X36) + #define ESP_BT_VS_CFG_TEST_SET_SCH_RAND_INFO_PTR_SUBCMD (0X37) + #define ESP_BT_VS_CFG_TEST_SET_DIAG_IO_SUBCMD (0X38) + #define ESP_BT_VS_CFG_TEST_SET_AGC_MAX_GAIN_SUBCMD (0X39) + #define ESP_BT_VS_CFG_TEST_ENABLE_CHAN_ASSESS_SUBCMD (0X40) + #define ESP_BT_VS_CFG_TEST_SET_BACKOFF_UPLIMIT_SUBCMD (0X41) + #define ESP_BT_VS_CFG_TEST_SET_CONN_TOP_PRIO_RESV_THRESH_SUBCMD (0X42) + #define ESP_BT_VS_CFG_TEST_SET_TEST_EVT_MSK_SUBCMD (0X43) + #define ESP_BT_VS_CFG_TEST_GET_WAKEUP_TIMEOUT_SUBCMD (0X45) + #define ESP_BT_VS_CFG_TEST_RELATED_SUBCMD_MAX (0Xff) + +// +// @brief HCI VS Events for Espressif's Internal-Use Debugging +// +// @note The following HCI VS debugging events are implemented in Bluetooth controller pre-compiled libraries. +// These events are not linked into the application binary, unless the function `esp_ble_internalTestFeaturesEnable(true)`is called from the application. +// Application developers **should not** call `esp_ble_internalTestFeaturesEnable(true)` in their applications. +// + +#define ESP_BT_VS_LE_RUNNING_STATUS_EVT_SUBCODE (0xC3) + + +#ifdef __cplusplus +} +#endif diff --git a/lib/bt/include/esp32c6/include/esp_bt.h b/lib/bt/include/esp32c6/include/esp_bt.h index 210ead42..c035b4a6 100644 --- a/lib/bt/include/esp32c6/include/esp_bt.h +++ b/lib/bt/include/esp32c6/include/esp_bt.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,6 +16,7 @@ #include "nimble/nimble_npl.h" #include "../../../../controller/esp32c6/esp_bt_cfg.h" #include "hal/efuse_hal.h" +#include "esp_private/esp_modem_clock.h" #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART #include "driver/uart.h" @@ -155,7 +156,7 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type */ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle); -#define CONFIG_VERSION 0x20231124 +#define CONFIG_VERSION 0x20250526 #define CONFIG_MAGIC 0x5A5AA5A5 /** @@ -196,13 +197,6 @@ typedef struct { uint8_t controller_run_cpu; /*!< CPU core on which the controller runs */ uint8_t enable_qa_test; /*!< Enable quality assurance (QA) testing */ uint8_t enable_bqb_test; /*!< Enable Bluetooth Qualification Test (BQB) testing */ - uint8_t enable_uart_hci; /*!< Enable UART HCI (Host Controller Interface) */ - uint8_t ble_hci_uart_port; /*!< UART port number for Bluetooth HCI */ - uint32_t ble_hci_uart_baud; /*!< Baud rate for Bluetooth HCI UART */ - uint8_t ble_hci_uart_data_bits; /*!< Number of data bits for Bluetooth HCI UART */ - uint8_t ble_hci_uart_stop_bits; /*!< Number of stop bits for Bluetooth HCI UART */ - uint8_t ble_hci_uart_flow_ctrl; /*!< Flow control settings for Bluetooth HCI UART */ - uint8_t ble_hci_uart_uart_parity; /*!< Parity settings for Bluetooth HCI UART */ uint8_t enable_tx_cca; /*!< Enable Transmit Clear Channel Assessment (TX CCA) */ uint8_t cca_rssi_thresh; /*!< RSSI threshold for Transmit Clear Channel Assessment (CCA) */ uint8_t sleep_en; /*!< Enable sleep mode */ @@ -212,14 +206,37 @@ typedef struct { uint8_t cca_drop_mode; /*!< CCA drop mode */ int8_t cca_low_tx_pwr; /*!< CCA low transmit power */ uint8_t main_xtal_freq; /*!< Main crystal frequency */ +#if CONFIG_IDF_TARGET_ESP32C6 uint32_t version_num; /*!< Controller configuration version number */ +#endif //CONFIG_IDF_TARGET_ESP32C6 uint8_t cpu_freq_mhz; /*!< CPU frequency in megahertz (MHz) */ uint8_t ignore_wl_for_direct_adv; /*!< Ignore the whitelist for direct advertising */ uint8_t enable_pcl; /*!< Enable power control */ uint8_t csa2_select; /*!< Select CSA#2*/ + uint8_t enable_csr; /*!< Enable CSR */ + uint8_t ble_aa_check; /*!< True if adds a verification step for the Access Address within the CONNECT_IND PDU; false otherwise. Configurable in menuconfig */ + uint8_t ble_llcp_disc_flag; /*!< Flag indicating whether the Controller disconnects after Instant Passed (0x28) error occurs. Configurable in menuconfig. + - The Controller does not disconnect after Instant Passed (0x28) by default. */ + uint16_t scan_backoff_upperlimitmax; /*!< The value of upperlimitmax is 2^n, The maximum value is 256 */ + uint8_t ble_chan_ass_en; /*!< Enable / disable BLE channel assessment. Configurable in menuconfig. + - 0 - Disable + - 1 - Enable (default) */ + uint8_t ble_data_lenth_zero_aux; /*!< Enable / disable auxiliary packets when the extended ADV data length is zero. Configurable in menuconfig. + - 0 - Disable (default) + - 1 - Enable */ + uint8_t vhci_enabled; /*!< VHCI mode is enabled */ + uint8_t ptr_check_enabled; /*!< Enable boundary check for internal memory. */ + uint8_t ble_adv_tx_options; /*!< The options for Extended advertising sending. */ + uint8_t skip_unnecessary_checks_en; /*!< The option to skip non-fatal state checks and perform extra handling for fatal checks. */ + uint8_t fast_conn_data_tx_en; /*!< The option for fast transmission of connection data + - 0 - Disable + - 1 - Enable (default) */ + int8_t ch39_txpwr; /*!< BLE transmit power (in dBm) used for BLE advertising on channel 39. */ uint32_t config_magic; /*!< Magic number for configuration validation */ } esp_bt_controller_config_t; + +#if CONFIG_IDF_TARGET_ESP32C6 #define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \ .config_version = CONFIG_VERSION, \ .ble_ll_resolv_list_size = CONFIG_BT_LE_LL_RESOLV_LIST_SIZE, \ @@ -253,13 +270,6 @@ typedef struct { .controller_run_cpu = 0, \ .enable_qa_test = RUN_QA_TEST, \ .enable_bqb_test = RUN_BQB_TEST, \ - .enable_uart_hci = HCI_UART_EN, \ - .ble_hci_uart_port = DEFAULT_BT_LE_HCI_UART_PORT, \ - .ble_hci_uart_baud = DEFAULT_BT_LE_HCI_UART_BAUD, \ - .ble_hci_uart_data_bits = DEFAULT_BT_LE_HCI_UART_DATA_BITS, \ - .ble_hci_uart_stop_bits = DEFAULT_BT_LE_HCI_UART_STOP_BITS, \ - .ble_hci_uart_flow_ctrl = DEFAULT_BT_LE_HCI_UART_FLOW_CTRL, \ - .ble_hci_uart_uart_parity = DEFAULT_BT_LE_HCI_UART_PARITY, \ .enable_tx_cca = DEFAULT_BT_LE_TX_CCA_ENABLED, \ .cca_rssi_thresh = 256 - DEFAULT_BT_LE_CCA_RSSI_THRESH, \ .sleep_en = NIMBLE_SLEEP_ENABLE, \ @@ -272,8 +282,80 @@ typedef struct { .ignore_wl_for_direct_adv = 0, \ .enable_pcl = DEFAULT_BT_LE_POWER_CONTROL_ENABLED, \ .csa2_select = DEFAULT_BT_LE_50_FEATURE_SUPPORT, \ + .enable_csr = DEFAULT_BT_LE_SUBRATE_ENABLED, \ + .ble_aa_check = DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS, \ + .ble_llcp_disc_flag = BT_LE_CTRL_LLCP_DISC_FLAG, \ + .scan_backoff_upperlimitmax = BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX, \ + .ble_chan_ass_en = DEFAULT_BT_LE_CTRL_CHAN_ASS_EN, \ + .ble_data_lenth_zero_aux = DEFAULT_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX, \ + .vhci_enabled = DEFAULT_BT_LE_VHCI_ENABLED, \ + .ptr_check_enabled = DEFAULT_BT_LE_PTR_CHECK_ENABLED, \ + .ble_adv_tx_options = 0, \ + .skip_unnecessary_checks_en = 0, \ + .fast_conn_data_tx_en = DEFAULT_BT_LE_CTRL_FAST_CONN_DATA_TX_EN, \ + .ch39_txpwr = BLE_LL_TX_PWR_DBM_N, \ + .config_magic = CONFIG_MAGIC, \ +} +#elif CONFIG_IDF_TARGET_ESP32C61 +#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \ + .config_version = CONFIG_VERSION, \ + .ble_ll_resolv_list_size = CONFIG_BT_LE_LL_RESOLV_LIST_SIZE, \ + .ble_hci_evt_hi_buf_count = DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT, \ + .ble_hci_evt_lo_buf_count = DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT, \ + .ble_ll_sync_list_cnt = DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST, \ + .ble_ll_sync_cnt = DEFAULT_BT_LE_MAX_PERIODIC_SYNCS, \ + .ble_ll_rsp_dup_list_count = CONFIG_BT_LE_LL_DUP_SCAN_LIST_COUNT, \ + .ble_ll_adv_dup_list_count = CONFIG_BT_LE_LL_DUP_SCAN_LIST_COUNT, \ + .ble_ll_tx_pwr_dbm = BLE_LL_TX_PWR_DBM_N, \ + .rtc_freq = RTC_FREQ_N, \ + .ble_ll_sca = CONFIG_BT_LE_LL_SCA, \ + .ble_ll_scan_phy_number = BLE_LL_SCAN_PHY_NUMBER_N, \ + .ble_ll_conn_def_auth_pyld_tmo = BLE_LL_CONN_DEF_AUTH_PYLD_TMO_N, \ + .ble_ll_jitter_usecs = BLE_LL_JITTER_USECS_N, \ + .ble_ll_sched_max_adv_pdu_usecs = BLE_LL_SCHED_MAX_ADV_PDU_USECS_N, \ + .ble_ll_sched_direct_adv_max_usecs = BLE_LL_SCHED_DIRECT_ADV_MAX_USECS_N, \ + .ble_ll_sched_adv_max_usecs = BLE_LL_SCHED_ADV_MAX_USECS_N, \ + .ble_scan_rsp_data_max_len = DEFAULT_BT_LE_SCAN_RSP_DATA_MAX_LEN_N, \ + .ble_ll_cfg_num_hci_cmd_pkts = BLE_LL_CFG_NUM_HCI_CMD_PKTS_N, \ + .ble_ll_ctrl_proc_timeout_ms = BLE_LL_CTRL_PROC_TIMEOUT_MS_N, \ + .nimble_max_connections = DEFAULT_BT_LE_MAX_CONNECTIONS, \ + .ble_whitelist_size = DEFAULT_BT_NIMBLE_WHITELIST_SIZE, \ + .ble_acl_buf_size = DEFAULT_BT_LE_ACL_BUF_SIZE, \ + .ble_acl_buf_count = DEFAULT_BT_LE_ACL_BUF_COUNT, \ + .ble_hci_evt_buf_size = DEFAULT_BT_LE_HCI_EVT_BUF_SIZE, \ + .ble_multi_adv_instances = DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES, \ + .ble_ext_adv_max_size = DEFAULT_BT_LE_EXT_ADV_MAX_SIZE, \ + .controller_task_stack_size = NIMBLE_LL_STACK_SIZE, \ + .controller_task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \ + .controller_run_cpu = 0, \ + .enable_qa_test = RUN_QA_TEST, \ + .enable_bqb_test = RUN_BQB_TEST, \ + .enable_tx_cca = DEFAULT_BT_LE_TX_CCA_ENABLED, \ + .cca_rssi_thresh = 256 - DEFAULT_BT_LE_CCA_RSSI_THRESH, \ + .sleep_en = NIMBLE_SLEEP_ENABLE, \ + .coex_phy_coded_tx_rx_time_limit = DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF, \ + .dis_scan_backoff = NIMBLE_DISABLE_SCAN_BACKOFF, \ + .ble_scan_classify_filter_enable = 1, \ + .main_xtal_freq = CONFIG_XTAL_FREQ, \ + .cpu_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, \ + .ignore_wl_for_direct_adv = 0, \ + .enable_pcl = DEFAULT_BT_LE_POWER_CONTROL_ENABLED, \ + .csa2_select = DEFAULT_BT_LE_50_FEATURE_SUPPORT, \ + .enable_csr = 0, \ + .ble_aa_check = DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS, \ + .ble_llcp_disc_flag = BT_LE_CTRL_LLCP_DISC_FLAG, \ + .scan_backoff_upperlimitmax = BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX, \ + .ble_chan_ass_en = DEFAULT_BT_LE_CTRL_CHAN_ASS_EN, \ + .ble_data_lenth_zero_aux = DEFAULT_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX, \ + .vhci_enabled = DEFAULT_BT_LE_VHCI_ENABLED, \ + .ptr_check_enabled = DEFAULT_BT_LE_PTR_CHECK_ENABLED, \ + .ble_adv_tx_options = 0, \ + .skip_unnecessary_checks_en = 0, \ + .fast_conn_data_tx_en = DEFAULT_BT_LE_CTRL_FAST_CONN_DATA_TX_EN, \ + .ch39_txpwr = BLE_LL_TX_PWR_DBM_N, \ .config_magic = CONFIG_MAGIC, \ } +#endif /** * @brief Initialize BT controller to allocate task and other resource. @@ -428,6 +510,14 @@ extern int esp_ble_hw_get_static_addr(esp_ble_addr_t *addr); void esp_ble_controller_log_dump_all(bool output); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +modem_clock_lpclk_src_t esp_bt_get_lpclk_src(void); + +void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src); + +uint32_t esp_bt_get_lpclk_freq(void); + +void esp_bt_set_lpclk_freq(uint32_t clk_freq); + #ifdef __cplusplus } #endif diff --git a/lib/bt/include/esp32c6/include/esp_bt_vs.h b/lib/bt/include/esp32c6/include/esp_bt_vs.h new file mode 100644 index 00000000..3cbed925 --- /dev/null +++ b/lib/bt/include/esp32c6/include/esp_bt_vs.h @@ -0,0 +1,360 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +// @brief HCI VS Commands for Espressif's Bluetooth Host +// +// @note The following vendor-specific HCI commands are exclusively for Espressif's Bluetooth Host (ESP-Bluedroid Host or ESP-NimBLE Host). +// If you are using a non-ESP host or HCI UART, these commands will remain disabled unless the initialization function is explicitly called from the application. +// Note, these init functions as well as these additional HCI VS commands are intended for Espressif's Bluetooth Host use only. +// Application developers **should not** call the init functions in their applications. +// + +/** + * @brief Config scanning duplicate exceptional list (OCF: 0x0108) + * + * @note The init function is `advFilter_stack_eanbleDupExcListCmd(true)` + */ +#define ESP_BT_VS_CONFIG_DUP_EXC_LIST_OCF (0x0108) +/** +* @brief Update exception list cmd parameters +*/ +struct bt_hci_vs_update_exc_list { + uint8_t subcode; /*!< Add, remove or clear exception list */ + uint32_t type; /*!< device type */ + uint8_t device_info[6]; /*!< device information */ +}; + +/** + * @brief Enable/disable advertising report flow control (OCF: 0x0109) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_SET_ADV_REPORT_FLOW_CTRL_OCF (0x0109) +/** +* @brief Init ADV flow control cmd parameters +*/ +struct bt_hci_vs_init_adv_flow_ctrl { + uint8_t enable; /*!< Enable ADV flow control */ + uint16_t num; /*!< ADV buffer maximum value */ + uint16_t adv_lost_threshold; /*!< ADV lost event triggered threshold */ +}; + +/** + * @brief Update the number of advertising report in ADV flow control (OCF: 0x010A) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_UPD_ADV_REPORT_FLOW_CTRL_NUM_OCF (0x010a) +/** +* @brief Update ADV flow control cmd parameters +*/ +struct bt_hci_vs_update_adv_flow_ctrl { + uint16_t num; /*!< The number of ADV report processed */ +}; + +/** + * @brief Clear legacy advertising (same as HCI_LE_Clear_Advertising_Sets) (OCF: 0x010C) + * + * @note The init function is `adv_stack_enableClearLegacyAdvVsCmd(true)` + */ +#define ESP_BT_VS_CLR_LEGACY_ADV_OCF (0x010c) +/** +* @brief Clear legacy ADV cmd parameters +*/ +struct bt_hci_vs_ble_clr_legacy_adv { + // no parameters +}; + +/** + * @brief Set parameters of duplicate list (OCF: 0x010D) + * + * @note The init function is `advFilter_stack_eanbleDupExcListCmd(true)` + */ +#define ESP_BT_VS_SET_DUP_LIST_PARAMS_OCF (0x010d) +/** +* @brief Set duplicate list cmd parameters +*/ +struct bt_hci_vs_ble_set_dup_params { + uint8_t dup_mode; /*!< Duplicate mode */ + uint8_t dup_ad_type; /*!< Duplicate data type */ + uint16_t ring_list_max_num; /*!< Duplicate list size */ +}; + +/** + * @brief Enable/disable duplicate and exception list (OCF: 0x010E) + * + * @note The init function is `advFilter_stack_eanbleDupExcListCmd(true)` + */ +#define ESP_BT_VS_ENABLE_DUP_EXC_LIST_OCF (0x010e) +/** +* @brief Enable duplicate and exception list cmd parameters +*/ +struct bt_hci_vs_ble_enable_dup_exc { + uint8_t enable; /*!< Enable or disable */ + uint8_t ring_list_reset; /*!< Reset list */ +}; + +/** + * @brief Enable optimization of multiple connections (OCF: 0x010F) + * + * @note The init function is `arr_stack_enableMultiConnVsCmd(true)` + */ +#define ESP_BT_VS_ENABLE_ARRANGEMENT_OCF (0x010f) +/** +* @brief Multiple connections optimization cmd parameters +*/ +struct bt_hci_vs_ble_enable_arrangement { + uint32_t common_factor; /*!< The greatest common factor of connection interval */ + uint8_t enable; /*!< Enable or disable */ +}; + +/** + * @brief Set scheduling length for a certain role (OCF: 0x0110) + * + * @note The init function is `arr_stack_enableMultiConnVsCmd(true)` + */ +#define ESP_BT_VS_SET_SCHED_ROLE_LEN_OCF (0x0110) +/** +* @brief Scheduling length cmd parameters +*/ +struct bt_hci_vs_ble_set_sched_role_len { + uint8_t role; /*!< BLE role; 0: central; 1: peripheral */ + uint32_t len; /*!< Length is us */ +}; + +/** + * @brief Set RSSI threshold for automatic power control (OCF: 0x0111) + * + * @note The init function is `pcl_stack_enableSetRssiThreshVsCmd(true)` + */ +#define ESP_BT_VS_SET_PCL_RSSI_THRESH_OCF (0x0111) +/** +* @brief PCL RSSI threshold cmd parameters +*/ +struct bt_hci_vs_ble_set_pcl_rssi_thresh { + uint16_t conn_handle; /*!< Connection handle */ + uint8_t rssi_thresh_min_1M; /*!< Lower limit for 1M */ + uint8_t rssi_thresh_max_1M; /*!< Upper limit for 1M */ + uint8_t rssi_thresh_min_2M; /*!< Lower limit for 2M */ + uint8_t rssi_thresh_max_2M; /*!< Upper limit for 2M */ + uint8_t rssi_thresh_min_s2coded; /*!< Lower limit for s2 coded */ + uint8_t rssi_thresh_max_s2coded; /*!< Upper limit for s2 coded */ + uint8_t rssi_thresh_min_s8coded; /*!< Lower limit for s8 coded */ + uint8_t rssi_thresh_max_s8coded; /*!< Upper limit for s8 coded */ +}; + +/** + * @brief Enable/disable channel selection algorithm #2 (OCF: 0x0112) + * + * @note The init function is `chanSel_stack_enableSetCsaVsCmd(true)` + */ +#define ESP_BT_VS_ENABLE_CSA2_OCF (0x0112) +/** +* @brief Enable/disable channel selection algorithm #2 cmd parameters +*/ +struct bt_hci_vs_ble_csa_enable { + uint8_t csa2_select; /*!< Select CSA2 */ +}; + +/** + * @brief Set parameters of controller logs (OCF: 0x0114) + * + * @note The init function is `log_stack_enableLogsRelatedVsCmd(true)` + */ +#define ESP_BT_VS_SET_LOG_PARAMS_OCF (0x0114) +/** +* @brief Controller logs cmd parameters +*/ +struct bt_hci_vs_ble_log_params { + uint8_t type; /*!< Operation type */ + uint32_t output_enable; /*!< Enable/disable output */ + uint8_t buffer_optoin /*!< Select log buffers */ +}; + +/** + * @brief Set BLE vendor events mask (OCF: 0x0116) + * + * @note The init function is `hci_stack_enableSetVsEvtMaskVsCmd(true)` + */ +#define ESP_BT_VS_SET_LE_VENDOR_EVTS_MASK_OCF (0x0116) +/** +* @brief Set BLE vendor events mask cmd parameters +*/ +struct bt_hci_vs_ble_set_vs_evts_mask { + uint32_t evt_masks; /*!< BLE vendor events Mask */ +}; + +/** + * @brief Set peer sleep clock accuracy to a constant value (OCF: 0x0118) + * + * @note The init function is `winWiden_stack_enableSetConstPeerScaVsCmd(true)` + */ +#define ESP_BT_VS_SET_CONST_PEER_SCA_OCF (0x0118) +/** +* @brief Peer constant SCA cmd parameters +*/ +struct bt_hci_vs_ble_set_const_peer_sca { + uint16_t peer_sca; /*!< Peer SCA */ +}; + +// @brief HCI VS Events for Espressif's Bluetooth Host +// +// @note The following HCI VS events are exclusively for Espressif's Bluetooth Host (ESP-Bluedroid Host or ESP-NimBLE Host). +// If you are using a non-ESP host or HCI UART, these events will remain disabled unless the initialization function is explicitly called from the application. +// Note, these init functions as well as these additional HCI VS events are intended for Espressif's Bluetooth Host use only. +// Application developers **should not** call the init functions in their applications. +// + +/** + * @brief BLE Scan/Connect Request, Aux Connect Response received event (EVTCODE: 0xFF, SUBCODE: 0xC0) + * + * @note The init function is `adv_stack_enableScanReqRxdVsEvent(true)` + */ +#define ESP_BT_VS_LE_CONN_SCAN_REQ_RXED_EVT_SUBCODE (0xC0) +/** +* @brief BLE Scan/Connect Request, Aux Connect Response received event parameters +*/ +struct bt_hci_vs_le_conn_scan_req_rxed_evt { + uint8_t evt_type; /*!< Event type; 0: SCAN_REQ; 1: CONN_IND */ + uint8_t handle; /*!< Advertisement handle */ + uint8_t peer_addr_type; /*!< Peer address type */ + uint8_t peer_addr[6]; /*!< Peer address */ +}; + +/** + * @brief BLE Channel Map Update Completion event (EVTCODE: 0xFF, SUBCODE: 0xC1) + * + * @note The init function is `conn_stack_enableChanMapUpdCompVsEvent(true)` + */ +#define ESP_BT_VS_LE_CHAN_UPDATE_COMP_EVT_SUBCODE (0xC1) +/** +* @brief BLE Channel Map Update Completion event parameters +*/ +struct bt_hci_vs_le_chan_update_comp_evt { + uint8_t status; /*!< Controller error code */ + uint16_t handle; /*!< Connection handle */ + uint8_t ch_map[5]; /*!< Updated channel map */ +}; + +/** + * @brief BLE Wakeup From Sleep event (EVTCODE: 0xFF, SUBCODE: 0xC3) + * + * @note The init function is `sleep_stack_enableWakeupVsEvent(true)` + */ +#define ESP_BT_VS_LE_SLEEP_WAKEUP_EVT_SUBCODE (0xC3) +/** +* @brief BLE wakeup event parameters +*/ +struct bt_hci_vs_le_sleep_wakeup_evt { + // no parameters +}; + +/** + * @brief BLE advertising report lost event for flow control (EVTCODE: 0x3E, SUBCODE: 0xF0) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_LE_ADV_LOST_EVT_SUBCODE (0xF0) +/** +* @brief ADV lost event parameters +*/ +struct bt_hci_vs_le_adv_lost_evt { + uint32_t nb_lost; /*!< The number of ADV report discarded */ +}; + +// +// @brief HCI VS Commands for Espressif's Internal-Use Debugging +// +// @note The following HCI VS debugging commands are implemented in Bluetooth controller pre-compiled libraries. +// These commands are not linked into the application binary, unless the function `esp_ble_internalTestFeaturesEnable(true)`is called from the application. +// They are intended for Espressif's internal use only. Application developers **should not** call `esp_ble_internalTestFeaturesEnable(true)` in their applications. +// + +#define ESP_BT_VS_CFG_TEST_RELATED_OCF (0x0113) + #define ESP_BT_VS_CFG_TEST_ENABLE_SUBCMD (0X00) + #define ESP_BT_VS_CFG_TEST_ENABLE_ADV_DELAY_SUBCMD (0X01) + #define ESP_BT_VS_CFG_TEST_SET_PREF_CODED_SUBCMD (0X02) + #define ESP_BT_VS_CFG_TEST_SET_DEFAULT_PRIV_MODE_SUBCMD (0X03) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_FOREVER_SUBCMD (0X04) + #define ESP_BT_VS_CFG_TEST_SET_EXPECTED_PEER_SUBCMD (0X05) + #define ESP_BT_VS_CFG_TEST_GET_ADV_TXED_CNT_SUBCMD (0X06) + #define ESP_BT_VS_CFG_TEST_GET_SCAN_RXED_CNT_SUBCMD (0X07) + #define ESP_BT_VS_CFG_TEST_SET_TXPWR_LVL_SUBCMD (0X08) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_LVL_SUBCMD (0X09) + #define ESP_BT_VS_CFG_TEST_SET_TXPWR_LVL_ENH_SUBCMD (0X0a) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_LVL_ENH_SUBCMD (0X0b) + #define ESP_BT_VS_CFG_TEST_IGNORE_WL_FOR_DIR_ADV_SUBCMD (0X0c) + #define ESP_BT_VS_CFG_TEST_GET_ADV_RXED_RSSI_SUBCMD (0X0d) + #define ESP_BT_VS_CFG_TEST_ENABLE_CCA_SUBCMD (0X0e) + #define ESP_BT_VS_CFG_TEST_SET_CCA_WIN_SUBCMD (0X0f) + #define ESP_BT_VS_CFG_TEST_READ_CCA_DATA_SUBCM (0X10) + #define ESP_BT_VS_CFG_TEST_CLEAR_RAND_ADDR_SUBCMD (0X11) + #define ESP_BT_VS_CFG_TEST_GET_MAX_TXPWR_SUBCMD (0X12) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_RANGE_SUBCMD (0X13) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_AA_SUBCMD (0X14) + #define ESP_BT_VS_CFG_TEST_SET_ADV_AA_SUBCMD (0X15) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_CHAN_SUBCMD (0X16) + #define ESP_BT_VS_CFG_TEST_SKIP_LIGHT_SLEEP_CHECK_SUBCMD (0X17) + #define ESP_BT_VS_CFG_TEST_SET_WAKEUP_OVERHEAD_SUBCMD (0X18) + #define ESP_BT_VS_CFG_TEST_GET_ADV_MIN_ITVL_SUBCMD (0X19) + #define ESP_BT_VS_CFG_TEST_GET_CTRL_STATUS_SUBCMD (0X1a) + #define ESP_BT_VS_CFG_TEST_SET_CONN_PHY_TXPWR_SUBCMD (0X1b) + #define ESP_BT_VS_CFG_TEST_GET_CONN_PHY_TXPWR_SUBCMD (0X1c) + #define ESP_BT_VS_CFG_TEST_GET_RXBUF_EMPTY_CNT_SUBCMD (0X1d) + #define ESP_BT_VS_CFG_TEST_RESTART_SUBCMD (0X1e) + #define ESP_BT_VS_CFG_TEST_ENABLE_RECODE_RX_STATE_SUBCMD (0X1f) + #define ESP_BT_VS_CFG_TEST_GET_RECODE_CNT_SUBCMD (0X20) + #define ESP_BT_VS_CFG_TEST_CLR_RECODE_CNT_SUBCMD (0X21) + #define ESP_BT_VS_CFG_TEST_GET_CTRL_COMPILE_VER_SUBCMD (0X24) + #define ESP_BT_VS_CFG_TEST_SET_AUX_ADV_OFFSET_SUBCMD (0X25) + #define ESP_BT_VS_CFG_TEST_INIT_FLEXIBLE_MODE_SUBCMD (0X26) + #define ESP_BT_VS_CFG_TEST_ENABLE_FLEXIBLE_MODE_SUBCMD (0X27) + #define ESP_BT_VS_CFG_TEST_SET_FLEXIBLE_CONN_ERR_SUBCMD (0X28) + #define ESP_BT_VS_CFG_TEST_SET_FLEXIBLE_ADV_ERR_SUBCMD (0X29) + #define ESP_BT_VS_CFG_TEST_SET_FLEXIBLE_SCAN_ERR_SUBCMD (0X2a) + #define ESP_BT_VS_CFG_TEST_GET_TXED_CRCERR_SUBCMD (0X2c) + #define ESP_BT_VS_CFG_TEST_GET_BACKOFF_UPLIMIT_SUBCMD (0X2d) + #define ESP_BT_VS_CFG_TEST_GET_RXED_ADV_ADI_SUBCMD (0X2f) + #define ESP_BT_VS_CFG_TEST_SET_SCH_RAND_MODE_SUBCMD (0X30) + #define ESP_BT_VS_CFG_TEST_SET_RX_SENS_THRESH_SUBCMD (0X31) + #define ESP_BT_VS_CFG_TEST_CHECK_MSYS_BUF_SUBCMD (0X32) + #define ESP_BT_VS_CFG_TEST_UPDATE_BLE_TIMER_SUBCMD (0X33) + #define ESP_BT_VS_CFG_TEST_UPDATE_BLE_RTC_SUBCMD (0X34) + #define ESP_BT_VS_CFG_TEST_SET_LOCKED_MEM_NUM_SUBCMD (0X35) + #define ESP_BT_VS_CFG_TEST_ALLOW_MEM_ALLOC_SUBCMD (0X36) + #define ESP_BT_VS_CFG_TEST_SET_SCH_RAND_INFO_PTR_SUBCMD (0X37) + #define ESP_BT_VS_CFG_TEST_SET_DIAG_IO_SUBCMD (0X38) + #define ESP_BT_VS_CFG_TEST_SET_AGC_MAX_GAIN_SUBCMD (0X39) + #define ESP_BT_VS_CFG_TEST_ENABLE_CHAN_ASSESS_SUBCMD (0X40) + #define ESP_BT_VS_CFG_TEST_SET_BACKOFF_UPLIMIT_SUBCMD (0X41) + #define ESP_BT_VS_CFG_TEST_SET_CONN_TOP_PRIO_RESV_THRESH_SUBCMD (0X42) + #define ESP_BT_VS_CFG_TEST_SET_TEST_EVT_MSK_SUBCMD (0X43) + #define ESP_BT_VS_CFG_TEST_GET_WAKEUP_TIMEOUT_SUBCMD (0X45) + #define ESP_BT_VS_CFG_TEST_RELATED_SUBCMD_MAX (0Xff) + +// +// @brief HCI VS Events for Espressif's Internal-Use Debugging +// +// @note The following HCI VS debugging events are implemented in Bluetooth controller pre-compiled libraries. +// These events are not linked into the application binary, unless the function `esp_ble_internalTestFeaturesEnable(true)`is called from the application. +// Application developers **should not** call `esp_ble_internalTestFeaturesEnable(true)` in their applications. +// + +#define ESP_BT_VS_LE_RUNNING_STATUS_EVT_SUBCODE (0xC3) + + +#ifdef __cplusplus +} +#endif diff --git a/lib/bt/include/esp32h2/include/esp_bt.h b/lib/bt/include/esp32h2/include/esp_bt.h index a1c7aed8..0aafa744 100644 --- a/lib/bt/include/esp32h2/include/esp_bt.h +++ b/lib/bt/include/esp32h2/include/esp_bt.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,6 +15,7 @@ #include "nimble/nimble_npl.h" #include "../../../../controller/esp32h2/esp_bt_cfg.h" +#include "esp_private/esp_modem_clock.h" #ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART #include "driver/uart.h" @@ -108,14 +109,6 @@ typedef enum { ESP_BLE_ENHANCED_PWR_TYPE_MAX, } esp_ble_enhanced_power_type_t; -/** - * @brief Address type and address value. - */ -typedef struct { - uint8_t type; /*!< Type of the Bluetooth address (public, random, etc.) */ - uint8_t val[6]; /*!< Array containing the 6-byte Bluetooth address value */ -} esp_ble_addr_t; - /** * @brief Select buffers */ @@ -124,6 +117,14 @@ typedef enum { ESP_BLE_LOG_BUF_CONTROLLER = 0x05, } esp_ble_log_buf_t; +/** + * @brief Address type and address value. + */ +typedef struct { + uint8_t type; /*!< Type of the Bluetooth address (public, random, etc.) */ + uint8_t val[6]; /*!< Array containing the 6-byte Bluetooth address value */ +} esp_ble_addr_t; + /** * @brief Set BLE TX power * Connection Tx power should only be set after connection created. @@ -160,7 +161,7 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type */ esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle); -#define CONFIG_VERSION 0x20231124 +#define CONFIG_VERSION 0x20250526 #define CONFIG_MAGIC 0x5A5AA5A5 /** @@ -201,13 +202,6 @@ typedef struct { uint8_t controller_run_cpu; /*!< CPU number on which the Bluetooth controller task runs */ uint8_t enable_qa_test; /*!< Enable for QA test */ uint8_t enable_bqb_test; /*!< Enable for BQB test */ - uint8_t enable_uart_hci; /*!< Enable UART for HCI (Host Controller Interface) */ - uint8_t ble_hci_uart_port; /*!< Port of UART for HCI */ - uint32_t ble_hci_uart_baud; /*!< Baudrate of UART for HCI */ - uint8_t ble_hci_uart_data_bits; /*!< Data bits of UART for HCI */ - uint8_t ble_hci_uart_stop_bits; /*!< Stop bits of UART for HCI */ - uint8_t ble_hci_uart_flow_ctrl; /*!< Flow control of UART for HCI */ - uint8_t ble_hci_uart_uart_parity; /*!< UART parity */ uint8_t enable_tx_cca; /*!< Enable Clear Channel Assessment (CCA) when transmitting */ uint8_t cca_rssi_thresh; /*!< RSSI threshold for CCA */ uint8_t sleep_en; /*!< Enable sleep functionality */ @@ -220,8 +214,27 @@ typedef struct { uint8_t cpu_freq_mhz; /*!< CPU frequency in megahertz */ uint8_t ignore_wl_for_direct_adv; /*!< Ignore the white list for directed advertising */ uint8_t enable_pcl; /*!< Enable power control */ - uint8_t csa2_select; /*!< Select CSA#2*/ - uint32_t config_magic; /*!< Configuration magic value */ + uint8_t csa2_select; /*!< Select CSA#2*/ + uint8_t enable_csr; /*!< Enable CSR */ + uint8_t ble_aa_check; /*!< True if adds a verification step for the Access Address within the CONNECT_IND PDU; false otherwise. Configurable in menuconfig */ + uint8_t ble_llcp_disc_flag; /*!< Flag indicating whether the Controller disconnects after Instant Passed (0x28) error occurs. Configurable in menuconfig. + - The Controller does not disconnect after Instant Passed (0x28) by default. */ + uint16_t scan_backoff_upperlimitmax; /*!< The value of upperlimitmax is 2^n, The maximum value is 256 */ + uint8_t ble_chan_ass_en; /*!< Enable / disable BLE channel assessment. Configurable in menuconfig. + - 0 - Disable + - 1 - Enable (default) */ + uint8_t ble_data_lenth_zero_aux; /*!< Enable / disable auxiliary packets when the extended ADV data length is zero. Configurable in menuconfig. + - 0 - Disable (default) + - 1 - Enable */ + uint8_t vhci_enabled; /*!< VHCI is enabled */ + uint8_t ptr_check_enabled; /*!< Enable boundary check for internal memory. */ + uint8_t ble_adv_tx_options; /*!< The options for Extended advertising sending. */ + uint8_t skip_unnecessary_checks_en; /*!< The option to skip non-fatal state checks and perform extra handling for fatal checks. */ + uint8_t fast_conn_data_tx_en; /*!< The option for fast transmission of connection data + - 0 - Disable + - 1 - Enable (default) */ + int8_t ch39_txpwr; /*!< BLE transmit power (in dBm) used for BLE advertising on channel 39. */ + uint32_t config_magic; /*!< Configuration magic value */ } esp_bt_controller_config_t; @@ -258,13 +271,6 @@ typedef struct { .controller_run_cpu = 0, \ .enable_qa_test = RUN_QA_TEST, \ .enable_bqb_test = RUN_BQB_TEST, \ - .enable_uart_hci = HCI_UART_EN, \ - .ble_hci_uart_port = DEFAULT_BT_LE_HCI_UART_PORT, \ - .ble_hci_uart_baud = DEFAULT_BT_LE_HCI_UART_BAUD, \ - .ble_hci_uart_data_bits = DEFAULT_BT_LE_HCI_UART_DATA_BITS, \ - .ble_hci_uart_stop_bits = DEFAULT_BT_LE_HCI_UART_STOP_BITS, \ - .ble_hci_uart_flow_ctrl = DEFAULT_BT_LE_HCI_UART_FLOW_CTRL, \ - .ble_hci_uart_uart_parity = DEFAULT_BT_LE_HCI_UART_PARITY, \ .enable_tx_cca = DEFAULT_BT_LE_TX_CCA_ENABLED, \ .cca_rssi_thresh = 256 - DEFAULT_BT_LE_CCA_RSSI_THRESH, \ .sleep_en = NIMBLE_SLEEP_ENABLE, \ @@ -274,8 +280,20 @@ typedef struct { .main_xtal_freq = CONFIG_XTAL_FREQ, \ .cpu_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, \ .ignore_wl_for_direct_adv = 0, \ - .enable_pcl = 0, \ - .csa2_select = DEFAULT_BT_LE_50_FEATURE_SUPPORT, \ + .enable_pcl = DEFAULT_BT_LE_POWER_CONTROL_ENABLED, \ + .csa2_select = DEFAULT_BT_LE_50_FEATURE_SUPPORT, \ + .enable_csr = 0, \ + .ble_aa_check = DEFAULT_BT_LE_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS, \ + .ble_llcp_disc_flag = BT_LE_CTRL_LLCP_DISC_FLAG, \ + .scan_backoff_upperlimitmax = BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX, \ + .ble_chan_ass_en = DEFAULT_BT_LE_CTRL_CHAN_ASS_EN, \ + .ble_data_lenth_zero_aux = DEFAULT_BT_LE_CTRL_ADV_DATA_LENGTH_ZERO_AUX, \ + .vhci_enabled = DEFAULT_BT_LE_VHCI_ENABLED, \ + .ptr_check_enabled = DEFAULT_BT_LE_PTR_CHECK_ENABLED, \ + .ble_adv_tx_options = 0, \ + .skip_unnecessary_checks_en = 0, \ + .fast_conn_data_tx_en = DEFAULT_BT_LE_CTRL_FAST_CONN_DATA_TX_EN, \ + .ch39_txpwr = BLE_LL_TX_PWR_DBM_N, \ .config_magic = CONFIG_MAGIC, \ } @@ -432,6 +450,14 @@ extern int esp_ble_hw_get_static_addr(esp_ble_addr_t *addr); void esp_ble_controller_log_dump_all(bool output); #endif // CONFIG_BT_LE_CONTROLLER_LOG_ENABLED +modem_clock_lpclk_src_t esp_bt_get_lpclk_src(void); + +void esp_bt_set_lpclk_src(modem_clock_lpclk_src_t clk_src); + +uint32_t esp_bt_get_lpclk_freq(void); + +void esp_bt_set_lpclk_freq(uint32_t clk_freq); + #ifdef __cplusplus } #endif diff --git a/lib/bt/include/esp32h2/include/esp_bt_vs.h b/lib/bt/include/esp32h2/include/esp_bt_vs.h new file mode 100644 index 00000000..3cbed925 --- /dev/null +++ b/lib/bt/include/esp32h2/include/esp_bt_vs.h @@ -0,0 +1,360 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +// @brief HCI VS Commands for Espressif's Bluetooth Host +// +// @note The following vendor-specific HCI commands are exclusively for Espressif's Bluetooth Host (ESP-Bluedroid Host or ESP-NimBLE Host). +// If you are using a non-ESP host or HCI UART, these commands will remain disabled unless the initialization function is explicitly called from the application. +// Note, these init functions as well as these additional HCI VS commands are intended for Espressif's Bluetooth Host use only. +// Application developers **should not** call the init functions in their applications. +// + +/** + * @brief Config scanning duplicate exceptional list (OCF: 0x0108) + * + * @note The init function is `advFilter_stack_eanbleDupExcListCmd(true)` + */ +#define ESP_BT_VS_CONFIG_DUP_EXC_LIST_OCF (0x0108) +/** +* @brief Update exception list cmd parameters +*/ +struct bt_hci_vs_update_exc_list { + uint8_t subcode; /*!< Add, remove or clear exception list */ + uint32_t type; /*!< device type */ + uint8_t device_info[6]; /*!< device information */ +}; + +/** + * @brief Enable/disable advertising report flow control (OCF: 0x0109) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_SET_ADV_REPORT_FLOW_CTRL_OCF (0x0109) +/** +* @brief Init ADV flow control cmd parameters +*/ +struct bt_hci_vs_init_adv_flow_ctrl { + uint8_t enable; /*!< Enable ADV flow control */ + uint16_t num; /*!< ADV buffer maximum value */ + uint16_t adv_lost_threshold; /*!< ADV lost event triggered threshold */ +}; + +/** + * @brief Update the number of advertising report in ADV flow control (OCF: 0x010A) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_UPD_ADV_REPORT_FLOW_CTRL_NUM_OCF (0x010a) +/** +* @brief Update ADV flow control cmd parameters +*/ +struct bt_hci_vs_update_adv_flow_ctrl { + uint16_t num; /*!< The number of ADV report processed */ +}; + +/** + * @brief Clear legacy advertising (same as HCI_LE_Clear_Advertising_Sets) (OCF: 0x010C) + * + * @note The init function is `adv_stack_enableClearLegacyAdvVsCmd(true)` + */ +#define ESP_BT_VS_CLR_LEGACY_ADV_OCF (0x010c) +/** +* @brief Clear legacy ADV cmd parameters +*/ +struct bt_hci_vs_ble_clr_legacy_adv { + // no parameters +}; + +/** + * @brief Set parameters of duplicate list (OCF: 0x010D) + * + * @note The init function is `advFilter_stack_eanbleDupExcListCmd(true)` + */ +#define ESP_BT_VS_SET_DUP_LIST_PARAMS_OCF (0x010d) +/** +* @brief Set duplicate list cmd parameters +*/ +struct bt_hci_vs_ble_set_dup_params { + uint8_t dup_mode; /*!< Duplicate mode */ + uint8_t dup_ad_type; /*!< Duplicate data type */ + uint16_t ring_list_max_num; /*!< Duplicate list size */ +}; + +/** + * @brief Enable/disable duplicate and exception list (OCF: 0x010E) + * + * @note The init function is `advFilter_stack_eanbleDupExcListCmd(true)` + */ +#define ESP_BT_VS_ENABLE_DUP_EXC_LIST_OCF (0x010e) +/** +* @brief Enable duplicate and exception list cmd parameters +*/ +struct bt_hci_vs_ble_enable_dup_exc { + uint8_t enable; /*!< Enable or disable */ + uint8_t ring_list_reset; /*!< Reset list */ +}; + +/** + * @brief Enable optimization of multiple connections (OCF: 0x010F) + * + * @note The init function is `arr_stack_enableMultiConnVsCmd(true)` + */ +#define ESP_BT_VS_ENABLE_ARRANGEMENT_OCF (0x010f) +/** +* @brief Multiple connections optimization cmd parameters +*/ +struct bt_hci_vs_ble_enable_arrangement { + uint32_t common_factor; /*!< The greatest common factor of connection interval */ + uint8_t enable; /*!< Enable or disable */ +}; + +/** + * @brief Set scheduling length for a certain role (OCF: 0x0110) + * + * @note The init function is `arr_stack_enableMultiConnVsCmd(true)` + */ +#define ESP_BT_VS_SET_SCHED_ROLE_LEN_OCF (0x0110) +/** +* @brief Scheduling length cmd parameters +*/ +struct bt_hci_vs_ble_set_sched_role_len { + uint8_t role; /*!< BLE role; 0: central; 1: peripheral */ + uint32_t len; /*!< Length is us */ +}; + +/** + * @brief Set RSSI threshold for automatic power control (OCF: 0x0111) + * + * @note The init function is `pcl_stack_enableSetRssiThreshVsCmd(true)` + */ +#define ESP_BT_VS_SET_PCL_RSSI_THRESH_OCF (0x0111) +/** +* @brief PCL RSSI threshold cmd parameters +*/ +struct bt_hci_vs_ble_set_pcl_rssi_thresh { + uint16_t conn_handle; /*!< Connection handle */ + uint8_t rssi_thresh_min_1M; /*!< Lower limit for 1M */ + uint8_t rssi_thresh_max_1M; /*!< Upper limit for 1M */ + uint8_t rssi_thresh_min_2M; /*!< Lower limit for 2M */ + uint8_t rssi_thresh_max_2M; /*!< Upper limit for 2M */ + uint8_t rssi_thresh_min_s2coded; /*!< Lower limit for s2 coded */ + uint8_t rssi_thresh_max_s2coded; /*!< Upper limit for s2 coded */ + uint8_t rssi_thresh_min_s8coded; /*!< Lower limit for s8 coded */ + uint8_t rssi_thresh_max_s8coded; /*!< Upper limit for s8 coded */ +}; + +/** + * @brief Enable/disable channel selection algorithm #2 (OCF: 0x0112) + * + * @note The init function is `chanSel_stack_enableSetCsaVsCmd(true)` + */ +#define ESP_BT_VS_ENABLE_CSA2_OCF (0x0112) +/** +* @brief Enable/disable channel selection algorithm #2 cmd parameters +*/ +struct bt_hci_vs_ble_csa_enable { + uint8_t csa2_select; /*!< Select CSA2 */ +}; + +/** + * @brief Set parameters of controller logs (OCF: 0x0114) + * + * @note The init function is `log_stack_enableLogsRelatedVsCmd(true)` + */ +#define ESP_BT_VS_SET_LOG_PARAMS_OCF (0x0114) +/** +* @brief Controller logs cmd parameters +*/ +struct bt_hci_vs_ble_log_params { + uint8_t type; /*!< Operation type */ + uint32_t output_enable; /*!< Enable/disable output */ + uint8_t buffer_optoin /*!< Select log buffers */ +}; + +/** + * @brief Set BLE vendor events mask (OCF: 0x0116) + * + * @note The init function is `hci_stack_enableSetVsEvtMaskVsCmd(true)` + */ +#define ESP_BT_VS_SET_LE_VENDOR_EVTS_MASK_OCF (0x0116) +/** +* @brief Set BLE vendor events mask cmd parameters +*/ +struct bt_hci_vs_ble_set_vs_evts_mask { + uint32_t evt_masks; /*!< BLE vendor events Mask */ +}; + +/** + * @brief Set peer sleep clock accuracy to a constant value (OCF: 0x0118) + * + * @note The init function is `winWiden_stack_enableSetConstPeerScaVsCmd(true)` + */ +#define ESP_BT_VS_SET_CONST_PEER_SCA_OCF (0x0118) +/** +* @brief Peer constant SCA cmd parameters +*/ +struct bt_hci_vs_ble_set_const_peer_sca { + uint16_t peer_sca; /*!< Peer SCA */ +}; + +// @brief HCI VS Events for Espressif's Bluetooth Host +// +// @note The following HCI VS events are exclusively for Espressif's Bluetooth Host (ESP-Bluedroid Host or ESP-NimBLE Host). +// If you are using a non-ESP host or HCI UART, these events will remain disabled unless the initialization function is explicitly called from the application. +// Note, these init functions as well as these additional HCI VS events are intended for Espressif's Bluetooth Host use only. +// Application developers **should not** call the init functions in their applications. +// + +/** + * @brief BLE Scan/Connect Request, Aux Connect Response received event (EVTCODE: 0xFF, SUBCODE: 0xC0) + * + * @note The init function is `adv_stack_enableScanReqRxdVsEvent(true)` + */ +#define ESP_BT_VS_LE_CONN_SCAN_REQ_RXED_EVT_SUBCODE (0xC0) +/** +* @brief BLE Scan/Connect Request, Aux Connect Response received event parameters +*/ +struct bt_hci_vs_le_conn_scan_req_rxed_evt { + uint8_t evt_type; /*!< Event type; 0: SCAN_REQ; 1: CONN_IND */ + uint8_t handle; /*!< Advertisement handle */ + uint8_t peer_addr_type; /*!< Peer address type */ + uint8_t peer_addr[6]; /*!< Peer address */ +}; + +/** + * @brief BLE Channel Map Update Completion event (EVTCODE: 0xFF, SUBCODE: 0xC1) + * + * @note The init function is `conn_stack_enableChanMapUpdCompVsEvent(true)` + */ +#define ESP_BT_VS_LE_CHAN_UPDATE_COMP_EVT_SUBCODE (0xC1) +/** +* @brief BLE Channel Map Update Completion event parameters +*/ +struct bt_hci_vs_le_chan_update_comp_evt { + uint8_t status; /*!< Controller error code */ + uint16_t handle; /*!< Connection handle */ + uint8_t ch_map[5]; /*!< Updated channel map */ +}; + +/** + * @brief BLE Wakeup From Sleep event (EVTCODE: 0xFF, SUBCODE: 0xC3) + * + * @note The init function is `sleep_stack_enableWakeupVsEvent(true)` + */ +#define ESP_BT_VS_LE_SLEEP_WAKEUP_EVT_SUBCODE (0xC3) +/** +* @brief BLE wakeup event parameters +*/ +struct bt_hci_vs_le_sleep_wakeup_evt { + // no parameters +}; + +/** + * @brief BLE advertising report lost event for flow control (EVTCODE: 0x3E, SUBCODE: 0xF0) + * + * @note The init function is `scan_stack_enableAdvFlowCtrlVsCmd(true)` + */ +#define ESP_BT_VS_LE_ADV_LOST_EVT_SUBCODE (0xF0) +/** +* @brief ADV lost event parameters +*/ +struct bt_hci_vs_le_adv_lost_evt { + uint32_t nb_lost; /*!< The number of ADV report discarded */ +}; + +// +// @brief HCI VS Commands for Espressif's Internal-Use Debugging +// +// @note The following HCI VS debugging commands are implemented in Bluetooth controller pre-compiled libraries. +// These commands are not linked into the application binary, unless the function `esp_ble_internalTestFeaturesEnable(true)`is called from the application. +// They are intended for Espressif's internal use only. Application developers **should not** call `esp_ble_internalTestFeaturesEnable(true)` in their applications. +// + +#define ESP_BT_VS_CFG_TEST_RELATED_OCF (0x0113) + #define ESP_BT_VS_CFG_TEST_ENABLE_SUBCMD (0X00) + #define ESP_BT_VS_CFG_TEST_ENABLE_ADV_DELAY_SUBCMD (0X01) + #define ESP_BT_VS_CFG_TEST_SET_PREF_CODED_SUBCMD (0X02) + #define ESP_BT_VS_CFG_TEST_SET_DEFAULT_PRIV_MODE_SUBCMD (0X03) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_FOREVER_SUBCMD (0X04) + #define ESP_BT_VS_CFG_TEST_SET_EXPECTED_PEER_SUBCMD (0X05) + #define ESP_BT_VS_CFG_TEST_GET_ADV_TXED_CNT_SUBCMD (0X06) + #define ESP_BT_VS_CFG_TEST_GET_SCAN_RXED_CNT_SUBCMD (0X07) + #define ESP_BT_VS_CFG_TEST_SET_TXPWR_LVL_SUBCMD (0X08) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_LVL_SUBCMD (0X09) + #define ESP_BT_VS_CFG_TEST_SET_TXPWR_LVL_ENH_SUBCMD (0X0a) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_LVL_ENH_SUBCMD (0X0b) + #define ESP_BT_VS_CFG_TEST_IGNORE_WL_FOR_DIR_ADV_SUBCMD (0X0c) + #define ESP_BT_VS_CFG_TEST_GET_ADV_RXED_RSSI_SUBCMD (0X0d) + #define ESP_BT_VS_CFG_TEST_ENABLE_CCA_SUBCMD (0X0e) + #define ESP_BT_VS_CFG_TEST_SET_CCA_WIN_SUBCMD (0X0f) + #define ESP_BT_VS_CFG_TEST_READ_CCA_DATA_SUBCM (0X10) + #define ESP_BT_VS_CFG_TEST_CLEAR_RAND_ADDR_SUBCMD (0X11) + #define ESP_BT_VS_CFG_TEST_GET_MAX_TXPWR_SUBCMD (0X12) + #define ESP_BT_VS_CFG_TEST_GET_TXPWR_RANGE_SUBCMD (0X13) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_AA_SUBCMD (0X14) + #define ESP_BT_VS_CFG_TEST_SET_ADV_AA_SUBCMD (0X15) + #define ESP_BT_VS_CFG_TEST_SET_SCAN_CHAN_SUBCMD (0X16) + #define ESP_BT_VS_CFG_TEST_SKIP_LIGHT_SLEEP_CHECK_SUBCMD (0X17) + #define ESP_BT_VS_CFG_TEST_SET_WAKEUP_OVERHEAD_SUBCMD (0X18) + #define ESP_BT_VS_CFG_TEST_GET_ADV_MIN_ITVL_SUBCMD (0X19) + #define ESP_BT_VS_CFG_TEST_GET_CTRL_STATUS_SUBCMD (0X1a) + #define ESP_BT_VS_CFG_TEST_SET_CONN_PHY_TXPWR_SUBCMD (0X1b) + #define ESP_BT_VS_CFG_TEST_GET_CONN_PHY_TXPWR_SUBCMD (0X1c) + #define ESP_BT_VS_CFG_TEST_GET_RXBUF_EMPTY_CNT_SUBCMD (0X1d) + #define ESP_BT_VS_CFG_TEST_RESTART_SUBCMD (0X1e) + #define ESP_BT_VS_CFG_TEST_ENABLE_RECODE_RX_STATE_SUBCMD (0X1f) + #define ESP_BT_VS_CFG_TEST_GET_RECODE_CNT_SUBCMD (0X20) + #define ESP_BT_VS_CFG_TEST_CLR_RECODE_CNT_SUBCMD (0X21) + #define ESP_BT_VS_CFG_TEST_GET_CTRL_COMPILE_VER_SUBCMD (0X24) + #define ESP_BT_VS_CFG_TEST_SET_AUX_ADV_OFFSET_SUBCMD (0X25) + #define ESP_BT_VS_CFG_TEST_INIT_FLEXIBLE_MODE_SUBCMD (0X26) + #define ESP_BT_VS_CFG_TEST_ENABLE_FLEXIBLE_MODE_SUBCMD (0X27) + #define ESP_BT_VS_CFG_TEST_SET_FLEXIBLE_CONN_ERR_SUBCMD (0X28) + #define ESP_BT_VS_CFG_TEST_SET_FLEXIBLE_ADV_ERR_SUBCMD (0X29) + #define ESP_BT_VS_CFG_TEST_SET_FLEXIBLE_SCAN_ERR_SUBCMD (0X2a) + #define ESP_BT_VS_CFG_TEST_GET_TXED_CRCERR_SUBCMD (0X2c) + #define ESP_BT_VS_CFG_TEST_GET_BACKOFF_UPLIMIT_SUBCMD (0X2d) + #define ESP_BT_VS_CFG_TEST_GET_RXED_ADV_ADI_SUBCMD (0X2f) + #define ESP_BT_VS_CFG_TEST_SET_SCH_RAND_MODE_SUBCMD (0X30) + #define ESP_BT_VS_CFG_TEST_SET_RX_SENS_THRESH_SUBCMD (0X31) + #define ESP_BT_VS_CFG_TEST_CHECK_MSYS_BUF_SUBCMD (0X32) + #define ESP_BT_VS_CFG_TEST_UPDATE_BLE_TIMER_SUBCMD (0X33) + #define ESP_BT_VS_CFG_TEST_UPDATE_BLE_RTC_SUBCMD (0X34) + #define ESP_BT_VS_CFG_TEST_SET_LOCKED_MEM_NUM_SUBCMD (0X35) + #define ESP_BT_VS_CFG_TEST_ALLOW_MEM_ALLOC_SUBCMD (0X36) + #define ESP_BT_VS_CFG_TEST_SET_SCH_RAND_INFO_PTR_SUBCMD (0X37) + #define ESP_BT_VS_CFG_TEST_SET_DIAG_IO_SUBCMD (0X38) + #define ESP_BT_VS_CFG_TEST_SET_AGC_MAX_GAIN_SUBCMD (0X39) + #define ESP_BT_VS_CFG_TEST_ENABLE_CHAN_ASSESS_SUBCMD (0X40) + #define ESP_BT_VS_CFG_TEST_SET_BACKOFF_UPLIMIT_SUBCMD (0X41) + #define ESP_BT_VS_CFG_TEST_SET_CONN_TOP_PRIO_RESV_THRESH_SUBCMD (0X42) + #define ESP_BT_VS_CFG_TEST_SET_TEST_EVT_MSK_SUBCMD (0X43) + #define ESP_BT_VS_CFG_TEST_GET_WAKEUP_TIMEOUT_SUBCMD (0X45) + #define ESP_BT_VS_CFG_TEST_RELATED_SUBCMD_MAX (0Xff) + +// +// @brief HCI VS Events for Espressif's Internal-Use Debugging +// +// @note The following HCI VS debugging events are implemented in Bluetooth controller pre-compiled libraries. +// These events are not linked into the application binary, unless the function `esp_ble_internalTestFeaturesEnable(true)`is called from the application. +// Application developers **should not** call `esp_ble_internalTestFeaturesEnable(true)` in their applications. +// + +#define ESP_BT_VS_LE_RUNNING_STATUS_EVT_SUBCODE (0xC3) + + +#ifdef __cplusplus +} +#endif diff --git a/lib/bt/include/esp32h4/include/esp_bt_cfg.h b/lib/bt/include/esp32h4/include/esp_bt_cfg.h index 768a0c6c..1f8caaec 100644 --- a/lib/bt/include/esp32h4/include/esp_bt_cfg.h +++ b/lib/bt/include/esp32h4/include/esp_bt_cfg.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -116,6 +116,20 @@ extern "C" { #define DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT (8) #endif + #if defined (CONFIG_BT_LE_HCI_UART_FLOWCTRL) + #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (CONFIG_BT_LE_HCI_UART_FLOWCTRL) + #if DEFAULT_BT_LE_HCI_UART_FLOW_CTRL + #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (CONFIG_BT_LE_HCI_UART_CTS_PIN) + #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (CONFIG_BT_LE_HCI_UART_RTS_PIN) + #else + #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (-1) + #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (-1) + #endif + #else + #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) + #define DEFAULT_BT_LE_HCI_UART_CTS_PIN (-1) + #define DEFAULT_BT_LE_HCI_UART_RTS_PIN (-1) + #endif #endif #define DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF CONFIG_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF @@ -156,8 +170,6 @@ extern "C" { #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (UART_DATA_8_BITS) #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (UART_STOP_BITS_1) #define DEFAULT_BT_LE_HCI_UART_PARITY (0) - #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (CONFIG_BT_LE_HCI_UART_TASK_STACK_SIZE) - #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) #else #define DEFAULT_BT_LE_HCI_UART_TX_PIN (0) #define DEFAULT_BT_LE_HCI_UART_RX_PIN (0) @@ -166,8 +178,6 @@ extern "C" { #define DEFAULT_BT_LE_HCI_UART_DATA_BITS (0) #define DEFAULT_BT_LE_HCI_UART_STOP_BITS (0) #define DEFAULT_BT_LE_HCI_UART_PARITY (0) - #define DEFAULT_BT_LE_HCI_UART_TASK_STACK_SIZE (0) - #define DEFAULT_BT_LE_HCI_UART_FLOW_CTRL (0) #endif /* Unchanged configuration */ diff --git a/lib/bt/linker.lf b/lib/bt/linker.lf deleted file mode 100644 index debff10a..00000000 --- a/lib/bt/linker.lf +++ /dev/null @@ -1,57 +0,0 @@ -[sections:bt_bss] -entries: - .bss+ - -[sections:bt_common] -entries: - COMMON - -[scheme:bt_start_end] -entries: - bt_bss -> dram0_bss - bt_common -> dram0_bss - data -> dram0_data - -# For the following fragments, order matters for -# 'ALIGN(4) ALIGN(4, post) SURROUND(sym)', which generates: -# -# . = ALIGN(4) -# _sym_start -# ... -# . = ALIGN(4) -# _sym_end - -[mapping:bt] -archive: libbt.a -entries: - if ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY = y: - * (extram_bss) - else: - * (bt_start_end); - bt_bss -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_bss), - bt_common -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_common), - data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(bt_data) - -[mapping:btdm] -archive: libbtdm_app.a -entries: - * (bt_start_end); - bt_bss -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(btdm_bss), - bt_common -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(btdm_common), - data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(btdm_data) - -[mapping:bt_controller] -archive: libble_app.a -entries: - * (bt_start_end); - bt_bss -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_bss), - bt_common -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_common), - data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_data) - -[mapping:nimble] -archive: libnimble.a -entries: - * (bt_start_end); - bt_bss -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(nimble_bss), - bt_common -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(nimble_common), - data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(nimble_data) diff --git a/lib/bt/linker.lf.esp32c2 b/lib/bt/linker.lf.esp32c2 deleted file mode 100644 index 40d8a563..00000000 --- a/lib/bt/linker.lf.esp32c2 +++ /dev/null @@ -1,60 +0,0 @@ -[sections:bt_text] -entries: - .iram1+ - -[sections:bt_bss] -entries: - .bss+ - .sbss+ - -[sections:bt_data] -entries: - .data+ - .sdata+ - .dram1+ - -[sections:bt_common] -entries: - COMMON - -[scheme:bt_start_end] -entries: - bt_text -> iram0_bt_text - bt_bss -> dram0_bt_bss - bt_common -> dram0_bt_bss - bt_data -> dram0_bt_data - -# For the following fragments, order matters for -# 'ALIGN(4) ALIGN(4, post) SURROUND(sym)', which generates: -# -# . = ALIGN(4) -# _sym_start -# ... -# . = ALIGN(4) -# _sym_end - -[mapping:bt] -archive: libbt.a -entries: - * (bt_start_end); - bt_bss -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_bss), - bt_common -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_common), - bt_data -> dram0_bt_data ALIGN(4) ALIGN(4, post) SURROUND(bt_data) - if ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY = y: - * (extram_bss) - -[mapping:btdm] -archive: libbtdm_app.a -entries: - * (bt_start_end); - bt_bss -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(btdm_bss), - bt_common -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(btdm_common), - bt_data -> dram0_bt_data ALIGN(4) ALIGN(4, post) SURROUND(btdm_data) - -[mapping:bt_controller] -archive: libble_app.a -entries: - * (bt_start_end); - bt_bss -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_bss), - bt_common -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_common), - bt_data -> dram0_bt_data ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_data) diff --git a/lib/bt/linker_common.lf b/lib/bt/linker_common.lf index 501acd95..a8f79683 100644 --- a/lib/bt/linker_common.lf +++ b/lib/bt/linker_common.lf @@ -6,37 +6,8 @@ entries: entries: COMMON -[scheme:bt_default] -entries: - bt_bss -> dram0_bss - bt_common -> dram0_bss - data -> dram0_data - [scheme:bt_extram_bss] entries: bt_bss -> extern_ram bt_common -> extern_ram data -> dram0_data - -# For the following fragments, order matters for -# 'ALIGN(4) ALIGN(4, post) SURROUND(sym)', which generates: -# -# . = ALIGN(4) -# _sym_start -# ... -# . = ALIGN(4) -# _sym_end - -[mapping:bt] -archive: libbt.a -entries: - if ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY = y: - * (bt_extram_bss); - bt_bss -> extern_ram ALIGN(4) ALIGN(4, post) SURROUND(bt_bss), - bt_common -> extern_ram ALIGN(4) ALIGN(4, post) SURROUND(bt_common), - data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(bt_data) - else: - * (bt_default); - bt_bss -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_bss), - bt_common -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_common), - data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(bt_data) diff --git a/lib/bt/linker_esp32c2.lf b/lib/bt/linker_esp32c2.lf index 7178420a..c9ab4c2e 100644 --- a/lib/bt/linker_esp32c2.lf +++ b/lib/bt/linker_esp32c2.lf @@ -2,6 +2,18 @@ entries: .iram1+ +[sections:bt_isr_iram_text] +entries: + .isr_iram1+ + +[sections:bt_conn_iram_text] +entries: + .conn_iram1+ + +[sections:bt_sleep_iram_text] +entries: + .sleep_iram1+ + [sections:bt_bss] entries: .bss+ @@ -19,10 +31,31 @@ entries: [scheme:bt_default] entries: - bt_iram_text -> iram0_bt_text - bt_bss -> dram0_bt_bss - bt_common -> dram0_bt_bss - bt_data -> dram0_bt_data + if BT_CTRL_RUN_IN_FLASH_ONLY = y: + bt_iram_text -> flash_text + bt_bss -> dram0_bt_bss + bt_common -> dram0_bt_bss + bt_data -> dram0_bt_data + + if BT_LE_PLACE_CONN_RELATED_INTO_IRAM = y: + bt_conn_iram_text -> iram0_bt_text + bt_isr_iram_text -> iram0_bt_text + else: + bt_conn_iram_text -> flash_text + bt_isr_iram_text -> flash_text + if BT_LE_PLACE_SLEEP_RELATED_INTO_IRAM = y: + bt_sleep_iram_text -> iram0_bt_text + else: + bt_sleep_iram_text -> flash_text + else: + bt_iram_text -> iram0_bt_text + bt_bss -> dram0_bt_bss + bt_common -> dram0_bt_bss + bt_data -> dram0_bt_data + + bt_conn_iram_text -> iram0_bt_text + bt_isr_iram_text -> iram0_bt_text + bt_sleep_iram_text -> iram0_bt_text # For the following fragments, order matters for # 'ALIGN(4) ALIGN(4, post) SURROUND(sym)', which generates: @@ -48,3 +81,11 @@ entries: bt_bss -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_bss), bt_common -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_common), bt_data -> dram0_bt_data ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_data) + +[mapping:ble_app_flash] +archive: libble_app_flash.a +entries: + * (bt_default); + bt_bss -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_bss), + bt_common -> dram0_bt_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_common), + bt_data -> dram0_bt_data ALIGN(4) ALIGN(4, post) SURROUND(bt_controller_data) diff --git a/lib/bt/linker_esp_ble_controller.lf b/lib/bt/linker_esp_ble_controller.lf index fe859811..0af407f8 100644 --- a/lib/bt/linker_esp_ble_controller.lf +++ b/lib/bt/linker_esp_ble_controller.lf @@ -1,3 +1,45 @@ +[sections:bt_iram_text] +entries: + .iram1+ + +[sections:high_perf_iram_text] +entries: + .high_perf_code_iram1+ + +[scheme:bt_default] +entries: + bt_bss -> dram0_bss + bt_common -> dram0_bss + data -> dram0_data + high_perf_iram_text -> iram0_text + if BT_CTRL_RUN_IN_FLASH_ONLY = y: + bt_iram_text -> flash_text + else: + bt_iram_text -> iram0_text + +# For the following fragments, order matters for +# 'ALIGN(4) ALIGN(4, post) SURROUND(sym)', which generates: +# +# . = ALIGN(4) +# _sym_start +# ... +# . = ALIGN(4) +# _sym_end + +[mapping:bt] +archive: libbt.a +entries: + if ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY = y: + * (bt_extram_bss); + bt_bss -> extern_ram ALIGN(4) ALIGN(4, post) SURROUND(bt_bss), + bt_common -> extern_ram ALIGN(4) ALIGN(4, post) SURROUND(bt_common), + data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(bt_data) + else: + * (bt_default); + bt_bss -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_bss), + bt_common -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_common), + data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(bt_data) + [mapping:ble_app] archive: libble_app.a entries: diff --git a/lib/bt/linker_rw_bt_controller.lf b/lib/bt/linker_rw_bt_controller.lf index 083d6e90..575aea58 100644 --- a/lib/bt/linker_rw_bt_controller.lf +++ b/lib/bt/linker_rw_bt_controller.lf @@ -1,3 +1,33 @@ +[scheme:bt_default] +entries: + bt_bss -> dram0_bss + bt_common -> dram0_bss + data -> dram0_data + +# For the following fragments, order matters for +# 'ALIGN(4) ALIGN(4, post) SURROUND(sym)', which generates: +# +# . = ALIGN(4) +# _sym_start +# ... +# . = ALIGN(4) +# _sym_end + +[mapping:bt] +archive: libbt.a +entries: + if ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY = y: + * (bt_extram_bss); + bt_bss -> extern_ram ALIGN(4) ALIGN(4, post) SURROUND(bt_bss), + bt_common -> extern_ram ALIGN(4) ALIGN(4, post) SURROUND(bt_common), + data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(bt_data) + else: + * (bt_default); + bt_bss -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_bss), + bt_common -> dram0_bss ALIGN(4) ALIGN(4, post) SURROUND(bt_common), + data -> dram0_data ALIGN(4) ALIGN(4, post) SURROUND(bt_data) + + [mapping:btdm] archive: libbtdm_app.a entries: diff --git a/lib/bt/porting/ext/tinycrypt/AUTHORS b/lib/bt/porting/ext/tinycrypt/AUTHORS deleted file mode 100644 index bd1c1a1f..00000000 --- a/lib/bt/porting/ext/tinycrypt/AUTHORS +++ /dev/null @@ -1,15 +0,0 @@ -Architect: -Rafael Misoczki - -Open Source Maintainer: -Constanza Heath -Rafael Misoczki - -Contributors: -Constanza Heath -Rafael Misoczki -Flavio Santes -Jarkko Sakkinen -Chris Morrison -Marti Bolivar -Colin Ian King diff --git a/lib/bt/porting/ext/tinycrypt/LICENSE b/lib/bt/porting/ext/tinycrypt/LICENSE deleted file mode 100644 index b3c55243..00000000 --- a/lib/bt/porting/ext/tinycrypt/LICENSE +++ /dev/null @@ -1,61 +0,0 @@ - -================================================================================ - - TinyCrypt Cryptographic Library - -================================================================================ - - Copyright (c) 2017, Intel Corporation. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - - Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - - Neither the name of the Intel Corporation nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -================================================================================ -Copyright (c) 2014, Kenneth MacKay -All rights reserved. - -https://github.com/kmackay/micro-ecc - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -================================================================================ diff --git a/lib/bt/porting/ext/tinycrypt/README b/lib/bt/porting/ext/tinycrypt/README deleted file mode 100644 index 48bdf9ba..00000000 --- a/lib/bt/porting/ext/tinycrypt/README +++ /dev/null @@ -1,70 +0,0 @@ - -================================================================================ - - TinyCrypt Cryptographic Library - -================================================================================ - - Copyright (c) 2017, Intel Corporation. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - - Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - - Neither the name of the Intel Corporation nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -================================================================================ - -Overview: - -The TinyCrypt Library provides an implementation for constrained devices of a -minimal set of standard cryptography primitives. - -Please, ***SEE THE DOCUMENTATION*** folder for more information on the supported -cryptographic primitives and the limitations of TinyCrypt library. For usage, -security and technicalities, please see the corresponding header file of each -cryptographic primitive. - -================================================================================ - -Organization: - -/lib: C source code of the cryptographic primitives. -/lib/include/tinycrypt: C header files of the cryptographic primitives. -/tests: Test vectors of the cryptographic primitives. -/doc: Documentation of TinyCrypt. - -================================================================================ - -Building: - -1) In Makefile.conf set: - - CFLAGS for compiler flags. - - CC for compiler. - - ENABLE_TESTS for enabling (true) or disabling (false) tests compilation. -2) In lib/Makefile select the primitives required by your project. -3) In tests/Makefile select the corresponding tests of the selected primitives. -4) make -5) run tests in tests/ - -================================================================================ diff --git a/lib/bt/porting/ext/tinycrypt/VERSION b/lib/bt/porting/ext/tinycrypt/VERSION deleted file mode 100644 index a45be462..00000000 --- a/lib/bt/porting/ext/tinycrypt/VERSION +++ /dev/null @@ -1 +0,0 @@ -0.2.8 diff --git a/lib/bt/porting/ext/tinycrypt/documentation/tinycrypt.rst b/lib/bt/porting/ext/tinycrypt/documentation/tinycrypt.rst deleted file mode 100644 index 356c099a..00000000 --- a/lib/bt/porting/ext/tinycrypt/documentation/tinycrypt.rst +++ /dev/null @@ -1,352 +0,0 @@ - -TinyCrypt Cryptographic Library -############################### -Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - -Overview -******** -The TinyCrypt Library provides an implementation for targeting constrained devices -with a minimal set of standard cryptography primitives, as listed below. To better -serve applications targeting constrained devices, TinyCrypt implementations differ -from the standard specifications (see the Important Remarks section for some -important differences). Certain cryptographic primitives depend on other -primitives, as mentioned in the list below. - -Aside from the Important Remarks section below, valuable information on the usage, -security and technicalities of each cryptographic primitive are found in the -corresponding header file. - -* SHA-256: - - * Type of primitive: Hash function. - * Standard Specification: NIST FIPS PUB 180-4. - * Requires: -- - -* HMAC-SHA256: - - * Type of primitive: Message authentication code. - * Standard Specification: RFC 2104. - * Requires: SHA-256 - -* HMAC-PRNG: - - * Type of primitive: Pseudo-random number generator (256-bit strength). - * Standard Specification: NIST SP 800-90A. - * Requires: SHA-256 and HMAC-SHA256. - -* AES-128: - - * Type of primitive: Block cipher. - * Standard Specification: NIST FIPS PUB 197. - * Requires: -- - -* AES-CBC mode: - - * Type of primitive: Encryption mode of operation. - * Standard Specification: NIST SP 800-38A. - * Requires: AES-128. - -* AES-CTR mode: - - * Type of primitive: Encryption mode of operation. - * Standard Specification: NIST SP 800-38A. - * Requires: AES-128. - -* AES-CMAC mode: - - * Type of primitive: Message authentication code. - * Standard Specification: NIST SP 800-38B. - * Requires: AES-128. - -* AES-CCM mode: - - * Type of primitive: Authenticated encryption. - * Standard Specification: NIST SP 800-38C. - * Requires: AES-128. - -* CTR-PRNG: - - * Type of primitive: Pseudo-random number generator (128-bit strength). - * Standard Specification: NIST SP 800-90A. - * Requires: AES-128. - -* ECC-DH: - - * Type of primitive: Key exchange based on curve NIST p-256. - * Standard Specification: RFC 6090. - * Requires: ECC auxiliary functions (ecc.h/c). - -* ECC-DSA: - - * Type of primitive: Digital signature based on curve NIST p-256. - * Standard Specification: RFC 6090. - * Requires: ECC auxiliary functions (ecc.h/c). - -Design Goals -************ - -* Minimize the code size of each cryptographic primitive. This means minimize - the size of a platform-independent implementation, as presented in TinyCrypt. - Note that various applications may require further features, optimizations with - respect to other metrics and countermeasures for particular threats. These - peculiarities would increase the code size and thus are not considered here. - -* Minimize the dependencies among the cryptographic primitives. This means - that it is unnecessary to build and allocate object code for more primitives - than the ones strictly required by the intended application. In other words, - one can select and compile only the primitives required by the application. - - -Important Remarks -***************** - -The cryptographic implementations in TinyCrypt library have some limitations. -Some of these limitations are inherent to the cryptographic primitives -themselves, while others are specific to TinyCrypt. These limitations were accepted -in order to meet its design goals (in special, minimal code size) and to better -serve applications targeting constrained devices in general. Some of these -limitations are discussed in-depth below. - -General Remarks -*************** - -* TinyCrypt does **not** intend to be fully side-channel resistant. Due to the - variety of side-channel attacks, many of them only relevant to certain - platforms. In this sense, instead of penalizing all library users with - side-channel countermeasures such as increasing the overall code size, - TinyCrypt only implements certain generic timing-attack countermeasures. - -Specific Remarks -**************** - -* SHA-256: - - * The number of bits_hashed in the state is not checked for overflow. Note - however that this will only be a problem if you intend to hash more than - 2^64 bits, which is an extremely large window. - -* HMAC: - - * The HMAC verification process is assumed to be performed by the application. - This compares the computed tag with some given tag. - Note that conventional memory-comparison methods (such as memcmp function) - might be vulnerable to timing attacks; thus be sure to use a constant-time - memory comparison function (such as compare_constant_time - function provided in lib/utils.c). - - * The tc_hmac_final function, responsible for computing the message tag, - cleans the state context before exiting. Thus, applications do not need to - clean the TCHmacState_t ctx after calling tc_hmac_final. This should not - be changed in future versions of the library as there are applications - currently relying on this good-practice/feature of TinyCrypt. - -* HMAC-PRNG: - - * Before using HMAC-PRNG, you *must* find an entropy source to produce a seed. - PRNGs only stretch the seed into a seemingly random output of arbitrary - length. The security of the output is exactly equal to the - unpredictability of the seed. - - * NIST SP 800-90A requires three items as seed material in the initialization - step: entropy seed, personalization and a nonce (which is not implemented). - TinyCrypt requires the personalization byte array and automatically creates - the entropy seed using a mandatory call to the re-seed function. - -* AES-128: - - * The current implementation does not support other key-lengths (such as 256 - bits). Note that if you need AES-256, it doesn't sound as though your - application is running in a constrained environment. AES-256 requires keys - twice the size as for AES-128, and the key schedule is 40% larger. - -* CTR mode: - - * The AES-CTR mode limits the size of a data message they encrypt to 2^32 - blocks. If you need to encrypt larger data sets, your application would - need to replace the key after 2^32 block encryptions. - -* CTR-PRNG: - - * Before using CTR-PRNG, you *must* find an entropy source to produce a seed. - PRNGs only stretch the seed into a seemingly random output of arbitrary - length. The security of the output is exactly equal to the - unpredictability of the seed. - -* CBC mode: - - * TinyCrypt CBC decryption assumes that the iv and the ciphertext are - contiguous (as produced by TinyCrypt CBC encryption). This allows for a - very efficient decryption algorithm that would not otherwise be possible. - -* CMAC mode: - - * AES128-CMAC mode of operation offers 64 bits of security against collision - attacks. Note however that an external attacker cannot generate the tags - him/herself without knowing the MAC key. In this sense, to attack the - collision property of AES128-CMAC, an external attacker would need the - cooperation of the legal user to produce an exponentially high number of - tags (e.g. 2^64) to finally be able to look for collisions and benefit - from them. As an extra precaution, the current implementation allows to at - most 2^48 calls to tc_cmac_update function before re-calling tc_cmac_setup - (allowing a new key to be set), as suggested in Appendix B of SP 800-38B. - -* CCM mode: - - * There are a few tradeoffs for the selection of the parameters of CCM mode. - In special, there is a tradeoff between the maximum number of invocations - of CCM under a given key and the maximum payload length for those - invocations. Both things are related to the parameter 'q' of CCM mode. The - maximum number of invocations of CCM under a given key is determined by - the nonce size, which is: 15-q bytes. The maximum payload length for those - invocations is defined as 2^(8q) bytes. - - To achieve minimal code size, TinyCrypt CCM implementation fixes q = 2, - which is a quite reasonable choice for constrained applications. The - implications of this choice are: - - The nonce size is: 13 bytes. - - The maximum payload length is: 2^16 bytes = 65 KB. - - The mac size parameter is an important parameter to estimate the security - against collision attacks (that aim at finding different messages that - produce the same authentication tag). TinyCrypt CCM implementation - accepts any even integer between 4 and 16, as suggested in SP 800-38C. - - * TinyCrypt CCM implementation accepts associated data of any length between - 0 and (2^16 - 2^8) = 65280 bytes. - - * TinyCrypt CCM implementation accepts: - - * Both non-empty payload and associated data (it encrypts and - authenticates the payload and only authenticates the associated data); - - * Non-empty payload and empty associated data (it encrypts and - authenticates the payload); - - * Non-empty associated data and empty payload (it degenerates to an - authentication-only mode on the associated data). - - * RFC-3610, which also specifies CCM, presents a few relevant security - suggestions, such as: it is recommended for most applications to use a - mac size greater than 8. Besides, it is emphasized that the usage of the - same nonce for two different messages which are encrypted with the same - key obviously destroys the security properties of CCM mode. - -* ECC-DH and ECC-DSA: - - * TinyCrypt ECC implementation is based on micro-ecc (see - https://github.com/kmackay/micro-ecc). In the original micro-ecc - documentation, there is an important remark about the way integers are - represented: - - "Integer representation: To reduce code size, all large integers are - represented using little-endian words - so the least significant word is - first. You can use the 'ecc_bytes2native()' and 'ecc_native2bytes()' - functions to convert between the native integer representation and the - standardized octet representation." - - Note that the assumed bit layout is: {31, 30, ..., 0}, {63, 62, ..., 32}, - {95, 94, ..., 64}, {127, 126, ..., 96} for a very-long-integer (vli) - consisting of 4 unsigned integers (as an example). - - * A cryptographically-secure PRNG function must be set (using uECC_set_rng()) - before calling uECC_make_key() or uECC_sign(). - -Examples of Applications -************************ -It is possible to do useful cryptography with only the given small set of -primitives. With this list of primitives it becomes feasible to support a range -of cryptography usages: - - * Measurement of code, data structures, and other digital artifacts (SHA256); - - * Generate commitments (SHA256); - - * Construct keys (HMAC-SHA256); - - * Extract entropy from strings containing some randomness (HMAC-SHA256); - - * Construct random mappings (HMAC-SHA256); - - * Construct nonces and challenges (HMAC-PRNG, CTR-PRNG); - - * Authenticate using a shared secret (HMAC-SHA256); - - * Create an authenticated, replay-protected session (HMAC-SHA256 + HMAC-PRNG); - - * Authenticated encryption (AES-128 + AES-CCM); - - * Key-exchange (EC-DH); - - * Digital signature (EC-DSA); - -Test Vectors -************ - -The library provides a test program for each cryptographic primitive (see 'test' -folder). Besides illustrating how to use the primitives, these tests evaluate -the correctness of the implementations by checking the results against -well-known publicly validated test vectors. - -For the case of the HMAC-PRNG, due to the necessity of performing an extensive -battery test to produce meaningful conclusions, we suggest the user to evaluate -the unpredictability of the implementation by using the NIST Statistical Test -Suite (see References). - -For the case of the EC-DH and EC-DSA implementations, most of the test vectors -were obtained from the site of the NIST Cryptographic Algorithm Validation -Program (CAVP), see References. - -References -********** - -* `NIST FIPS PUB 180-4 (SHA-256)`_ - -.. _NIST FIPS PUB 180-4 (SHA-256): - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf - -* `NIST FIPS PUB 197 (AES-128)`_ - -.. _NIST FIPS PUB 197 (AES-128): - http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf - -* `NIST SP800-90A (HMAC-PRNG)`_ - -.. _NIST SP800-90A (HMAC-PRNG): - http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf - -* `NIST SP 800-38A (AES-CBC and AES-CTR)`_ - -.. _NIST SP 800-38A (AES-CBC and AES-CTR): - http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - -* `NIST SP 800-38B (AES-CMAC)`_ - -.. _NIST SP 800-38B (AES-CMAC): - http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf - -* `NIST SP 800-38C (AES-CCM)`_ - -.. _NIST SP 800-38C (AES-CCM): - http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf - -* `NIST Statistical Test Suite (useful for testing HMAC-PRNG)`_ - -.. _NIST Statistical Test Suite (useful for testing HMAC-PRNG): - http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html - -* `NIST Cryptographic Algorithm Validation Program (CAVP) site`_ - -.. _NIST Cryptographic Algorithm Validation Program (CAVP) site: - http://csrc.nist.gov/groups/STM/cavp/ - -* `RFC 2104 (HMAC-SHA256)`_ - -.. _RFC 2104 (HMAC-SHA256): - https://www.ietf.org/rfc/rfc2104.txt - -* `RFC 6090 (ECC-DH and ECC-DSA)`_ - -.. _RFC 6090 (ECC-DH and ECC-DSA): - https://www.ietf.org/rfc/rfc6090.txt diff --git a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/aes.h b/lib/bt/porting/ext/tinycrypt/include/tinycrypt/aes.h deleted file mode 100644 index 885c02e0..00000000 --- a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/aes.h +++ /dev/null @@ -1,130 +0,0 @@ -/* aes.h - TinyCrypt interface to an AES-128 implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief -- Interface to an AES-128 implementation. - * - * Overview: AES-128 is a NIST approved block cipher specified in - * FIPS 197. Block ciphers are deterministic algorithms that - * perform a transformation specified by a symmetric key in fixed- - * length data sets, also called blocks. - * - * Security: AES-128 provides approximately 128 bits of security. - * - * Usage: 1) call tc_aes128_set_encrypt/decrypt_key to set the key. - * - * 2) call tc_aes_encrypt/decrypt to process the data. - */ - -#ifndef __TC_AES_H__ -#define __TC_AES_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define Nb (4) /* number of columns (32-bit words) comprising the state */ -#define Nk (4) /* number of 32-bit words comprising the key */ -#define Nr (10) /* number of rounds */ -#define TC_AES_BLOCK_SIZE (Nb*Nk) -#define TC_AES_KEY_SIZE (Nb*Nk) - -typedef struct tc_aes_key_sched_struct { - unsigned int words[Nb*(Nr+1)]; -} *TCAesKeySched_t; - -/** - * @brief Set AES-128 encryption key - * Uses key k to initialize s - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL - * @note This implementation skips the additional steps required for keys - * larger than 128 bits, and must not be used for AES-192 or - * AES-256 key schedule -- see FIPS 197 for details - * @param s IN/OUT -- initialized struct tc_aes_key_sched_struct - * @param k IN -- points to the AES key - */ -int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k); - -/** - * @brief AES-128 Encryption procedure - * Encrypts contents of in buffer into out buffer under key; - * schedule s - * @note Assumes s was initialized by aes_set_encrypt_key; - * out and in point to 16 byte buffers - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: out == NULL or in == NULL or s == NULL - * @param out IN/OUT -- buffer to receive ciphertext block - * @param in IN -- a plaintext block to encrypt - * @param s IN -- initialized AES key schedule - */ -int tc_aes_encrypt(uint8_t *out, const uint8_t *in, - const TCAesKeySched_t s); - -/** - * @brief Set the AES-128 decryption key - * Uses key k to initialize s - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL - * @note This is the implementation of the straightforward inverse cipher - * using the cipher documented in FIPS-197 figure 12, not the - * equivalent inverse cipher presented in Figure 15 - * @warning This routine skips the additional steps required for keys larger - * than 128, and must not be used for AES-192 or AES-256 key - * schedule -- see FIPS 197 for details - * @param s IN/OUT -- initialized struct tc_aes_key_sched_struct - * @param k IN -- points to the AES key - */ -int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k); - -/** - * @brief AES-128 Encryption procedure - * Decrypts in buffer into out buffer under key schedule s - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: out is NULL or in is NULL or s is NULL - * @note Assumes s was initialized by aes_set_encrypt_key - * out and in point to 16 byte buffers - * @param out IN/OUT -- buffer to receive ciphertext block - * @param in IN -- a plaintext block to encrypt - * @param s IN -- initialized AES key schedule - */ -int tc_aes_decrypt(uint8_t *out, const uint8_t *in, - const TCAesKeySched_t s); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_AES_H__ */ diff --git a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/cbc_mode.h b/lib/bt/porting/ext/tinycrypt/include/tinycrypt/cbc_mode.h deleted file mode 100644 index 4a837fd0..00000000 --- a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/cbc_mode.h +++ /dev/null @@ -1,151 +0,0 @@ -/* cbc_mode.h - TinyCrypt interface to a CBC mode implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to a CBC mode implementation. - * - * Overview: CBC (for "cipher block chaining") mode is a NIST approved mode of - * operation defined in SP 800-38a. It can be used with any block - * cipher to provide confidentiality of strings whose lengths are - * multiples of the block_size of the underlying block cipher. - * TinyCrypt hard codes AES as the block cipher. - * - * Security: CBC mode provides data confidentiality given that the maximum - * number q of blocks encrypted under a single key satisfies - * q < 2^63, which is not a practical constraint (it is considered a - * good practice to replace the encryption when q == 2^56). CBC mode - * provides NO data integrity. - * - * CBC mode assumes that the IV value input into the - * tc_cbc_mode_encrypt is randomly generated. The TinyCrypt library - * provides HMAC-PRNG module, which generates suitable IVs. Other - * methods for generating IVs are acceptable, provided that the - * values of the IVs generated appear random to any adversary, - * including someone with complete knowledge of the system design. - * - * The randomness property on which CBC mode's security depends is - * the unpredictability of the IV. Since it is unpredictable, this - * means in practice that CBC mode requires that the IV is stored - * somehow with the ciphertext in order to recover the plaintext. - * - * TinyCrypt CBC encryption prepends the IV to the ciphertext, - * because this affords a more efficient (few buffers) decryption. - * Hence tc_cbc_mode_encrypt assumes the ciphertext buffer is always - * 16 bytes larger than the plaintext buffer. - * - * Requires: AES-128 - * - * Usage: 1) call tc_cbc_mode_encrypt to encrypt data. - * - * 2) call tc_cbc_mode_decrypt to decrypt data. - * - */ - -#ifndef __TC_CBC_MODE_H__ -#define __TC_CBC_MODE_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief CBC encryption procedure - * CBC encrypts inlen bytes of the in buffer into the out buffer - * using the encryption key schedule provided, prepends iv to out - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * out == NULL or - * in == NULL or - * ctr == NULL or - * sched == NULL or - * inlen == 0 or - * (inlen % TC_AES_BLOCK_SIZE) != 0 or - * (outlen % TC_AES_BLOCK_SIZE) != 0 or - * outlen != inlen + TC_AES_BLOCK_SIZE - * @note Assumes: - sched has been configured by aes_set_encrypt_key - * - iv contains a 16 byte random string - * - out buffer is large enough to hold the ciphertext + iv - * - out buffer is a contiguous buffer - * - in holds the plaintext and is a contiguous buffer - * - inlen gives the number of bytes in the in buffer - * @param out IN/OUT -- buffer to receive the ciphertext - * @param outlen IN -- length of ciphertext buffer in bytes - * @param in IN -- plaintext to encrypt - * @param inlen IN -- length of plaintext buffer in bytes - * @param iv IN -- the IV for the this encrypt/decrypt - * @param sched IN -- AES key schedule for this encrypt - */ -int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, const uint8_t *iv, - const TCAesKeySched_t sched); - -/** - * @brief CBC decryption procedure - * CBC decrypts inlen bytes of the in buffer into the out buffer - * using the provided encryption key schedule - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * out == NULL or - * in == NULL or - * sched == NULL or - * inlen == 0 or - * outlen == 0 or - * (inlen % TC_AES_BLOCK_SIZE) != 0 or - * (outlen % TC_AES_BLOCK_SIZE) != 0 or - * outlen != inlen + TC_AES_BLOCK_SIZE - * @note Assumes:- in == iv + ciphertext, i.e. the iv and the ciphertext are - * contiguous. This allows for a very efficient decryption - * algorithm that would not otherwise be possible - * - sched was configured by aes_set_decrypt_key - * - out buffer is large enough to hold the decrypted plaintext - * and is a contiguous buffer - * - inlen gives the number of bytes in the in buffer - * @param out IN/OUT -- buffer to receive decrypted data - * @param outlen IN -- length of plaintext buffer in bytes - * @param in IN -- ciphertext to decrypt, including IV - * @param inlen IN -- length of ciphertext buffer in bytes - * @param iv IN -- the IV for the this encrypt/decrypt - * @param sched IN -- AES key schedule for this decrypt - * - */ -int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, const uint8_t *iv, - const TCAesKeySched_t sched); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_CBC_MODE_H__ */ diff --git a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ccm_mode.h b/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ccm_mode.h deleted file mode 100644 index 69c798e2..00000000 --- a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ccm_mode.h +++ /dev/null @@ -1,211 +0,0 @@ -/* ccm_mode.h - TinyCrypt interface to a CCM mode implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to a CCM mode implementation. - * - * Overview: CCM (for "Counter with CBC-MAC") mode is a NIST approved mode of - * operation defined in SP 800-38C. - * - * TinyCrypt CCM implementation accepts: - * - * 1) Both non-empty payload and associated data (it encrypts and - * authenticates the payload and also authenticates the associated - * data); - * 2) Non-empty payload and empty associated data (it encrypts and - * authenticates the payload); - * 3) Non-empty associated data and empty payload (it degenerates to - * an authentication mode on the associated data). - * - * TinyCrypt CCM implementation accepts associated data of any length - * between 0 and (2^16 - 2^8) bytes. - * - * Security: The mac length parameter is an important parameter to estimate the - * security against collision attacks (that aim at finding different - * messages that produce the same authentication tag). TinyCrypt CCM - * implementation accepts any even integer between 4 and 16, as - * suggested in SP 800-38C. - * - * RFC-3610, which also specifies CCM, presents a few relevant - * security suggestions, such as: it is recommended for most - * applications to use a mac length greater than 8. Besides, the - * usage of the same nonce for two different messages which are - * encrypted with the same key destroys the security of CCM mode. - * - * Requires: AES-128 - * - * Usage: 1) call tc_ccm_config to configure. - * - * 2) call tc_ccm_mode_encrypt to encrypt data and generate tag. - * - * 3) call tc_ccm_mode_decrypt to decrypt data and verify tag. - */ - -#ifndef __TC_CCM_MODE_H__ -#define __TC_CCM_MODE_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* max additional authenticated size in bytes: 2^16 - 2^8 = 65280 */ -#define TC_CCM_AAD_MAX_BYTES 0xff00 - -/* max message size in bytes: 2^(8L) = 2^16 = 65536 */ -#define TC_CCM_PAYLOAD_MAX_BYTES 0x10000 - -/* struct tc_ccm_mode_struct represents the state of a CCM computation */ -typedef struct tc_ccm_mode_struct { - TCAesKeySched_t sched; /* AES key schedule */ - uint8_t *nonce; /* nonce required by CCM */ - unsigned int mlen; /* mac length in bytes (parameter t in SP-800 38C) */ -} *TCCcmMode_t; - -/** - * @brief CCM configuration procedure - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * c == NULL or - * sched == NULL or - * nonce == NULL or - * mlen != {4, 6, 8, 10, 12, 16} - * @param c -- CCM state - * @param sched IN -- AES key schedule - * @param nonce IN - nonce - * @param nlen -- nonce length in bytes - * @param mlen -- mac length in bytes (parameter t in SP-800 38C) - */ -int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce, - unsigned int nlen, unsigned int mlen); - -/** - * @brief CCM tag generation and encryption procedure - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * out == NULL or - * c == NULL or - * ((plen > 0) and (payload == NULL)) or - * ((alen > 0) and (associated_data == NULL)) or - * (alen >= TC_CCM_AAD_MAX_BYTES) or - * (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or - * (olen < plen + maclength) - * - * @param out OUT -- encrypted data - * @param olen IN -- output length in bytes - * @param associated_data IN -- associated data - * @param alen IN -- associated data length in bytes - * @param payload IN -- payload - * @param plen IN -- payload length in bytes - * @param c IN -- CCM state - * - * @note: out buffer should be at least (plen + c->mlen) bytes long. - * - * @note: The sequence b for encryption is formatted as follows: - * b = [FLAGS | nonce | counter ], where: - * FLAGS is 1 byte long - * nonce is 13 bytes long - * counter is 2 bytes long - * The byte FLAGS is composed by the following 8 bits: - * 0-2 bits: used to represent the value of q-1 - * 3-7 btis: always 0's - * - * @note: The sequence b for authentication is formatted as follows: - * b = [FLAGS | nonce | length(mac length)], where: - * FLAGS is 1 byte long - * nonce is 13 bytes long - * length(mac length) is 2 bytes long - * The byte FLAGS is composed by the following 8 bits: - * 0-2 bits: used to represent the value of q-1 - * 3-5 bits: mac length (encoded as: (mlen-2)/2) - * 6: Adata (0 if alen == 0, and 1 otherwise) - * 7: always 0 - */ -int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen, - const uint8_t *associated_data, - unsigned int alen, const uint8_t *payload, - unsigned int plen, TCCcmMode_t c); - -/** - * @brief CCM decryption and tag verification procedure - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * out == NULL or - * c == NULL or - * ((plen > 0) and (payload == NULL)) or - * ((alen > 0) and (associated_data == NULL)) or - * (alen >= TC_CCM_AAD_MAX_BYTES) or - * (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or - * (olen < plen - c->mlen) - * - * @param out OUT -- decrypted data - * @param associated_data IN -- associated data - * @param alen IN -- associated data length in bytes - * @param payload IN -- payload - * @param plen IN -- payload length in bytes - * @param c IN -- CCM state - * - * @note: out buffer should be at least (plen - c->mlen) bytes long. - * - * @note: The sequence b for encryption is formatted as follows: - * b = [FLAGS | nonce | counter ], where: - * FLAGS is 1 byte long - * nonce is 13 bytes long - * counter is 2 bytes long - * The byte FLAGS is composed by the following 8 bits: - * 0-2 bits: used to represent the value of q-1 - * 3-7 btis: always 0's - * - * @note: The sequence b for authentication is formatted as follows: - * b = [FLAGS | nonce | length(mac length)], where: - * FLAGS is 1 byte long - * nonce is 13 bytes long - * length(mac length) is 2 bytes long - * The byte FLAGS is composed by the following 8 bits: - * 0-2 bits: used to represent the value of q-1 - * 3-5 bits: mac length (encoded as: (mlen-2)/2) - * 6: Adata (0 if alen == 0, and 1 otherwise) - * 7: always 0 - */ -int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen, - const uint8_t *associated_data, - unsigned int alen, const uint8_t *payload, unsigned int plen, - TCCcmMode_t c); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_CCM_MODE_H__ */ diff --git a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/cmac_mode.h b/lib/bt/porting/ext/tinycrypt/include/tinycrypt/cmac_mode.h deleted file mode 100644 index f44b0a53..00000000 --- a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/cmac_mode.h +++ /dev/null @@ -1,194 +0,0 @@ -/* cmac_mode.h -- interface to a CMAC implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to a CMAC implementation. - * - * Overview: CMAC is defined NIST in SP 800-38B, and is the standard algorithm - * for computing a MAC using a block cipher. It can compute the MAC - * for a byte string of any length. It is distinguished from CBC-MAC - * in the processing of the final message block; CMAC uses a - * different technique to compute the final message block is full - * size or only partial, while CBC-MAC uses the same technique for - * both. This difference permits CMAC to be applied to variable - * length messages, while all messages authenticated by CBC-MAC must - * be the same length. - * - * Security: AES128-CMAC mode of operation offers 64 bits of security against - * collision attacks. Note however that an external attacker cannot - * generate the tags him/herself without knowing the MAC key. In this - * sense, to attack the collision property of AES128-CMAC, an - * external attacker would need the cooperation of the legal user to - * produce an exponentially high number of tags (e.g. 2^64) to - * finally be able to look for collisions and benefit from them. As - * an extra precaution, the current implementation allows to at most - * 2^48 calls to the tc_cmac_update function before re-calling - * tc_cmac_setup (allowing a new key to be set), as suggested in - * Appendix B of SP 800-38B. - * - * Requires: AES-128 - * - * Usage: This implementation provides a "scatter-gather" interface, so that - * the CMAC value can be computed incrementally over a message - * scattered in different segments throughout memory. Experience shows - * this style of interface tends to minimize the burden of programming - * correctly. Like all symmetric key operations, it is session - * oriented. - * - * To begin a CMAC session, use tc_cmac_setup to initialize a struct - * tc_cmac_struct with encryption key and buffer. Our implementation - * always assume that the AES key to be the same size as the block - * cipher block size. Once setup, this data structure can be used for - * many CMAC computations. - * - * Once the state has been setup with a key, computing the CMAC of - * some data requires three steps: - * - * (1) first use tc_cmac_init to initialize a new CMAC computation. - * (2) next mix all of the data into the CMAC computation state using - * tc_cmac_update. If all of the data resides in a single data - * segment then only one tc_cmac_update call is needed; if data - * is scattered throughout memory in n data segments, then n calls - * will be needed. CMAC IS ORDER SENSITIVE, to be able to detect - * attacks that swap bytes, so the order in which data is mixed - * into the state is critical! - * (3) Once all of the data for a message has been mixed, use - * tc_cmac_final to compute the CMAC tag value. - * - * Steps (1)-(3) can be repeated as many times as you want to CMAC - * multiple messages. A practical limit is 2^48 1K messages before you - * have to change the key. - * - * Once you are done computing CMAC with a key, it is a good idea to - * destroy the state so an attacker cannot recover the key; use - * tc_cmac_erase to accomplish this. - */ - -#ifndef __TC_CMAC_MODE_H__ -#define __TC_CMAC_MODE_H__ - -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* padding for last message block */ -#define TC_CMAC_PADDING 0x80 - -/* struct tc_cmac_struct represents the state of a CMAC computation */ -typedef struct tc_cmac_struct { -/* initialization vector */ - uint8_t iv[TC_AES_BLOCK_SIZE]; -/* used if message length is a multiple of block_size bytes */ - uint8_t K1[TC_AES_BLOCK_SIZE]; -/* used if message length isn't a multiple block_size bytes */ - uint8_t K2[TC_AES_BLOCK_SIZE]; -/* where to put bytes that didn't fill a block */ - uint8_t leftover[TC_AES_BLOCK_SIZE]; -/* identifies the encryption key */ - unsigned int keyid; -/* next available leftover location */ - unsigned int leftover_offset; -/* AES key schedule */ - TCAesKeySched_t sched; -/* calls to tc_cmac_update left before re-key */ - uint64_t countdown; -} *TCCmacState_t; - -/** - * @brief Configures the CMAC state to use the given AES key - * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state - * returns TC_CRYPTO_FAIL (0) if: - * s == NULL or - * key == NULL - * - * @param s IN/OUT -- the state to set up - * @param key IN -- the key to use - * @param sched IN -- AES key schedule - */ -int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, - TCAesKeySched_t sched); - -/** - * @brief Erases the CMAC state - * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state - * returns TC_CRYPTO_FAIL (0) if: - * s == NULL - * - * @param s IN/OUT -- the state to erase - */ -int tc_cmac_erase(TCCmacState_t s); - -/** - * @brief Initializes a new CMAC computation - * @return returns TC_CRYPTO_SUCCESS (1) after having initialized the CMAC state - * returns TC_CRYPTO_FAIL (0) if: - * s == NULL - * - * @param s IN/OUT -- the state to initialize - */ -int tc_cmac_init(TCCmacState_t s); - -/** - * @brief Incrementally computes CMAC over the next data segment - * @return returns TC_CRYPTO_SUCCESS (1) after successfully updating the CMAC state - * returns TC_CRYPTO_FAIL (0) if: - * s == NULL or - * if data == NULL when dlen > 0 - * - * @param s IN/OUT -- the CMAC state - * @param data IN -- the next data segment to MAC - * @param dlen IN -- the length of data in bytes - */ -int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t dlen); - -/** - * @brief Generates the tag from the CMAC state - * @return returns TC_CRYPTO_SUCCESS (1) after successfully generating the tag - * returns TC_CRYPTO_FAIL (0) if: - * tag == NULL or - * s == NULL - * - * @param tag OUT -- the CMAC tag - * @param s IN -- CMAC state - */ -int tc_cmac_final(uint8_t *tag, TCCmacState_t s); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_CMAC_MODE_H__ */ diff --git a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/constants.h b/lib/bt/porting/ext/tinycrypt/include/tinycrypt/constants.h deleted file mode 100644 index 965490e0..00000000 --- a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/constants.h +++ /dev/null @@ -1,61 +0,0 @@ -/* constants.h - TinyCrypt interface to constants */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief -- Interface to constants. - * - */ - -#ifndef __TC_CONSTANTS_H__ -#define __TC_CONSTANTS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#ifndef NULL -#define NULL ((void *)0) -#endif - -#define TC_CRYPTO_SUCCESS 1 -#define TC_CRYPTO_FAIL 0 - -#define TC_ZERO_BYTE 0x00 - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_CONSTANTS_H__ */ diff --git a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ctr_mode.h b/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ctr_mode.h deleted file mode 100644 index dc221f9e..00000000 --- a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ctr_mode.h +++ /dev/null @@ -1,108 +0,0 @@ -/* ctr_mode.h - TinyCrypt interface to CTR mode */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to CTR mode. - * - * Overview: CTR (pronounced "counter") mode is a NIST approved mode of - * operation defined in SP 800-38a. It can be used with any - * block cipher to provide confidentiality of strings of any - * length. TinyCrypt hard codes AES128 as the block cipher. - * - * Security: CTR mode achieves confidentiality only if the counter value is - * never reused with a same encryption key. If the counter is - * repeated, than an adversary might be able to defeat the scheme. - * - * A usual method to ensure different counter values refers to - * initialize the counter in a given value (0, for example) and - * increases it every time a new block is enciphered. This naturally - * leaves to a limitation on the number q of blocks that can be - * enciphered using a same key: q < 2^(counter size). - * - * TinyCrypt uses a counter of 32 bits. This means that after 2^32 - * block encryptions, the counter will be reused (thus losing CBC - * security). 2^32 block encryptions should be enough for most of - * applications targeting constrained devices. Applications intended - * to encrypt a larger number of blocks must replace the key after - * 2^32 block encryptions. - * - * CTR mode provides NO data integrity. - * - * Requires: AES-128 - * - * Usage: 1) call tc_ctr_mode to process the data to encrypt/decrypt. - * - */ - -#ifndef __TC_CTR_MODE_H__ -#define __TC_CTR_MODE_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief CTR mode encryption/decryption procedure. - * CTR mode encrypts (or decrypts) inlen bytes from in buffer into out buffer - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * out == NULL or - * in == NULL or - * ctr == NULL or - * sched == NULL or - * inlen == 0 or - * outlen == 0 or - * inlen != outlen - * @note Assumes:- The current value in ctr has NOT been used with sched - * - out points to inlen bytes - * - in points to inlen bytes - * - ctr is an integer counter in littleEndian format - * - sched was initialized by aes_set_encrypt_key - * @param out OUT -- produced ciphertext (plaintext) - * @param outlen IN -- length of ciphertext buffer in bytes - * @param in IN -- data to encrypt (or decrypt) - * @param inlen IN -- length of input data in bytes - * @param ctr IN/OUT -- the current counter value - * @param sched IN -- an initialized AES key schedule - */ -int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_CTR_MODE_H__ */ diff --git a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ctr_prng.h b/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ctr_prng.h deleted file mode 100644 index 69cbe020..00000000 --- a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ctr_prng.h +++ /dev/null @@ -1,166 +0,0 @@ -/* ctr_prng.h - TinyCrypt interface to a CTR-PRNG implementation */ - -/* - * Copyright (c) 2016, Chris Morrison - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to a CTR-PRNG implementation. - * - * Overview: A pseudo-random number generator (PRNG) generates a sequence - * of numbers that have a distribution close to the one expected - * for a sequence of truly random numbers. The NIST Special - * Publication 800-90A specifies several mechanisms to generate - * sequences of pseudo random numbers, including the CTR-PRNG one - * which is based on AES. TinyCrypt implements CTR-PRNG with - * AES-128. - * - * Security: A cryptographically secure PRNG depends on the existence of an - * entropy source to provide a truly random seed as well as the - * security of the primitives used as the building blocks (AES-128 - * in this instance). - * - * Requires: - AES-128 - * - * Usage: 1) call tc_ctr_prng_init to seed the prng context - * - * 2) call tc_ctr_prng_reseed to mix in additional entropy into - * the prng context - * - * 3) call tc_ctr_prng_generate to output the pseudo-random data - * - * 4) call tc_ctr_prng_uninstantiate to zero out the prng context - */ - -#ifndef __TC_CTR_PRNG_H__ -#define __TC_CTR_PRNG_H__ - -#include - -#define TC_CTR_PRNG_RESEED_REQ -1 - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - /* updated each time another BLOCKLEN_BYTES bytes are produced */ - uint8_t V[TC_AES_BLOCK_SIZE]; - - /* updated whenever the PRNG is reseeded */ - struct tc_aes_key_sched_struct key; - - /* number of requests since initialization/reseeding */ - uint64_t reseedCount; -} TCCtrPrng_t; - - -/** - * @brief CTR-PRNG initialization procedure - * Initializes prng context with entropy and personalization string (if any) - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * ctx == NULL, - * entropy == NULL, - * entropyLen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) - * @note Only the first (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes of - * both the entropy and personalization inputs are used - - * supplying additional bytes has no effect. - * @param ctx IN/OUT -- the PRNG context to initialize - * @param entropy IN -- entropy used to seed the PRNG - * @param entropyLen IN -- entropy length in bytes - * @param personalization IN -- personalization string used to seed the PRNG - * (may be null) - * @param plen IN -- personalization length in bytes - * - */ -int tc_ctr_prng_init(TCCtrPrng_t * const ctx, - uint8_t const * const entropy, - unsigned int entropyLen, - uint8_t const * const personalization, - unsigned int pLen); - -/** - * @brief CTR-PRNG reseed procedure - * Mixes entropy and additional_input into the prng context - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * ctx == NULL, - * entropy == NULL, - * entropylen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) - * @note It is better to reseed an existing prng context rather than - * re-initialise, so that any existing entropy in the context is - * presereved. This offers some protection against undetected failures - * of the entropy source. - * @note Assumes tc_ctr_prng_init has been called for ctx - * @param ctx IN/OUT -- the PRNG state - * @param entropy IN -- entropy to mix into the prng - * @param entropylen IN -- length of entropy in bytes - * @param additional_input IN -- additional input to the prng (may be null) - * @param additionallen IN -- additional input length in bytes - */ -int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx, - uint8_t const * const entropy, - unsigned int entropyLen, - uint8_t const * const additional_input, - unsigned int additionallen); - -/** - * @brief CTR-PRNG generate procedure - * Generates outlen pseudo-random bytes into out buffer, updates prng - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CTR_PRNG_RESEED_REQ (-1) if a reseed is needed - * returns TC_CRYPTO_FAIL (0) if: - * ctx == NULL, - * out == NULL, - * outlen >= 2^16 - * @note Assumes tc_ctr_prng_init has been called for ctx - * @param ctx IN/OUT -- the PRNG context - * @param additional_input IN -- additional input to the prng (may be null) - * @param additionallen IN -- additional input length in bytes - * @param out IN/OUT -- buffer to receive output - * @param outlen IN -- size of out buffer in bytes - */ -int tc_ctr_prng_generate(TCCtrPrng_t * const ctx, - uint8_t const * const additional_input, - unsigned int additionallen, - uint8_t * const out, - unsigned int outlen); - -/** - * @brief CTR-PRNG uninstantiate procedure - * Zeroes the internal state of the supplied prng context - * @return none - * @param ctx IN/OUT -- the PRNG context - */ -void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_CTR_PRNG_H__ */ diff --git a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc.h b/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc.h deleted file mode 100644 index e8357320..00000000 --- a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc.h +++ /dev/null @@ -1,545 +0,0 @@ -/* ecc.h - TinyCrypt interface to common ECC functions */ - -/* Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief -- Interface to common ECC functions. - * - * Overview: This software is an implementation of common functions - * necessary to elliptic curve cryptography. This implementation uses - * curve NIST p-256. - * - * Security: The curve NIST p-256 provides approximately 128 bits of security. - * - */ - -#ifndef __TC_UECC_H__ -#define __TC_UECC_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Word size (4 bytes considering 32-bits architectures) */ -#define uECC_WORD_SIZE 4 - -/* setting max number of calls to prng: */ -#ifndef uECC_RNG_MAX_TRIES -#define uECC_RNG_MAX_TRIES 64 -#endif - -/* defining data types to store word and bit counts: */ -typedef int8_t wordcount_t; -typedef int16_t bitcount_t; -/* defining data type for comparison result: */ -typedef int8_t cmpresult_t; -/* defining data type to store ECC coordinate/point in 32bits words: */ -typedef unsigned int uECC_word_t; -/* defining data type to store an ECC coordinate/point in 64bits words: */ -typedef uint64_t uECC_dword_t; - -/* defining masks useful for ecc computations: */ -#define HIGH_BIT_SET 0x80000000 -#define uECC_WORD_BITS 32 -#define uECC_WORD_BITS_SHIFT 5 -#define uECC_WORD_BITS_MASK 0x01F - -/* Number of words of 32 bits to represent an element of the the curve p-256: */ -#define NUM_ECC_WORDS 8 -/* Number of bytes to represent an element of the the curve p-256: */ -#define NUM_ECC_BYTES (uECC_WORD_SIZE*NUM_ECC_WORDS) - -/* structure that represents an elliptic curve (e.g. p256):*/ -struct uECC_Curve_t; -typedef const struct uECC_Curve_t * uECC_Curve; -struct uECC_Curve_t { - wordcount_t num_words; - wordcount_t num_bytes; - bitcount_t num_n_bits; - uECC_word_t p[NUM_ECC_WORDS]; - uECC_word_t n[NUM_ECC_WORDS]; - uECC_word_t G[NUM_ECC_WORDS * 2]; - uECC_word_t b[NUM_ECC_WORDS]; - void (*double_jacobian)(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * Z1, - uECC_Curve curve); - void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve); - void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product); -}; - -/* - * @brief computes doubling of point ion jacobian coordinates, in place. - * @param X1 IN/OUT -- x coordinate - * @param Y1 IN/OUT -- y coordinate - * @param Z1 IN/OUT -- z coordinate - * @param curve IN -- elliptic curve - */ -void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, - uECC_word_t * Z1, uECC_Curve curve); - -/* - * @brief Computes x^3 + ax + b. result must not overlap x. - * @param result OUT -- x^3 + ax + b - * @param x IN -- value of x - * @param curve IN -- elliptic curve - */ -void x_side_default(uECC_word_t *result, const uECC_word_t *x, - uECC_Curve curve); - -/* - * @brief Computes result = product % curve_p - * from http://www.nsa.gov/ia/_files/nist-routines.pdf - * @param result OUT -- product % curve_p - * @param product IN -- value to be reduced mod curve_p - */ -void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int *product); - -/* Bytes to words ordering: */ -#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e -#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a -#define BITS_TO_WORDS(num_bits) \ - ((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8)) -#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8) - -/* definition of curve NIST p-256: */ -static const struct uECC_Curve_t curve_secp256r1 = { - NUM_ECC_WORDS, - NUM_ECC_BYTES, - 256, /* num_n_bits */ { - BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), - BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00), - BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), - BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF) - }, { - BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3), - BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC), - BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), - BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF) - }, { - BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4), - BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77), - BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8), - BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B), - - BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB), - BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B), - BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E), - BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F) - }, { - BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B), - BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65), - BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3), - BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A) - }, - &double_jacobian_default, - &x_side_default, - &vli_mmod_fast_secp256r1 -}; - -uECC_Curve uECC_secp256r1(void); - -/* - * @brief Generates a random integer in the range 0 < random < top. - * Both random and top have num_words words. - * @param random OUT -- random integer in the range 0 < random < top - * @param top IN -- upper limit - * @param num_words IN -- number of words - * @return a random integer in the range 0 < random < top - */ -int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, - wordcount_t num_words); - - -/* uECC_RNG_Function type - * The RNG function should fill 'size' random bytes into 'dest'. It should - * return 1 if 'dest' was filled with random data, or 0 if the random data could - * not be generated. The filled-in values should be either truly random, or from - * a cryptographically-secure PRNG. - * - * A correctly functioning RNG function must be set (using uECC_set_rng()) - * before calling uECC_make_key() or uECC_sign(). - * - * Setting a correctly functioning RNG function improves the resistance to - * side-channel attacks for uECC_shared_secret(). - * - * A correct RNG function is set by default. If you are building on another - * POSIX-compliant system that supports /dev/random or /dev/urandom, you can - * define uECC_POSIX to use the predefined RNG. - */ -typedef int(*uECC_RNG_Function)(uint8_t *dest, unsigned int size); - -/* - * @brief Set the function that will be used to generate random bytes. The RNG - * function should return 1 if the random data was generated, or 0 if the random - * data could not be generated. - * - * @note On platforms where there is no predefined RNG function, this must be - * called before uECC_make_key() or uECC_sign() are used. - * - * @param rng_function IN -- function that will be used to generate random bytes - */ -void uECC_set_rng(uECC_RNG_Function rng_function); - -/* - * @brief provides current uECC_RNG_Function. - * @return Returns the function that will be used to generate random bytes. - */ -uECC_RNG_Function uECC_get_rng(void); - -/* - * @brief computes the size of a private key for the curve in bytes. - * @param curve IN -- elliptic curve - * @return size of a private key for the curve in bytes. - */ -int uECC_curve_private_key_size(uECC_Curve curve); - -/* - * @brief computes the size of a public key for the curve in bytes. - * @param curve IN -- elliptic curve - * @return the size of a public key for the curve in bytes. - */ -int uECC_curve_public_key_size(uECC_Curve curve); - -/* - * @brief Compute the corresponding public key for a private key. - * @param private_key IN -- The private key to compute the public key for - * @param public_key OUT -- Will be filled in with the corresponding public key - * @param curve - * @return Returns 1 if key was computed successfully, 0 if an error occurred. - */ -int uECC_compute_public_key(const uint8_t *private_key, - uint8_t *public_key, uECC_Curve curve); - -/* - * @brief Compute public-key. - * @return corresponding public-key. - * @param result OUT -- public-key - * @param private_key IN -- private-key - * @param curve IN -- elliptic curve - */ -uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, - uECC_word_t *private_key, uECC_Curve curve); - -/* - * @brief Regularize the bitcount for the private key so that attackers cannot - * use a side channel attack to learn the number of leading zeros. - * @return Regularized k - * @param k IN -- private-key - * @param k0 IN/OUT -- regularized k - * @param k1 IN/OUT -- regularized k - * @param curve IN -- elliptic curve - */ -uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, - uECC_word_t *k1, uECC_Curve curve); - -/* - * @brief Point multiplication algorithm using Montgomery's ladder with co-Z - * coordinates. See http://eprint.iacr.org/2011/338.pdf. - * @note Result may overlap point. - * @param result OUT -- returns scalar*point - * @param point IN -- elliptic curve point - * @param scalar IN -- scalar - * @param initial_Z IN -- initial value for z - * @param num_bits IN -- number of bits in scalar - * @param curve IN -- elliptic curve - */ -void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, - const uECC_word_t * scalar, const uECC_word_t * initial_Z, - bitcount_t num_bits, uECC_Curve curve); - -/* - * @brief Constant-time comparison to zero - secure way to compare long integers - * @param vli IN -- very long integer - * @param num_words IN -- number of words in the vli - * @return 1 if vli == 0, 0 otherwise. - */ -uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words); - -/* - * @brief Check if 'point' is the point at infinity - * @param point IN -- elliptic curve point - * @param curve IN -- elliptic curve - * @return if 'point' is the point at infinity, 0 otherwise. - */ -uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve); - -/* - * @brief computes the sign of left - right, in constant time. - * @param left IN -- left term to be compared - * @param right IN -- right term to be compared - * @param num_words IN -- number of words - * @return the sign of left - right - */ -cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, - wordcount_t num_words); - -/* - * @brief computes sign of left - right, not in constant time. - * @note should not be used if inputs are part of a secret - * @param left IN -- left term to be compared - * @param right IN -- right term to be compared - * @param num_words IN -- number of words - * @return the sign of left - right - */ -cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right, - wordcount_t num_words); - -/* - * @brief Computes result = (left - right) % mod. - * @note Assumes that (left < mod) and (right < mod), and that result does not - * overlap mod. - * @param result OUT -- (left - right) % mod - * @param left IN -- leftright term in modular subtraction - * @param right IN -- right term in modular subtraction - * @param mod IN -- mod - * @param num_words IN -- number of words - */ -void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod, - wordcount_t num_words); - -/* - * @brief Computes P' = (x1', y1', Z3), P + Q = (x3, y3, Z3) or - * P => P', Q => P + Q - * @note assumes Input P = (x1, y1, Z), Q = (x2, y2, Z) - * @param X1 IN -- x coordinate of P - * @param Y1 IN -- y coordinate of P - * @param X2 IN -- x coordinate of Q - * @param Y2 IN -- y coordinate of Q - * @param curve IN -- elliptic curve - */ -void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2, - uECC_word_t * Y2, uECC_Curve curve); - -/* - * @brief Computes (x1 * z^2, y1 * z^3) - * @param X1 IN -- previous x1 coordinate - * @param Y1 IN -- previous y1 coordinate - * @param Z IN -- z value - * @param curve IN -- elliptic curve - */ -void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z, - uECC_Curve curve); - -/* - * @brief Check if bit is set. - * @return Returns nonzero if bit 'bit' of vli is set. - * @warning It is assumed that the value provided in 'bit' is within the - * boundaries of the word-array 'vli'. - * @note The bit ordering layout assumed for vli is: {31, 30, ..., 0}, - * {63, 62, ..., 32}, {95, 94, ..., 64}, {127, 126,..., 96} for a vli consisting - * of 4 uECC_word_t elements. - */ -uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit); - -/* - * @brief Computes result = product % mod, where product is 2N words long. - * @param result OUT -- product % mod - * @param mod IN -- module - * @param num_words IN -- number of words - * @warning Currently only designed to work for curve_p or curve_n. - */ -void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, - const uECC_word_t *mod, wordcount_t num_words); - -/* - * @brief Computes modular product (using curve->mmod_fast) - * @param result OUT -- (left * right) mod % curve_p - * @param left IN -- left term in product - * @param right IN -- right term in product - * @param curve IN -- elliptic curve - */ -void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, uECC_Curve curve); - -/* - * @brief Computes result = left - right. - * @note Can modify in place. - * @param result OUT -- left - right - * @param left IN -- left term in subtraction - * @param right IN -- right term in subtraction - * @param num_words IN -- number of words - * @return borrow - */ -uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, wordcount_t num_words); - -/* - * @brief Constant-time comparison function(secure way to compare long ints) - * @param left IN -- left term in comparison - * @param right IN -- right term in comparison - * @param num_words IN -- number of words - * @return Returns 0 if left == right, 1 otherwise. - */ -uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right, - wordcount_t num_words); - -/* - * @brief Computes (left * right) % mod - * @param result OUT -- (left * right) % mod - * @param left IN -- left term in product - * @param right IN -- right term in product - * @param mod IN -- mod - * @param num_words IN -- number of words - */ -void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod, - wordcount_t num_words); - -/* - * @brief Computes (1 / input) % mod - * @note All VLIs are the same size. - * @note See "Euclid's GCD to Montgomery Multiplication to the Great Divide" - * @param result OUT -- (1 / input) % mod - * @param input IN -- value to be modular inverted - * @param mod IN -- mod - * @param num_words -- number of words - */ -void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, - const uECC_word_t *mod, wordcount_t num_words); - -/* - * @brief Sets dest = src. - * @param dest OUT -- destination buffer - * @param src IN -- origin buffer - * @param num_words IN -- number of words - */ -void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, - wordcount_t num_words); - -/* - * @brief Computes (left + right) % mod. - * @note Assumes that (left < mod) and right < mod), and that result does not - * overlap mod. - * @param result OUT -- (left + right) % mod. - * @param left IN -- left term in addition - * @param right IN -- right term in addition - * @param mod IN -- mod - * @param num_words IN -- number of words - */ -void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod, - wordcount_t num_words); - -/* - * @brief Counts the number of bits required to represent vli. - * @param vli IN -- very long integer - * @param max_words IN -- number of words - * @return number of bits in given vli - */ -bitcount_t uECC_vli_numBits(const uECC_word_t *vli, - const wordcount_t max_words); - -/* - * @brief Erases (set to 0) vli - * @param vli IN -- very long integer - * @param num_words IN -- number of words - */ -void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words); - -/* - * @brief check if it is a valid point in the curve - * @param point IN -- point to be checked - * @param curve IN -- elliptic curve - * @return 0 if point is valid - * @exception returns -1 if it is a point at infinity - * @exception returns -2 if x or y is smaller than p, - * @exception returns -3 if y^2 != x^3 + ax + b. - */ -int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve); - -/* - * @brief Check if a public key is valid. - * @param public_key IN -- The public key to be checked. - * @return returns 0 if the public key is valid - * @exception returns -1 if it is a point at infinity - * @exception returns -2 if x or y is smaller than p, - * @exception returns -3 if y^2 != x^3 + ax + b. - * @exception returns -4 if public key is the group generator. - * - * @note Note that you are not required to check for a valid public key before - * using any other uECC functions. However, you may wish to avoid spending CPU - * time computing a shared secret or verifying a signature using an invalid - * public key. - */ -int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve); - - /* - * @brief Converts an integer in uECC native format to big-endian bytes. - * @param bytes OUT -- bytes representation - * @param num_bytes IN -- number of bytes - * @param native IN -- uECC native representation - */ -void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, - const unsigned int *native); - -/* - * @brief Converts big-endian bytes to an integer in uECC native format. - * @param native OUT -- uECC native representation - * @param bytes IN -- bytes representation - * @param num_bytes IN -- number of bytes - */ -void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes, - int num_bytes); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_UECC_H__ */ diff --git a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_dh.h b/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_dh.h deleted file mode 100644 index b828e195..00000000 --- a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_dh.h +++ /dev/null @@ -1,131 +0,0 @@ -/* ecc_dh.h - TinyCrypt interface to EC-DH implementation */ - -/* - * Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief -- Interface to EC-DH implementation. - * - * Overview: This software is an implementation of EC-DH. This implementation - * uses curve NIST p-256. - * - * Security: The curve NIST p-256 provides approximately 128 bits of security. - */ - -#ifndef __TC_ECC_DH_H__ -#define __TC_ECC_DH_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Create a public/private key pair. - * @return returns TC_CRYPTO_SUCCESS (1) if the key pair was generated successfully - * returns TC_CRYPTO_FAIL (0) if error while generating key pair - * - * @param p_public_key OUT -- Will be filled in with the public key. Must be at - * least 2 * the curve size (in bytes) long. For curve secp256r1, p_public_key - * must be 64 bytes long. - * @param p_private_key OUT -- Will be filled in with the private key. Must be as - * long as the curve order (for secp256r1, p_private_key must be 32 bytes long). - * - * @note side-channel countermeasure: algorithm strengthened against timing - * attack. - * @warning A cryptographically-secure PRNG function must be set (using - * uECC_set_rng()) before calling uECC_make_key(). - */ -int uECC_make_key(uint8_t *p_public_key, uint8_t *p_private_key, uECC_Curve curve); - -#ifdef ENABLE_TESTS - -/** - * @brief Create a public/private key pair given a specific d. - * - * @note THIS FUNCTION SHOULD BE CALLED ONLY FOR TEST PURPOSES. Refer to - * uECC_make_key() function for real applications. - */ -int uECC_make_key_with_d(uint8_t *p_public_key, uint8_t *p_private_key, - unsigned int *d, uECC_Curve curve); -#endif - -/** - * @brief Compute a shared secret given your secret key and someone else's - * public key. - * @return returns TC_CRYPTO_SUCCESS (1) if the shared secret was computed successfully - * returns TC_CRYPTO_FAIL (0) otherwise - * - * @param p_secret OUT -- Will be filled in with the shared secret value. Must be - * the same size as the curve size (for curve secp256r1, secret must be 32 bytes - * long. - * @param p_public_key IN -- The public key of the remote party. - * @param p_private_key IN -- Your private key. - * - * @warning It is recommended to use the output of uECC_shared_secret() as the - * input of a recommended Key Derivation Function (see NIST SP 800-108) in - * order to produce a cryptographically secure symmetric key. - */ -int uECC_shared_secret(const uint8_t *p_public_key, const uint8_t *p_private_key, - uint8_t *p_secret, uECC_Curve curve); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_ECC_DH_H__ */ diff --git a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_dsa.h b/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_dsa.h deleted file mode 100644 index aca00bc9..00000000 --- a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_dsa.h +++ /dev/null @@ -1,139 +0,0 @@ -/* ecc_dh.h - TinyCrypt interface to EC-DSA implementation */ - -/* - * Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief -- Interface to EC-DSA implementation. - * - * Overview: This software is an implementation of EC-DSA. This implementation - * uses curve NIST p-256. - * - * Security: The curve NIST p-256 provides approximately 128 bits of security. - * - * Usage: - To sign: Compute a hash of the data you wish to sign (SHA-2 is - * recommended) and pass it in to ecdsa_sign function along with your - * private key and a random number. You must use a new non-predictable - * random number to generate each new signature. - * - To verify a signature: Compute the hash of the signed data using - * the same hash as the signer and pass it to this function along with - * the signer's public key and the signature values (r and s). - */ - -#ifndef __TC_ECC_DSA_H__ -#define __TC_ECC_DSA_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Generate an ECDSA signature for a given hash value. - * @return returns TC_CRYPTO_SUCCESS (1) if the signature generated successfully - * returns TC_CRYPTO_FAIL (0) if an error occurred. - * - * @param p_private_key IN -- Your private key. - * @param p_message_hash IN -- The hash of the message to sign. - * @param p_hash_size IN -- The size of p_message_hash in bytes. - * @param p_signature OUT -- Will be filled in with the signature value. Must be - * at least 2 * curve size long (for secp256r1, signature must be 64 bytes long). - * - * @warning A cryptographically-secure PRNG function must be set (using - * uECC_set_rng()) before calling uECC_sign(). - * @note Usage: Compute a hash of the data you wish to sign (SHA-2 is - * recommended) and pass it in to this function along with your private key. - * @note side-channel countermeasure: algorithm strengthened against timing - * attack. - */ -int uECC_sign(const uint8_t *p_private_key, const uint8_t *p_message_hash, - unsigned p_hash_size, uint8_t *p_signature, uECC_Curve curve); - -#ifdef ENABLE_TESTS -/* - * THIS FUNCTION SHOULD BE CALLED FOR TEST PURPOSES ONLY. - * Refer to uECC_sign() function for real applications. - */ -int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, - unsigned int hash_size, uECC_word_t *k, uint8_t *signature, - uECC_Curve curve); -#endif - -/** - * @brief Verify an ECDSA signature. - * @return returns TC_SUCCESS (1) if the signature is valid - * returns TC_FAIL (0) if the signature is invalid. - * - * @param p_public_key IN -- The signer's public key. - * @param p_message_hash IN -- The hash of the signed data. - * @param p_hash_size IN -- The size of p_message_hash in bytes. - * @param p_signature IN -- The signature values. - * - * @note Usage: Compute the hash of the signed data using the same hash as the - * signer and pass it to this function along with the signer's public key and - * the signature values (hash_size and signature). - */ -int uECC_verify(const uint8_t *p_public_key, const uint8_t *p_message_hash, - unsigned int p_hash_size, const uint8_t *p_signature, uECC_Curve curve); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_ECC_DSA_H__ */ diff --git a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_platform_specific.h b/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_platform_specific.h deleted file mode 100644 index a55adf4f..00000000 --- a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/ecc_platform_specific.h +++ /dev/null @@ -1,81 +0,0 @@ -/* uECC_platform_specific.h - Interface to platform specific functions*/ - -/* Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE.*/ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * uECC_platform_specific.h -- Interface to platform specific functions - */ - -#ifndef __UECC_PLATFORM_SPECIFIC_H_ -#define __UECC_PLATFORM_SPECIFIC_H_ - -/* - * The RNG function should fill 'size' random bytes into 'dest'. It should - * return 1 if 'dest' was filled with random data, or 0 if the random data could - * not be generated. The filled-in values should be either truly random, or from - * a cryptographically-secure PRNG. - * - * A cryptographically-secure PRNG function must be set (using uECC_set_rng()) - * before calling uECC_make_key() or uECC_sign(). - * - * Setting a cryptographically-secure PRNG function improves the resistance to - * side-channel attacks for uECC_shared_secret(). - * - * A correct PRNG function is set by default (default_RNG_defined = 1) and works - * for some platforms, such as Unix and Linux. For other platforms, you may need - * to provide another PRNG function. -*/ -#define default_RNG_defined 0 - -int default_CSPRNG(uint8_t *dest, unsigned int size); - -#endif /* __UECC_PLATFORM_SPECIFIC_H_ */ diff --git a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/hmac.h b/lib/bt/porting/ext/tinycrypt/include/tinycrypt/hmac.h deleted file mode 100644 index 3a081494..00000000 --- a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/hmac.h +++ /dev/null @@ -1,139 +0,0 @@ -/* hmac.h - TinyCrypt interface to an HMAC implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to an HMAC implementation. - * - * Overview: HMAC is a message authentication code based on hash functions. - * TinyCrypt hard codes SHA-256 as the hash function. A message - * authentication code based on hash functions is also called a - * keyed cryptographic hash function since it performs a - * transformation specified by a key in an arbitrary length data - * set into a fixed length data set (also called tag). - * - * Security: The security of the HMAC depends on the length of the key and - * on the security of the hash function. Note that HMAC primitives - * are much less affected by collision attacks than their - * corresponding hash functions. - * - * Requires: SHA-256 - * - * Usage: 1) call tc_hmac_set_key to set the HMAC key. - * - * 2) call tc_hmac_init to initialize a struct hash_state before - * processing the data. - * - * 3) call tc_hmac_update to process the next input segment; - * tc_hmac_update can be called as many times as needed to process - * all of the segments of the input; the order is important. - * - * 4) call tc_hmac_final to out put the tag. - */ - -#ifndef __TC_HMAC_H__ -#define __TC_HMAC_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct tc_hmac_state_struct { - /* the internal state required by h */ - struct tc_sha256_state_struct hash_state; - /* HMAC key schedule */ - uint8_t key[2*TC_SHA256_BLOCK_SIZE]; -}; -typedef struct tc_hmac_state_struct *TCHmacState_t; - -/** - * @brief HMAC set key procedure - * Configures ctx to use key - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if - * ctx == NULL or - * key == NULL or - * key_size == 0 - * @param ctx IN/OUT -- the struct tc_hmac_state_struct to initial - * @param key IN -- the HMAC key to configure - * @param key_size IN -- the HMAC key size - */ -int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key, - unsigned int key_size); - -/** - * @brief HMAC init procedure - * Initializes ctx to begin the next HMAC operation - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL - * @param ctx IN/OUT -- struct tc_hmac_state_struct buffer to init - */ -int tc_hmac_init(TCHmacState_t ctx); - -/** - * @brief HMAC update procedure - * Mixes data_length bytes addressed by data into state - * @return returns TC_CRYPTO_SUCCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL - * @note Assumes state has been initialized by tc_hmac_init - * @param ctx IN/OUT -- state of HMAC computation so far - * @param data IN -- data to incorporate into state - * @param data_length IN -- size of data in bytes - */ -int tc_hmac_update(TCHmacState_t ctx, const void *data, - unsigned int data_length); - -/** - * @brief HMAC final procedure - * Writes the HMAC tag into the tag buffer - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * tag == NULL or - * ctx == NULL or - * key == NULL or - * taglen != TC_SHA256_DIGEST_SIZE - * @note ctx is erased before exiting. This should never be changed/removed. - * @note Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes - * state has been initialized by tc_hmac_init - * @param tag IN/OUT -- buffer to receive computed HMAC tag - * @param taglen IN -- size of tag in bytes - * @param ctx IN/OUT -- the HMAC state for computing tag - */ -int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx); - -#ifdef __cplusplus -} -#endif - -#endif /*__TC_HMAC_H__*/ diff --git a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/hmac_prng.h b/lib/bt/porting/ext/tinycrypt/include/tinycrypt/hmac_prng.h deleted file mode 100644 index ad12cbbf..00000000 --- a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/hmac_prng.h +++ /dev/null @@ -1,164 +0,0 @@ -/* hmac_prng.h - TinyCrypt interface to an HMAC-PRNG implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to an HMAC-PRNG implementation. - * - * Overview: A pseudo-random number generator (PRNG) generates a sequence - * of numbers that have a distribution close to the one expected - * for a sequence of truly random numbers. The NIST Special - * Publication 800-90A specifies several mechanisms to generate - * sequences of pseudo random numbers, including the HMAC-PRNG one - * which is based on HMAC. TinyCrypt implements HMAC-PRNG with - * certain modifications from the NIST SP 800-90A spec. - * - * Security: A cryptographically secure PRNG depends on the existence of an - * entropy source to provide a truly random seed as well as the - * security of the primitives used as the building blocks (HMAC and - * SHA256, for TinyCrypt). - * - * The NIST SP 800-90A standard tolerates a null personalization, - * while TinyCrypt requires a non-null personalization. This is - * because a personalization string (the host name concatenated - * with a time stamp, for example) is easily computed and might be - * the last line of defense against failure of the entropy source. - * - * Requires: - SHA-256 - * - HMAC - * - * Usage: 1) call tc_hmac_prng_init to set the HMAC key and process the - * personalization data. - * - * 2) call tc_hmac_prng_reseed to process the seed and additional - * input. - * - * 3) call tc_hmac_prng_generate to out put the pseudo-random data. - */ - -#ifndef __TC_HMAC_PRNG_H__ -#define __TC_HMAC_PRNG_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define TC_HMAC_PRNG_RESEED_REQ -1 - -struct tc_hmac_prng_struct { - /* the HMAC instance for this PRNG */ - struct tc_hmac_state_struct h; - /* the PRNG key */ - uint8_t key[TC_SHA256_DIGEST_SIZE]; - /* PRNG state */ - uint8_t v[TC_SHA256_DIGEST_SIZE]; - /* calls to tc_hmac_prng_generate left before re-seed */ - unsigned int countdown; -}; - -typedef struct tc_hmac_prng_struct *TCHmacPrng_t; - -/** - * @brief HMAC-PRNG initialization procedure - * Initializes prng with personalization, disables tc_hmac_prng_generate - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * prng == NULL, - * personalization == NULL, - * plen > MAX_PLEN - * @note Assumes: - personalization != NULL. - * The personalization is a platform unique string (e.g., the host - * name) and is the last line of defense against failure of the - * entropy source - * @warning NIST SP 800-90A specifies 3 items as seed material during - * initialization: entropy seed, personalization, and an optional - * nonce. TinyCrypts requires instead a non-null personalization - * (which is easily computed) and indirectly requires an entropy - * seed (since the reseed function is mandatorily called after - * init) - * @param prng IN/OUT -- the PRNG state to initialize - * @param personalization IN -- personalization string - * @param plen IN -- personalization length in bytes - */ -int tc_hmac_prng_init(TCHmacPrng_t prng, - const uint8_t *personalization, - unsigned int plen); - -/** - * @brief HMAC-PRNG reseed procedure - * Mixes seed into prng, enables tc_hmac_prng_generate - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * prng == NULL, - * seed == NULL, - * seedlen < MIN_SLEN, - * seendlen > MAX_SLEN, - * additional_input != (const uint8_t *) 0 && additionallen == 0, - * additional_input != (const uint8_t *) 0 && additionallen > MAX_ALEN - * @note Assumes:- tc_hmac_prng_init has been called for prng - * - seed has sufficient entropy. - * - * @param prng IN/OUT -- the PRNG state - * @param seed IN -- entropy to mix into the prng - * @param seedlen IN -- length of seed in bytes - * @param additional_input IN -- additional input to the prng - * @param additionallen IN -- additional input length in bytes - */ -int tc_hmac_prng_reseed(TCHmacPrng_t prng, const uint8_t *seed, - unsigned int seedlen, const uint8_t *additional_input, - unsigned int additionallen); - -/** - * @brief HMAC-PRNG generate procedure - * Generates outlen pseudo-random bytes into out buffer, updates prng - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_HMAC_PRNG_RESEED_REQ (-1) if a reseed is needed - * returns TC_CRYPTO_FAIL (0) if: - * out == NULL, - * prng == NULL, - * outlen == 0, - * outlen >= MAX_OUT - * @note Assumes tc_hmac_prng_init has been called for prng - * @param out IN/OUT -- buffer to receive output - * @param outlen IN -- size of out buffer in bytes - * @param prng IN/OUT -- the PRNG state - */ -int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_HMAC_PRNG_H__ */ diff --git a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/sha256.h b/lib/bt/porting/ext/tinycrypt/include/tinycrypt/sha256.h deleted file mode 100644 index af5e8baf..00000000 --- a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/sha256.h +++ /dev/null @@ -1,129 +0,0 @@ -/* sha256.h - TinyCrypt interface to a SHA-256 implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to a SHA-256 implementation. - * - * Overview: SHA-256 is a NIST approved cryptographic hashing algorithm - * specified in FIPS 180. A hash algorithm maps data of arbitrary - * size to data of fixed length. - * - * Security: SHA-256 provides 128 bits of security against collision attacks - * and 256 bits of security against pre-image attacks. SHA-256 does - * NOT behave like a random oracle, but it can be used as one if - * the string being hashed is prefix-free encoded before hashing. - * - * Usage: 1) call tc_sha256_init to initialize a struct - * tc_sha256_state_struct before hashing a new string. - * - * 2) call tc_sha256_update to hash the next string segment; - * tc_sha256_update can be called as many times as needed to hash - * all of the segments of a string; the order is important. - * - * 3) call tc_sha256_final to out put the digest from a hashing - * operation. - */ - -#ifndef __TC_SHA256_H__ -#define __TC_SHA256_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define TC_SHA256_BLOCK_SIZE (64) -#define TC_SHA256_DIGEST_SIZE (32) -#define TC_SHA256_STATE_BLOCKS (TC_SHA256_DIGEST_SIZE/4) - -struct tc_sha256_state_struct { - unsigned int iv[TC_SHA256_STATE_BLOCKS]; - uint64_t bits_hashed; - uint8_t leftover[TC_SHA256_BLOCK_SIZE]; - size_t leftover_offset; -}; - -typedef struct tc_sha256_state_struct *TCSha256State_t; - -/** - * @brief SHA256 initialization procedure - * Initializes s - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if s == NULL - * @param s Sha256 state struct - */ -int tc_sha256_init(TCSha256State_t s); - -/** - * @brief SHA256 update procedure - * Hashes data_length bytes addressed by data into state s - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * s == NULL, - * s->iv == NULL, - * data == NULL - * @note Assumes s has been initialized by tc_sha256_init - * @warning The state buffer 'leftover' is left in memory after processing - * If your application intends to have sensitive data in this - * buffer, remind to erase it after the data has been processed - * @param s Sha256 state struct - * @param data message to hash - * @param datalen length of message to hash - */ -int tc_sha256_update (TCSha256State_t s, const uint8_t *data, size_t datalen); - -/** - * @brief SHA256 final procedure - * Inserts the completed hash computation into digest - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * s == NULL, - * s->iv == NULL, - * digest == NULL - * @note Assumes: s has been initialized by tc_sha256_init - * digest points to at least TC_SHA256_DIGEST_SIZE bytes - * @warning The state buffer 'leftover' is left in memory after processing - * If your application intends to have sensitive data in this - * buffer, remind to erase it after the data has been processed - * @param digest unsigned eight bit integer - * @param Sha256 state struct - */ -int tc_sha256_final(uint8_t *digest, TCSha256State_t s); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_SHA256_H__ */ diff --git a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/utils.h b/lib/bt/porting/ext/tinycrypt/include/tinycrypt/utils.h deleted file mode 100644 index bab5c320..00000000 --- a/lib/bt/porting/ext/tinycrypt/include/tinycrypt/utils.h +++ /dev/null @@ -1,95 +0,0 @@ -/* utils.h - TinyCrypt interface to platform-dependent run-time operations */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to platform-dependent run-time operations. - * - */ - -#ifndef __TC_UTILS_H__ -#define __TC_UTILS_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Copy the the buffer 'from' to the buffer 'to'. - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * from_len > to_len. - * - * @param to OUT -- destination buffer - * @param to_len IN -- length of destination buffer - * @param from IN -- origin buffer - * @param from_len IN -- length of origin buffer - */ -unsigned int _copy(uint8_t *to, unsigned int to_len, - const uint8_t *from, unsigned int from_len); - -/** - * @brief Set the value 'val' into the buffer 'to', 'len' times. - * - * @param to OUT -- destination buffer - * @param val IN -- value to be set in 'to' - * @param len IN -- number of times the value will be copied - */ -void _set(void *to, uint8_t val, unsigned int len); - -/* - * @brief AES specific doubling function, which utilizes - * the finite field used by AES. - * @return Returns a^2 - * - * @param a IN/OUT -- value to be doubled - */ -uint8_t _double_byte(uint8_t a); - -/* - * @brief Constant-time algorithm to compare if two sequences of bytes are equal - * @return Returns 0 if equal, and non-zero otherwise - * - * @param a IN -- sequence of bytes a - * @param b IN -- sequence of bytes b - * @param size IN -- size of sequences a and b - */ -int _compare(const uint8_t *a, const uint8_t *b, size_t size); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_UTILS_H__ */ diff --git a/lib/bt/porting/ext/tinycrypt/src/aes_decrypt.c b/lib/bt/porting/ext/tinycrypt/src/aes_decrypt.c deleted file mode 100644 index 993a6180..00000000 --- a/lib/bt/porting/ext/tinycrypt/src/aes_decrypt.c +++ /dev/null @@ -1,164 +0,0 @@ -/* aes_decrypt.c - TinyCrypt implementation of AES decryption procedure */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -static const uint8_t inv_sbox[256] = { - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, - 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, - 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, - 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, - 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, - 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, - 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, - 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, - 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, - 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, - 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, - 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, - 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, - 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, - 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, - 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, - 0x55, 0x21, 0x0c, 0x7d -}; - -int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k) -{ - return tc_aes128_set_encrypt_key(s, k); -} - -#define mult8(a)(_double_byte(_double_byte(_double_byte(a)))) -#define mult9(a)(mult8(a)^(a)) -#define multb(a)(mult8(a)^_double_byte(a)^(a)) -#define multd(a)(mult8(a)^_double_byte(_double_byte(a))^(a)) -#define multe(a)(mult8(a)^_double_byte(_double_byte(a))^_double_byte(a)) - -static inline void mult_row_column(uint8_t *out, const uint8_t *in) -{ - out[0] = multe(in[0]) ^ multb(in[1]) ^ multd(in[2]) ^ mult9(in[3]); - out[1] = mult9(in[0]) ^ multe(in[1]) ^ multb(in[2]) ^ multd(in[3]); - out[2] = multd(in[0]) ^ mult9(in[1]) ^ multe(in[2]) ^ multb(in[3]); - out[3] = multb(in[0]) ^ multd(in[1]) ^ mult9(in[2]) ^ multe(in[3]); -} - -static inline void inv_mix_columns(uint8_t *s) -{ - uint8_t t[Nb*Nk]; - - mult_row_column(t, s); - mult_row_column(&t[Nb], s+Nb); - mult_row_column(&t[2*Nb], s+(2*Nb)); - mult_row_column(&t[3*Nb], s+(3*Nb)); - (void)_copy(s, sizeof(t), t, sizeof(t)); -} - -static inline void add_round_key(uint8_t *s, const unsigned int *k) -{ - s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16); - s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]); - s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16); - s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]); - s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16); - s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]); - s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16); - s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]); -} - -static inline void inv_sub_bytes(uint8_t *s) -{ - unsigned int i; - - for (i = 0; i < (Nb*Nk); ++i) { - s[i] = inv_sbox[s[i]]; - } -} - -/* - * This inv_shift_rows also implements the matrix flip required for - * inv_mix_columns, but performs it here to reduce the number of memory - * operations. - */ -static inline void inv_shift_rows(uint8_t *s) -{ - uint8_t t[Nb*Nk]; - - t[0] = s[0]; t[1] = s[13]; t[2] = s[10]; t[3] = s[7]; - t[4] = s[4]; t[5] = s[1]; t[6] = s[14]; t[7] = s[11]; - t[8] = s[8]; t[9] = s[5]; t[10] = s[2]; t[11] = s[15]; - t[12] = s[12]; t[13] = s[9]; t[14] = s[6]; t[15] = s[3]; - (void)_copy(s, sizeof(t), t, sizeof(t)); -} - -int tc_aes_decrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s) -{ - uint8_t state[Nk*Nb]; - unsigned int i; - - if (out == (uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } else if (in == (const uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } else if (s == (TCAesKeySched_t) 0) { - return TC_CRYPTO_FAIL; - } - - (void)_copy(state, sizeof(state), in, sizeof(state)); - - add_round_key(state, s->words + Nb*Nr); - - for (i = Nr - 1; i > 0; --i) { - inv_shift_rows(state); - inv_sub_bytes(state); - add_round_key(state, s->words + Nb*i); - inv_mix_columns(state); - } - - inv_shift_rows(state); - inv_sub_bytes(state); - add_round_key(state, s->words); - - (void)_copy(out, sizeof(state), state, sizeof(state)); - - /*zeroing out the state buffer */ - _set(state, TC_ZERO_BYTE, sizeof(state)); - - - return TC_CRYPTO_SUCCESS; -} diff --git a/lib/bt/porting/ext/tinycrypt/src/aes_encrypt.c b/lib/bt/porting/ext/tinycrypt/src/aes_encrypt.c deleted file mode 100644 index 8991aee5..00000000 --- a/lib/bt/porting/ext/tinycrypt/src/aes_encrypt.c +++ /dev/null @@ -1,191 +0,0 @@ -/* aes_encrypt.c - TinyCrypt implementation of AES encryption procedure */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -static const uint8_t sbox[256] = { - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, - 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, - 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, - 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, - 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, - 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, - 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, - 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, - 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, - 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, - 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, - 0xb0, 0x54, 0xbb, 0x16 -}; - -static inline unsigned int rotword(unsigned int a) -{ - return (((a) >> 24)|((a) << 8)); -} - -#define subbyte(a, o)(sbox[((a) >> (o))&0xff] << (o)) -#define subword(a)(subbyte(a, 24)|subbyte(a, 16)|subbyte(a, 8)|subbyte(a, 0)) - -int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k) -{ - const unsigned int rconst[11] = { - 0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, - 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000 - }; - unsigned int i; - unsigned int t; - - if (s == (TCAesKeySched_t) 0) { - return TC_CRYPTO_FAIL; - } else if (k == (const uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } - - for (i = 0; i < Nk; ++i) { - s->words[i] = (k[Nb*i]<<24) | (k[Nb*i+1]<<16) | - (k[Nb*i+2]<<8) | (k[Nb*i+3]); - } - - for (; i < (Nb * (Nr + 1)); ++i) { - t = s->words[i-1]; - if ((i % Nk) == 0) { - t = subword(rotword(t)) ^ rconst[i/Nk]; - } - s->words[i] = s->words[i-Nk] ^ t; - } - - return TC_CRYPTO_SUCCESS; -} - -static inline void add_round_key(uint8_t *s, const unsigned int *k) -{ - s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16); - s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]); - s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16); - s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]); - s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16); - s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]); - s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16); - s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]); -} - -static inline void sub_bytes(uint8_t *s) -{ - unsigned int i; - - for (i = 0; i < (Nb * Nk); ++i) { - s[i] = sbox[s[i]]; - } -} - -#define triple(a)(_double_byte(a)^(a)) - -static inline void mult_row_column(uint8_t *out, const uint8_t *in) -{ - out[0] = _double_byte(in[0]) ^ triple(in[1]) ^ in[2] ^ in[3]; - out[1] = in[0] ^ _double_byte(in[1]) ^ triple(in[2]) ^ in[3]; - out[2] = in[0] ^ in[1] ^ _double_byte(in[2]) ^ triple(in[3]); - out[3] = triple(in[0]) ^ in[1] ^ in[2] ^ _double_byte(in[3]); -} - -static inline void mix_columns(uint8_t *s) -{ - uint8_t t[Nb*Nk]; - - mult_row_column(t, s); - mult_row_column(&t[Nb], s+Nb); - mult_row_column(&t[2 * Nb], s + (2 * Nb)); - mult_row_column(&t[3 * Nb], s + (3 * Nb)); - (void) _copy(s, sizeof(t), t, sizeof(t)); -} - -/* - * This shift_rows also implements the matrix flip required for mix_columns, but - * performs it here to reduce the number of memory operations. - */ -static inline void shift_rows(uint8_t *s) -{ - uint8_t t[Nb * Nk]; - - t[0] = s[0]; t[1] = s[5]; t[2] = s[10]; t[3] = s[15]; - t[4] = s[4]; t[5] = s[9]; t[6] = s[14]; t[7] = s[3]; - t[8] = s[8]; t[9] = s[13]; t[10] = s[2]; t[11] = s[7]; - t[12] = s[12]; t[13] = s[1]; t[14] = s[6]; t[15] = s[11]; - (void) _copy(s, sizeof(t), t, sizeof(t)); -} - -int tc_aes_encrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s) -{ - uint8_t state[Nk*Nb]; - unsigned int i; - - if (out == (uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } else if (in == (const uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } else if (s == (TCAesKeySched_t) 0) { - return TC_CRYPTO_FAIL; - } - - (void)_copy(state, sizeof(state), in, sizeof(state)); - add_round_key(state, s->words); - - for (i = 0; i < (Nr - 1); ++i) { - sub_bytes(state); - shift_rows(state); - mix_columns(state); - add_round_key(state, s->words + Nb*(i+1)); - } - - sub_bytes(state); - shift_rows(state); - add_round_key(state, s->words + Nb*(i+1)); - - (void)_copy(out, sizeof(state), state, sizeof(state)); - - /* zeroing out the state buffer */ - _set(state, TC_ZERO_BYTE, sizeof(state)); - - return TC_CRYPTO_SUCCESS; -} diff --git a/lib/bt/porting/ext/tinycrypt/src/cbc_mode.c b/lib/bt/porting/ext/tinycrypt/src/cbc_mode.c deleted file mode 100644 index 62d7879e..00000000 --- a/lib/bt/porting/ext/tinycrypt/src/cbc_mode.c +++ /dev/null @@ -1,114 +0,0 @@ -/* cbc_mode.c - TinyCrypt implementation of CBC mode encryption & decryption */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, const uint8_t *iv, - const TCAesKeySched_t sched) -{ - - uint8_t buffer[TC_AES_BLOCK_SIZE]; - unsigned int n, m; - - /* input sanity check: */ - if (out == (uint8_t *) 0 || - in == (const uint8_t *) 0 || - sched == (TCAesKeySched_t) 0 || - inlen == 0 || - outlen == 0 || - (inlen % TC_AES_BLOCK_SIZE) != 0 || - (outlen % TC_AES_BLOCK_SIZE) != 0 || - outlen != inlen + TC_AES_BLOCK_SIZE) { - return TC_CRYPTO_FAIL; - } - - /* copy iv to the buffer */ - (void)_copy(buffer, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE); - /* copy iv to the output buffer */ - (void)_copy(out, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE); - out += TC_AES_BLOCK_SIZE; - - for (n = m = 0; n < inlen; ++n) { - buffer[m++] ^= *in++; - if (m == TC_AES_BLOCK_SIZE) { - (void)tc_aes_encrypt(buffer, buffer, sched); - (void)_copy(out, TC_AES_BLOCK_SIZE, - buffer, TC_AES_BLOCK_SIZE); - out += TC_AES_BLOCK_SIZE; - m = 0; - } - } - - return TC_CRYPTO_SUCCESS; -} - -int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, const uint8_t *iv, - const TCAesKeySched_t sched) -{ - - uint8_t buffer[TC_AES_BLOCK_SIZE]; - const uint8_t *p; - unsigned int n, m; - - /* sanity check the inputs */ - if (out == (uint8_t *) 0 || - in == (const uint8_t *) 0 || - sched == (TCAesKeySched_t) 0 || - inlen == 0 || - outlen == 0 || - (inlen % TC_AES_BLOCK_SIZE) != 0 || - (outlen % TC_AES_BLOCK_SIZE) != 0 || - outlen != inlen - TC_AES_BLOCK_SIZE) { - return TC_CRYPTO_FAIL; - } - - /* - * Note that in == iv + ciphertext, i.e. the iv and the ciphertext are - * contiguous. This allows for a very efficient decryption algorithm - * that would not otherwise be possible. - */ - p = iv; - for (n = m = 0; n < inlen; ++n) { - if ((n % TC_AES_BLOCK_SIZE) == 0) { - (void)tc_aes_decrypt(buffer, in, sched); - in += TC_AES_BLOCK_SIZE; - m = 0; - } - *out++ = buffer[m++] ^ *p++; - } - - return TC_CRYPTO_SUCCESS; -} diff --git a/lib/bt/porting/ext/tinycrypt/src/ccm_mode.c b/lib/bt/porting/ext/tinycrypt/src/ccm_mode.c deleted file mode 100644 index 929adac6..00000000 --- a/lib/bt/porting/ext/tinycrypt/src/ccm_mode.c +++ /dev/null @@ -1,266 +0,0 @@ -/* ccm_mode.c - TinyCrypt implementation of CCM mode */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -#include - -int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce, - unsigned int nlen, unsigned int mlen) -{ - - /* input sanity check: */ - if (c == (TCCcmMode_t) 0 || - sched == (TCAesKeySched_t) 0 || - nonce == (uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } else if (nlen != 13) { - return TC_CRYPTO_FAIL; /* The allowed nonce size is: 13. See documentation.*/ - } else if ((mlen < 4) || (mlen > 16) || (mlen & 1)) { - return TC_CRYPTO_FAIL; /* The allowed mac sizes are: 4, 6, 8, 10, 12, 14, 16.*/ - } - - c->mlen = mlen; - c->sched = sched; - c->nonce = nonce; - - return TC_CRYPTO_SUCCESS; -} - -/** - * Variation of CBC-MAC mode used in CCM. - */ -static void ccm_cbc_mac(uint8_t *T, const uint8_t *data, unsigned int dlen, - unsigned int flag, TCAesKeySched_t sched) -{ - - unsigned int i; - - if (flag > 0) { - T[0] ^= (uint8_t)(dlen >> 8); - T[1] ^= (uint8_t)(dlen); - dlen += 2; i = 2; - } else { - i = 0; - } - - while (i < dlen) { - T[i++ % (Nb * Nk)] ^= *data++; - if (((i % (Nb * Nk)) == 0) || dlen == i) { - (void) tc_aes_encrypt(T, T, sched); - } - } -} - -/** - * Variation of CTR mode used in CCM. - * The CTR mode used by CCM is slightly different than the conventional CTR - * mode (the counter is increased before encryption, instead of after - * encryption). Besides, it is assumed that the counter is stored in the last - * 2 bytes of the nonce. - */ -static int ccm_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched) -{ - - uint8_t buffer[TC_AES_BLOCK_SIZE]; - uint8_t nonce[TC_AES_BLOCK_SIZE]; - uint16_t block_num; - unsigned int i; - - /* input sanity check: */ - if (out == (uint8_t *) 0 || - in == (uint8_t *) 0 || - ctr == (uint8_t *) 0 || - sched == (TCAesKeySched_t) 0 || - inlen == 0 || - outlen == 0 || - outlen != inlen) { - return TC_CRYPTO_FAIL; - } - - /* copy the counter to the nonce */ - (void) _copy(nonce, sizeof(nonce), ctr, sizeof(nonce)); - - /* select the last 2 bytes of the nonce to be incremented */ - block_num = (uint16_t) ((nonce[14] << 8)|(nonce[15])); - for (i = 0; i < inlen; ++i) { - if ((i % (TC_AES_BLOCK_SIZE)) == 0) { - block_num++; - nonce[14] = (uint8_t)(block_num >> 8); - nonce[15] = (uint8_t)(block_num); - if (!tc_aes_encrypt(buffer, nonce, sched)) { - return TC_CRYPTO_FAIL; - } - } - /* update the output */ - *out++ = buffer[i % (TC_AES_BLOCK_SIZE)] ^ *in++; - } - - /* update the counter */ - ctr[14] = nonce[14]; ctr[15] = nonce[15]; - - return TC_CRYPTO_SUCCESS; -} - -int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen, - const uint8_t *associated_data, - unsigned int alen, const uint8_t *payload, - unsigned int plen, TCCcmMode_t c) -{ - - /* input sanity check: */ - if ((out == (uint8_t *) 0) || - (c == (TCCcmMode_t) 0) || - ((plen > 0) && (payload == (uint8_t *) 0)) || - ((alen > 0) && (associated_data == (uint8_t *) 0)) || - (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */ - (plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */ - (olen < (plen + c->mlen))) { /* invalid output buffer size */ - return TC_CRYPTO_FAIL; - } - - uint8_t b[Nb * Nk]; - uint8_t tag[Nb * Nk]; - unsigned int i; - - /* GENERATING THE AUTHENTICATION TAG: */ - - /* formatting the sequence b for authentication: */ - b[0] = ((alen > 0) ? 0x40:0) | (((c->mlen - 2) / 2 << 3)) | (1); - for (i = 1; i <= 13; ++i) { - b[i] = c->nonce[i - 1]; - } - b[14] = (uint8_t)(plen >> 8); - b[15] = (uint8_t)(plen); - - /* computing the authentication tag using cbc-mac: */ - (void) tc_aes_encrypt(tag, b, c->sched); - if (alen > 0) { - ccm_cbc_mac(tag, associated_data, alen, 1, c->sched); - } - if (plen > 0) { - ccm_cbc_mac(tag, payload, plen, 0, c->sched); - } - - /* ENCRYPTION: */ - - /* formatting the sequence b for encryption: */ - b[0] = 1; /* q - 1 = 2 - 1 = 1 */ - b[14] = b[15] = TC_ZERO_BYTE; - - /* encrypting payload using ctr mode: */ - ccm_ctr_mode(out, plen, payload, plen, b, c->sched); - - b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter for ctr_mode (0):*/ - - /* encrypting b and adding the tag to the output: */ - (void) tc_aes_encrypt(b, b, c->sched); - out += plen; - for (i = 0; i < c->mlen; ++i) { - *out++ = tag[i] ^ b[i]; - } - - return TC_CRYPTO_SUCCESS; -} - -int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen, - const uint8_t *associated_data, - unsigned int alen, const uint8_t *payload, - unsigned int plen, TCCcmMode_t c) -{ - - /* input sanity check: */ - if ((out == (uint8_t *) 0) || - (c == (TCCcmMode_t) 0) || - ((plen > 0) && (payload == (uint8_t *) 0)) || - ((alen > 0) && (associated_data == (uint8_t *) 0)) || - (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */ - (plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */ - (olen < plen - c->mlen)) { /* invalid output buffer size */ - return TC_CRYPTO_FAIL; - } - - uint8_t b[Nb * Nk]; - uint8_t tag[Nb * Nk]; - unsigned int i; - - /* DECRYPTION: */ - - /* formatting the sequence b for decryption: */ - b[0] = 1; /* q - 1 = 2 - 1 = 1 */ - for (i = 1; i < 14; ++i) { - b[i] = c->nonce[i - 1]; - } - b[14] = b[15] = TC_ZERO_BYTE; /* initial counter value is 0 */ - - /* decrypting payload using ctr mode: */ - ccm_ctr_mode(out, plen - c->mlen, payload, plen - c->mlen, b, c->sched); - - b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter value (0) */ - - /* encrypting b and restoring the tag from input: */ - (void) tc_aes_encrypt(b, b, c->sched); - for (i = 0; i < c->mlen; ++i) { - tag[i] = *(payload + plen - c->mlen + i) ^ b[i]; - } - - /* VERIFYING THE AUTHENTICATION TAG: */ - - /* formatting the sequence b for authentication: */ - b[0] = ((alen > 0) ? 0x40:0)|(((c->mlen - 2) / 2 << 3)) | (1); - for (i = 1; i < 14; ++i) { - b[i] = c->nonce[i - 1]; - } - b[14] = (uint8_t)((plen - c->mlen) >> 8); - b[15] = (uint8_t)(plen - c->mlen); - - /* computing the authentication tag using cbc-mac: */ - (void) tc_aes_encrypt(b, b, c->sched); - if (alen > 0) { - ccm_cbc_mac(b, associated_data, alen, 1, c->sched); - } - if (plen > 0) { - ccm_cbc_mac(b, out, plen - c->mlen, 0, c->sched); - } - - /* comparing the received tag and the computed one: */ - if (_compare(b, tag, c->mlen) == 0) { - return TC_CRYPTO_SUCCESS; - } else { - /* erase the decrypted buffer in case of mac validation failure: */ - _set(out, 0, plen - c->mlen); - return TC_CRYPTO_FAIL; - } -} diff --git a/lib/bt/porting/ext/tinycrypt/src/cmac_mode.c b/lib/bt/porting/ext/tinycrypt/src/cmac_mode.c deleted file mode 100644 index 96d147e8..00000000 --- a/lib/bt/porting/ext/tinycrypt/src/cmac_mode.c +++ /dev/null @@ -1,254 +0,0 @@ -/* cmac_mode.c - TinyCrypt CMAC mode implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -/* max number of calls until change the key (2^48).*/ -const static uint64_t MAX_CALLS = ((uint64_t)1 << 48); - -/* - * gf_wrap -- In our implementation, GF(2^128) is represented as a 16 byte - * array with byte 0 the most significant and byte 15 the least significant. - * High bit carry reduction is based on the primitive polynomial - * - * X^128 + X^7 + X^2 + X + 1, - * - * which leads to the reduction formula X^128 = X^7 + X^2 + X + 1. Indeed, - * since 0 = (X^128 + X^7 + X^2 + 1) mod (X^128 + X^7 + X^2 + X + 1) and since - * addition of polynomials with coefficients in Z/Z(2) is just XOR, we can - * add X^128 to both sides to get - * - * X^128 = (X^7 + X^2 + X + 1) mod (X^128 + X^7 + X^2 + X + 1) - * - * and the coefficients of the polynomial on the right hand side form the - * string 1000 0111 = 0x87, which is the value of gf_wrap. - * - * This gets used in the following way. Doubling in GF(2^128) is just a left - * shift by 1 bit, except when the most significant bit is 1. In the latter - * case, the relation X^128 = X^7 + X^2 + X + 1 says that the high order bit - * that overflows beyond 128 bits can be replaced by addition of - * X^7 + X^2 + X + 1 <--> 0x87 to the low order 128 bits. Since addition - * in GF(2^128) is represented by XOR, we therefore only have to XOR 0x87 - * into the low order byte after a left shift when the starting high order - * bit is 1. - */ -const unsigned char gf_wrap = 0x87; - -/* - * assumes: out != NULL and points to a GF(2^n) value to receive the - * doubled value; - * in != NULL and points to a 16 byte GF(2^n) value - * to double; - * the in and out buffers do not overlap. - * effects: doubles the GF(2^n) value pointed to by "in" and places - * the result in the GF(2^n) value pointed to by "out." - */ -void gf_double(uint8_t *out, uint8_t *in) -{ - - /* start with low order byte */ - uint8_t *x = in + (TC_AES_BLOCK_SIZE - 1); - - /* if msb == 1, we need to add the gf_wrap value, otherwise add 0 */ - uint8_t carry = (in[0] >> 7) ? gf_wrap : 0; - - out += (TC_AES_BLOCK_SIZE - 1); - for (;;) { - *out-- = (*x << 1) ^ carry; - if (x == in) { - break; - } - carry = *x-- >> 7; - } -} - -int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, TCAesKeySched_t sched) -{ - - /* input sanity check: */ - if (s == (TCCmacState_t) 0 || - key == (const uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } - - /* put s into a known state */ - _set(s, 0, sizeof(*s)); - s->sched = sched; - - /* configure the encryption key used by the underlying block cipher */ - tc_aes128_set_encrypt_key(s->sched, key); - - /* compute s->K1 and s->K2 from s->iv using s->keyid */ - _set(s->iv, 0, TC_AES_BLOCK_SIZE); - tc_aes_encrypt(s->iv, s->iv, s->sched); - gf_double (s->K1, s->iv); - gf_double (s->K2, s->K1); - - /* reset s->iv to 0 in case someone wants to compute now */ - tc_cmac_init(s); - - return TC_CRYPTO_SUCCESS; -} - -int tc_cmac_erase(TCCmacState_t s) -{ - if (s == (TCCmacState_t) 0) { - return TC_CRYPTO_FAIL; - } - - /* destroy the current state */ - _set(s, 0, sizeof(*s)); - - return TC_CRYPTO_SUCCESS; -} - -int tc_cmac_init(TCCmacState_t s) -{ - /* input sanity check: */ - if (s == (TCCmacState_t) 0) { - return TC_CRYPTO_FAIL; - } - - /* CMAC starts with an all zero initialization vector */ - _set(s->iv, 0, TC_AES_BLOCK_SIZE); - - /* and the leftover buffer is empty */ - _set(s->leftover, 0, TC_AES_BLOCK_SIZE); - s->leftover_offset = 0; - - /* Set countdown to max number of calls allowed before re-keying: */ - s->countdown = MAX_CALLS; - - return TC_CRYPTO_SUCCESS; -} - -int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t data_length) -{ - unsigned int i; - - /* input sanity check: */ - if (s == (TCCmacState_t) 0) { - return TC_CRYPTO_FAIL; - } - if (data_length == 0) { - return TC_CRYPTO_SUCCESS; - } - if (data == (const uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } - - if (s->countdown == 0) { - return TC_CRYPTO_FAIL; - } - - s->countdown--; - - if (s->leftover_offset > 0) { - /* last data added to s didn't end on a TC_AES_BLOCK_SIZE byte boundary */ - size_t remaining_space = TC_AES_BLOCK_SIZE - s->leftover_offset; - - if (data_length < remaining_space) { - /* still not enough data to encrypt this time either */ - _copy(&s->leftover[s->leftover_offset], data_length, data, data_length); - s->leftover_offset += data_length; - return TC_CRYPTO_SUCCESS; - } - /* leftover block is now full; encrypt it first */ - _copy(&s->leftover[s->leftover_offset], - remaining_space, - data, - remaining_space); - data_length -= remaining_space; - data += remaining_space; - s->leftover_offset = 0; - - for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) { - s->iv[i] ^= s->leftover[i]; - } - tc_aes_encrypt(s->iv, s->iv, s->sched); - } - - /* CBC encrypt each (except the last) of the data blocks */ - while (data_length > TC_AES_BLOCK_SIZE) { - for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) { - s->iv[i] ^= data[i]; - } - tc_aes_encrypt(s->iv, s->iv, s->sched); - data += TC_AES_BLOCK_SIZE; - data_length -= TC_AES_BLOCK_SIZE; - } - - if (data_length > 0) { - /* save leftover data for next time */ - _copy(s->leftover, data_length, data, data_length); - s->leftover_offset = data_length; - } - - return TC_CRYPTO_SUCCESS; -} - -int tc_cmac_final(uint8_t *tag, TCCmacState_t s) -{ - uint8_t *k; - unsigned int i; - - /* input sanity check: */ - if (tag == (uint8_t *) 0 || - s == (TCCmacState_t) 0) { - return TC_CRYPTO_FAIL; - } - - if (s->leftover_offset == TC_AES_BLOCK_SIZE) { - /* the last message block is a full-sized block */ - k = (uint8_t *) s->K1; - } else { - /* the final message block is not a full-sized block */ - size_t remaining = TC_AES_BLOCK_SIZE - s->leftover_offset; - - _set(&s->leftover[s->leftover_offset], 0, remaining); - s->leftover[s->leftover_offset] = TC_CMAC_PADDING; - k = (uint8_t *) s->K2; - } - for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) { - s->iv[i] ^= s->leftover[i] ^ k[i]; - } - - tc_aes_encrypt(tag, s->iv, s->sched); - - /* erasing state: */ - tc_cmac_erase(s); - - return TC_CRYPTO_SUCCESS; -} diff --git a/lib/bt/porting/ext/tinycrypt/src/ctr_mode.c b/lib/bt/porting/ext/tinycrypt/src/ctr_mode.c deleted file mode 100644 index 1dfb92df..00000000 --- a/lib/bt/porting/ext/tinycrypt/src/ctr_mode.c +++ /dev/null @@ -1,85 +0,0 @@ -/* ctr_mode.c - TinyCrypt CTR mode implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched) -{ - - uint8_t buffer[TC_AES_BLOCK_SIZE]; - uint8_t nonce[TC_AES_BLOCK_SIZE]; - unsigned int block_num; - unsigned int i; - - /* input sanity check: */ - if (out == (uint8_t *) 0 || - in == (uint8_t *) 0 || - ctr == (uint8_t *) 0 || - sched == (TCAesKeySched_t) 0 || - inlen == 0 || - outlen == 0 || - outlen != inlen) { - return TC_CRYPTO_FAIL; - } - - /* copy the ctr to the nonce */ - (void)_copy(nonce, sizeof(nonce), ctr, sizeof(nonce)); - - /* select the last 4 bytes of the nonce to be incremented */ - block_num = (nonce[12] << 24) | (nonce[13] << 16) | - (nonce[14] << 8) | (nonce[15]); - for (i = 0; i < inlen; ++i) { - if ((i % (TC_AES_BLOCK_SIZE)) == 0) { - /* encrypt data using the current nonce */ - if (tc_aes_encrypt(buffer, nonce, sched)) { - block_num++; - nonce[12] = (uint8_t)(block_num >> 24); - nonce[13] = (uint8_t)(block_num >> 16); - nonce[14] = (uint8_t)(block_num >> 8); - nonce[15] = (uint8_t)(block_num); - } else { - return TC_CRYPTO_FAIL; - } - } - /* update the output */ - *out++ = buffer[i%(TC_AES_BLOCK_SIZE)] ^ *in++; - } - - /* update the counter */ - ctr[12] = nonce[12]; ctr[13] = nonce[13]; - ctr[14] = nonce[14]; ctr[15] = nonce[15]; - - return TC_CRYPTO_SUCCESS; -} diff --git a/lib/bt/porting/ext/tinycrypt/src/ctr_prng.c b/lib/bt/porting/ext/tinycrypt/src/ctr_prng.c deleted file mode 100644 index 5090c397..00000000 --- a/lib/bt/porting/ext/tinycrypt/src/ctr_prng.c +++ /dev/null @@ -1,279 +0,0 @@ -/* ctr_prng.c - TinyCrypt implementation of CTR-PRNG */ - -/* - * Copyright (c) 2016, Chris Morrison - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -/* - * This PRNG is based on the CTR_DRBG described in Recommendation for Random - * Number Generation Using Deterministic Random Bit Generators, - * NIST SP 800-90A Rev. 1. - * - * Annotations to particular steps (e.g. 10.2.1.2 Step 1) refer to the steps - * described in that document. - * - */ - -/** - * @brief Array incrementer - * Treats the supplied array as one contiguous number (MSB in arr[0]), and - * increments it by one - * @return none - * @param arr IN/OUT -- array to be incremented - * @param len IN -- size of arr in bytes - */ -static void arrInc(uint8_t arr[], unsigned int len) -{ - unsigned int i; - if (0 != arr) { - for (i = len; i > 0U; i--) { - if (++arr[i-1] != 0U) { - break; - } - } - } -} - -/** - * @brief CTR PRNG update - * Updates the internal state of supplied the CTR PRNG context - * increments it by one - * @return none - * @note Assumes: providedData is (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes long - * @param ctx IN/OUT -- CTR PRNG state - * @param providedData IN -- data used when updating the internal state - */ -static void tc_ctr_prng_update(TCCtrPrng_t * const ctx, uint8_t const * const providedData) -{ - if (0 != ctx) { - /* 10.2.1.2 step 1 */ - uint8_t temp[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE]; - unsigned int len = 0U; - - /* 10.2.1.2 step 2 */ - while (len < sizeof temp) { - unsigned int blocklen = sizeof(temp) - len; - uint8_t output_block[TC_AES_BLOCK_SIZE]; - - /* 10.2.1.2 step 2.1 */ - arrInc(ctx->V, sizeof ctx->V); - - /* 10.2.1.2 step 2.2 */ - if (blocklen > TC_AES_BLOCK_SIZE) { - blocklen = TC_AES_BLOCK_SIZE; - } - (void)tc_aes_encrypt(output_block, ctx->V, &ctx->key); - - /* 10.2.1.2 step 2.3/step 3 */ - memcpy(&(temp[len]), output_block, blocklen); - - len += blocklen; - } - - /* 10.2.1.2 step 4 */ - if (0 != providedData) { - unsigned int i; - for (i = 0U; i < sizeof temp; i++) { - temp[i] ^= providedData[i]; - } - } - - /* 10.2.1.2 step 5 */ - (void)tc_aes128_set_encrypt_key(&ctx->key, temp); - - /* 10.2.1.2 step 6 */ - memcpy(ctx->V, &(temp[TC_AES_KEY_SIZE]), TC_AES_BLOCK_SIZE); - } -} - -int tc_ctr_prng_init(TCCtrPrng_t * const ctx, - uint8_t const * const entropy, - unsigned int entropyLen, - uint8_t const * const personalization, - unsigned int pLen) -{ - int result = TC_CRYPTO_FAIL; - unsigned int i; - uint8_t personalization_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U}; - uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE]; - uint8_t zeroArr[TC_AES_BLOCK_SIZE] = {0U}; - - if (0 != personalization) { - /* 10.2.1.3.1 step 1 */ - unsigned int len = pLen; - if (len > sizeof personalization_buf) { - len = sizeof personalization_buf; - } - - /* 10.2.1.3.1 step 2 */ - memcpy(personalization_buf, personalization, len); - } - - if ((0 != ctx) && (0 != entropy) && (entropyLen >= sizeof seed_material)) { - /* 10.2.1.3.1 step 3 */ - memcpy(seed_material, entropy, sizeof seed_material); - for (i = 0U; i < sizeof seed_material; i++) { - seed_material[i] ^= personalization_buf[i]; - } - - /* 10.2.1.3.1 step 4 */ - (void)tc_aes128_set_encrypt_key(&ctx->key, zeroArr); - - /* 10.2.1.3.1 step 5 */ - memset(ctx->V, 0x00, sizeof ctx->V); - - /* 10.2.1.3.1 step 6 */ - tc_ctr_prng_update(ctx, seed_material); - - /* 10.2.1.3.1 step 7 */ - ctx->reseedCount = 1U; - - result = TC_CRYPTO_SUCCESS; - } - return result; -} - -int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx, - uint8_t const * const entropy, - unsigned int entropyLen, - uint8_t const * const additional_input, - unsigned int additionallen) -{ - unsigned int i; - int result = TC_CRYPTO_FAIL; - uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U}; - uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE]; - - if (0 != additional_input) { - /* 10.2.1.4.1 step 1 */ - unsigned int len = additionallen; - if (len > sizeof additional_input_buf) { - len = sizeof additional_input_buf; - } - - /* 10.2.1.4.1 step 2 */ - memcpy(additional_input_buf, additional_input, len); - } - - unsigned int seedlen = (unsigned int)TC_AES_KEY_SIZE + (unsigned int)TC_AES_BLOCK_SIZE; - if ((0 != ctx) && (entropyLen >= seedlen)) { - /* 10.2.1.4.1 step 3 */ - memcpy(seed_material, entropy, sizeof seed_material); - for (i = 0U; i < sizeof seed_material; i++) { - seed_material[i] ^= additional_input_buf[i]; - } - - /* 10.2.1.4.1 step 4 */ - tc_ctr_prng_update(ctx, seed_material); - - /* 10.2.1.4.1 step 5 */ - ctx->reseedCount = 1U; - - result = TC_CRYPTO_SUCCESS; - } - return result; -} - -int tc_ctr_prng_generate(TCCtrPrng_t * const ctx, - uint8_t const * const additional_input, - unsigned int additionallen, - uint8_t * const out, - unsigned int outlen) -{ - /* 2^48 - see section 10.2.1 */ - static const uint64_t MAX_REQS_BEFORE_RESEED = 0x1000000000000ULL; - - /* 2^19 bits - see section 10.2.1 */ - static const unsigned int MAX_BYTES_PER_REQ = 65536U; - - unsigned int result = TC_CRYPTO_FAIL; - - if ((0 != ctx) && (0 != out) && (outlen < MAX_BYTES_PER_REQ)) { - /* 10.2.1.5.1 step 1 */ - if (ctx->reseedCount > MAX_REQS_BEFORE_RESEED) { - result = TC_CTR_PRNG_RESEED_REQ; - } else { - uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U}; - if (0 != additional_input) { - /* 10.2.1.5.1 step 2 */ - unsigned int len = additionallen; - if (len > sizeof additional_input_buf) { - len = sizeof additional_input_buf; - } - memcpy(additional_input_buf, additional_input, len); - tc_ctr_prng_update(ctx, additional_input_buf); - } - - /* 10.2.1.5.1 step 3 - implicit */ - - /* 10.2.1.5.1 step 4 */ - unsigned int len = 0U; - while (len < outlen) { - unsigned int blocklen = outlen - len; - uint8_t output_block[TC_AES_BLOCK_SIZE]; - - /* 10.2.1.5.1 step 4.1 */ - arrInc(ctx->V, sizeof ctx->V); - - /* 10.2.1.5.1 step 4.2 */ - (void)tc_aes_encrypt(output_block, ctx->V, &ctx->key); - - /* 10.2.1.5.1 step 4.3/step 5 */ - if (blocklen > TC_AES_BLOCK_SIZE) { - blocklen = TC_AES_BLOCK_SIZE; - } - memcpy(&(out[len]), output_block, blocklen); - - len += blocklen; - } - - /* 10.2.1.5.1 step 6 */ - tc_ctr_prng_update(ctx, additional_input_buf); - - /* 10.2.1.5.1 step 7 */ - ctx->reseedCount++; - - /* 10.2.1.5.1 step 8 */ - result = TC_CRYPTO_SUCCESS; - } - } - - return result; -} - -void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx) -{ - if (0 != ctx) { - memset(ctx->key.words, 0x00, sizeof ctx->key.words); - memset(ctx->V, 0x00, sizeof ctx->V); - ctx->reseedCount = 0U; - } -} diff --git a/lib/bt/porting/ext/tinycrypt/src/ecc.c b/lib/bt/porting/ext/tinycrypt/src/ecc.c deleted file mode 100644 index 03d9187f..00000000 --- a/lib/bt/porting/ext/tinycrypt/src/ecc.c +++ /dev/null @@ -1,939 +0,0 @@ -/* ecc.c - TinyCrypt implementation of common ECC functions */ - -/* - * Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform - * has access to enough entropy in order to feed the PRNG regularly. */ -#if default_RNG_defined -static uECC_RNG_Function g_rng_function = &default_CSPRNG; -#else -static uECC_RNG_Function g_rng_function = 0; -#endif - -void uECC_set_rng(uECC_RNG_Function rng_function) -{ - g_rng_function = rng_function; -} - -uECC_RNG_Function uECC_get_rng(void) -{ - return g_rng_function; -} - -int uECC_curve_private_key_size(uECC_Curve curve) -{ - return BITS_TO_BYTES(curve->num_n_bits); -} - -int uECC_curve_public_key_size(uECC_Curve curve) -{ - return 2 * curve->num_bytes; -} - -void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) -{ - wordcount_t i; - for (i = 0; i < num_words; ++i) { - vli[i] = 0; - } -} - -uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words) -{ - uECC_word_t bits = 0; - wordcount_t i; - for (i = 0; i < num_words; ++i) { - bits |= vli[i]; - } - return (bits == 0); -} - -uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit) -{ - return (vli[bit >> uECC_WORD_BITS_SHIFT] & - ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK))); -} - -/* Counts the number of words in vli. */ -static wordcount_t vli_numDigits(const uECC_word_t *vli, - const wordcount_t max_words) -{ - - wordcount_t i; - /* Search from the end until we find a non-zero digit. We do it in reverse - * because we expect that most digits will be nonzero. */ - for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) { - } - - return (i + 1); -} - -bitcount_t uECC_vli_numBits(const uECC_word_t *vli, - const wordcount_t max_words) -{ - - uECC_word_t i; - uECC_word_t digit; - - wordcount_t num_digits = vli_numDigits(vli, max_words); - if (num_digits == 0) { - return 0; - } - - digit = vli[num_digits - 1]; - for (i = 0; digit; ++i) { - digit >>= 1; - } - - return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i); -} - -void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, - wordcount_t num_words) -{ - wordcount_t i; - - for (i = 0; i < num_words; ++i) { - dest[i] = src[i]; - } -} - -cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, - const uECC_word_t *right, - wordcount_t num_words) -{ - wordcount_t i; - - for (i = num_words - 1; i >= 0; --i) { - if (left[i] > right[i]) { - return 1; - } else if (left[i] < right[i]) { - return -1; - } - } - return 0; -} - -uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right, - wordcount_t num_words) -{ - - uECC_word_t diff = 0; - wordcount_t i; - - for (i = num_words - 1; i >= 0; --i) { - diff |= (left[i] ^ right[i]); - } - return !(diff == 0); -} - -uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond) -{ - return (p_true*(cond)) | (p_false*(!cond)); -} - -/* Computes result = left - right, returning borrow, in constant time. - * Can modify in place. */ -uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, wordcount_t num_words) -{ - uECC_word_t borrow = 0; - wordcount_t i; - for (i = 0; i < num_words; ++i) { - uECC_word_t diff = left[i] - right[i] - borrow; - uECC_word_t val = (diff > left[i]); - borrow = cond_set(val, borrow, (diff != left[i])); - - result[i] = diff; - } - return borrow; -} - -/* Computes result = left + right, returning carry, in constant time. - * Can modify in place. */ -static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, wordcount_t num_words) -{ - uECC_word_t carry = 0; - wordcount_t i; - for (i = 0; i < num_words; ++i) { - uECC_word_t sum = left[i] + right[i] + carry; - uECC_word_t val = (sum < left[i]); - carry = cond_set(val, carry, (sum != left[i])); - result[i] = sum; - } - return carry; -} - -cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, - wordcount_t num_words) -{ - uECC_word_t tmp[NUM_ECC_WORDS]; - uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words); - uECC_word_t equal = uECC_vli_isZero(tmp, num_words); - return (!equal - 2 * neg); -} - -/* Computes vli = vli >> 1. */ -static void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) -{ - uECC_word_t *end = vli; - uECC_word_t carry = 0; - - vli += num_words; - while (vli-- > end) { - uECC_word_t temp = *vli; - *vli = (temp >> 1) | carry; - carry = temp << (uECC_WORD_BITS - 1); - } -} - -static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0, - uECC_word_t *r1, uECC_word_t *r2) -{ - - uECC_dword_t p = (uECC_dword_t)a * b; - uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0; - r01 += p; - *r2 += (r01 < p); - *r1 = r01 >> uECC_WORD_BITS; - *r0 = (uECC_word_t)r01; - -} - -/* Computes result = left * right. Result must be 2 * num_words long. */ -static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, wordcount_t num_words) -{ - - uECC_word_t r0 = 0; - uECC_word_t r1 = 0; - uECC_word_t r2 = 0; - wordcount_t i, k; - - /* Compute each digit of result in sequence, maintaining the carries. */ - for (k = 0; k < num_words; ++k) { - - for (i = 0; i <= k; ++i) { - muladd(left[i], right[k - i], &r0, &r1, &r2); - } - - result[k] = r0; - r0 = r1; - r1 = r2; - r2 = 0; - } - - for (k = num_words; k < num_words * 2 - 1; ++k) { - - for (i = (k + 1) - num_words; i < num_words; ++i) { - muladd(left[i], right[k - i], &r0, &r1, &r2); - } - result[k] = r0; - r0 = r1; - r1 = r2; - r2 = 0; - } - result[num_words * 2 - 1] = r0; -} - -void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod, - wordcount_t num_words) -{ - uECC_word_t carry = uECC_vli_add(result, left, right, num_words); - if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) { - /* result > mod (result = mod + remainder), so subtract mod to get - * remainder. */ - uECC_vli_sub(result, result, mod, num_words); - } -} - -void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod, - wordcount_t num_words) -{ - uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words); - if (l_borrow) { - /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x, - * we can get the correct result from result + mod (with overflow). */ - uECC_vli_add(result, result, mod, num_words); - } -} - -/* Computes result = product % mod, where product is 2N words long. */ -/* Currently only designed to work for curve_p or curve_n. */ -void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, - const uECC_word_t *mod, wordcount_t num_words) -{ - uECC_word_t mod_multiple[2 * NUM_ECC_WORDS]; - uECC_word_t tmp[2 * NUM_ECC_WORDS]; - uECC_word_t *v[2] = {tmp, product}; - uECC_word_t index; - - /* Shift mod so its highest set bit is at the maximum position. */ - bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - - uECC_vli_numBits(mod, num_words); - wordcount_t word_shift = shift / uECC_WORD_BITS; - wordcount_t bit_shift = shift % uECC_WORD_BITS; - uECC_word_t carry = 0; - uECC_vli_clear(mod_multiple, word_shift); - if (bit_shift > 0) { - for(index = 0; index < (uECC_word_t)num_words; ++index) { - mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry; - carry = mod[index] >> (uECC_WORD_BITS - bit_shift); - } - } else { - uECC_vli_set(mod_multiple + word_shift, mod, num_words); - } - - for (index = 1; shift >= 0; --shift) { - uECC_word_t borrow = 0; - wordcount_t i; - for (i = 0; i < num_words * 2; ++i) { - uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow; - if (diff != v[index][i]) { - borrow = (diff > v[index][i]); - } - v[1 - index][i] = diff; - } - /* Swap the index if there was no borrow */ - index = !(index ^ borrow); - uECC_vli_rshift1(mod_multiple, num_words); - mod_multiple[num_words - 1] |= mod_multiple[num_words] << - (uECC_WORD_BITS - 1); - uECC_vli_rshift1(mod_multiple + num_words, num_words); - } - uECC_vli_set(result, v[index], num_words); -} - -void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod, - wordcount_t num_words) -{ - uECC_word_t product[2 * NUM_ECC_WORDS]; - uECC_vli_mult(product, left, right, num_words); - uECC_vli_mmod(result, product, mod, num_words); -} - -void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, uECC_Curve curve) -{ - uECC_word_t product[2 * NUM_ECC_WORDS]; - uECC_vli_mult(product, left, right, curve->num_words); - - curve->mmod_fast(result, product); -} - -static void uECC_vli_modSquare_fast(uECC_word_t *result, - const uECC_word_t *left, - uECC_Curve curve) -{ - uECC_vli_modMult_fast(result, left, left, curve); -} - - -#define EVEN(vli) (!(vli[0] & 1)) - -static void vli_modInv_update(uECC_word_t *uv, - const uECC_word_t *mod, - wordcount_t num_words) -{ - - uECC_word_t carry = 0; - - if (!EVEN(uv)) { - carry = uECC_vli_add(uv, uv, mod, num_words); - } - uECC_vli_rshift1(uv, num_words); - if (carry) { - uv[num_words - 1] |= HIGH_BIT_SET; - } -} - -void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, - const uECC_word_t *mod, wordcount_t num_words) -{ - uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS]; - uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS]; - cmpresult_t cmpResult; - - if (uECC_vli_isZero(input, num_words)) { - uECC_vli_clear(result, num_words); - return; - } - - uECC_vli_set(a, input, num_words); - uECC_vli_set(b, mod, num_words); - uECC_vli_clear(u, num_words); - u[0] = 1; - uECC_vli_clear(v, num_words); - while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) { - if (EVEN(a)) { - uECC_vli_rshift1(a, num_words); - vli_modInv_update(u, mod, num_words); - } else if (EVEN(b)) { - uECC_vli_rshift1(b, num_words); - vli_modInv_update(v, mod, num_words); - } else if (cmpResult > 0) { - uECC_vli_sub(a, a, b, num_words); - uECC_vli_rshift1(a, num_words); - if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) { - uECC_vli_add(u, u, mod, num_words); - } - uECC_vli_sub(u, u, v, num_words); - vli_modInv_update(u, mod, num_words); - } else { - uECC_vli_sub(b, b, a, num_words); - uECC_vli_rshift1(b, num_words); - if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) { - uECC_vli_add(v, v, mod, num_words); - } - uECC_vli_sub(v, v, u, num_words); - vli_modInv_update(v, mod, num_words); - } - } - uECC_vli_set(result, u, num_words); -} - -/* ------ Point operations ------ */ - -void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, - uECC_word_t * Z1, uECC_Curve curve) -{ - /* t1 = X, t2 = Y, t3 = Z */ - uECC_word_t t4[NUM_ECC_WORDS]; - uECC_word_t t5[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; - - if (uECC_vli_isZero(Z1, num_words)) { - return; - } - - uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */ - uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */ - uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */ - uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */ - uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */ - - uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */ - uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */ - uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */ - uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */ - - uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */ - uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */ - if (uECC_vli_testBit(X1, 0)) { - uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words); - uECC_vli_rshift1(X1, num_words); - X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1); - } else { - uECC_vli_rshift1(X1, num_words); - } - - /* t1 = 3/2*(x1^2 - z1^4) = B */ - uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */ - uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */ - uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */ - uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */ - uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */ - /* t4 = B * (A - x3) - y1^4 = y3: */ - uECC_vli_modSub(t4, X1, t4, curve->p, num_words); - - uECC_vli_set(X1, Z1, num_words); - uECC_vli_set(Z1, Y1, num_words); - uECC_vli_set(Y1, t4, num_words); -} - -void x_side_default(uECC_word_t *result, - const uECC_word_t *x, - uECC_Curve curve) -{ - uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */ - wordcount_t num_words = curve->num_words; - - uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */ - uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */ - uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */ - /* r = x^3 - 3x + b: */ - uECC_vli_modAdd(result, result, curve->b, curve->p, num_words); -} - -uECC_Curve uECC_secp256r1(void) -{ - return &curve_secp256r1; -} - -void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) -{ - unsigned int tmp[NUM_ECC_WORDS]; - int carry; - - /* t */ - uECC_vli_set(result, product, NUM_ECC_WORDS); - - /* s1 */ - tmp[0] = tmp[1] = tmp[2] = 0; - tmp[3] = product[11]; - tmp[4] = product[12]; - tmp[5] = product[13]; - tmp[6] = product[14]; - tmp[7] = product[15]; - carry = uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS); - carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); - - /* s2 */ - tmp[3] = product[12]; - tmp[4] = product[13]; - tmp[5] = product[14]; - tmp[6] = product[15]; - tmp[7] = 0; - carry += uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS); - carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); - - /* s3 */ - tmp[0] = product[8]; - tmp[1] = product[9]; - tmp[2] = product[10]; - tmp[3] = tmp[4] = tmp[5] = 0; - tmp[6] = product[14]; - tmp[7] = product[15]; - carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); - - /* s4 */ - tmp[0] = product[9]; - tmp[1] = product[10]; - tmp[2] = product[11]; - tmp[3] = product[13]; - tmp[4] = product[14]; - tmp[5] = product[15]; - tmp[6] = product[13]; - tmp[7] = product[8]; - carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); - - /* d1 */ - tmp[0] = product[11]; - tmp[1] = product[12]; - tmp[2] = product[13]; - tmp[3] = tmp[4] = tmp[5] = 0; - tmp[6] = product[8]; - tmp[7] = product[10]; - carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); - - /* d2 */ - tmp[0] = product[12]; - tmp[1] = product[13]; - tmp[2] = product[14]; - tmp[3] = product[15]; - tmp[4] = tmp[5] = 0; - tmp[6] = product[9]; - tmp[7] = product[11]; - carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); - - /* d3 */ - tmp[0] = product[13]; - tmp[1] = product[14]; - tmp[2] = product[15]; - tmp[3] = product[8]; - tmp[4] = product[9]; - tmp[5] = product[10]; - tmp[6] = 0; - tmp[7] = product[12]; - carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); - - /* d4 */ - tmp[0] = product[14]; - tmp[1] = product[15]; - tmp[2] = 0; - tmp[3] = product[9]; - tmp[4] = product[10]; - tmp[5] = product[11]; - tmp[6] = 0; - tmp[7] = product[13]; - carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); - - if (carry < 0) { - do { - carry += uECC_vli_add(result, result, curve_secp256r1.p, NUM_ECC_WORDS); - } - while (carry < 0); - } else { - while (carry || - uECC_vli_cmp_unsafe(curve_secp256r1.p, result, NUM_ECC_WORDS) != 1) { - carry -= uECC_vli_sub(result, result, curve_secp256r1.p, NUM_ECC_WORDS); - } - } -} - -uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve) -{ - return uECC_vli_isZero(point, curve->num_words * 2); -} - -void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z, - uECC_Curve curve) -{ - uECC_word_t t1[NUM_ECC_WORDS]; - - uECC_vli_modSquare_fast(t1, Z, curve); /* z^2 */ - uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */ - uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */ - uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */ -} - -/* P = (x1, y1) => 2P, (x2, y2) => P' */ -static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1, - uECC_word_t * X2, uECC_word_t * Y2, - const uECC_word_t * const initial_Z, - uECC_Curve curve) -{ - uECC_word_t z[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; - if (initial_Z) { - uECC_vli_set(z, initial_Z, num_words); - } else { - uECC_vli_clear(z, num_words); - z[0] = 1; - } - - uECC_vli_set(X2, X1, num_words); - uECC_vli_set(Y2, Y1, num_words); - - apply_z(X1, Y1, z, curve); - curve->double_jacobian(X1, Y1, z, curve); - apply_z(X2, Y2, z, curve); -} - -void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, - uECC_word_t * X2, uECC_word_t * Y2, - uECC_Curve curve) -{ - /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ - uECC_word_t t5[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; - - uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ - uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ - uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ - uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ - uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ - uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */ - - uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */ - uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */ - uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */ - uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */ - uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */ - uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */ - uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */ - - uECC_vli_set(X2, t5, num_words); -} - -/* Input P = (x1, y1, Z), Q = (x2, y2, Z) - Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3) - or P => P - Q, Q => P + Q - */ -static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1, - uECC_word_t * X2, uECC_word_t * Y2, - uECC_Curve curve) -{ - /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ - uECC_word_t t5[NUM_ECC_WORDS]; - uECC_word_t t6[NUM_ECC_WORDS]; - uECC_word_t t7[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; - - uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ - uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ - uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ - uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ - uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */ - uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ - - uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */ - uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */ - uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */ - uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */ - uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */ - - uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */ - uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */ - /* t4 = (y2 - y1)*(B - x3) - E = y3: */ - uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); - - uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */ - uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */ - uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */ - uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */ - /* t2 = (y2+y1)*(x3' - B) - E = y3': */ - uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words); - - uECC_vli_set(X1, t7, num_words); -} - -void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, - const uECC_word_t * scalar, - const uECC_word_t * initial_Z, - bitcount_t num_bits, uECC_Curve curve) -{ - /* R0 and R1 */ - uECC_word_t Rx[2][NUM_ECC_WORDS]; - uECC_word_t Ry[2][NUM_ECC_WORDS]; - uECC_word_t z[NUM_ECC_WORDS]; - bitcount_t i; - uECC_word_t nb; - wordcount_t num_words = curve->num_words; - - uECC_vli_set(Rx[1], point, num_words); - uECC_vli_set(Ry[1], point + num_words, num_words); - - XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve); - - for (i = num_bits - 2; i > 0; --i) { - nb = !uECC_vli_testBit(scalar, i); - XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); - XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); - } - - nb = !uECC_vli_testBit(scalar, 0); - XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); - - /* Find final 1/Z value. */ - uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */ - uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */ - uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */ - uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0))*/ - /* yP / (xP * Yb * (X1 - X0)) */ - uECC_vli_modMult_fast(z, z, point + num_words, curve); - /* Xb * yP / (xP * Yb * (X1 - X0)) */ - uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve); - /* End 1/Z calculation */ - - XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); - apply_z(Rx[0], Ry[0], z, curve); - - uECC_vli_set(result, Rx[0], num_words); - uECC_vli_set(result + num_words, Ry[0], num_words); -} - -uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, - uECC_word_t *k1, uECC_Curve curve) -{ - - wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); - - bitcount_t num_n_bits = curve->num_n_bits; - - uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) || - (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) && - uECC_vli_testBit(k0, num_n_bits)); - - uECC_vli_add(k1, k0, curve->n, num_n_words); - - return carry; -} - -uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, - uECC_word_t *private_key, - uECC_Curve curve) -{ - - uECC_word_t tmp1[NUM_ECC_WORDS]; - uECC_word_t tmp2[NUM_ECC_WORDS]; - uECC_word_t *p2[2] = {tmp1, tmp2}; - uECC_word_t carry; - - /* Regularize the bitcount for the private key so that attackers cannot - * use a side channel attack to learn the number of leading zeros. */ - carry = regularize_k(private_key, tmp1, tmp2, curve); - - EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve); - - if (EccPoint_isZero(result, curve)) { - return 0; - } - return 1; -} - -/* Converts an integer in uECC native format to big-endian bytes. */ -void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, - const unsigned int *native) -{ - wordcount_t i; - for (i = 0; i < num_bytes; ++i) { - unsigned b = num_bytes - 1 - i; - bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)); - } -} - -/* Converts big-endian bytes to an integer in uECC native format. */ -void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes, - int num_bytes) -{ - wordcount_t i; - uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE); - for (i = 0; i < num_bytes; ++i) { - unsigned b = num_bytes - 1 - i; - native[b / uECC_WORD_SIZE] |= - (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE)); - } -} - -int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, - wordcount_t num_words) -{ - uECC_word_t mask = (uECC_word_t)-1; - uECC_word_t tries; - bitcount_t num_bits = uECC_vli_numBits(top, num_words); - - if (!g_rng_function) { - return 0; - } - - for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { - if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) { - return 0; - } - random[num_words - 1] &= - mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); - if (!uECC_vli_isZero(random, num_words) && - uECC_vli_cmp(top, random, num_words) == 1) { - return 1; - } - } - return 0; -} - - -int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) -{ - uECC_word_t tmp1[NUM_ECC_WORDS]; - uECC_word_t tmp2[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; - - /* The point at infinity is invalid. */ - if (EccPoint_isZero(point, curve)) { - return -1; - } - - /* x and y must be smaller than p. */ - if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 || - uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) { - return -2; - } - - uECC_vli_modSquare_fast(tmp1, point + num_words, curve); - curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */ - - /* Make sure that y^2 == x^3 + ax + b */ - if (uECC_vli_equal(tmp1, tmp2, num_words) != 0) - return -3; - - return 0; -} - -int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve) -{ - - uECC_word_t _public[NUM_ECC_WORDS * 2]; - - uECC_vli_bytesToNative(_public, public_key, curve->num_bytes); - uECC_vli_bytesToNative( - _public + curve->num_words, - public_key + curve->num_bytes, - curve->num_bytes); - - if (uECC_vli_cmp_unsafe(_public, curve->G, NUM_ECC_WORDS * 2) == 0) { - return -4; - } - - return uECC_valid_point(_public, curve); -} - -int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, - uECC_Curve curve) -{ - - uECC_word_t _private[NUM_ECC_WORDS]; - uECC_word_t _public[NUM_ECC_WORDS * 2]; - - uECC_vli_bytesToNative( - _private, - private_key, - BITS_TO_BYTES(curve->num_n_bits)); - - /* Make sure the private key is in the range [1, n-1]. */ - if (uECC_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) { - return 0; - } - - if (uECC_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) != 1) { - return 0; - } - - /* Compute public key. */ - if (!EccPoint_compute_public_key(_public, _private, curve)) { - return 0; - } - - uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public); - uECC_vli_nativeToBytes( - public_key + - curve->num_bytes, curve->num_bytes, _public + curve->num_words); - return 1; -} diff --git a/lib/bt/porting/ext/tinycrypt/src/ecc_dh.c b/lib/bt/porting/ext/tinycrypt/src/ecc_dh.c deleted file mode 100644 index ecd8df3b..00000000 --- a/lib/bt/porting/ext/tinycrypt/src/ecc_dh.c +++ /dev/null @@ -1,200 +0,0 @@ -/* ec_dh.c - TinyCrypt implementation of EC-DH */ - -/* - * Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include -#include -#include -#include - -#if default_RNG_defined -static uECC_RNG_Function g_rng_function = &default_CSPRNG; -#else -static uECC_RNG_Function g_rng_function = 0; -#endif - -int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key, - unsigned int *d, uECC_Curve curve) -{ - - uECC_word_t _private[NUM_ECC_WORDS]; - uECC_word_t _public[NUM_ECC_WORDS * 2]; - - /* This function is designed for test purposes-only (such as validating NIST - * test vectors) as it uses a provided value for d instead of generating - * it uniformly at random. */ - memcpy (_private, d, NUM_ECC_BYTES); - - /* Computing public-key from private: */ - if (EccPoint_compute_public_key(_public, _private, curve)) { - - /* Converting buffers to correct bit order: */ - uECC_vli_nativeToBytes(private_key, - BITS_TO_BYTES(curve->num_n_bits), - _private); - uECC_vli_nativeToBytes(public_key, - curve->num_bytes, - _public); - uECC_vli_nativeToBytes(public_key + curve->num_bytes, - curve->num_bytes, - _public + curve->num_words); - - /* erasing temporary buffer used to store secret: */ - memset(_private, 0, NUM_ECC_BYTES); - - return 1; - } - return 0; -} - -int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve) -{ - - uECC_word_t _random[NUM_ECC_WORDS * 2]; - uECC_word_t _private[NUM_ECC_WORDS]; - uECC_word_t _public[NUM_ECC_WORDS * 2]; - uECC_word_t tries; - - for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { - /* Generating _private uniformly at random: */ - uECC_RNG_Function rng_function = uECC_get_rng(); - if (!rng_function || - !rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS*uECC_WORD_SIZE)) { - return 0; - } - - /* computing modular reduction of _random (see FIPS 186.4 B.4.1): */ - uECC_vli_mmod(_private, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits)); - - /* Computing public-key from private: */ - if (EccPoint_compute_public_key(_public, _private, curve)) { - - /* Converting buffers to correct bit order: */ - uECC_vli_nativeToBytes(private_key, - BITS_TO_BYTES(curve->num_n_bits), - _private); - uECC_vli_nativeToBytes(public_key, - curve->num_bytes, - _public); - uECC_vli_nativeToBytes(public_key + curve->num_bytes, - curve->num_bytes, - _public + curve->num_words); - - /* erasing temporary buffer that stored secret: */ - memset(_private, 0, NUM_ECC_BYTES); - - return 1; - } - } - return 0; -} - -int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, - uint8_t *secret, uECC_Curve curve) -{ - - uECC_word_t _public[NUM_ECC_WORDS * 2]; - uECC_word_t _private[NUM_ECC_WORDS]; - - uECC_word_t tmp[NUM_ECC_WORDS]; - uECC_word_t *p2[2] = {_private, tmp}; - uECC_word_t *initial_Z = 0; - uECC_word_t carry; - wordcount_t num_words = curve->num_words; - wordcount_t num_bytes = curve->num_bytes; - int r; - - /* Converting buffers to correct bit order: */ - uECC_vli_bytesToNative(_private, - private_key, - BITS_TO_BYTES(curve->num_n_bits)); - uECC_vli_bytesToNative(_public, - public_key, - num_bytes); - uECC_vli_bytesToNative(_public + num_words, - public_key + num_bytes, - num_bytes); - - /* Regularize the bitcount for the private key so that attackers cannot use a - * side channel attack to learn the number of leading zeros. */ - carry = regularize_k(_private, _private, tmp, curve); - - /* If an RNG function was specified, try to get a random initial Z value to - * improve protection against side-channel attacks. */ - if (g_rng_function) { - if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) { - r = 0; - goto clear_and_out; - } - initial_Z = p2[carry]; - } - - EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1, - curve); - - uECC_vli_nativeToBytes(secret, num_bytes, _public); - r = !EccPoint_isZero(_public, curve); - -clear_and_out: - /* erasing temporary buffer used to store secret: */ - memset(p2, 0, sizeof(p2)); - __asm__ __volatile__("" :: "g"(p2) : "memory"); - memset(tmp, 0, sizeof(tmp)); - __asm__ __volatile__("" :: "g"(tmp) : "memory"); - memset(_private, 0, sizeof(_private)); - __asm__ __volatile__("" :: "g"(_private) : "memory"); - - return r; -} diff --git a/lib/bt/porting/ext/tinycrypt/src/ecc_dsa.c b/lib/bt/porting/ext/tinycrypt/src/ecc_dsa.c deleted file mode 100644 index 02424d4e..00000000 --- a/lib/bt/porting/ext/tinycrypt/src/ecc_dsa.c +++ /dev/null @@ -1,294 +0,0 @@ -/* ec_dsa.c - TinyCrypt implementation of EC-DSA */ - -/* Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE.*/ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -#if default_RNG_defined -static uECC_RNG_Function g_rng_function = &default_CSPRNG; -#else -static uECC_RNG_Function g_rng_function = 0; -#endif - -static void bits2int(uECC_word_t *native, const uint8_t *bits, - unsigned bits_size, uECC_Curve curve) -{ - unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits); - unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits); - int shift; - uECC_word_t carry; - uECC_word_t *ptr; - - if (bits_size > num_n_bytes) { - bits_size = num_n_bytes; - } - - uECC_vli_clear(native, num_n_words); - uECC_vli_bytesToNative(native, bits, bits_size); - if (bits_size * 8 <= (unsigned)curve->num_n_bits) { - return; - } - shift = bits_size * 8 - curve->num_n_bits; - carry = 0; - ptr = native + num_n_words; - while (ptr-- > native) { - uECC_word_t temp = *ptr; - *ptr = (temp >> shift) | carry; - carry = temp << (uECC_WORD_BITS - shift); - } - - /* Reduce mod curve_n */ - if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) { - uECC_vli_sub(native, native, curve->n, num_n_words); - } -} - -int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, - unsigned hash_size, uECC_word_t *k, uint8_t *signature, - uECC_Curve curve) -{ - - uECC_word_t tmp[NUM_ECC_WORDS]; - uECC_word_t s[NUM_ECC_WORDS]; - uECC_word_t *k2[2] = {tmp, s}; - uECC_word_t p[NUM_ECC_WORDS * 2]; - uECC_word_t carry; - wordcount_t num_words = curve->num_words; - wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); - bitcount_t num_n_bits = curve->num_n_bits; - - /* Make sure 0 < k < curve_n */ - if (uECC_vli_isZero(k, num_words) || - uECC_vli_cmp(curve->n, k, num_n_words) != 1) { - return 0; - } - - carry = regularize_k(k, tmp, s, curve); - EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve); - if (uECC_vli_isZero(p, num_words)) { - return 0; - } - - /* If an RNG function was specified, get a random number - to prevent side channel analysis of k. */ - if (!g_rng_function) { - uECC_vli_clear(tmp, num_n_words); - tmp[0] = 1; - } - else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) { - return 0; - } - - /* Prevent side channel analysis of uECC_vli_modInv() to determine - bits of k / the private key by premultiplying by a random number */ - uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */ - uECC_vli_modInv(k, k, curve->n, num_n_words); /* k = 1 / k' */ - uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */ - - uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */ - - /* tmp = d: */ - uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits)); - - s[num_n_words - 1] = 0; - uECC_vli_set(s, p, num_words); - uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */ - - bits2int(tmp, message_hash, hash_size, curve); - uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */ - uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */ - if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) { - return 0; - } - - uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s); - return 1; -} - -int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash, - unsigned hash_size, uint8_t *signature, uECC_Curve curve) -{ - uECC_word_t _random[2*NUM_ECC_WORDS]; - uECC_word_t k[NUM_ECC_WORDS]; - uECC_word_t tries; - - for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { - /* Generating _random uniformly at random: */ - uECC_RNG_Function rng_function = uECC_get_rng(); - if (!rng_function || - !rng_function((uint8_t *)_random, 2*NUM_ECC_WORDS*uECC_WORD_SIZE)) { - return 0; - } - - // computing k as modular reduction of _random (see FIPS 186.4 B.5.1): - uECC_vli_mmod(k, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits)); - - if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature, - curve)) { - return 1; - } - } - return 0; -} - -static bitcount_t smax(bitcount_t a, bitcount_t b) -{ - return (a > b ? a : b); -} - -int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, - unsigned hash_size, const uint8_t *signature, - uECC_Curve curve) -{ - - uECC_word_t u1[NUM_ECC_WORDS], u2[NUM_ECC_WORDS]; - uECC_word_t z[NUM_ECC_WORDS]; - uECC_word_t sum[NUM_ECC_WORDS * 2]; - uECC_word_t rx[NUM_ECC_WORDS]; - uECC_word_t ry[NUM_ECC_WORDS]; - uECC_word_t tx[NUM_ECC_WORDS]; - uECC_word_t ty[NUM_ECC_WORDS]; - uECC_word_t tz[NUM_ECC_WORDS]; - const uECC_word_t *points[4]; - const uECC_word_t *point; - bitcount_t num_bits; - bitcount_t i; - - uECC_word_t _public[NUM_ECC_WORDS * 2]; - uECC_word_t r[NUM_ECC_WORDS], s[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; - wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); - - rx[num_n_words - 1] = 0; - r[num_n_words - 1] = 0; - s[num_n_words - 1] = 0; - - uECC_vli_bytesToNative(_public, public_key, curve->num_bytes); - uECC_vli_bytesToNative(_public + num_words, public_key + curve->num_bytes, - curve->num_bytes); - uECC_vli_bytesToNative(r, signature, curve->num_bytes); - uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes); - - /* r, s must not be 0. */ - if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) { - return 0; - } - - /* r, s must be < n. */ - if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 || - uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) { - return 0; - } - - /* Calculate u1 and u2. */ - uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */ - u1[num_n_words - 1] = 0; - bits2int(u1, message_hash, hash_size, curve); - uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */ - uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */ - - /* Calculate sum = G + Q. */ - uECC_vli_set(sum, _public, num_words); - uECC_vli_set(sum + num_words, _public + num_words, num_words); - uECC_vli_set(tx, curve->G, num_words); - uECC_vli_set(ty, curve->G + num_words, num_words); - uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */ - XYcZ_add(tx, ty, sum, sum + num_words, curve); - uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */ - apply_z(sum, sum + num_words, z, curve); - - /* Use Shamir's trick to calculate u1*G + u2*Q */ - points[0] = 0; - points[1] = curve->G; - points[2] = _public; - points[3] = sum; - num_bits = smax(uECC_vli_numBits(u1, num_n_words), - uECC_vli_numBits(u2, num_n_words)); - - point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | - ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; - uECC_vli_set(rx, point, num_words); - uECC_vli_set(ry, point + num_words, num_words); - uECC_vli_clear(z, num_words); - z[0] = 1; - - for (i = num_bits - 2; i >= 0; --i) { - uECC_word_t index; - curve->double_jacobian(rx, ry, z, curve); - - index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1); - point = points[index]; - if (point) { - uECC_vli_set(tx, point, num_words); - uECC_vli_set(ty, point + num_words, num_words); - apply_z(tx, ty, z, curve); - uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */ - XYcZ_add(tx, ty, rx, ry, curve); - uECC_vli_modMult_fast(z, z, tz, curve); - } - } - - uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */ - apply_z(rx, ry, z, curve); - - /* v = x1 (mod n) */ - if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) { - uECC_vli_sub(rx, rx, curve->n, num_n_words); - } - - /* Accept only if v == r. */ - return (int)(uECC_vli_equal(rx, r, num_words) == 0); -} diff --git a/lib/bt/porting/ext/tinycrypt/src/ecc_platform_specific.c b/lib/bt/porting/ext/tinycrypt/src/ecc_platform_specific.c deleted file mode 100644 index ca7650d8..00000000 --- a/lib/bt/porting/ext/tinycrypt/src/ecc_platform_specific.c +++ /dev/null @@ -1,104 +0,0 @@ -/* uECC_platform_specific.c - Implementation of platform specific functions*/ - -/* Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE.*/ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * uECC_platform_specific.c -- Implementation of platform specific functions - */ - - -#if defined(unix) || defined(__linux__) || defined(__unix__) || \ - defined(__unix) | (defined(__APPLE__) && defined(__MACH__)) || \ - defined(uECC_POSIX) - -/* Some POSIX-like system with /dev/urandom or /dev/random. */ -#include -#include -#include - -#include - -#ifndef O_CLOEXEC -#define O_CLOEXEC 0 -#endif - -int default_CSPRNG(uint8_t *dest, unsigned int size) { - - /* input sanity check: */ - if (dest == (uint8_t *) 0 || (size <= 0)) - return 0; - - int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); - if (fd == -1) { - fd = open("/dev/random", O_RDONLY | O_CLOEXEC); - if (fd == -1) { - return 0; - } - } - - char *ptr = (char *)dest; - size_t left = (size_t) size; - while (left > 0) { - ssize_t bytes_read = read(fd, ptr, left); - if (bytes_read <= 0) { // read failed - close(fd); - return 0; - } - left -= bytes_read; - ptr += bytes_read; - } - - close(fd); - return 1; -} - -#endif /* platform */ diff --git a/lib/bt/porting/ext/tinycrypt/src/hmac.c b/lib/bt/porting/ext/tinycrypt/src/hmac.c deleted file mode 100644 index 89878cec..00000000 --- a/lib/bt/porting/ext/tinycrypt/src/hmac.c +++ /dev/null @@ -1,148 +0,0 @@ -/* hmac.c - TinyCrypt implementation of the HMAC algorithm */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size) -{ - const uint8_t inner_pad = (uint8_t) 0x36; - const uint8_t outer_pad = (uint8_t) 0x5c; - unsigned int i; - - for (i = 0; i < key_size; ++i) { - key[i] = inner_pad ^ new_key[i]; - key[i + TC_SHA256_BLOCK_SIZE] = outer_pad ^ new_key[i]; - } - for (; i < TC_SHA256_BLOCK_SIZE; ++i) { - key[i] = inner_pad; key[i + TC_SHA256_BLOCK_SIZE] = outer_pad; - } -} - -int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key, - unsigned int key_size) -{ - - /* input sanity check: */ - if (ctx == (TCHmacState_t) 0 || - key == (const uint8_t *) 0 || - key_size == 0) { - return TC_CRYPTO_FAIL; - } - - const uint8_t dummy_key[key_size]; - struct tc_hmac_state_struct dummy_state; - - if (key_size <= TC_SHA256_BLOCK_SIZE) { - /* - * The next three lines consist of dummy calls just to avoid - * certain timing attacks. Without these dummy calls, - * adversaries would be able to learn whether the key_size is - * greater than TC_SHA256_BLOCK_SIZE by measuring the time - * consumed in this process. - */ - (void)tc_sha256_init(&dummy_state.hash_state); - (void)tc_sha256_update(&dummy_state.hash_state, - dummy_key, - key_size); - (void)tc_sha256_final(&dummy_state.key[TC_SHA256_DIGEST_SIZE], - &dummy_state.hash_state); - - /* Actual code for when key_size <= TC_SHA256_BLOCK_SIZE: */ - rekey(ctx->key, key, key_size); - } else { - (void)tc_sha256_init(&ctx->hash_state); - (void)tc_sha256_update(&ctx->hash_state, key, key_size); - (void)tc_sha256_final(&ctx->key[TC_SHA256_DIGEST_SIZE], - &ctx->hash_state); - rekey(ctx->key, - &ctx->key[TC_SHA256_DIGEST_SIZE], - TC_SHA256_DIGEST_SIZE); - } - - return TC_CRYPTO_SUCCESS; -} - -int tc_hmac_init(TCHmacState_t ctx) -{ - - /* input sanity check: */ - if (ctx == (TCHmacState_t) 0) { - return TC_CRYPTO_FAIL; - } - - (void) tc_sha256_init(&ctx->hash_state); - (void) tc_sha256_update(&ctx->hash_state, ctx->key, TC_SHA256_BLOCK_SIZE); - - return TC_CRYPTO_SUCCESS; -} - -int tc_hmac_update(TCHmacState_t ctx, - const void *data, - unsigned int data_length) -{ - - /* input sanity check: */ - if (ctx == (TCHmacState_t) 0) { - return TC_CRYPTO_FAIL; - } - - (void)tc_sha256_update(&ctx->hash_state, data, data_length); - - return TC_CRYPTO_SUCCESS; -} - -int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx) -{ - - /* input sanity check: */ - if (tag == (uint8_t *) 0 || - taglen != TC_SHA256_DIGEST_SIZE || - ctx == (TCHmacState_t) 0) { - return TC_CRYPTO_FAIL; - } - - (void) tc_sha256_final(tag, &ctx->hash_state); - - (void)tc_sha256_init(&ctx->hash_state); - (void)tc_sha256_update(&ctx->hash_state, - &ctx->key[TC_SHA256_BLOCK_SIZE], - TC_SHA256_BLOCK_SIZE); - (void)tc_sha256_update(&ctx->hash_state, tag, TC_SHA256_DIGEST_SIZE); - (void)tc_sha256_final(tag, &ctx->hash_state); - - /* destroy the current state */ - _set(ctx, 0, sizeof(*ctx)); - - return TC_CRYPTO_SUCCESS; -} diff --git a/lib/bt/porting/ext/tinycrypt/src/hmac_prng.c b/lib/bt/porting/ext/tinycrypt/src/hmac_prng.c deleted file mode 100644 index 68b5b1fa..00000000 --- a/lib/bt/porting/ext/tinycrypt/src/hmac_prng.c +++ /dev/null @@ -1,212 +0,0 @@ -/* hmac_prng.c - TinyCrypt implementation of HMAC-PRNG */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -/* - * min bytes in the seed string. - * MIN_SLEN*8 must be at least the expected security level. - */ -static const unsigned int MIN_SLEN = 32; - -/* - * max bytes in the seed string; - * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes). - */ -static const unsigned int MAX_SLEN = UINT32_MAX; - -/* - * max bytes in the personalization string; - * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes). - */ -static const unsigned int MAX_PLEN = UINT32_MAX; - -/* - * max bytes in the additional_info string; - * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes). - */ -static const unsigned int MAX_ALEN = UINT32_MAX; - -/* - * max number of generates between re-seeds; - * TinyCrypt accepts up to (2^32 - 1) which is the maximal value of - * a 32-bit unsigned int variable, while SP800-90A specifies a maximum of 2^48. - */ -static const unsigned int MAX_GENS = UINT32_MAX; - -/* - * maximum bytes per generate call; - * SP800-90A specifies a maximum up to 2^19. - */ -static const unsigned int MAX_OUT = (1 << 19); - -/* - * Assumes: prng != NULL, e != NULL, len >= 0. - */ -static void update(TCHmacPrng_t prng, const uint8_t *e, unsigned int len) -{ - const uint8_t separator0 = 0x00; - const uint8_t separator1 = 0x01; - - /* use current state, e and separator 0 to compute a new prng key: */ - (void)tc_hmac_init(&prng->h); - (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); - (void)tc_hmac_update(&prng->h, &separator0, sizeof(separator0)); - (void)tc_hmac_update(&prng->h, e, len); - (void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h); - /* configure the new prng key into the prng's instance of hmac */ - (void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); - - /* use the new key to compute a new state variable v */ - (void)tc_hmac_init(&prng->h); - (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); - (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h); - - /* use current state, e and separator 1 to compute a new prng key: */ - (void)tc_hmac_init(&prng->h); - (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); - (void)tc_hmac_update(&prng->h, &separator1, sizeof(separator1)); - (void)tc_hmac_update(&prng->h, e, len); - (void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h); - /* configure the new prng key into the prng's instance of hmac */ - (void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); - - /* use the new key to compute a new state variable v */ - (void)tc_hmac_init(&prng->h); - (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); - (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h); -} - -int tc_hmac_prng_init(TCHmacPrng_t prng, - const uint8_t *personalization, - unsigned int plen) -{ - - /* input sanity check: */ - if (prng == (TCHmacPrng_t) 0 || - personalization == (uint8_t *) 0 || - plen > MAX_PLEN) { - return TC_CRYPTO_FAIL; - } - - /* put the generator into a known state: */ - _set(prng->key, 0x00, sizeof(prng->key)); - _set(prng->v, 0x01, sizeof(prng->v)); - tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); - /* update assumes SOME key has been configured into HMAC */ - - update(prng, personalization, plen); - - /* force a reseed before allowing tc_hmac_prng_generate to succeed: */ - prng->countdown = 0; - - return TC_CRYPTO_SUCCESS; -} - -int tc_hmac_prng_reseed(TCHmacPrng_t prng, - const uint8_t *seed, - unsigned int seedlen, - const uint8_t *additional_input, - unsigned int additionallen) -{ - - /* input sanity check: */ - if (prng == (TCHmacPrng_t) 0 || - seed == (const uint8_t *) 0 || - seedlen < MIN_SLEN || - seedlen > MAX_SLEN) { - return TC_CRYPTO_FAIL; - } - - if (additional_input != (const uint8_t *) 0) { - /* - * Abort if additional_input is provided but has inappropriate - * length - */ - if (additionallen == 0 || - additionallen > MAX_ALEN) { - return TC_CRYPTO_FAIL; - } else { - /* call update for the seed and additional_input */ - update(prng, seed, seedlen); - update(prng, additional_input, additionallen); - } - } else { - /* call update only for the seed */ - update(prng, seed, seedlen); - } - - /* ... and enable hmac_prng_generate */ - prng->countdown = MAX_GENS; - - return TC_CRYPTO_SUCCESS; -} - -int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng) -{ - unsigned int bufferlen; - - /* input sanity check: */ - if (out == (uint8_t *) 0 || - prng == (TCHmacPrng_t) 0 || - outlen == 0 || - outlen > MAX_OUT) { - return TC_CRYPTO_FAIL; - } else if (prng->countdown == 0) { - return TC_HMAC_PRNG_RESEED_REQ; - } - - prng->countdown--; - - while (outlen != 0) { - /* operate HMAC in OFB mode to create "random" outputs */ - (void)tc_hmac_init(&prng->h); - (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); - (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h); - - bufferlen = (TC_SHA256_DIGEST_SIZE > outlen) ? - outlen : TC_SHA256_DIGEST_SIZE; - (void)_copy(out, bufferlen, prng->v, bufferlen); - - out += bufferlen; - outlen = (outlen > TC_SHA256_DIGEST_SIZE) ? - (outlen - TC_SHA256_DIGEST_SIZE) : 0; - } - - /* block future PRNG compromises from revealing past state */ - update(prng, prng->v, TC_SHA256_DIGEST_SIZE); - - return TC_CRYPTO_SUCCESS; -} diff --git a/lib/bt/porting/ext/tinycrypt/src/sha256.c b/lib/bt/porting/ext/tinycrypt/src/sha256.c deleted file mode 100644 index b4efd204..00000000 --- a/lib/bt/porting/ext/tinycrypt/src/sha256.c +++ /dev/null @@ -1,217 +0,0 @@ -/* sha256.c - TinyCrypt SHA-256 crypto hash algorithm implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -static void compress(unsigned int *iv, const uint8_t *data); - -int tc_sha256_init(TCSha256State_t s) -{ - /* input sanity check: */ - if (s == (TCSha256State_t) 0) { - return TC_CRYPTO_FAIL; - } - - /* - * Setting the initial state values. - * These values correspond to the first 32 bits of the fractional parts - * of the square roots of the first 8 primes: 2, 3, 5, 7, 11, 13, 17 - * and 19. - */ - _set((uint8_t *) s, 0x00, sizeof(*s)); - s->iv[0] = 0x6a09e667; - s->iv[1] = 0xbb67ae85; - s->iv[2] = 0x3c6ef372; - s->iv[3] = 0xa54ff53a; - s->iv[4] = 0x510e527f; - s->iv[5] = 0x9b05688c; - s->iv[6] = 0x1f83d9ab; - s->iv[7] = 0x5be0cd19; - - return TC_CRYPTO_SUCCESS; -} - -int tc_sha256_update(TCSha256State_t s, const uint8_t *data, size_t datalen) -{ - /* input sanity check: */ - if (s == (TCSha256State_t) 0 || - data == (void *) 0) { - return TC_CRYPTO_FAIL; - } else if (datalen == 0) { - return TC_CRYPTO_SUCCESS; - } - - while (datalen-- > 0) { - s->leftover[s->leftover_offset++] = *(data++); - if (s->leftover_offset >= TC_SHA256_BLOCK_SIZE) { - compress(s->iv, s->leftover); - s->leftover_offset = 0; - s->bits_hashed += (TC_SHA256_BLOCK_SIZE << 3); - } - } - - return TC_CRYPTO_SUCCESS; -} - -int tc_sha256_final(uint8_t *digest, TCSha256State_t s) -{ - unsigned int i; - - /* input sanity check: */ - if (digest == (uint8_t *) 0 || - s == (TCSha256State_t) 0) { - return TC_CRYPTO_FAIL; - } - - s->bits_hashed += (s->leftover_offset << 3); - - s->leftover[s->leftover_offset++] = 0x80; /* always room for one byte */ - if (s->leftover_offset > (sizeof(s->leftover) - 8)) { - /* there is not room for all the padding in this block */ - _set(s->leftover + s->leftover_offset, 0x00, - sizeof(s->leftover) - s->leftover_offset); - compress(s->iv, s->leftover); - s->leftover_offset = 0; - } - - /* add the padding and the length in big-Endian format */ - _set(s->leftover + s->leftover_offset, 0x00, - sizeof(s->leftover) - 8 - s->leftover_offset); - s->leftover[sizeof(s->leftover) - 1] = (uint8_t)(s->bits_hashed); - s->leftover[sizeof(s->leftover) - 2] = (uint8_t)(s->bits_hashed >> 8); - s->leftover[sizeof(s->leftover) - 3] = (uint8_t)(s->bits_hashed >> 16); - s->leftover[sizeof(s->leftover) - 4] = (uint8_t)(s->bits_hashed >> 24); - s->leftover[sizeof(s->leftover) - 5] = (uint8_t)(s->bits_hashed >> 32); - s->leftover[sizeof(s->leftover) - 6] = (uint8_t)(s->bits_hashed >> 40); - s->leftover[sizeof(s->leftover) - 7] = (uint8_t)(s->bits_hashed >> 48); - s->leftover[sizeof(s->leftover) - 8] = (uint8_t)(s->bits_hashed >> 56); - - /* hash the padding and length */ - compress(s->iv, s->leftover); - - /* copy the iv out to digest */ - for (i = 0; i < TC_SHA256_STATE_BLOCKS; ++i) { - unsigned int t = *((unsigned int *) &s->iv[i]); - *digest++ = (uint8_t)(t >> 24); - *digest++ = (uint8_t)(t >> 16); - *digest++ = (uint8_t)(t >> 8); - *digest++ = (uint8_t)(t); - } - - /* destroy the current state */ - _set(s, 0, sizeof(*s)); - - return TC_CRYPTO_SUCCESS; -} - -/* - * Initializing SHA-256 Hash constant words K. - * These values correspond to the first 32 bits of the fractional parts of the - * cube roots of the first 64 primes between 2 and 311. - */ -static const unsigned int k256[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, - 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, - 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, - 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, - 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, - 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -static inline unsigned int ROTR(unsigned int a, unsigned int n) -{ - return (((a) >> n) | ((a) << (32 - n))); -} - -#define Sigma0(a)(ROTR((a), 2) ^ ROTR((a), 13) ^ ROTR((a), 22)) -#define Sigma1(a)(ROTR((a), 6) ^ ROTR((a), 11) ^ ROTR((a), 25)) -#define sigma0(a)(ROTR((a), 7) ^ ROTR((a), 18) ^ ((a) >> 3)) -#define sigma1(a)(ROTR((a), 17) ^ ROTR((a), 19) ^ ((a) >> 10)) - -#define Ch(a, b, c)(((a) & (b)) ^ ((~(a)) & (c))) -#define Maj(a, b, c)(((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c))) - -static inline unsigned int BigEndian(const uint8_t **c) -{ - unsigned int n = 0; - - n = (((unsigned int)(*((*c)++))) << 24); - n |= ((unsigned int)(*((*c)++)) << 16); - n |= ((unsigned int)(*((*c)++)) << 8); - n |= ((unsigned int)(*((*c)++))); - return n; -} - -static void compress(unsigned int *iv, const uint8_t *data) -{ - unsigned int a, b, c, d, e, f, g, h; - unsigned int s0, s1; - unsigned int t1, t2; - unsigned int work_space[16]; - unsigned int n; - unsigned int i; - - a = iv[0]; b = iv[1]; c = iv[2]; d = iv[3]; - e = iv[4]; f = iv[5]; g = iv[6]; h = iv[7]; - - for (i = 0; i < 16; ++i) { - n = BigEndian(&data); - t1 = work_space[i] = n; - t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i]; - t2 = Sigma0(a) + Maj(a, b, c); - h = g; g = f; f = e; e = d + t1; - d = c; c = b; b = a; a = t1 + t2; - } - - for ( ; i < 64; ++i) { - s0 = work_space[(i+1)&0x0f]; - s0 = sigma0(s0); - s1 = work_space[(i+14)&0x0f]; - s1 = sigma1(s1); - - t1 = work_space[i&0xf] += s0 + s1 + work_space[(i+9)&0xf]; - t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i]; - t2 = Sigma0(a) + Maj(a, b, c); - h = g; g = f; f = e; e = d + t1; - d = c; c = b; b = a; a = t1 + t2; - } - - iv[0] += a; iv[1] += b; iv[2] += c; iv[3] += d; - iv[4] += e; iv[5] += f; iv[6] += g; iv[7] += h; -} diff --git a/lib/bt/porting/ext/tinycrypt/src/utils.c b/lib/bt/porting/ext/tinycrypt/src/utils.c deleted file mode 100644 index 13cc4951..00000000 --- a/lib/bt/porting/ext/tinycrypt/src/utils.c +++ /dev/null @@ -1,74 +0,0 @@ -/* utils.c - TinyCrypt platform-dependent run-time operations */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -#include - -#define MASK_TWENTY_SEVEN 0x1b - -unsigned int _copy(uint8_t *to, unsigned int to_len, - const uint8_t *from, unsigned int from_len) -{ - if (from_len <= to_len) { - (void)memcpy(to, from, from_len); - return from_len; - } else { - return TC_CRYPTO_FAIL; - } -} - -void _set(void *to, uint8_t val, unsigned int len) -{ - (void)memset(to, val, len); -} - -/* - * Doubles the value of a byte for values up to 127. - */ -uint8_t _double_byte(uint8_t a) -{ - return ((a<<1) ^ ((a>>7) * MASK_TWENTY_SEVEN)); -} - -int _compare(const uint8_t *a, const uint8_t *b, size_t size) -{ - const uint8_t *tempa = a; - const uint8_t *tempb = b; - uint8_t result = 0; - - for (unsigned int i = 0; i < size; i++) { - result |= tempa[i] ^ tempb[i]; - } - return result; -} diff --git a/lib/bt/porting/include/ble_hci_trans.h b/lib/bt/porting/include/ble_hci_trans.h deleted file mode 100644 index 05267b6b..00000000 --- a/lib/bt/porting/include/ble_hci_trans.h +++ /dev/null @@ -1,315 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef H_HCI_TRANSPORT_ -#define H_HCI_TRANSPORT_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "os/os_mempool.h" - -#define BLE_HCI_TRANS_CMD_SZ 260 -/*** Type of buffers for holding commands and events. */ -/** - * Controller-to-host event buffers. Events have one of two priorities: - * o Low-priority (BLE_HCI_TRANS_BUF_EVT_LO) - * o High-priority (BLE_HCI_TRANS_BUF_EVT_HI) - * - * Low-priority event buffers are only used for advertising reports. If there - * are no free low-priority event buffers, then an incoming advertising report - * will get dropped. - * - * High-priority event buffers are for everything except advertising reports. - * If there are no free high-priority event buffers, a request to allocate one - * will try to allocate a low-priority buffer instead. - * - * If you want all events to be given equal treatment, then you should allocate - * low-priority events only. - * - * Event priorities solve the problem of critical events getting dropped due to - * a flood of advertising reports. This solution is likely temporary: when - * HCI flow control is added, event priorities may become obsolete. - * - * Not all transports distinguish between low and high priority events. If the - * transport does not have separate settings for low and high buffer counts, - * then it treats all events with equal priority. - */ -#define BLE_HCI_TRANS_BUF_EVT_LO 1 -#define BLE_HCI_TRANS_BUF_EVT_HI 2 - -/* Host-to-controller command. */ -#define BLE_HCI_TRANS_BUF_CMD 3 - -/** Callback function types; executed when HCI packets are received. */ -typedef int ble_hci_trans_rx_cmd_fn(uint8_t *cmd, void *arg); -typedef int ble_hci_trans_rx_acl_fn(struct os_mbuf *om, void *arg); - -#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED -#define ble_transport_alloc_cmd() ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD) -#define ble_transport_alloc_event(X) ble_hci_trans_buf_alloc(X ? BLE_HCI_TRANS_BUF_EVT_LO : BLE_HCI_TRANS_BUF_EVT_HI) -#define ble_transport_free ble_hci_trans_buf_free - -struct ble_hci_trans_funcs_t { - int(*_ble_hci_trans_hs_acl_tx)(struct os_mbuf *om); - int(*_ble_hci_trans_hs_cmd_tx)(uint8_t *cmd); - int(*_ble_hci_trans_ll_acl_tx)(struct os_mbuf *om); - int(*_ble_hci_trans_ll_evt_tx)(uint8_t *hci_ev); - int(*_ble_hci_trans_reset)(void); - int(*_ble_hci_trans_set_acl_free_cb)(os_mempool_put_fn *cb, void *arg); -}; - -extern struct ble_hci_trans_funcs_t *ble_hci_trans_funcs_ptr; - -/** - * Sends an HCI event from the controller to the host. - * - * @param cmd The HCI event to send. This buffer must be - * allocated via ble_hci_trans_buf_alloc(). - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_ll_evt_tx(uint8_t *hci_ev); -#define ble_hci_trans_ll_evt_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_evt_tx - -/** - * Sends ACL data from controller to host. - * - * @param om The ACL data packet to send. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_ll_acl_tx(struct os_mbuf *om); -#define ble_hci_trans_ll_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_acl_tx - -/** - * Sends an HCI command from the host to the controller. - * - * @param cmd The HCI command to send. This buffer must be - * allocated via ble_hci_trans_buf_alloc(). - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_hs_cmd_tx(uint8_t *cmd); -#define ble_hci_trans_hs_cmd_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_cmd_tx - -/** - * Sends ACL data from host to controller. - * - * @param om The ACL data packet to send. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_hs_acl_tx(struct os_mbuf *om); -#define ble_hci_trans_hs_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_acl_tx - -/** - * Allocates a flat buffer of the specified type. - * - * @param type The type of buffer to allocate; one of the - * BLE_HCI_TRANS_BUF_[...] constants. - * - * @return The allocated buffer on success; - * NULL on buffer exhaustion. - */ -extern uint8_t *r_ble_hci_trans_buf_alloc(int type); -#define ble_hci_trans_buf_alloc r_ble_hci_trans_buf_alloc - -/** - * Frees the specified flat buffer. The buffer must have been allocated via - * ble_hci_trans_buf_alloc(). - * - * @param buf The buffer to free. - */ -extern void r_ble_hci_trans_buf_free(uint8_t *buf); -#define ble_hci_trans_buf_free r_ble_hci_trans_buf_free - -/** - * Configures a callback to get executed whenever an ACL data packet is freed. - * The function is called immediately before the free occurs. - * - * @param cb The callback to configure. - * @param arg An optional argument to pass to the callback. - * - * @return 0 on success; - * BLE_ERR_UNSUPPORTED if the transport does not - * support this operation. - */ -extern int r_ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg); -#define ble_hci_trans_set_acl_free_cb ble_hci_trans_funcs_ptr->_ble_hci_trans_set_acl_free_cb - -/** - * Configures the HCI transport to operate with a controller. The transport - * will execute specified callbacks upon receiving HCI packets from the host. - * - * @param cmd_cb The callback to execute upon receiving an HCI - * command. - * @param cmd_arg Optional argument to pass to the command - * callback. - * @param acl_cb The callback to execute upon receiving ACL - * data. - * @param acl_arg Optional argument to pass to the ACL - * callback. - */ -extern void r_ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb, - void *cmd_arg, - ble_hci_trans_rx_acl_fn *acl_cb, - void *acl_arg); -#define ble_hci_trans_cfg_ll r_ble_hci_trans_cfg_ll - -/** - * Configures the HCI transport to operate with a host. The transport will - * execute specified callbacks upon receiving HCI packets from the controller. - * - * @param evt_cb The callback to execute upon receiving an HCI - * event. - * @param evt_arg Optional argument to pass to the event - * callback. - * @param acl_cb The callback to execute upon receiving ACL - * data. - * @param acl_arg Optional argument to pass to the ACL - * callback. - */ -extern void r_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb, - void *evt_arg, - ble_hci_trans_rx_acl_fn *acl_cb, - void *acl_arg); -#define ble_hci_trans_cfg_hs r_ble_hci_trans_cfg_hs - -/** - * Resets the HCI module to a clean state. Frees all buffers and reinitializes - * the underlying transport. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_reset(void); -#define ble_hci_trans_reset ble_hci_trans_funcs_ptr->_ble_hci_trans_reset - -void esp_ble_hci_trans_init(uint8_t); - -#else -/** - * Sends an HCI event from the controller to the host. - * - * @param cmd The HCI event to send. This buffer must be - * allocated via ble_hci_trans_buf_alloc(). - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -int ble_hci_trans_ll_evt_tx(uint8_t *hci_ev); - -/** - * Sends ACL data from controller to host. - * - * @param om The ACL data packet to send. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -int ble_hci_trans_ll_acl_tx(struct os_mbuf *om); - -/** - * Sends an HCI command from the host to the controller. - * - * @param cmd The HCI command to send. This buffer must be - * allocated via ble_hci_trans_buf_alloc(). - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -int ble_hci_trans_hs_cmd_tx(uint8_t *cmd); - -/** - * Sends ACL data from host to controller. - * - * @param om The ACL data packet to send. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -int ble_hci_trans_hs_acl_tx(struct os_mbuf *om); - -/** - * Allocates a flat buffer of the specified type. - * - * @param type The type of buffer to allocate; one of the - * BLE_HCI_TRANS_BUF_[...] constants. - * - * @return The allocated buffer on success; - * NULL on buffer exhaustion. - */ -int esp_ble_hci_trans_hs_cmd_tx(uint8_t *cmd); - -/** - * Sends ACL data from host to controller. - * - * @param om The ACL data packet to send. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -int esp_ble_hci_trans_hs_acl_tx(struct os_mbuf *om); - -/** - * Allocates a flat buffer of the specified type. - * - * @param type The type of buffer to allocate; one of the - * BLE_HCI_TRANS_BUF_[...] constants. - * - * @return The allocated buffer on success; - * NULL on buffer exhaustion. - */ -uint8_t *esp_ble_hci_trans_buf_alloc(int type); - -/** - * Frees the specified flat buffer. The buffer must have been allocated via - * ble_hci_trans_buf_alloc(). - * - * @param buf The buffer to free. - */ -void esp_ble_hci_trans_buf_free(uint8_t *buf); - -/** - * Configures the HCI transport to operate with a host. The transport will - * execute specified callbacks upon receiving HCI packets from the controller. - * - * @param evt_cb The callback to execute upon receiving an HCI - * event. - * @param evt_arg Optional argument to pass to the event - * callback. - * @param acl_cb The callback to execute upon receiving ACL - * data. - * @param acl_arg Optional argument to pass to the ACL - * callback. - */ -void esp_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb, - void *evt_arg, - ble_hci_trans_rx_acl_fn *acl_cb, - void *acl_arg); - -/** - * Resets the HCI module to a clean state. Frees all buffers and reinitializes - * the underlying transport. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -int esp_ble_hci_trans_reset(void); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* H_HCI_TRANSPORT_ */ diff --git a/lib/bt/porting/mem/bt_osi_mem.c b/lib/bt/porting/mem/bt_osi_mem.c index 69c656dd..612099d2 100644 --- a/lib/bt/porting/mem/bt_osi_mem.c +++ b/lib/bt/porting/mem/bt_osi_mem.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,18 +7,31 @@ #include "esp_attr.h" #include "esp_heap_caps.h" #include "sdkconfig.h" +#include "esp_log.h" +#include +static uint8_t log_count; IRAM_ATTR void *bt_osi_mem_malloc(size_t size) { + void *mem = NULL; #ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL - return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + mem = heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL - return heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); + mem = heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT - return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + mem = heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); #else - return malloc(size); + mem = malloc(size); #endif + if (!mem) { + log_count ++; + if ((log_count % 100) == 0) { + ESP_EARLY_LOGI("ESP_LOG_INFO","malloc failed (size %zu)",size); + log_count = 0; + } + assert(mem != NULL); + } + return mem; } IRAM_ATTR void *bt_osi_mem_calloc(size_t n, size_t size) diff --git a/lib/bt/porting/mem/bt_osi_mem.h b/lib/bt/porting/mem/bt_osi_mem.h deleted file mode 100644 index 9ab06d0a..00000000 --- a/lib/bt/porting/mem/bt_osi_mem.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "sdkconfig.h" -#include "esp_attr.h" -#include "esp_heap_caps.h" - -void *bt_osi_mem_malloc(size_t size); - -void *bt_osi_mem_calloc(size_t n, size_t size); - -void *bt_osi_mem_malloc_internal(size_t size); - -void *bt_osi_mem_calloc_internal(size_t n, size_t size); - -void bt_osi_mem_free(void *ptr); diff --git a/lib/bt/porting/nimble/include/nimble/ble.h b/lib/bt/porting/nimble/include/nimble/ble.h deleted file mode 100644 index f037d356..00000000 --- a/lib/bt/porting/nimble/include/nimble/ble.h +++ /dev/null @@ -1,319 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF) - * - * SPDX-License-Identifier: Apache-2.0 - * - * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD - */ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_ -#define H_BLE_ - -#include -#include -#include "syscfg/syscfg.h" -#include "os/os.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* The number of advertising instances */ -#define BLE_ADV_INSTANCES (MYNEWT_VAL(BLE_MULTI_ADV_INSTANCES) + 1) - -/* BLE encryption block definitions */ -#define BLE_ENC_BLOCK_SIZE (16) - -/* 4 byte header + 251 byte payload. */ -#define BLE_ACL_MAX_PKT_SIZE 255 - -struct ble_encryption_block -{ - uint8_t key[BLE_ENC_BLOCK_SIZE]; - uint8_t plain_text[BLE_ENC_BLOCK_SIZE]; - uint8_t cipher_text[BLE_ENC_BLOCK_SIZE]; -}; - -/* - * BLE MBUF structure: - * - * The BLE mbuf structure is as follows. Note that this structure applies to - * the packet header mbuf (not mbufs that are part of a "packet chain"): - * struct os_mbuf (16) - * struct os_mbuf_pkthdr (8) - * struct ble_mbuf_hdr (8) - * Data buffer (payload size, in bytes) - * - * The BLE mbuf header contains the following: - * flags: bitfield with the following values - * 0x01: Set if there was a match on the whitelist - * 0x02: Set if a connect request was transmitted upon receiving pdu - * 0x04: Set the first time we transmit the PDU (used to detect retry). - * channel: The logical BLE channel PHY channel # (0 - 39) - * crcok: flag denoting CRC check passed (1) or failed (0). - * rssi: RSSI, in dBm. - */ -struct ble_mbuf_hdr_rxinfo -{ - uint16_t flags; - uint8_t channel; - uint8_t handle; - int8_t rssi; - /* XXX: we could just use single phy_mode field */ - int8_t phy; - uint8_t phy_mode; -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - int8_t rpa_index; -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - void *user_data; -#endif -}; - -/* - * Flag definitions for rxinfo - * - * Note: it's ok to have symbols with the same values as long as they cannot be - * set for the same PDU (e.g. one use by scanner, other one used by - * connection) - */ -#define BLE_MBUF_HDR_F_CONN_CREDIT (0x8000) -#define BLE_MBUF_HDR_F_IGNORED (0x8000) -#define BLE_MBUF_HDR_F_SCAN_REQ_TXD (0x4000) -#define BLE_MBUF_HDR_F_INITA_RESOLVED (0x2000) -#define BLE_MBUF_HDR_F_TARGETA_RESOLVED (0x2000) -#define BLE_MBUF_HDR_F_EXT_ADV_SEC (0x1000) -#define BLE_MBUF_HDR_F_EXT_ADV (0x0800) -#define BLE_MBUF_HDR_F_RESOLVED (0x0400) -#define BLE_MBUF_HDR_F_AUX_PTR_WAIT (0x0200) -#define BLE_MBUF_HDR_F_AUX_INVALID (0x0100) -#define BLE_MBUF_HDR_F_CRC_OK (0x0080) -#define BLE_MBUF_HDR_F_DEVMATCH (0x0040) -#define BLE_MBUF_HDR_F_MIC_FAILURE (0x0020) -#define BLE_MBUF_HDR_F_SCAN_RSP_TXD (0x0010) -#define BLE_MBUF_HDR_F_SCAN_RSP_RXD (0x0008) -#define BLE_MBUF_HDR_F_RXSTATE_MASK (0x0007) - -/* Transmit info. NOTE: no flags defined */ -struct ble_mbuf_hdr_txinfo -{ - uint8_t flags; - uint8_t reserve0; - uint8_t pyld_len; - uint8_t hdr_byte; - uint16_t offset; -}; - -struct ble_mbuf_hdr -{ - union { - struct ble_mbuf_hdr_rxinfo rxinfo; - struct ble_mbuf_hdr_txinfo txinfo; - }; - uint32_t beg_cputime; - uint32_t rem_usecs; -}; - -#define BLE_MBUF_HDR_IGNORED(hdr) \ - (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_IGNORED)) - -#define BLE_MBUF_HDR_SCAN_REQ_TXD(hdr) \ - (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_REQ_TXD)) - -#define BLE_MBUF_HDR_EXT_ADV_SEC(hdr) \ - (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_EXT_ADV_SEC)) - -#define BLE_MBUF_HDR_EXT_ADV(hdr) \ - (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_EXT_ADV)) - -#define BLE_MBUF_HDR_DEVMATCH(hdr) \ - (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_DEVMATCH)) - -#define BLE_MBUF_HDR_SCAN_RSP_RXD(hdr) \ - (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_RSP_RXD)) - -#define BLE_MBUF_HDR_AUX_INVALID(hdr) \ - (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_AUX_INVALID)) - -#define BLE_MBUF_HDR_WAIT_AUX(hdr) \ - (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_AUX_PTR_WAIT)) - -#define BLE_MBUF_HDR_CRC_OK(hdr) \ - (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_CRC_OK)) - -#define BLE_MBUF_HDR_MIC_FAILURE(hdr) \ - (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_MIC_FAILURE)) - -#define BLE_MBUF_HDR_RESOLVED(hdr) \ - (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_RESOLVED)) - -#define BLE_MBUF_HDR_INITA_RESOLVED(hdr) \ - (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_INITA_RESOLVED)) - -#define BLE_MBUF_HDR_TARGETA_RESOLVED(hdr) \ - (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_TARGETA_RESOLVED)) - -#define BLE_MBUF_HDR_RX_STATE(hdr) \ - ((uint8_t)((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_RXSTATE_MASK)) - -#define BLE_MBUF_HDR_PTR(om) \ - (struct ble_mbuf_hdr *)((uint8_t *)om + sizeof(struct os_mbuf) + \ - sizeof(struct os_mbuf_pkthdr)) - -/* BLE mbuf overhead per packet header mbuf */ -#define BLE_MBUF_PKTHDR_OVERHEAD \ - (sizeof(struct os_mbuf_pkthdr) + sizeof(struct ble_mbuf_hdr)) - -#define BLE_MBUF_MEMBLOCK_OVERHEAD \ - (sizeof(struct os_mbuf) + BLE_MBUF_PKTHDR_OVERHEAD) - -/* Length of host user header. Only contains the peer's connection handle. */ -#define BLE_MBUF_HS_HDR_LEN (2) - -#define BLE_DEV_ADDR_LEN (6) -extern uint8_t g_dev_addr[BLE_DEV_ADDR_LEN]; -extern uint8_t g_random_addr[BLE_DEV_ADDR_LEN]; - -/* BLE Error Codes (Core v4.2 Vol 2 part D) */ -enum ble_error_codes -{ - /* An "error" code of 0x0 means success */ - BLE_ERR_SUCCESS = 0x00, - BLE_ERR_UNKNOWN_HCI_CMD = 0x01, - BLE_ERR_UNK_CONN_ID = 0x02, - BLE_ERR_HW_FAIL = 0x03, - BLE_ERR_PAGE_TMO = 0x04, - BLE_ERR_AUTH_FAIL = 0x05, - BLE_ERR_PINKEY_MISSING = 0x06, - BLE_ERR_MEM_CAPACITY = 0x07, - BLE_ERR_CONN_SPVN_TMO = 0x08, - BLE_ERR_CONN_LIMIT = 0x09, - BLE_ERR_SYNCH_CONN_LIMIT = 0x0a, - BLE_ERR_ACL_CONN_EXISTS = 0x0b, - BLE_ERR_CMD_DISALLOWED = 0x0c, - BLE_ERR_CONN_REJ_RESOURCES = 0x0d, - BLE_ERR_CONN_REJ_SECURITY = 0x0e, - BLE_ERR_CONN_REJ_BD_ADDR = 0x0f, - BLE_ERR_CONN_ACCEPT_TMO = 0x10, - BLE_ERR_UNSUPPORTED = 0x11, - BLE_ERR_INV_HCI_CMD_PARMS = 0x12, - BLE_ERR_REM_USER_CONN_TERM = 0x13, - BLE_ERR_RD_CONN_TERM_RESRCS = 0x14, - BLE_ERR_RD_CONN_TERM_PWROFF = 0x15, - BLE_ERR_CONN_TERM_LOCAL = 0x16, - BLE_ERR_REPEATED_ATTEMPTS = 0x17, - BLE_ERR_NO_PAIRING = 0x18, - BLE_ERR_UNK_LMP = 0x19, - BLE_ERR_UNSUPP_REM_FEATURE = 0x1a, - BLE_ERR_SCO_OFFSET = 0x1b, - BLE_ERR_SCO_ITVL = 0x1c, - BLE_ERR_SCO_AIR_MODE = 0x1d, - BLE_ERR_INV_LMP_LL_PARM = 0x1e, - BLE_ERR_UNSPECIFIED = 0x1f, - BLE_ERR_UNSUPP_LMP_LL_PARM = 0x20, - BLE_ERR_NO_ROLE_CHANGE = 0x21, - BLE_ERR_LMP_LL_RSP_TMO = 0x22, - BLE_ERR_LMP_COLLISION = 0x23, - BLE_ERR_LMP_PDU = 0x24, - BLE_ERR_ENCRYPTION_MODE = 0x25, - BLE_ERR_LINK_KEY_CHANGE = 0x26, - BLE_ERR_UNSUPP_QOS = 0x27, - BLE_ERR_INSTANT_PASSED = 0x28, - BLE_ERR_UNIT_KEY_PAIRING = 0x29, - BLE_ERR_DIFF_TRANS_COLL = 0x2a, - /* BLE_ERR_RESERVED = 0x2b */ - BLE_ERR_QOS_PARM = 0x2c, - BLE_ERR_QOS_REJECTED = 0x2d, - BLE_ERR_CHAN_CLASS = 0x2e, - BLE_ERR_INSUFFICIENT_SEC = 0x2f, - BLE_ERR_PARM_OUT_OF_RANGE = 0x30, - /* BLE_ERR_RESERVED = 0x31 */ - BLE_ERR_PENDING_ROLE_SW = 0x32, - /* BLE_ERR_RESERVED = 0x33 */ - BLE_ERR_RESERVED_SLOT = 0x34, - BLE_ERR_ROLE_SW_FAIL = 0x35, - BLE_ERR_INQ_RSP_TOO_BIG = 0x36, - BLE_ERR_SEC_SIMPLE_PAIR = 0x37, - BLE_ERR_HOST_BUSY_PAIR = 0x38, - BLE_ERR_CONN_REJ_CHANNEL = 0x39, - BLE_ERR_CTLR_BUSY = 0x3a, - BLE_ERR_CONN_PARMS = 0x3b, - BLE_ERR_DIR_ADV_TMO = 0x3c, - BLE_ERR_CONN_TERM_MIC = 0x3d, - BLE_ERR_CONN_ESTABLISHMENT = 0x3e, - BLE_ERR_MAC_CONN_FAIL = 0x3f, - BLE_ERR_COARSE_CLK_ADJ = 0x40, - BLE_ERR_TYPE0_SUBMAP_NDEF = 0x41, - BLE_ERR_UNK_ADV_INDENT = 0x42, - BLE_ERR_LIMIT_REACHED = 0x43, - BLE_ERR_OPERATION_CANCELLED = 0x44, - BLE_ERR_PACKET_TOO_LONG = 0x45, - BLE_ERR_MAX = 0xff -}; - -/* HW error codes */ -#define BLE_HW_ERR_DO_NOT_USE (0) /* XXX: reserve this one for now */ -#define BLE_HW_ERR_HCI_SYNC_LOSS (1) - -/* Own Bluetooth Device address type */ -#define BLE_OWN_ADDR_PUBLIC (0x00) -#define BLE_OWN_ADDR_RANDOM (0x01) -#define BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT (0x02) -#define BLE_OWN_ADDR_RPA_RANDOM_DEFAULT (0x03) - -/* Bluetooth Device address type */ -#define BLE_ADDR_PUBLIC (0x00) -#define BLE_ADDR_RANDOM (0x01) -#define BLE_ADDR_PUBLIC_ID (0x02) -#define BLE_ADDR_RANDOM_ID (0x03) - -#define BLE_ADDR_ANY (&(ble_addr_t) { 0, {0, 0, 0, 0, 0, 0} }) - -#define BLE_ADDR_IS_RPA(addr) (((addr)->type == BLE_ADDR_RANDOM) && \ - ((addr)->val[5] & 0xc0) == 0x40) -#define BLE_ADDR_IS_NRPA(addr) (((addr)->type == BLE_ADDR_RANDOM) && \ - ((addr)->val[5] & 0xc0) == 0x00) -#define BLE_ADDR_IS_STATIC(addr) (((addr)->type == BLE_ADDR_RANDOM) && \ - ((addr)->val[5] & 0xc0) == 0xc0) - -typedef struct { - uint8_t type; - uint8_t val[6]; -} ble_addr_t; - - -static inline int ble_addr_cmp(const ble_addr_t *a, const ble_addr_t *b) -{ - int type_diff; - - type_diff = a->type - b->type; - if (type_diff != 0) { - return type_diff; - } - - return memcmp(a->val, b->val, sizeof(a->val)); -} - -#ifdef __cplusplus -} -#endif - -#endif /* H_BLE_ */ diff --git a/lib/bt/porting/nimble/include/nimble/ble_hci_trans.h b/lib/bt/porting/nimble/include/nimble/ble_hci_trans.h deleted file mode 100644 index 5bbf9224..00000000 --- a/lib/bt/porting/nimble/include/nimble/ble_hci_trans.h +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_HCI_TRANSPORT_ -#define H_HCI_TRANSPORT_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "os/os_mempool.h" - -#define BLE_HCI_TRANS_CMD_SZ 260 -/*** Type of buffers for holding commands and events. */ -/** - * Controller-to-host event buffers. Events have one of two priorities: - * o Low-priority (BLE_HCI_TRANS_BUF_EVT_LO) - * o High-priority (BLE_HCI_TRANS_BUF_EVT_HI) - * - * Low-priority event buffers are only used for advertising reports. If there - * are no free low-priority event buffers, then an incoming advertising report - * will get dropped. - * - * High-priority event buffers are for everything except advertising reports. - * If there are no free high-priority event buffers, a request to allocate one - * will try to allocate a low-priority buffer instead. - * - * If you want all events to be given equal treatment, then you should allocate - * low-priority events only. - * - * Event priorities solve the problem of critical events getting dropped due to - * a flood of advertising reports. This solution is likely temporary: when - * HCI flow control is added, event priorities may become obsolete. - * - * Not all transports distinguish between low and high priority events. If the - * transport does not have separate settings for low and high buffer counts, - * then it treats all events with equal priority. - */ -#define BLE_HCI_TRANS_BUF_EVT_LO 1 -#define BLE_HCI_TRANS_BUF_EVT_HI 2 - -/* Host-to-controller command. */ -#define BLE_HCI_TRANS_BUF_CMD 3 - -/** Callback function types; executed when HCI packets are received. */ -typedef int ble_hci_trans_rx_cmd_fn(uint8_t *cmd, void *arg); -typedef int ble_hci_trans_rx_acl_fn(struct os_mbuf *om, void *arg); - -#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED -#define ble_transport_alloc_cmd() ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD) -#define ble_transport_alloc_event(X) ble_hci_trans_buf_alloc(X ? BLE_HCI_TRANS_BUF_EVT_LO : BLE_HCI_TRANS_BUF_EVT_HI) -#define ble_transport_free ble_hci_trans_buf_free - -struct ble_hci_trans_funcs_t { - int(*_ble_hci_trans_hs_acl_tx)(struct os_mbuf *om); - int(*_ble_hci_trans_hs_cmd_tx)(uint8_t *cmd); - int(*_ble_hci_trans_ll_acl_tx)(struct os_mbuf *om); - int(*_ble_hci_trans_ll_evt_tx)(uint8_t *hci_ev); - int(*_ble_hci_trans_reset)(void); - int(*_ble_hci_trans_set_acl_free_cb)(os_mempool_put_fn *cb, void *arg); -}; - -extern struct ble_hci_trans_funcs_t *ble_hci_trans_funcs_ptr; - -/** - * Sends an HCI event from the controller to the host. - * - * @param cmd The HCI event to send. This buffer must be - * allocated via ble_hci_trans_buf_alloc(). - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_ll_evt_tx(uint8_t *hci_ev); -#define ble_hci_trans_ll_evt_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_evt_tx - -/** - * Sends ACL data from controller to host. - * - * @param om The ACL data packet to send. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_ll_acl_tx(struct os_mbuf *om); -#define ble_hci_trans_ll_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_acl_tx - -/** - * Sends an HCI command from the host to the controller. - * - * @param cmd The HCI command to send. This buffer must be - * allocated via ble_hci_trans_buf_alloc(). - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_hs_cmd_tx(uint8_t *cmd); -#define ble_hci_trans_hs_cmd_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_cmd_tx - -/** - * Sends ACL data from host to controller. - * - * @param om The ACL data packet to send. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_hs_acl_tx(struct os_mbuf *om); -#define ble_hci_trans_hs_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_acl_tx - -/** - * Allocates a flat buffer of the specified type. - * - * @param type The type of buffer to allocate; one of the - * BLE_HCI_TRANS_BUF_[...] constants. - * - * @return The allocated buffer on success; - * NULL on buffer exhaustion. - */ -extern uint8_t *r_ble_hci_trans_buf_alloc(int type); -#define ble_hci_trans_buf_alloc r_ble_hci_trans_buf_alloc - -/** - * Frees the specified flat buffer. The buffer must have been allocated via - * ble_hci_trans_buf_alloc(). - * - * @param buf The buffer to free. - */ -extern void r_ble_hci_trans_buf_free(uint8_t *buf); -#define ble_hci_trans_buf_free r_ble_hci_trans_buf_free - -/** - * Configures a callback to get executed whenever an ACL data packet is freed. - * The function is called immediately before the free occurs. - * - * @param cb The callback to configure. - * @param arg An optional argument to pass to the callback. - * - * @return 0 on success; - * BLE_ERR_UNSUPPORTED if the transport does not - * support this operation. - */ -extern int r_ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg); -#define ble_hci_trans_set_acl_free_cb ble_hci_trans_funcs_ptr->_ble_hci_trans_set_acl_free_cb - -/** - * Configures the HCI transport to operate with a controller. The transport - * will execute specified callbacks upon receiving HCI packets from the host. - * - * @param cmd_cb The callback to execute upon receiving an HCI - * command. - * @param cmd_arg Optional argument to pass to the command - * callback. - * @param acl_cb The callback to execute upon receiving ACL - * data. - * @param acl_arg Optional argument to pass to the ACL - * callback. - */ -extern void r_ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb, - void *cmd_arg, - ble_hci_trans_rx_acl_fn *acl_cb, - void *acl_arg); -#define ble_hci_trans_cfg_ll r_ble_hci_trans_cfg_ll - -/** - * Configures the HCI transport to operate with a host. The transport will - * execute specified callbacks upon receiving HCI packets from the controller. - * - * @param evt_cb The callback to execute upon receiving an HCI - * event. - * @param evt_arg Optional argument to pass to the event - * callback. - * @param acl_cb The callback to execute upon receiving ACL - * data. - * @param acl_arg Optional argument to pass to the ACL - * callback. - */ -extern void r_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb, - void *evt_arg, - ble_hci_trans_rx_acl_fn *acl_cb, - void *acl_arg); -#define ble_hci_trans_cfg_hs r_ble_hci_trans_cfg_hs - -/** - * Resets the HCI module to a clean state. Frees all buffers and reinitializes - * the underlying transport. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_reset(void); -#define ble_hci_trans_reset ble_hci_trans_funcs_ptr->_ble_hci_trans_reset - -void esp_ble_hci_trans_init(uint8_t); - -#else -/** - * Sends an HCI event from the controller to the host. - * - * @param cmd The HCI event to send. This buffer must be - * allocated via ble_hci_trans_buf_alloc(). - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -int ble_hci_trans_ll_evt_tx(uint8_t *hci_ev); - -/** - * Sends ACL data from controller to host. - * - * @param om The ACL data packet to send. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -int ble_hci_trans_ll_acl_tx(struct os_mbuf *om); - -/** - * Sends an HCI command from the host to the controller. - * - * @param cmd The HCI command to send. This buffer must be - * allocated via ble_hci_trans_buf_alloc(). - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -int ble_hci_trans_hs_cmd_tx(uint8_t *cmd); - -/** - * Sends ACL data from host to controller. - * - * @param om The ACL data packet to send. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -int ble_hci_trans_hs_acl_tx(struct os_mbuf *om); - -/** - * Allocates a flat buffer of the specified type. - * - * @param type The type of buffer to allocate; one of the - * BLE_HCI_TRANS_BUF_[...] constants. - * - * @return The allocated buffer on success; - * NULL on buffer exhaustion. - */ -int esp_ble_hci_trans_hs_cmd_tx(uint8_t *cmd); - -/** - * Sends ACL data from host to controller. - * - * @param om The ACL data packet to send. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -int esp_ble_hci_trans_hs_acl_tx(struct os_mbuf *om); - -/** - * Allocates a flat buffer of the specified type. - * - * @param type The type of buffer to allocate; one of the - * BLE_HCI_TRANS_BUF_[...] constants. - * - * @return The allocated buffer on success; - * NULL on buffer exhaustion. - */ -uint8_t *esp_ble_hci_trans_buf_alloc(int type); - -/** - * Frees the specified flat buffer. The buffer must have been allocated via - * ble_hci_trans_buf_alloc(). - * - * @param buf The buffer to free. - */ -void esp_ble_hci_trans_buf_free(uint8_t *buf); - -/** - * Configures the HCI transport to operate with a host. The transport will - * execute specified callbacks upon receiving HCI packets from the controller. - * - * @param evt_cb The callback to execute upon receiving an HCI - * event. - * @param evt_arg Optional argument to pass to the event - * callback. - * @param acl_cb The callback to execute upon receiving ACL - * data. - * @param acl_arg Optional argument to pass to the ACL - * callback. - */ -void esp_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb, - void *evt_arg, - ble_hci_trans_rx_acl_fn *acl_cb, - void *acl_arg); - -/** - * Resets the HCI module to a clean state. Frees all buffers and reinitializes - * the underlying transport. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -int esp_ble_hci_trans_reset(void); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* H_HCI_TRANSPORT_ */ diff --git a/lib/bt/porting/nimble/include/nimble/nimble_npl.h b/lib/bt/porting/nimble/include/nimble/nimble_npl.h deleted file mode 100644 index c11a2972..00000000 --- a/lib/bt/porting/nimble/include/nimble/nimble_npl.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef _NIMBLE_NPL_H_ -#define _NIMBLE_NPL_H_ - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct ble_npl_event; -typedef void ble_npl_event_fn(struct ble_npl_event *ev); - -enum ble_npl_error { - BLE_NPL_OK = 0, - BLE_NPL_ENOMEM = 1, - BLE_NPL_EINVAL = 2, - BLE_NPL_INVALID_PARAM = 3, - BLE_NPL_MEM_NOT_ALIGNED = 4, - BLE_NPL_BAD_MUTEX = 5, - BLE_NPL_TIMEOUT = 6, - BLE_NPL_ERR_IN_ISR = 7, - BLE_NPL_ERR_PRIV = 8, - BLE_NPL_OS_NOT_STARTED = 9, - BLE_NPL_ENOENT = 10, - BLE_NPL_EBUSY = 11, - BLE_NPL_ERROR = 12, -}; - -typedef enum ble_npl_error ble_npl_error_t; - -/* Include OS-specific definitions */ -#include "nimble/nimble_npl_os.h" - -/* - * Generic - */ - -bool ble_npl_os_started(void); - -void *ble_npl_get_current_task_id(void); - -/* - * Event queue - */ - -void ble_npl_eventq_init(struct ble_npl_eventq *evq); - -void ble_npl_eventq_deinit(struct ble_npl_eventq *evq); - -struct ble_npl_event *ble_npl_eventq_get(struct ble_npl_eventq *evq, - ble_npl_time_t tmo); - -void ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev); - -void ble_npl_eventq_remove(struct ble_npl_eventq *evq, - struct ble_npl_event *ev); - -void ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn, - void *arg); - -bool ble_npl_event_is_queued(struct ble_npl_event *ev); - -void *ble_npl_event_get_arg(struct ble_npl_event *ev); - -void ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg); - -bool ble_npl_eventq_is_empty(struct ble_npl_eventq *evq); - -void ble_npl_event_run(struct ble_npl_event *ev); - -/* - * Mutexes - */ - -ble_npl_error_t ble_npl_mutex_init(struct ble_npl_mutex *mu); - -ble_npl_error_t ble_npl_mutex_pend(struct ble_npl_mutex *mu, - ble_npl_time_t timeout); - -ble_npl_error_t ble_npl_mutex_release(struct ble_npl_mutex *mu); - -ble_npl_error_t ble_npl_mutex_deinit(struct ble_npl_mutex *mu); - -/* - * Semaphores - */ - -ble_npl_error_t ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens); - -ble_npl_error_t ble_npl_sem_pend(struct ble_npl_sem *sem, - ble_npl_time_t timeout); - -ble_npl_error_t ble_npl_sem_release(struct ble_npl_sem *sem); - -ble_npl_error_t ble_npl_sem_deinit(struct ble_npl_sem *sem); - -uint16_t ble_npl_sem_get_count(struct ble_npl_sem *sem); - -/* - * Callouts - */ - -int ble_npl_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq, - ble_npl_event_fn *ev_cb, void *ev_arg); - -ble_npl_error_t ble_npl_callout_reset(struct ble_npl_callout *co, - ble_npl_time_t ticks); - -void ble_npl_callout_stop(struct ble_npl_callout *co); - -bool ble_npl_callout_is_active(struct ble_npl_callout *co); - -ble_npl_time_t ble_npl_callout_get_ticks(struct ble_npl_callout *co); - -ble_npl_time_t ble_npl_callout_remaining_ticks(struct ble_npl_callout *co, - ble_npl_time_t time); - -void ble_npl_callout_set_arg(struct ble_npl_callout *co, - void *arg); -/* - * Time functions - */ - -ble_npl_time_t ble_npl_time_get(void); - -ble_npl_error_t ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks); - -ble_npl_error_t ble_npl_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms); - -ble_npl_time_t ble_npl_time_ms_to_ticks32(uint32_t ms); - -uint32_t ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks); - -void ble_npl_time_delay(ble_npl_time_t ticks); - -/* - * Hardware-specific - * - * These symbols should be most likely defined by application since they are - * specific to hardware, not to OS. - */ - -#if NIMBLE_CFG_CONTROLLER - -void ble_npl_hw_set_isr(int irqn, uint32_t addr); - -#endif - -uint32_t ble_npl_hw_enter_critical(void); - -void ble_npl_hw_exit_critical(uint32_t ctx); - -bool ble_npl_hw_is_in_critical(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _NIMBLE_NPL_H_ */ diff --git a/lib/bt/porting/nimble/include/nimble/nimble_opt.h b/lib/bt/porting/nimble/include/nimble/nimble_opt.h deleted file mode 100644 index f0e988b2..00000000 --- a/lib/bt/porting/nimble/include/nimble/nimble_opt.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_NIMBLE_OPT_ -#define H_NIMBLE_OPT_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Include automatically-generated settings. */ -#include "nimble/nimble_opt_auto.h" - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/bt/porting/nimble/include/nimble/nimble_opt_auto.h b/lib/bt/porting/nimble/include/nimble/nimble_opt_auto.h deleted file mode 100644 index daf21533..00000000 --- a/lib/bt/porting/nimble/include/nimble/nimble_opt_auto.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF) - * - * SPDX-License-Identifier: Apache-2.0 - * - * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD - */ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_NIMBLE_OPT_AUTO_ -#define H_NIMBLE_OPT_AUTO_ - -#include "syscfg/syscfg.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*** - * Automatic options. - * - * These settings are generated automatically from the user-specified syscfg - * settings. - */ - -#undef NIMBLE_BLE_ADVERTISE -#define NIMBLE_BLE_ADVERTISE \ - (MYNEWT_VAL(BLE_ROLE_BROADCASTER) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL)) - -#undef NIMBLE_BLE_SCAN -#define NIMBLE_BLE_SCAN \ - (MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_OBSERVER)) - -#undef NIMBLE_BLE_CONNECT -#define NIMBLE_BLE_CONNECT \ - (MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_ROLE_PERIPHERAL)) - - -/** Supported client ATT commands. */ - -#undef NIMBLE_BLE_ATT_CLT_FIND_INFO -#define NIMBLE_BLE_ATT_CLT_FIND_INFO \ - (MYNEWT_VAL(BLE_GATT_DISC_ALL_DSCS)) - -#undef NIMBLE_BLE_ATT_CLT_FIND_TYPE -#define NIMBLE_BLE_ATT_CLT_FIND_TYPE \ - (MYNEWT_VAL(BLE_GATT_DISC_SVC_UUID)) - -#undef NIMBLE_BLE_ATT_CLT_READ_TYPE -#define NIMBLE_BLE_ATT_CLT_READ_TYPE \ - (MYNEWT_VAL(BLE_GATT_FIND_INC_SVCS) || \ - MYNEWT_VAL(BLE_GATT_DISC_ALL_CHRS) || \ - MYNEWT_VAL(BLE_GATT_DISC_CHRS_UUID) || \ - MYNEWT_VAL(BLE_GATT_READ_UUID)) - -#undef NIMBLE_BLE_ATT_CLT_READ -#define NIMBLE_BLE_ATT_CLT_READ \ - (MYNEWT_VAL(BLE_GATT_READ) || \ - MYNEWT_VAL(BLE_GATT_READ_LONG) || \ - MYNEWT_VAL(BLE_GATT_FIND_INC_SVCS)) - -#undef NIMBLE_BLE_ATT_CLT_READ_BLOB -#define NIMBLE_BLE_ATT_CLT_READ_BLOB \ - (MYNEWT_VAL(BLE_GATT_READ_LONG)) - -#undef NIMBLE_BLE_ATT_CLT_READ_MULT -#define NIMBLE_BLE_ATT_CLT_READ_MULT \ - (MYNEWT_VAL(BLE_GATT_READ_MULT)) - -#undef NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE -#define NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE \ - (MYNEWT_VAL(BLE_GATT_DISC_ALL_SVCS)) - -#undef NIMBLE_BLE_ATT_CLT_WRITE -#define NIMBLE_BLE_ATT_CLT_WRITE \ - (MYNEWT_VAL(BLE_GATT_WRITE)) - -#undef NIMBLE_BLE_ATT_CLT_SIGNED_WRITE -#define NIMBLE_BLE_ATT_CLT_SIGNED_WRITE \ - (MYNEWT_VAL(BLE_GATT_SIGNED_WRITE)) - -#undef NIMBLE_BLE_ATT_CLT_WRITE_NO_RSP -#define NIMBLE_BLE_ATT_CLT_WRITE_NO_RSP \ - (MYNEWT_VAL(BLE_GATT_WRITE_NO_RSP)) - -#undef NIMBLE_BLE_ATT_CLT_PREP_WRITE -#define NIMBLE_BLE_ATT_CLT_PREP_WRITE \ - (MYNEWT_VAL(BLE_GATT_WRITE_LONG)) - -#undef NIMBLE_BLE_ATT_CLT_EXEC_WRITE -#define NIMBLE_BLE_ATT_CLT_EXEC_WRITE \ - (MYNEWT_VAL(BLE_GATT_WRITE_LONG)) - -#undef NIMBLE_BLE_ATT_CLT_NOTIFY -#define NIMBLE_BLE_ATT_CLT_NOTIFY \ - (MYNEWT_VAL(BLE_GATT_NOTIFY)) - -#undef NIMBLE_BLE_ATT_CLT_INDICATE -#define NIMBLE_BLE_ATT_CLT_INDICATE \ - (MYNEWT_VAL(BLE_GATT_INDICATE)) - -/** Security manager settings. */ - -#undef NIMBLE_BLE_SM -#define NIMBLE_BLE_SM (MYNEWT_VAL(BLE_SM_LEGACY) || MYNEWT_VAL(BLE_SM_SC)) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/bt/porting/nimble/include/nimble/nimble_port.h b/lib/bt/porting/nimble/include/nimble/nimble_port.h deleted file mode 100644 index f4a98543..00000000 --- a/lib/bt/porting/nimble/include/nimble/nimble_port.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef _NIMBLE_PORT_H -#define _NIMBLE_PORT_H - -#include "esp_err.h" -#include "nimble/nimble_npl.h" - -#define NIMBLE_CORE (CONFIG_BT_NIMBLE_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_NIMBLE_PINNED_TO_CORE : tskNO_AFFINITY) - -#define NIMBLE_HS_STACK_SIZE CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE - -#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED -#define NIMBLE_LL_STACK_SIZE CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** -* @brief nimble_port_init - Initialize controller and NimBLE host stack -* -* @return esp_err_t - ESP_OK ( if success) -* Error code in case of failure -*/ -esp_err_t nimble_port_init(void); - -/** -* @brief nimble_port_deinit - Deinitialize controller and NimBLE host stack -* -* @return esp_err_t - ESP_OK ( if success) -* Error code in case of failure -*/ -esp_err_t nimble_port_deinit(void); - -void nimble_port_run(void); -int nimble_port_stop(void); - -/** - * @brief esp_nimble_init - Initialize the NimBLE host stack - * - * @return esp_err_t - */ -esp_err_t esp_nimble_init(void); - -/** - * @brief esp_nimble_deinit - Deinitialize the NimBLE host stack - * - * @return esp_err_t - */ -esp_err_t esp_nimble_deinit(void); - -struct ble_npl_eventq *nimble_port_get_dflt_eventq(void); - - -#ifdef __cplusplus -} -#endif - -#endif /* _NIMBLE_PORT_H */ diff --git a/lib/bt/porting/nimble/include/os/endian.h b/lib/bt/porting/nimble/include/os/endian.h deleted file mode 100644 index 2e06a8b5..00000000 --- a/lib/bt/porting/nimble/include/os/endian.h +++ /dev/null @@ -1,296 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF) - * - * SPDX-License-Identifier: Apache-2.0 - * - * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD - */ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_ENDIAN_ -#define H_ENDIAN_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Internal helpers */ -#ifndef os_bswap_64 -#define os_bswap_64(x) ((uint64_t) \ - ((((x) & 0xff00000000000000ull) >> 56) | \ - (((x) & 0x00ff000000000000ull) >> 40) | \ - (((x) & 0x0000ff0000000000ull) >> 24) | \ - (((x) & 0x000000ff00000000ull) >> 8) | \ - (((x) & 0x00000000ff000000ull) << 8) | \ - (((x) & 0x0000000000ff0000ull) << 24) | \ - (((x) & 0x000000000000ff00ull) << 40) | \ - (((x) & 0x00000000000000ffull) << 56))) -#endif - -#ifndef os_bswap_32 -#define os_bswap_32(x) ((uint32_t) \ - ((((x) & 0xff000000) >> 24) | \ - (((x) & 0x00ff0000) >> 8) | \ - (((x) & 0x0000ff00) << 8) | \ - (((x) & 0x000000ff) << 24))) -#endif - -#ifndef os_bswap_16 -#define os_bswap_16(x) ((uint16_t) \ - ((((x) & 0xff00) >> 8) | \ - (((x) & 0x00ff) << 8))) -#endif - -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - -#ifndef ntohll -#define ntohll(x) ((uint64_t)(x)) -#endif - -#ifndef htonll -#define htonll(x) ((uint64_t)(x)) -#endif - -#ifndef ntohl -#define ntohl(x) ((uint32_t)(x)) -#endif - -#ifndef htonl -#define htonl(x) ((uint32_t)(x)) -#endif - -#ifndef ntohs -#define ntohs(x) ((uint16_t)(x)) -#endif - -#ifndef htons -#define htons(x) ((uint16_t)(x)) -#endif - -#ifndef htobe16 -#define htobe16(x) ((uint16_t)(x)) -#endif - -#ifndef htole16 -#define htole16(x) os_bswap_16 (x) -#endif - -#ifndef be16toh -#define be16toh(x) ((uint16_t)(x)) -#endif - -#ifndef le16toh -#define le16toh(x) os_bswap_16 (x) -#endif - -#ifndef htobe32 -#define htobe32(x) ((uint32_t)(x)) -#endif - -#ifndef htole32 -#define htole32(x) os_bswap_32 (x) -#endif - -#ifndef be32toh -#define be32toh(x) ((uint32_t)(x)) -#endif - -#ifndef le32toh -#define le32toh(x) os_bswap_32 (x) -#endif - -#ifndef htobe64 -#define htobe64(x) ((uint64_t)(x)) -#endif - -#ifndef htole64 -#define htole64(x) os_bswap_64 (x) -#endif - -#ifndef be64toh -#define be64toh(x) ((uint64_t)(x)) -#endif - -#ifndef le64toh -#define le64toh(x) os_bswap_64 (x) -#endif - -#else - -#ifndef ntohll -#define ntohll(x) os_bswap_64(x) -#endif - -#ifndef htonll -#define htonll ntohll -#endif - -/* These are not used in NimBLE and ESP-IDF uses them from LwIP */ -#if 0 -#ifndef ntohl -#define ntohl(x) os_bswap_32(x) -#endif - -#ifndef htonl -#define htonl ntohl -#endif - -#ifndef htons -#define htons(x) os_bswap_16(x) -#endif - -#ifndef ntohs -#define ntohs htons -#endif -#endif - -#ifndef htobe16 -#define htobe16(x) os_bswap_16(x) -#endif - -#ifndef htole16 -#define htole16(x) ((uint16_t)(x)) -#endif - -#ifndef be16toh -#define be16toh(x) os_bswap_16(x) -#endif - -#ifndef le16toh -#define le16toh(x) ((uint16_t)(x)) -#endif - -#ifndef htobe32 -#define htobe32(x) os_bswap_32(x) -#endif - -#ifndef htole32 -#define htole32(x) ((uint32_t)(x)) -#endif - -#ifndef be32toh -#define be32toh(x) os_bswap_32(x) -#endif - -#ifndef le32toh -#define le32toh(x) ((uint32_t)(x)) -#endif - -#ifndef htobe64 -#define htobe64(x) os_bswap_64(x) -#endif - -#ifndef htole64 -#define htole64(x) ((uint64_t)(x)) -#endif - -#ifndef be64toh -#define be64toh(x) os_bswap_64(x) -#endif - -#ifndef le64toh -#define le64toh(x) ((uint64_t)(x)) -#endif - -#endif - -#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED -void r_put_le16(void *buf, uint16_t x); -#define put_le16 r_put_le16 - -void r_put_le24(void *buf, uint32_t x); -#define put_le24 r_put_le24 - -void r_put_le32(void *buf, uint32_t x); -#define put_le32 r_put_le32 - -void r_put_le64(void *buf, uint64_t x); -#define put_le64 r_put_le64 - -uint16_t r_get_le16(const void *buf); -#define get_le16 r_get_le16 - -uint32_t r_get_le24(const void *buf); -#define get_le24 r_get_le24 - -uint32_t r_get_le32(const void *buf); -#define get_le32 r_get_le32 - -uint64_t r_get_le64(const void *buf); -#define get_le64 r_get_le64 - -void r_put_be16(void *buf, uint16_t x); -#define put_be16 r_put_be16 - -void r_put_be24(void *buf, uint32_t x); -#define put_be24 r_put_be24 - -void r_put_be32(void *buf, uint32_t x); -#define put_be32 r_put_be32 - -void r_put_be64(void *buf, uint64_t x); -#define put_be64 r_put_be64 - -uint16_t r_get_be16(const void *buf); -#define get_be16 r_get_be16 - -uint32_t r_get_be24(const void *buf); -#define get_be24 r_get_be24 - -uint32_t r_get_be32(const void *buf); -#define get_be32 r_get_be32 - -uint64_t r_get_be64(const void *buf); -#define get_be64 r_get_be64 - -void r_swap_in_place(void *buf, int len); -#define swap_in_place r_swap_in_place - -void r_swap_buf(uint8_t *dst, const uint8_t *src, int len); -#define swap_buf r_swap_buf - - -#else -void put_le16(void *buf, uint16_t x); -void put_le24(void *buf, uint32_t x); -void put_le32(void *buf, uint32_t x); -void put_le64(void *buf, uint64_t x); -uint16_t get_le16(const void *buf); -uint32_t get_le24(const void *buf); -uint32_t get_le32(const void *buf); -uint64_t get_le64(const void *buf); -void put_be16(void *buf, uint16_t x); -void put_be24(void *buf, uint32_t x); -void put_be32(void *buf, uint32_t x); -void put_be64(void *buf, uint64_t x); -uint16_t get_be16(const void *buf); -uint32_t get_be24(const void *buf); -uint32_t get_be32(const void *buf); -uint64_t get_be64(const void *buf); -void swap_in_place(void *buf, int len); -void swap_buf(uint8_t *dst, const uint8_t *src, int len); -#endif -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/bt/porting/nimble/include/os/os.h b/lib/bt/porting/nimble/include/os/os.h deleted file mode 100644 index 56fdf52d..00000000 --- a/lib/bt/porting/nimble/include/os/os.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF) - * - * SPDX-License-Identifier: Apache-2.0 - * - * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD - */ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef _OS_H -#define _OS_H - -#include -#include "esp_assert.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined __cplusplus && !defined static_assert -#define static_assert _Static_assert -#endif - -#include "nimble/nimble_npl.h" - -#define OS_ALIGN(__n, __a) ( \ - (((__n) & ((__a) - 1)) == 0) ? \ - (__n) : \ - ((__n) + ((__a) - ((__n) & ((__a) - 1)))) \ - ) -#define OS_ALIGNMENT (BLE_NPL_OS_ALIGNMENT) - -typedef uint32_t os_sr_t; -#define OS_ENTER_CRITICAL(_sr) (_sr = ble_npl_hw_enter_critical()) -#define OS_EXIT_CRITICAL(_sr) (ble_npl_hw_exit_critical(_sr)) -#define OS_ASSERT_CRITICAL() assert(ble_npl_hw_is_in_critical()) - -/* Mynewt components (not abstracted in NPL) */ -#include "os/endian.h" -#include "os/queue.h" -#include "os/os_error.h" -#include "os/os_mbuf.h" -#include "os/os_mempool.h" - -#ifdef __cplusplus -} -#endif - -#endif /* _OS_H */ diff --git a/lib/bt/porting/nimble/include/os/os_error.h b/lib/bt/porting/nimble/include/os/os_error.h deleted file mode 100644 index 2e736e39..00000000 --- a/lib/bt/porting/nimble/include/os/os_error.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF) - * - * SPDX-License-Identifier: Apache-2.0 - * - * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD - */ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_OS_ERROR_ -#define H_OS_ERROR_ - -#include "os/os.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* OS error enumerations */ -enum os_error { - OS_OK = 0, - OS_ENOMEM = 1, - OS_EINVAL = 2, - OS_INVALID_PARM = 3, - OS_MEM_NOT_ALIGNED = 4, - OS_BAD_MUTEX = 5, - OS_TIMEOUT = 6, - OS_ERR_IN_ISR = 7, /* Function cannot be called from ISR */ - OS_ERR_PRIV = 8, /* Privileged access error */ - OS_NOT_STARTED = 9, /* OS must be started to call this function, but isn't */ - OS_ENOENT = 10, /* No such thing */ - OS_EBUSY = 11, /* Resource busy */ - OS_ERROR = 12, /* Generic Error */ -}; - -typedef enum os_error os_error_t; - -/** - * @brief Converts an OS error code (`OS_[...]`) to an equivalent system error - * code (`SYS_E[...]`). - * - * @param os_error The OS error code to convert. - * - * @return The equivalent system error code. - */ -int os_error_to_sys(os_error_t os_error); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/lib/bt/porting/nimble/include/os/os_mbuf.h b/lib/bt/porting/nimble/include/os/os_mbuf.h deleted file mode 100644 index e6fd6b90..00000000 --- a/lib/bt/porting/nimble/include/os/os_mbuf.h +++ /dev/null @@ -1,1145 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF) - * - * SPDX-License-Identifier: Apache-2.0 - * - * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD - */ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - -/** - * @addtogroup OSKernel - * @{ - * @defgroup OSMbuf Chained Memory Buffers - * @{ - */ - - -#ifndef _OS_MBUF_H -#define _OS_MBUF_H - -#include "os/os.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * A mbuf pool from which to allocate mbufs. This contains a pointer to the os - * mempool to allocate mbufs out of, the total number of elements in the pool, - * and the amount of "user" data in a non-packet header mbuf. The total pool - * size, in bytes, should be: - * os_mbuf_count * (omp_databuf_len + sizeof(struct os_mbuf)) - */ -struct os_mbuf_pool { - /** - * Total length of the databuf in each mbuf. This is the size of the - * mempool block, minus the mbuf header - */ - uint16_t omp_databuf_len; - /** - * The memory pool which to allocate mbufs out of - */ - struct os_mempool *omp_pool; - - STAILQ_ENTRY(os_mbuf_pool) omp_next; -}; - - -/** - * A packet header structure that preceeds the mbuf packet headers. - */ -struct os_mbuf_pkthdr { - /** - * Overall length of the packet. - */ - uint16_t omp_len; - /** - * Flags - */ - uint16_t omp_flags; - - STAILQ_ENTRY(os_mbuf_pkthdr) omp_next; -}; - -/** - * Chained memory buffer. - */ -struct os_mbuf { - /** - * Current pointer to data in the structure - */ - uint8_t *om_data; - /** - * Flags associated with this buffer, see OS_MBUF_F_* defintions - */ - uint8_t om_flags; - /** - * Length of packet header - */ - uint8_t om_pkthdr_len; - /** - * Length of data in this buffer - */ - uint16_t om_len; - - /** - * The mbuf pool this mbuf was allocated out of - */ - struct os_mbuf_pool *om_omp; - - SLIST_ENTRY(os_mbuf) om_next; - - /** - * Pointer to the beginning of the data, after this buffer - */ - uint8_t om_databuf[0]; -}; - -/** - * Structure representing a queue of mbufs. - */ -struct os_mqueue { - STAILQ_HEAD(, os_mbuf_pkthdr) mq_head; - /** Event to post when new buffers are available on the queue. */ - struct ble_npl_event mq_ev; -}; - -/* - * Given a flag number, provide the mask for it - * - * @param __n The number of the flag in the mask - */ -#define OS_MBUF_F_MASK(__n) (1 << (__n)) - -/* - * Checks whether a given mbuf is a packet header mbuf - * - * @param __om The mbuf to check - */ -#define OS_MBUF_IS_PKTHDR(__om) \ - ((__om)->om_pkthdr_len >= sizeof (struct os_mbuf_pkthdr)) - -/** Get a packet header pointer given an mbuf pointer */ -#define OS_MBUF_PKTHDR(__om) ((struct os_mbuf_pkthdr *) \ - (void *)((uint8_t *)&(__om)->om_data + sizeof(struct os_mbuf))) - -/** Given a mbuf packet header pointer, return a pointer to the mbuf */ -#define OS_MBUF_PKTHDR_TO_MBUF(__hdr) \ - (struct os_mbuf *)(void *)((uint8_t *)(__hdr) - sizeof(struct os_mbuf)) - -/** - * Gets the length of an entire mbuf chain. The specified mbuf must have a - * packet header. - */ -#define OS_MBUF_PKTLEN(__om) (OS_MBUF_PKTHDR(__om)->omp_len) - -/** - * Access the data of a mbuf, and cast it to type - * - * @param __om The mbuf to access, and cast - * @param __type The type to cast it to - */ -#define OS_MBUF_DATA(__om, __type) \ - (__type) ((__om)->om_data) - -/** - * Access the "user header" in the head of an mbuf chain. - * - * @param om Pointer to the head of an mbuf chain. - */ -#define OS_MBUF_USRHDR(om) \ - (void *)((uint8_t *)om + sizeof (struct os_mbuf) + \ - sizeof (struct os_mbuf_pkthdr)) - -/** - * Retrieves the length of the user header in an mbuf. - * - * @param om Pointer to the mbuf to query. - */ -#define OS_MBUF_USRHDR_LEN(om) \ - ((om)->om_pkthdr_len - sizeof (struct os_mbuf_pkthdr)) - - -/** @cond INTERNAL_HIDDEN */ - -/* - * Called by OS_MBUF_LEADINGSPACE() macro - */ -static inline uint16_t -_os_mbuf_leadingspace(struct os_mbuf *om) -{ - uint16_t startoff; - uint16_t leadingspace; - - startoff = 0; - if (OS_MBUF_IS_PKTHDR(om)) { - startoff = om->om_pkthdr_len; - } - - leadingspace = (uint16_t) (OS_MBUF_DATA(om, uint8_t *) - - ((uint8_t *) &om->om_databuf[0] + startoff)); - - return (leadingspace); -} - -/** @endcond */ - -/** - * Returns the leading space (space at the beginning) of the mbuf. - * Works on both packet header, and regular mbufs, as it accounts - * for the additional space allocated to the packet header. - * - * @param __omp Is the mbuf pool (which contains packet header length.) - * @param __om Is the mbuf in that pool to get the leadingspace for - * - * @return Amount of leading space available in the mbuf - */ -#define OS_MBUF_LEADINGSPACE(__om) _os_mbuf_leadingspace(__om) - - -/** @cond INTERNAL_HIDDEN */ - -/* Called by OS_MBUF_TRAILINGSPACE() macro. */ -static inline uint16_t -_os_mbuf_trailingspace(struct os_mbuf *om) -{ - struct os_mbuf_pool *omp; - - omp = om->om_omp; - - return (&om->om_databuf[0] + omp->omp_databuf_len) - - (om->om_data + om->om_len); -} - -/** @endcond */ - -/** - * Returns the trailing space (space at the end) of the mbuf. - * Works on both packet header and regular mbufs. - * - * @param __omp The mbuf pool for this mbuf - * @param __om Is the mbuf in that pool to get trailing space for - * - * @return The amount of trailing space available in the mbuf - */ -#define OS_MBUF_TRAILINGSPACE(__om) _os_mbuf_trailingspace(__om) - - -#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED -/** - * Initializes an mqueue. An mqueue is a queue of mbufs that ties to a - * particular task's event queue. Mqueues form a helper API around a common - * paradigm: wait on an event queue until at least one packet is available, - * then process a queue of packets. - * - * When mbufs are available on the queue, an event OS_EVENT_T_MQUEUE_DATA - * will be posted to the task's mbuf queue. - * - * @param mq The mqueue to initialize - * @param ev_cb The callback to associate with the mqeueue - * event. Typically, this callback pulls each - * packet off the mqueue and processes them. - * @param arg The argument to associate with the mqueue event. - * - * @return 0 on success, non-zero on failure. - */ -int r_os_mqueue_init(struct os_mqueue *mq, ble_npl_event_fn *ev_cb, void *arg); -#define os_mqueue_init r_os_mqueue_init - - -/** - * Remove and return a single mbuf from the mbuf queue. Does not block. - * - * @param mq The mbuf queue to pull an element off of. - * - * @return The next mbuf in the queue, or NULL if queue has no mbufs. - */ -struct os_mbuf *r_os_mqueue_get(struct os_mqueue *); -#define os_mqueue_get r_os_mqueue_get -/** - * Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated - * with the mqueue gets posted to the specified eventq. - * - * @param mq The mbuf queue to append the mbuf to. - * @param evq The event queue to post an event to. - * @param m The mbuf to append to the mbuf queue. - * - * @return 0 on success, non-zero on failure. - */ -int r_os_mqueue_put(struct os_mqueue *, struct ble_npl_eventq *, struct os_mbuf *); -#define os_mqueue_put r_os_mqueue_put - - -/** - * MSYS is a system level mbuf registry. Allows the system to share - * packet buffers amongst the various networking stacks that can be running - * simultaeneously. - * - * Mbuf pools are created in the system initialization code, and then when - * a mbuf is allocated out of msys, it will try and find the best fit based - * upon estimated mbuf size. - * - * os_msys_register() registers a mbuf pool with MSYS, and allows MSYS to - * allocate mbufs out of it. - * - * @param new_pool The pool to register with MSYS - * - * @return 0 on success, non-zero on failure - */ -int r_os_msys_register(struct os_mbuf_pool *); -#define os_msys_register r_os_msys_register - - -/** - * Allocate a mbuf from msys. Based upon the data size requested, - * os_msys_get() will choose the mbuf pool that has the best fit. - * - * @param dsize The estimated size of the data being stored in the mbuf - * @param leadingspace The amount of leadingspace to allocate in the mbuf - * - * @return A freshly allocated mbuf on success, NULL on failure. - */ -struct os_mbuf *r_os_msys_get(uint16_t dsize, uint16_t leadingspace); -#define os_msys_get r_os_msys_get -/** - * De-registers all mbuf pools from msys. - */ -void r_os_msys_reset(void); -#define os_msys_reset r_os_msys_reset - - -/** - * Allocate a packet header structure from the MSYS pool. See - * os_msys_register() for a description of MSYS. - * - * @param dsize The estimated size of the data being stored in the mbuf - * @param user_hdr_len The length to allocate for the packet header structure - * - * @return A freshly allocated mbuf on success, NULL on failure. - */ -struct os_mbuf *r_os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len); -#define os_msys_get_pkthdr r_os_msys_get_pkthdr -/** - * Count the number of blocks in all the mbuf pools that are allocated. - * - * @return total number of blocks allocated in Msys - */ -int r_os_msys_count(void); -#define os_msys_count r_os_msys_count - - -/** - * Return the number of free blocks in Msys - * - * @return Number of free blocks available in Msys - */ -int r_os_msys_num_free(void); -#define os_msys_num_free r_os_msys_num_free - - -/** - * Initialize a pool of mbufs. - * - * @param omp The mbuf pool to initialize - * @param mp The memory pool that will hold this mbuf pool - * @param buf_len The length of the buffer itself. - * @param nbufs The number of buffers in the pool - * - * @return 0 on success, error code on failure. - */ -int r_os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp, - uint16_t, uint16_t); -#define os_mbuf_pool_init r_os_mbuf_pool_init -/** - * Get an mbuf from the mbuf pool. The mbuf is allocated, and initialized - * prior to being returned. - * - * @param omp The mbuf pool to return the packet from - * @param leadingspace The amount of leadingspace to put before the data - * section by default. - * - * @return An initialized mbuf on success, and NULL on failure. - */ -struct os_mbuf *r_os_mbuf_get(struct os_mbuf_pool *omp, uint16_t); -#define os_mbuf_get r_os_mbuf_get -/** - * Allocate a new packet header mbuf out of the os_mbuf_pool. - * - * @param omp The mbuf pool to allocate out of - * @param user_pkthdr_len The packet header length to reserve for the caller. - * - * @return A freshly allocated mbuf on success, NULL on failure. - */ -struct os_mbuf *r_os_mbuf_get_pkthdr(struct os_mbuf_pool *omp, - uint8_t pkthdr_len); -#define os_mbuf_get_pkthdr r_os_mbuf_get_pkthdr -/** - * Duplicate a chain of mbufs. Return the start of the duplicated chain. - * - * @param omp The mbuf pool to duplicate out of - * @param om The mbuf chain to duplicate - * - * @return A pointer to the new chain of mbufs - */ -struct os_mbuf *r_os_mbuf_dup(struct os_mbuf *m); -#define os_mbuf_dup r_os_mbuf_dup -/** - * Locates the specified absolute offset within an mbuf chain. The offset - * can be one past than the total length of the chain, but no greater. - * - * @param om The start of the mbuf chain to seek within. - * @param off The absolute address to find. - * @param out_off On success, this points to the relative offset - * within the returned mbuf. - * - * @return The mbuf containing the specified offset on - * success. - * NULL if the specified offset is out of bounds. - */ -struct os_mbuf *r_os_mbuf_off(const struct os_mbuf *om, int off, - uint16_t *out_off); -#define os_mbuf_off r_os_mbuf_off - -/* - * Copy data from an mbuf chain starting "off" bytes from the beginning, - * continuing for "len" bytes, into the indicated buffer. - * - * @param m The mbuf chain to copy from - * @param off The offset into the mbuf chain to begin copying from - * @param len The length of the data to copy - * @param dst The destination buffer to copy into - * - * @return 0 on success; - * -1 if the mbuf does not contain enough data. - */ -int r_os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst); -#define os_mbuf_copydata r_os_mbuf_copydata - - -/** - * @brief Calculates the length of an mbuf chain. - * - * Calculates the length of an mbuf chain. If the mbuf contains a packet - * header, you should use `OS_MBUF_PKTLEN()` as a more efficient alternative to - * this function. - * - * @param om The mbuf to measure. - * - * @return The length, in bytes, of the provided mbuf - * chain. - */ -uint16_t r_os_mbuf_len(const struct os_mbuf *om); -#define os_mbuf_len r_os_mbuf_len - - -/** - * Append data onto a mbuf - * - * @param om The mbuf to append the data onto - * @param data The data to append onto the mbuf - * @param len The length of the data to append - * - * @return 0 on success, and an error code on failure - */ -int r_os_mbuf_append(struct os_mbuf *m, const void *, uint16_t); -#define os_mbuf_append r_os_mbuf_append - - -/** - * Reads data from one mbuf and appends it to another. On error, the specified - * data range may be partially appended. Neither mbuf is required to contain - * an mbuf packet header. - * - * @param dst The mbuf to append to. - * @param src The mbuf to copy data from. - * @param src_off The absolute offset within the source mbuf - * chain to read from. - * @param len The number of bytes to append. - * - * @return 0 on success; - * OS_EINVAL if the specified range extends beyond - * the end of the source mbuf chain. - */ -int r_os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src, - uint16_t src_off, uint16_t len); -#define os_mbuf_appendfrom r_os_mbuf_appendfrom -/** - * Release a mbuf back to the pool - * - * @param omp The Mbuf pool to release back to - * @param om The Mbuf to release back to the pool - * - * @return 0 on success, -1 on failure - */ -int r_os_mbuf_free(struct os_mbuf *mb); -#define os_mbuf_free r_os_mbuf_free - - -/** - * Free a chain of mbufs - * - * @param omp The mbuf pool to free the chain of mbufs into - * @param om The starting mbuf of the chain to free back into the pool - * - * @return 0 on success, -1 on failure - */ -int r_os_mbuf_free_chain(struct os_mbuf *om); -#define os_mbuf_free_chain r_os_mbuf_free_chain - - -/** - * Adjust the length of a mbuf, trimming either from the head or the tail - * of the mbuf. - * - * @param mp The mbuf chain to adjust - * @param req_len The length to trim from the mbuf. If positive, trims - * from the head of the mbuf, if negative, trims from the - * tail of the mbuf. - */ -void r_os_mbuf_adj(struct os_mbuf *mp, int req_len); -#define os_mbuf_adj r_os_mbuf_adj - - - -/** - * Performs a memory compare of the specified region of an mbuf chain against a - * flat buffer. - * - * @param om The start of the mbuf chain to compare. - * @param off The offset within the mbuf chain to start the - * comparison. - * @param data The flat buffer to compare. - * @param len The length of the flat buffer. - * - * @return 0 if both memory regions are identical; - * A memcmp return code if there is a mismatch; - * INT_MAX if the mbuf is too short. - */ -int r_os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len); -#define os_mbuf_cmpf r_os_mbuf_cmpf - - -/** - * Compares the contents of two mbuf chains. The ranges of the two chains to - * be compared are specified via the two offset parameters and the len - * parameter. Neither mbuf chain is required to contain a packet header. - * - * @param om1 The first mbuf chain to compare. - * @param offset1 The absolute offset within om1 at which to - * start the comparison. - * @param om2 The second mbuf chain to compare. - * @param offset2 The absolute offset within om2 at which to - * start the comparison. - * @param len The number of bytes to compare. - * - * @return 0 if both mbuf segments are identical; - * A memcmp() return code if the segment contents - * differ; - * INT_MAX if a specified range extends beyond the - * end of its corresponding mbuf chain. - */ -int r_os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1, - const struct os_mbuf *om2, uint16_t offset2, - uint16_t len); -#define os_mbuf_cmpm r_os_mbuf_cmpm -/** - * Increases the length of an mbuf chain by adding data to the front. If there - * is insufficient room in the leading mbuf, additional mbufs are allocated and - * prepended as necessary. If this function fails to allocate an mbuf, the - * entire chain is freed. - * - * The specified mbuf chain does not need to contain a packet header. - * - * @param omp The mbuf pool to allocate from. - * @param om The head of the mbuf chain. - * @param len The number of bytes to prepend. - * - * @return The new head of the chain on success; - * NULL on failure. - */ -struct os_mbuf *r_os_mbuf_prepend(struct os_mbuf *om, int len); -#define os_mbuf_prepend r_os_mbuf_prepend -/** - * Prepends a chunk of empty data to the specified mbuf chain and ensures the - * chunk is contiguous. If either operation fails, the specified mbuf chain is - * freed and NULL is returned. - * - * @param om The mbuf chain to prepend to. - * @param len The number of bytes to prepend and pullup. - * - * @return The modified mbuf on success; - * NULL on failure (and the mbuf chain is freed). - */ -struct os_mbuf *r_os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len); -#define os_mbuf_prepend_pullup r_os_mbuf_prepend_pullup -/** - * Copies the contents of a flat buffer into an mbuf chain, starting at the - * specified destination offset. If the mbuf is too small for the source data, - * it is extended as necessary. If the destination mbuf contains a packet - * header, the header length is updated. - * - * @param omp The mbuf pool to allocate from. - * @param om The mbuf chain to copy into. - * @param off The offset within the chain to copy to. - * @param src The source buffer to copy from. - * @param len The number of bytes to copy. - * - * @return 0 on success; nonzero on failure. - */ -int r_os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len); -#define os_mbuf_copyinto r_os_mbuf_copyinto - - -/** - * Attaches a second mbuf chain onto the end of the first. If the first chain - * contains a packet header, the header's length is updated. If the second - * chain has a packet header, its header is cleared. - * - * @param first The mbuf chain being attached to. - * @param second The mbuf chain that gets attached. - */ -void r_os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second); -#define os_mbuf_concat r_os_mbuf_concat - - - -/** - * Increases the length of an mbuf chain by the specified amount. If there is - * not sufficient room in the last buffer, a new buffer is allocated and - * appended to the chain. It is an error to request more data than can fit in - * a single buffer. - * - * @param omp - * @param om The head of the chain to extend. - * @param len The number of bytes to extend by. - * - * @return A pointer to the new data on success; - * NULL on failure. - */ -void *r_os_mbuf_extend(struct os_mbuf *om, uint16_t len); -#define os_mbuf_extend r_os_mbuf_extend -/** - * Rearrange a mbuf chain so that len bytes are contiguous, - * and in the data area of an mbuf (so that OS_MBUF_DATA() will - * work on a structure of size len.) Returns the resulting - * mbuf chain on success, free's it and returns NULL on failure. - * - * If there is room, it will add up to "max_protohdr - len" - * extra bytes to the contiguous region, in an attempt to avoid being - * called next time. - * - * @param omp The mbuf pool to take the mbufs out of - * @param om The mbuf chain to make contiguous - * @param len The number of bytes in the chain to make contiguous - * - * @return The contiguous mbuf chain on success, NULL on failure. - */ -struct os_mbuf *r_os_mbuf_pullup(struct os_mbuf *om, uint16_t len); -#define os_mbuf_pullup r_os_mbuf_pullup - -/** - * Removes and frees empty mbufs from the front of a chain. If the chain - * contains a packet header, it is preserved. - * - * @param om The mbuf chain to trim. - * - * @return The head of the trimmed mbuf chain. - */ -struct os_mbuf *r_os_mbuf_trim_front(struct os_mbuf *om); -#define os_mbuf_trim_front r_os_mbuf_trim_front -/** - * Increases the length of an mbuf chain by inserting a gap at the specified - * offset. The contents of the gap are indeterminate. If the mbuf chain - * contains a packet header, its total length is increased accordingly. - * - * This function never frees the provided mbuf chain. - * - * @param om The mbuf chain to widen. - * @param off The offset at which to insert the gap. - * @param len The size of the gap to insert. - * - * @return 0 on success; SYS_[...] error code on failure. - */ -int r_os_mbuf_widen(struct os_mbuf *om, uint16_t off, uint16_t len); -#define os_mbuf_widen r_os_mbuf_widen - - - -/** - * Creates a single chained mbuf from m1 and m2 utilizing all - * the available buffer space in all mbufs in the resulting - * chain. In other words, ensures there is no leading space in - * any mbuf in the resulting chain and trailing space only in - * the last mbuf in the chain. Mbufs from either chain may be - * freed if not needed. No mbufs are allocated. Note that mbufs - * from m2 are added to the end of m1. If m1 has a packet - * header, it is retained and length updated. If m2 has a packet - * header it is discarded. If m1 is NULL, NULL is returned and - * m2 is left untouched. - * - * @param m1 Pointer to first mbuf chain to pack - * @param m2 Pointer to second mbuf chain to pack - * - * @return struct os_mbuf* Pointer to resulting mbuf chain - */ -struct os_mbuf *r_os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2); -#define os_mbuf_pack_chains r_os_mbuf_pack_chains - -#else -/** - * Initializes an mqueue. An mqueue is a queue of mbufs that ties to a - * particular task's event queue. Mqueues form a helper API around a common - * paradigm: wait on an event queue until at least one packet is available, - * then process a queue of packets. - * - * When mbufs are available on the queue, an event OS_EVENT_T_MQUEUE_DATA - * will be posted to the task's mbuf queue. - * - * @param mq The mqueue to initialize - * @param ev_cb The callback to associate with the mqeueue - * event. Typically, this callback pulls each - * packet off the mqueue and processes them. - * @param arg The argument to associate with the mqueue event. - * - * @return 0 on success, non-zero on failure. - */ -int os_mqueue_init(struct os_mqueue *mq, ble_npl_event_fn *ev_cb, void *arg); - -/** - * Remove and return a single mbuf from the mbuf queue. Does not block. - * - * @param mq The mbuf queue to pull an element off of. - * - * @return The next mbuf in the queue, or NULL if queue has no mbufs. - */ -struct os_mbuf *os_mqueue_get(struct os_mqueue *); - -/** - * Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated - * with the mqueue gets posted to the specified eventq. - * - * @param mq The mbuf queue to append the mbuf to. - * @param evq The event queue to post an event to. - * @param m The mbuf to append to the mbuf queue. - * - * @return 0 on success, non-zero on failure. - */ -int os_mqueue_put(struct os_mqueue *, struct ble_npl_eventq *, struct os_mbuf *); - -/** - * MSYS is a system level mbuf registry. Allows the system to share - * packet buffers amongst the various networking stacks that can be running - * simultaeneously. - * - * Mbuf pools are created in the system initialization code, and then when - * a mbuf is allocated out of msys, it will try and find the best fit based - * upon estimated mbuf size. - * - * os_msys_register() registers a mbuf pool with MSYS, and allows MSYS to - * allocate mbufs out of it. - * - * @param new_pool The pool to register with MSYS - * - * @return 0 on success, non-zero on failure - */ -int os_msys_register(struct os_mbuf_pool *); - -/** - * Allocate a mbuf from msys. Based upon the data size requested, - * os_msys_get() will choose the mbuf pool that has the best fit. - * - * @param dsize The estimated size of the data being stored in the mbuf - * @param leadingspace The amount of leadingspace to allocate in the mbuf - * - * @return A freshly allocated mbuf on success, NULL on failure. - */ -struct os_mbuf *os_msys_get(uint16_t dsize, uint16_t leadingspace); - -/** - * De-registers all mbuf pools from msys. - */ -void os_msys_reset(void); - -/** - * Allocate a packet header structure from the MSYS pool. See - * os_msys_register() for a description of MSYS. - * - * @param dsize The estimated size of the data being stored in the mbuf - * @param user_hdr_len The length to allocate for the packet header structure - * - * @return A freshly allocated mbuf on success, NULL on failure. - */ -struct os_mbuf *os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len); - -/** - * Count the number of blocks in all the mbuf pools that are allocated. - * - * @return total number of blocks allocated in Msys - */ -int os_msys_count(void); - -/** - * Return the number of free blocks in Msys - * - * @return Number of free blocks available in Msys - */ -int os_msys_num_free(void); - -/** - * Initialize a pool of mbufs. - * - * @param omp The mbuf pool to initialize - * @param mp The memory pool that will hold this mbuf pool - * @param buf_len The length of the buffer itself. - * @param nbufs The number of buffers in the pool - * - * @return 0 on success, error code on failure. - */ -int os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp, - uint16_t, uint16_t); - -/** - * Get an mbuf from the mbuf pool. The mbuf is allocated, and initialized - * prior to being returned. - * - * @param omp The mbuf pool to return the packet from - * @param leadingspace The amount of leadingspace to put before the data - * section by default. - * - * @return An initialized mbuf on success, and NULL on failure. - */ -struct os_mbuf *os_mbuf_get(struct os_mbuf_pool *omp, uint16_t); - -/** - * Allocate a new packet header mbuf out of the os_mbuf_pool. - * - * @param omp The mbuf pool to allocate out of - * @param user_pkthdr_len The packet header length to reserve for the caller. - * - * @return A freshly allocated mbuf on success, NULL on failure. - */ -struct os_mbuf *os_mbuf_get_pkthdr(struct os_mbuf_pool *omp, - uint8_t pkthdr_len); - -/** - * Duplicate a chain of mbufs. Return the start of the duplicated chain. - * - * @param omp The mbuf pool to duplicate out of - * @param om The mbuf chain to duplicate - * - * @return A pointer to the new chain of mbufs - */ -struct os_mbuf *os_mbuf_dup(struct os_mbuf *m); - -/** - * Locates the specified absolute offset within an mbuf chain. The offset - * can be one past than the total length of the chain, but no greater. - * - * @param om The start of the mbuf chain to seek within. - * @param off The absolute address to find. - * @param out_off On success, this points to the relative offset - * within the returned mbuf. - * - * @return The mbuf containing the specified offset on - * success. - * NULL if the specified offset is out of bounds. - */ -struct os_mbuf *os_mbuf_off(const struct os_mbuf *om, int off, - uint16_t *out_off); - - -/* - * Copy data from an mbuf chain starting "off" bytes from the beginning, - * continuing for "len" bytes, into the indicated buffer. - * - * @param m The mbuf chain to copy from - * @param off The offset into the mbuf chain to begin copying from - * @param len The length of the data to copy - * @param dst The destination buffer to copy into - * - * @return 0 on success; - * -1 if the mbuf does not contain enough data. - */ -int os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst); - -/** - * @brief Calculates the length of an mbuf chain. - * - * Calculates the length of an mbuf chain. If the mbuf contains a packet - * header, you should use `OS_MBUF_PKTLEN()` as a more efficient alternative to - * this function. - * - * @param om The mbuf to measure. - * - * @return The length, in bytes, of the provided mbuf - * chain. - */ -uint16_t os_mbuf_len(const struct os_mbuf *om); - -/** - * Append data onto a mbuf - * - * @param om The mbuf to append the data onto - * @param data The data to append onto the mbuf - * @param len The length of the data to append - * - * @return 0 on success, and an error code on failure - */ -int os_mbuf_append(struct os_mbuf *m, const void *, uint16_t); - -/** - * Reads data from one mbuf and appends it to another. On error, the specified - * data range may be partially appended. Neither mbuf is required to contain - * an mbuf packet header. - * - * @param dst The mbuf to append to. - * @param src The mbuf to copy data from. - * @param src_off The absolute offset within the source mbuf - * chain to read from. - * @param len The number of bytes to append. - * - * @return 0 on success; - * OS_EINVAL if the specified range extends beyond - * the end of the source mbuf chain. - */ -int os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src, - uint16_t src_off, uint16_t len); - -/** - * Release a mbuf back to the pool - * - * @param omp The Mbuf pool to release back to - * @param om The Mbuf to release back to the pool - * - * @return 0 on success, -1 on failure - */ -int os_mbuf_free(struct os_mbuf *mb); - -/** - * Free a chain of mbufs - * - * @param omp The mbuf pool to free the chain of mbufs into - * @param om The starting mbuf of the chain to free back into the pool - * - * @return 0 on success, -1 on failure - */ -int os_mbuf_free_chain(struct os_mbuf *om); - -/** - * Adjust the length of a mbuf, trimming either from the head or the tail - * of the mbuf. - * - * @param mp The mbuf chain to adjust - * @param req_len The length to trim from the mbuf. If positive, trims - * from the head of the mbuf, if negative, trims from the - * tail of the mbuf. - */ -void os_mbuf_adj(struct os_mbuf *mp, int req_len); - - -/** - * Performs a memory compare of the specified region of an mbuf chain against a - * flat buffer. - * - * @param om The start of the mbuf chain to compare. - * @param off The offset within the mbuf chain to start the - * comparison. - * @param data The flat buffer to compare. - * @param len The length of the flat buffer. - * - * @return 0 if both memory regions are identical; - * A memcmp return code if there is a mismatch; - * INT_MAX if the mbuf is too short. - */ -int os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len); - -/** - * Compares the contents of two mbuf chains. The ranges of the two chains to - * be compared are specified via the two offset parameters and the len - * parameter. Neither mbuf chain is required to contain a packet header. - * - * @param om1 The first mbuf chain to compare. - * @param offset1 The absolute offset within om1 at which to - * start the comparison. - * @param om2 The second mbuf chain to compare. - * @param offset2 The absolute offset within om2 at which to - * start the comparison. - * @param len The number of bytes to compare. - * - * @return 0 if both mbuf segments are identical; - * A memcmp() return code if the segment contents - * differ; - * INT_MAX if a specified range extends beyond the - * end of its corresponding mbuf chain. - */ -int os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1, - const struct os_mbuf *om2, uint16_t offset2, - uint16_t len); - -/** - * Increases the length of an mbuf chain by adding data to the front. If there - * is insufficient room in the leading mbuf, additional mbufs are allocated and - * prepended as necessary. If this function fails to allocate an mbuf, the - * entire chain is freed. - * - * The specified mbuf chain does not need to contain a packet header. - * - * @param omp The mbuf pool to allocate from. - * @param om The head of the mbuf chain. - * @param len The number of bytes to prepend. - * - * @return The new head of the chain on success; - * NULL on failure. - */ -struct os_mbuf *os_mbuf_prepend(struct os_mbuf *om, int len); - -/** - * Prepends a chunk of empty data to the specified mbuf chain and ensures the - * chunk is contiguous. If either operation fails, the specified mbuf chain is - * freed and NULL is returned. - * - * @param om The mbuf chain to prepend to. - * @param len The number of bytes to prepend and pullup. - * - * @return The modified mbuf on success; - * NULL on failure (and the mbuf chain is freed). - */ -struct os_mbuf *os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len); - -/** - * Copies the contents of a flat buffer into an mbuf chain, starting at the - * specified destination offset. If the mbuf is too small for the source data, - * it is extended as necessary. If the destination mbuf contains a packet - * header, the header length is updated. - * - * @param omp The mbuf pool to allocate from. - * @param om The mbuf chain to copy into. - * @param off The offset within the chain to copy to. - * @param src The source buffer to copy from. - * @param len The number of bytes to copy. - * - * @return 0 on success; nonzero on failure. - */ -int os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len); - -/** - * Attaches a second mbuf chain onto the end of the first. If the first chain - * contains a packet header, the header's length is updated. If the second - * chain has a packet header, its header is cleared. - * - * @param first The mbuf chain being attached to. - * @param second The mbuf chain that gets attached. - */ -void os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second); - - -/** - * Increases the length of an mbuf chain by the specified amount. If there is - * not sufficient room in the last buffer, a new buffer is allocated and - * appended to the chain. It is an error to request more data than can fit in - * a single buffer. - * - * @param omp - * @param om The head of the chain to extend. - * @param len The number of bytes to extend by. - * - * @return A pointer to the new data on success; - * NULL on failure. - */ -void *os_mbuf_extend(struct os_mbuf *om, uint16_t len); - -/** - * Rearrange a mbuf chain so that len bytes are contiguous, - * and in the data area of an mbuf (so that OS_MBUF_DATA() will - * work on a structure of size len.) Returns the resulting - * mbuf chain on success, free's it and returns NULL on failure. - * - * If there is room, it will add up to "max_protohdr - len" - * extra bytes to the contiguous region, in an attempt to avoid being - * called next time. - * - * @param omp The mbuf pool to take the mbufs out of - * @param om The mbuf chain to make contiguous - * @param len The number of bytes in the chain to make contiguous - * - * @return The contiguous mbuf chain on success, NULL on failure. - */ -struct os_mbuf *os_mbuf_pullup(struct os_mbuf *om, uint16_t len); - - -/** - * Removes and frees empty mbufs from the front of a chain. If the chain - * contains a packet header, it is preserved. - * - * @param om The mbuf chain to trim. - * - * @return The head of the trimmed mbuf chain. - */ -struct os_mbuf *os_mbuf_trim_front(struct os_mbuf *om); - -/** - * Increases the length of an mbuf chain by inserting a gap at the specified - * offset. The contents of the gap are indeterminate. If the mbuf chain - * contains a packet header, its total length is increased accordingly. - * - * This function never frees the provided mbuf chain. - * - * @param om The mbuf chain to widen. - * @param off The offset at which to insert the gap. - * @param len The size of the gap to insert. - * - * @return 0 on success; SYS_[...] error code on failure. - */ -int os_mbuf_widen(struct os_mbuf *om, uint16_t off, uint16_t len); - - -/** - * Creates a single chained mbuf from m1 and m2 utilizing all - * the available buffer space in all mbufs in the resulting - * chain. In other words, ensures there is no leading space in - * any mbuf in the resulting chain and trailing space only in - * the last mbuf in the chain. Mbufs from either chain may be - * freed if not needed. No mbufs are allocated. Note that mbufs - * from m2 are added to the end of m1. If m1 has a packet - * header, it is retained and length updated. If m2 has a packet - * header it is discarded. If m1 is NULL, NULL is returned and - * m2 is left untouched. - * - * @param m1 Pointer to first mbuf chain to pack - * @param m2 Pointer to second mbuf chain to pack - * - * @return struct os_mbuf* Pointer to resulting mbuf chain - */ -struct os_mbuf *os_mbuf_pack_chains(struct os_mbuf *m1, struct os_mbuf *m2); - -#endif -#ifdef __cplusplus -} -#endif - -#endif /* _OS_MBUF_H */ - - -/** - * @} OSMbuf - * @} OSKernel - */ diff --git a/lib/bt/porting/nimble/include/os/os_mempool.h b/lib/bt/porting/nimble/include/os/os_mempool.h deleted file mode 100644 index 3ef8e6d5..00000000 --- a/lib/bt/porting/nimble/include/os/os_mempool.h +++ /dev/null @@ -1,407 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF) - * - * SPDX-License-Identifier: Apache-2.0 - * - * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD - */ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/** - * @addtogroup OSKernel - * @{ - * @defgroup OSMempool Memory Pools - * @{ - */ - - -#ifndef _OS_MEMPOOL_H_ -#define _OS_MEMPOOL_H_ - -#include -#include "os/os.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * A memory block structure. This simply contains a pointer to the free list - * chain and is only used when the block is on the free list. When the block - * has been removed from the free list the entire memory block is usable by the - * caller. - */ -struct os_memblock { - SLIST_ENTRY(os_memblock) mb_next; -}; - -/* XXX: Change this structure so that we keep the first address in the pool? */ -/* XXX: add memory debug structure and associated code */ -/* XXX: Change how I coded the SLIST_HEAD here. It should be named: - SLIST_HEAD(,os_memblock) mp_head; */ - -/** - * Memory pool - */ -struct os_mempool { - /** Size of the memory blocks, in bytes. */ - uint32_t mp_block_size; - /** The number of memory blocks. */ - uint16_t mp_num_blocks; - /** The number of free blocks left */ - uint16_t mp_num_free; - /** The lowest number of free blocks seen */ - uint16_t mp_min_free; - /** Bitmap of OS_MEMPOOL_F_[...] values. */ - uint8_t mp_flags; - /** Address of memory buffer used by pool */ - uint32_t mp_membuf_addr; - STAILQ_ENTRY(os_mempool) mp_list; - SLIST_HEAD(,os_memblock); - /** Name for memory block */ - const char *name; -}; - -/** - * Indicates an extended mempool. Address can be safely cast to - * (struct os_mempool_ext *). - */ -#define OS_MEMPOOL_F_EXT 0x01 - -struct os_mempool_ext; - -/** - * Block put callback function. If configured, this callback gets executed - * whenever a block is freed to the corresponding extended mempool. Note: The - * os_memblock_put() function calls this callback instead of freeing the block - * itself. Therefore, it is the callback's responsibility to free the block - * via a call to os_memblock_put_from_cb(). - * - * @param ome The extended mempool that a block is being - * freed back to. - * @param data The block being freed. - * @param arg Optional argument configured along with the - * callback. - * - * @return Indicates whether the block was successfully - * freed. A non-zero value should only be - * returned if the block was not successfully - * released back to its pool. - */ -typedef os_error_t os_mempool_put_fn(struct os_mempool_ext *ome, void *data, - void *arg); - -struct os_mempool_ext { - struct os_mempool mpe_mp; - - /* Callback that is executed immediately when a block is freed. */ - os_mempool_put_fn *mpe_put_cb; - void *mpe_put_arg; -}; - -#define OS_MEMPOOL_INFO_NAME_LEN (32) - -/** - * Information describing a memory pool, used to return OS information - * to the management layer. - */ -struct os_mempool_info { - /** Size of the memory blocks in the pool */ - int omi_block_size; - /** Number of memory blocks in the pool */ - int omi_num_blocks; - /** Number of free memory blocks */ - int omi_num_free; - /** Minimum number of free memory blocks ever */ - int omi_min_free; - /** Name of the memory pool */ - char omi_name[OS_MEMPOOL_INFO_NAME_LEN]; -}; - -/** - * Get information about the next system memory pool. - * - * @param mempool The current memory pool, or NULL if starting iteration. - * @param info A pointer to the structure to return memory pool information - * into. - * - * @return The next memory pool in the list to get information about, or NULL - * when at the last memory pool. - */ -struct os_mempool *os_mempool_info_get_next(struct os_mempool *, - struct os_mempool_info *); - -#if (OS_ALIGNMENT == 4) -typedef uint32_t os_membuf_t; -#elif (OS_ALIGNMENT == 8) -typedef uint64_t os_membuf_t; -#elif (OS_ALIGNMENT == 16) -typedef __uint128_t os_membuf_t; -#else -#error "Unhandled `OS_ALIGNMENT` for `os_membuf_t`" -#endif /* OS_ALIGNMENT == * */ -#define OS_MEMPOOL_SIZE(n,blksize) ((((blksize) + ((OS_ALIGNMENT)-1)) / (OS_ALIGNMENT)) * (n)) - -/** Calculates the number of bytes required to initialize a memory pool. */ -#define OS_MEMPOOL_BYTES(n,blksize) \ - (sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize))) - -#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED -/** - * Initialize a memory pool. - * - * @param mp Pointer to a pointer to a mempool - * @param blocks The number of blocks in the pool - * @param blocks_size The size of the block, in bytes. - * @param membuf Pointer to memory to contain blocks. - * @param name Name of the pool. - * - * @return os_error_t - */ -os_error_t r_os_mempool_init(struct os_mempool *mp, uint16_t blocks, - uint32_t block_size, void *membuf, const char *name); -#define os_mempool_init r_os_mempool_init -/** - * Initializes an extended memory pool. Extended attributes (e.g., callbacks) - * are not specified when this function is called; they are assigned manually - * after initialization. - * - * @param mpe The extended memory pool to initialize. - * @param blocks The number of blocks in the pool. - * @param block_size The size of each block, in bytes. - * @param membuf Pointer to memory to contain blocks. - * @param name Name of the pool. - * - * @return os_error_t - */ -os_error_t r_os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks, - uint32_t block_size, void *membuf, const char *name); -#define os_mempool_ext_init r_os_mempool_ext_init -/** - * Removes the specified mempool from the list of initialized mempools. - * - * @param mp The mempool to unregister. - * - * @return 0 on success; - * OS_INVALID_PARM if the mempool is not - * registered. - */ -os_error_t r_os_mempool_unregister(struct os_mempool *mp); -#define os_mempool_unregister r_os_mempool_unregister - - -/** - * Clears a memory pool. - * - * @param mp The mempool to clear. - * - * @return os_error_t - */ -os_error_t r_os_mempool_clear(struct os_mempool *mp); -#define os_mempool_clear r_os_mempool_clear - - -/** - * Performs an integrity check of the specified mempool. This function - * attempts to detect memory corruption in the specified memory pool. - * - * @param mp The mempool to check. - * - * @return true if the memory pool passes the integrity - * check; - * false if the memory pool is corrupt. - */ -bool r_os_mempool_is_sane(const struct os_mempool *mp); -#define os_mempool_is_sane r_os_mempool_is_sane - - -/** - * Checks if a memory block was allocated from the specified mempool. - * - * @param mp The mempool to check as parent. - * @param block_addr The memory block to check as child. - * - * @return 0 if the block does not belong to the mempool; - * 1 if the block does belong to the mempool. - */ -int r_os_memblock_from(const struct os_mempool *mp, const void *block_addr); -#define os_memblock_from r_os_memblock_from - - -/** - * Get a memory block from a memory pool - * - * @param mp Pointer to the memory pool - * - * @return void* Pointer to block if available; NULL otherwise - */ -void *r_os_memblock_get(struct os_mempool *mp); -#define os_memblock_get r_os_memblock_get -/** - * Puts the memory block back into the pool, ignoring the put callback, if any. - * This function should only be called from a put callback to free a block - * without causing infinite recursion. - * - * @param mp Pointer to memory pool - * @param block_addr Pointer to memory block - * - * @return os_error_t - */ -os_error_t r_os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr); -#define os_memblock_put_from_cb r_os_memblock_put_from_cb - - -/** - * Puts the memory block back into the pool - * - * @param mp Pointer to memory pool - * @param block_addr Pointer to memory block - * - * @return os_error_t - */ -os_error_t r_os_memblock_put(struct os_mempool *mp, void *block_addr); -#define os_memblock_put r_os_memblock_put - -#else -/** - * Initialize a memory pool. - * - * @param mp Pointer to a pointer to a mempool - * @param blocks The number of blocks in the pool - * @param blocks_size The size of the block, in bytes. - * @param membuf Pointer to memory to contain blocks. - * @param name Name of the pool. - * - * @return os_error_t - */ -os_error_t os_mempool_init(struct os_mempool *mp, uint16_t blocks, - uint32_t block_size, void *membuf, const char *name); - -/** - * Initializes an extended memory pool. Extended attributes (e.g., callbacks) - * are not specified when this function is called; they are assigned manually - * after initialization. - * - * @param mpe The extended memory pool to initialize. - * @param blocks The number of blocks in the pool. - * @param block_size The size of each block, in bytes. - * @param membuf Pointer to memory to contain blocks. - * @param name Name of the pool. - * - * @return os_error_t - */ -os_error_t os_mempool_ext_init(struct os_mempool_ext *mpe, uint16_t blocks, - uint32_t block_size, void *membuf, const char *name); - -/** - * Removes the specified mempool from the list of initialized mempools. - * - * @param mp The mempool to unregister. - * - * @return 0 on success; - * OS_INVALID_PARM if the mempool is not - * registered. - */ -os_error_t os_mempool_unregister(struct os_mempool *mp); - -/** - * Clears a memory pool. - * - * @param mp The mempool to clear. - * - * @return os_error_t - */ -os_error_t os_mempool_clear(struct os_mempool *mp); - -/** - * Clears an extended memory pool. - * - * @param mpe The extended memory pool to clear. - * - * @return os_error_t - */ -os_error_t os_mempool_ext_clear(struct os_mempool_ext *mpe); - -/** - * Performs an integrity check of the specified mempool. This function - * attempts to detect memory corruption in the specified memory pool. - * - * @param mp The mempool to check. - * - * @return true if the memory pool passes the integrity - * check; - * false if the memory pool is corrupt. - */ -bool os_mempool_is_sane(const struct os_mempool *mp); - -/** - * Checks if a memory block was allocated from the specified mempool. - * - * @param mp The mempool to check as parent. - * @param block_addr The memory block to check as child. - * - * @return 0 if the block does not belong to the mempool; - * 1 if the block does belong to the mempool. - */ -int os_memblock_from(const struct os_mempool *mp, const void *block_addr); - -/** - * Get a memory block from a memory pool - * - * @param mp Pointer to the memory pool - * - * @return void* Pointer to block if available; NULL otherwise - */ -void *os_memblock_get(struct os_mempool *mp); - -/** - * Puts the memory block back into the pool, ignoring the put callback, if any. - * This function should only be called from a put callback to free a block - * without causing infinite recursion. - * - * @param mp Pointer to memory pool - * @param block_addr Pointer to memory block - * - * @return os_error_t - */ -os_error_t os_memblock_put_from_cb(struct os_mempool *mp, void *block_addr); - -/** - * Puts the memory block back into the pool - * - * @param mp Pointer to memory pool - * @param block_addr Pointer to memory block - * - * @return os_error_t - */ -os_error_t os_memblock_put(struct os_mempool *mp, void *block_addr); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _OS_MEMPOOL_H_ */ - - -/** - * @} OSMempool - * @} OSKernel - */ diff --git a/lib/bt/porting/nimble/include/os/queue.h b/lib/bt/porting/nimble/include/os/queue.h deleted file mode 100644 index c184a394..00000000 --- a/lib/bt/porting/nimble/include/os/queue.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - * $FreeBSD: src/sys/sys/queue.h,v 1.32.2.7 2002/04/17 14:21:02 des Exp $ - */ - -#ifndef _QUEUE_H_ -#define _QUEUE_H_ - -/* The common BSD linked list queue macros are already defined here for ESP-IDF */ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * This file defines circular queues. The other types of data structures: - * singly-linked lists, singly-linked tail queues, lists and tail queues - * are used from sys/queue.h - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A singly-linked tail queue is headed by a pair of pointers, one to the - * head of the list and the other to the tail of the list. The elements are - * singly linked for minimum space and pointer manipulation overhead at the - * expense of O(n) removal for arbitrary elements. New elements can be added - * to the list after an existing element, at the head of the list, or at the - * end of the list. Elements being removed from the head of the tail queue - * should use the explicit macro for this purpose for optimum efficiency. - * A singly-linked tail queue may only be traversed in the forward direction. - * Singly-linked tail queues are ideal for applications with large datasets - * and few or no removals or for implementing a FIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * A circle queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the list. - * A circle queue may be traversed in either direction, but has a more - * complex end of list detection. - * - * For details on the use of these macros, see the queue(3) manual page. - * - * - * SLIST LIST STAILQ TAILQ CIRCLEQ - * _HEAD + + + + + - * _HEAD_INITIALIZER + + + + + - * _ENTRY + + + + + - * _INIT + + + + + - * _EMPTY + + + + + - * _FIRST + + + + + - * _NEXT + + + + + - * _PREV - - - + + - * _LAST - - + + + - * _FOREACH + + + + + - * _FOREACH_REVERSE - - - + + - * _INSERT_HEAD + + + + + - * _INSERT_BEFORE - + - + + - * _INSERT_AFTER + + + + + - * _INSERT_TAIL - - + + + - * _REMOVE_HEAD + - + - - - * _REMOVE + + + + + - * - */ - -/* - * Circular queue declarations. - */ -#define CIRCLEQ_HEAD(name, type) \ -struct name { \ - struct type *cqh_first; /* first element */ \ - struct type *cqh_last; /* last element */ \ -} - -#define CIRCLEQ_HEAD_INITIALIZER(head) \ - { (void *)&(head), (void *)&(head) } - -#define CIRCLEQ_ENTRY(type) \ -struct { \ - struct type *cqe_next; /* next element */ \ - struct type *cqe_prev; /* previous element */ \ -} - -/* - * Circular queue functions. - */ -#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) - -#define CIRCLEQ_FIRST(head) ((head)->cqh_first) - -#define CIRCLEQ_FOREACH(var, head, field) \ - for ((var) = CIRCLEQ_FIRST((head)); \ - (var) != (void *)(head) || ((var) = NULL); \ - (var) = CIRCLEQ_NEXT((var), field)) - -#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ - for ((var) = CIRCLEQ_LAST((head)); \ - (var) != (void *)(head) || ((var) = NULL); \ - (var) = CIRCLEQ_PREV((var), field)) - -#define CIRCLEQ_INIT(head) do { \ - CIRCLEQ_FIRST((head)) = (void *)(head); \ - CIRCLEQ_LAST((head)) = (void *)(head); \ -} while (0) - -#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field); \ - CIRCLEQ_PREV((elm), field) = (listelm); \ - if (CIRCLEQ_NEXT((listelm), field) == (void *)(head)) \ - CIRCLEQ_LAST((head)) = (elm); \ - else \ - CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\ - CIRCLEQ_NEXT((listelm), field) = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ - CIRCLEQ_NEXT((elm), field) = (listelm); \ - CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field); \ - if (CIRCLEQ_PREV((listelm), field) == (void *)(head)) \ - CIRCLEQ_FIRST((head)) = (elm); \ - else \ - CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\ - CIRCLEQ_PREV((listelm), field) = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ - CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head)); \ - CIRCLEQ_PREV((elm), field) = (void *)(head); \ - if (CIRCLEQ_LAST((head)) == (void *)(head)) \ - CIRCLEQ_LAST((head)) = (elm); \ - else \ - CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm); \ - CIRCLEQ_FIRST((head)) = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ - CIRCLEQ_NEXT((elm), field) = (void *)(head); \ - CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head)); \ - if (CIRCLEQ_FIRST((head)) == (void *)(head)) \ - CIRCLEQ_FIRST((head)) = (elm); \ - else \ - CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm); \ - CIRCLEQ_LAST((head)) = (elm); \ -} while (0) - -#define CIRCLEQ_LAST(head) ((head)->cqh_last) - -#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next) - -#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev) - -#define CIRCLEQ_REMOVE(head, elm, field) do { \ - if (CIRCLEQ_NEXT((elm), field) == (void *)(head)) \ - CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field); \ - else \ - CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) = \ - CIRCLEQ_PREV((elm), field); \ - if (CIRCLEQ_PREV((elm), field) == (void *)(head)) \ - CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field); \ - else \ - CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) = \ - CIRCLEQ_NEXT((elm), field); \ -} while (0) - -#ifdef __cplusplus -} -#endif - -#endif /* !_SYS_QUEUE_H_ */ diff --git a/lib/bt/porting/nimble/include/os/util.h b/lib/bt/porting/nimble/include/os/util.h deleted file mode 100644 index 2438373e..00000000 --- a/lib/bt/porting/nimble/include/os/util.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF) - * - * SPDX-License-Identifier: Apache-2.0 - * - * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD - */ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_OS_UTIL_ -#define H_OS_UTIL_ - -/* Helpers to pass integers as pointers and vice-versa */ -#define POINTER_TO_UINT(p) ((unsigned int) ((uintptr_t) (p))) -#define UINT_TO_POINTER(u) ((void *) ((uintptr_t) (u))) -#define POINTER_TO_INT(p) ((int) ((intptr_t) (p))) -#define INT_TO_POINTER(u) ((void *) ((intptr_t) (u))) - -/* Helper to retrieve pointer to "parent" object in structure */ -#define CONTAINER_OF(ptr, type, field) \ - ((type *)(((char *)(ptr)) - offsetof(type, field))) - -/* Helper to calculate number of elements in array */ -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(array) \ - (sizeof(array) / sizeof((array)[0])) -#endif -#endif diff --git a/lib/bt/porting/nimble/src/os_msys_init.c b/lib/bt/porting/nimble/src/os_msys_init.c deleted file mode 100644 index bf4f4145..00000000 --- a/lib/bt/porting/nimble/src/os_msys_init.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF) - * - * SPDX-License-Identifier: Apache-2.0 - * - * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD - */ - -#include - -#include "os/os.h" -#include "mem_api.h" -#include "bt_osi_mem.h" -#include "esp_err.h" - -#if CONFIG_BT_NIMBLE_ENABLED -#include "syscfg/syscfg.h" -#endif - -#define SYSINIT_PANIC_ASSERT(rc) assert(rc); - -static STAILQ_HEAD(, os_mbuf_pool) g_msys_pool_list = - STAILQ_HEAD_INITIALIZER(g_msys_pool_list); - -#if CONFIG_BT_NIMBLE_ENABLED -#define OS_MSYS_1_BLOCK_COUNT MYNEWT_VAL(MSYS_1_BLOCK_COUNT) -#define OS_MSYS_1_BLOCK_SIZE MYNEWT_VAL(MSYS_1_BLOCK_SIZE) -#define OS_MSYS_2_BLOCK_COUNT MYNEWT_VAL(MSYS_2_BLOCK_COUNT) -#define OS_MSYS_2_BLOCK_SIZE MYNEWT_VAL(MSYS_2_BLOCK_SIZE) - -#define OS_MSYS_1_SANITY_MIN_COUNT MYNEWT_VAL(MSYS_1_SANITY_MIN_COUNT) -#define OS_MSYS_2_SANITY_MIN_COUNT MYNEWT_VAL(MSYS_2_SANITY_MIN_COUNT) -#if CONFIG_BT_NIMBLE_MSYS_BUF_FROM_HEAP -#define OS_MSYS_BLOCK_FROM_HEAP (1) -#else -#define OS_MSYS_BLOCK_FROM_HEAP (0) -#endif // CONFIG_BT_NIMBLE_MSYS_BUF_FROM_HEAP -#else -#define OS_MSYS_1_BLOCK_COUNT CONFIG_BT_LE_MSYS_1_BLOCK_COUNT -#define OS_MSYS_1_BLOCK_SIZE CONFIG_BT_LE_MSYS_1_BLOCK_SIZE -#define OS_MSYS_2_BLOCK_COUNT CONFIG_BT_LE_MSYS_2_BLOCK_COUNT -#define OS_MSYS_2_BLOCK_SIZE CONFIG_BT_LE_MSYS_2_BLOCK_SIZE - -#define OS_MSYS_1_SANITY_MIN_COUNT 0 -#define OS_MSYS_2_SANITY_MIN_COUNT 0 - -#if CONFIG_BT_LE_MSYS_BUF_FROM_HEAP -#define OS_MSYS_BLOCK_FROM_HEAP (1) -#else -#define OS_MSYS_BLOCK_FROM_HEAP (0) -#endif // CONFIG_BT_LE_MSYS_BUF_FROM_HEAP -#endif - - - -#if OS_MSYS_1_BLOCK_COUNT > 0 -#define SYSINIT_MSYS_1_MEMBLOCK_SIZE \ - OS_ALIGN(OS_MSYS_1_BLOCK_SIZE, 4) -#define SYSINIT_MSYS_1_MEMPOOL_SIZE \ - OS_MEMPOOL_SIZE(OS_MSYS_1_BLOCK_COUNT, \ - SYSINIT_MSYS_1_MEMBLOCK_SIZE) - -#if !CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER -static os_membuf_t *os_msys_init_1_data; -static struct os_mbuf_pool os_msys_init_1_mbuf_pool; -static struct os_mempool os_msys_init_1_mempool; -#endif // !CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER -#endif - -#if OS_MSYS_2_BLOCK_COUNT > 0 -#define SYSINIT_MSYS_2_MEMBLOCK_SIZE \ - OS_ALIGN(OS_MSYS_2_BLOCK_SIZE, 4) -#define SYSINIT_MSYS_2_MEMPOOL_SIZE \ - OS_MEMPOOL_SIZE(OS_MSYS_2_BLOCK_COUNT, \ - SYSINIT_MSYS_2_MEMBLOCK_SIZE) - -#if !CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER -static os_membuf_t *os_msys_init_2_data; -static struct os_mbuf_pool os_msys_init_2_mbuf_pool; -static struct os_mempool os_msys_init_2_mempool; -#endif // !CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER -#endif - -#if CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER -extern int esp_ble_msys_init(uint16_t msys_size1, uint16_t msys_size2, uint16_t msys_cnt1, uint16_t msys_cnt2, uint8_t from_heap); -extern void esp_ble_msys_deinit(void); - -int os_msys_init(void) -{ - return esp_ble_msys_init(SYSINIT_MSYS_1_MEMBLOCK_SIZE, - SYSINIT_MSYS_2_MEMBLOCK_SIZE, - OS_MSYS_1_BLOCK_COUNT, - OS_MSYS_2_BLOCK_COUNT, - OS_MSYS_BLOCK_FROM_HEAP); -} - -void os_msys_deinit(void) -{ - esp_ble_msys_deinit(); -} - -#else // CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER - -#if OS_MSYS_SANITY_ENABLED - -/** - * Retrieves the minimum safe buffer count for an msys pool. That is, the - * lowest a pool's buffer count can be without causing the sanity check to - * fail. - * - * @param idx The index of the msys pool to query. - * - * @return The msys pool's minimum safe buffer count. - */ -static int -IRAM_ATTR os_msys_sanity_min_count(int idx) -{ - switch (idx) { - case 0: - return OS_MSYS_1_SANITY_MIN_COUNT; - - case 1: - return OS_MSYS_2_SANITY_MIN_COUNT; - - default: - BLE_LL_ASSERT(0); - return ESP_OK; - } -} - -static int -IRAM_ATTR os_msys_sanity(struct os_sanity_check *sc, void *arg) -{ - const struct os_mbuf_pool *omp; - int min_count; - int idx; - - idx = 0; - STAILQ_FOREACH(omp, &g_msys_pool_list, omp_next) { - min_count = os_msys_sanity_min_count(idx); - if (omp->omp_pool->mp_num_free < min_count) { - return OS_ENOMEM; - } - - idx++; - } - - return ESP_OK; -} -#endif - -static void -os_msys_init_once(void *data, struct os_mempool *mempool, - struct os_mbuf_pool *mbuf_pool, - int block_count, int block_size, const char *name) -{ - int rc; - - rc = mem_init_mbuf_pool(data, mempool, mbuf_pool, block_count, block_size, - name); - SYSINIT_PANIC_ASSERT(rc == 0); - - rc = os_msys_register(mbuf_pool); - SYSINIT_PANIC_ASSERT(rc == 0); -} - -int -os_msys_buf_alloc(void) -{ -#if OS_MSYS_1_BLOCK_COUNT > 0 - os_msys_init_1_data = (os_membuf_t *)bt_osi_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_1_MEMPOOL_SIZE)); - if (!os_msys_init_1_data) { - return ESP_ERR_NO_MEM; - } -#endif - -#if OS_MSYS_2_BLOCK_COUNT > 0 - os_msys_init_2_data = (os_membuf_t *)bt_osi_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_2_MEMPOOL_SIZE)); - if (!os_msys_init_2_data) { -#if OS_MSYS_1_BLOCK_COUNT > 0 - bt_osi_mem_free(os_msys_init_1_data); - os_msys_init_1_data = NULL; -#endif - return ESP_ERR_NO_MEM; - } -#endif - - return ESP_OK; -} - -void -os_msys_buf_free(void) -{ -#if OS_MSYS_1_BLOCK_COUNT > 0 - bt_osi_mem_free(os_msys_init_1_data); - os_msys_init_1_data = NULL; -#endif - -#if OS_MSYS_2_BLOCK_COUNT > 0 - bt_osi_mem_free(os_msys_init_2_data); - os_msys_init_2_data = NULL; -#endif - -} - -void os_msys_init(void) -{ -#if OS_MSYS_SANITY_ENABLED - int rc; -#endif - - os_msys_reset(); - -#if OS_MSYS_1_BLOCK_COUNT > 0 - os_msys_init_once(os_msys_init_1_data, - &os_msys_init_1_mempool, - &os_msys_init_1_mbuf_pool, - OS_MSYS_1_BLOCK_COUNT, - SYSINIT_MSYS_1_MEMBLOCK_SIZE, - "msys_1"); -#endif - -#if OS_MSYS_2_BLOCK_COUNT > 0 - os_msys_init_once(os_msys_init_2_data, - &os_msys_init_2_mempool, - &os_msys_init_2_mbuf_pool, - OS_MSYS_2_BLOCK_COUNT, - SYSINIT_MSYS_2_MEMBLOCK_SIZE, - "msys_2"); -#endif - -#if OS_MSYS_SANITY_ENABLED - os_msys_sc.sc_func = os_msys_sanity; - os_msys_sc.sc_checkin_itvl = - OS_TICKS_PER_SEC * MYNEWT_VAL(MSYS_SANITY_TIMEOUT) / 1000; - rc = os_sanity_check_register(&os_msys_sc); - SYSINIT_PANIC_ASSERT(rc == 0); -#endif -} -#endif // CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER diff --git a/lib/bt/porting/npl/freertos/src/npl_os_freertos.c b/lib/bt/porting/npl/freertos/src/npl_os_freertos.c index 29e2567d..73f42526 100644 --- a/lib/bt/porting/npl/freertos/src/npl_os_freertos.c +++ b/lib/bt/porting/npl/freertos/src/npl_os_freertos.c @@ -21,6 +21,7 @@ #include "esp_log.h" #include "soc/soc_caps.h" #include "esp_bt.h" +#include "bt_osi_mem.h" portMUX_TYPE ble_port_mutex = portMUX_INITIALIZER_UNLOCKED; @@ -95,7 +96,7 @@ IRAM_ATTR npl_freertos_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn } #else if(!ev->event) { - ev->event = malloc(sizeof(struct ble_npl_event_freertos)); + ev->event = bt_osi_mem_malloc_internal(sizeof(struct ble_npl_event_freertos)); } #endif event = (struct ble_npl_event_freertos *)ev->event; @@ -109,11 +110,13 @@ IRAM_ATTR npl_freertos_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn void IRAM_ATTR npl_freertos_event_deinit(struct ble_npl_event *ev) { - BLE_LL_ASSERT(ev->event); + if (!ev->event) { + return; + } #if OS_MEM_ALLOC os_memblock_put(&ble_freertos_ev_pool,ev->event); #else - free(ev->event); + bt_osi_mem_free(ev->event); #endif ev->event = NULL; } @@ -144,7 +147,7 @@ npl_freertos_eventq_init(struct ble_npl_eventq *evq) } #else if(!evq->eventq) { - evq->eventq = malloc(sizeof(struct ble_npl_eventq_freertos)); + evq->eventq = bt_osi_mem_malloc_internal(sizeof(struct ble_npl_eventq_freertos)); eventq = (struct ble_npl_eventq_freertos*)evq->eventq; BLE_LL_ASSERT(eventq); memset(eventq, 0, sizeof(*eventq)); @@ -167,7 +170,7 @@ npl_freertos_eventq_deinit(struct ble_npl_eventq *evq) #if OS_MEM_ALLOC os_memblock_put(&ble_freertos_evq_pool,eventq); #else - free((void *)eventq); + bt_osi_mem_free((void *)eventq); #endif evq->eventq = NULL; } @@ -357,7 +360,7 @@ npl_freertos_mutex_init(struct ble_npl_mutex *mu) } #else if(!mu->mutex) { - mu->mutex = malloc(sizeof(struct ble_npl_mutex_freertos)); + mu->mutex = bt_osi_mem_malloc_internal(sizeof(struct ble_npl_mutex_freertos)); mutex = (struct ble_npl_mutex_freertos *)mu->mutex; if (!mutex) { @@ -388,7 +391,7 @@ npl_freertos_mutex_deinit(struct ble_npl_mutex *mu) #if OS_MEM_ALLOC os_memblock_put(&ble_freertos_mutex_pool,mutex); #else - free((void *)mutex); + bt_osi_mem_free((void *)mutex); #endif mu->mutex = NULL; @@ -494,7 +497,7 @@ npl_freertos_sem_init(struct ble_npl_sem *sem, uint16_t tokens) } #else if(!sem->sem) { - sem->sem = malloc(sizeof(struct ble_npl_sem_freertos)); + sem->sem = bt_osi_mem_malloc_internal(sizeof(struct ble_npl_sem_freertos)); semaphore = (struct ble_npl_sem_freertos *)sem->sem; if (!semaphore) { @@ -525,7 +528,7 @@ npl_freertos_sem_deinit(struct ble_npl_sem *sem) #if OS_MEM_ALLOC os_memblock_put(&ble_freertos_sem_pool,semaphore); #else - free((void *)semaphore); + bt_osi_mem_free((void *)semaphore); #endif sem->sem = NULL; @@ -684,7 +687,7 @@ npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq #else if(!co->co) { - co->co = malloc(sizeof(struct ble_npl_callout_freertos)); + co->co = bt_osi_mem_malloc_internal(sizeof(struct ble_npl_callout_freertos)); callout = (struct ble_npl_callout_freertos *)co->co; if (!callout) { return -1; @@ -704,7 +707,7 @@ npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq if (esp_timer_create(&create_args, &callout->handle) != ESP_OK) { ble_npl_event_deinit(&callout->ev); - free((void *)callout); + bt_osi_mem_free((void *)callout); co->co = NULL; return -1; } @@ -713,7 +716,7 @@ npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq if (!callout->handle) { ble_npl_event_deinit(&callout->ev); - free((void *)callout); + bt_osi_mem_free((void *)callout); co->co = NULL; return -1; } @@ -761,7 +764,7 @@ npl_freertos_callout_deinit(struct ble_npl_callout *co) #if OS_MEM_ALLOC os_memblock_put(&ble_freertos_co_pool,callout); #else - free((void *)callout); + bt_osi_mem_free((void *)callout); #endif // OS_MEM_ALLOC co->co = NULL; memset(co, 0, sizeof(struct ble_npl_callout)); @@ -1089,7 +1092,7 @@ struct npl_funcs_t * npl_freertos_funcs_get(void) void npl_freertos_funcs_init(void) { - npl_funcs = (struct npl_funcs_t *)malloc(sizeof(struct npl_funcs_t)); + npl_funcs = (struct npl_funcs_t *)bt_osi_mem_malloc_internal(sizeof(struct npl_funcs_t)); if(!npl_funcs) { printf("npl funcs init failed\n"); assert(0); @@ -1123,7 +1126,7 @@ int npl_freertos_mempool_init(void) ble_freertos_total_event_cnt = ble_total_evt_count; if (ble_total_evt_count) { - ble_freertos_ev_buf = malloc(OS_MEMPOOL_SIZE(ble_total_evt_count, + ble_freertos_ev_buf = bt_osi_mem_malloc_internal(OS_MEMPOOL_SIZE(ble_total_evt_count, sizeof (struct ble_npl_event_freertos)) * sizeof(os_membuf_t)); if (!ble_freertos_ev_buf) { @@ -1138,7 +1141,7 @@ int npl_freertos_mempool_init(void) } if (ble_total_evtq_count) { - ble_freertos_evq_buf = malloc(OS_MEMPOOL_SIZE(ble_total_evtq_count, + ble_freertos_evq_buf = bt_osi_mem_malloc_internal(OS_MEMPOOL_SIZE(ble_total_evtq_count, sizeof (struct ble_npl_eventq_freertos)) * sizeof(os_membuf_t)); if (!ble_freertos_evq_buf) { @@ -1153,7 +1156,7 @@ int npl_freertos_mempool_init(void) } if (ble_total_co_count) { - ble_freertos_co_buf = malloc(OS_MEMPOOL_SIZE(ble_total_co_count, + ble_freertos_co_buf = bt_osi_mem_malloc_internal(OS_MEMPOOL_SIZE(ble_total_co_count, sizeof (struct ble_npl_callout_freertos)) * sizeof(os_membuf_t)); if (!ble_freertos_co_buf) { @@ -1168,7 +1171,7 @@ int npl_freertos_mempool_init(void) } if (ble_total_sem_count) { - ble_freertos_sem_buf = malloc(OS_MEMPOOL_SIZE(ble_total_sem_count, + ble_freertos_sem_buf = bt_osi_mem_malloc_internal(OS_MEMPOOL_SIZE(ble_total_sem_count, sizeof (struct ble_npl_sem_freertos)) * sizeof(os_membuf_t)); if (!ble_freertos_sem_buf) { @@ -1183,7 +1186,7 @@ int npl_freertos_mempool_init(void) } if (ble_total_mutex_count) { - ble_freertos_mutex_buf = malloc(OS_MEMPOOL_SIZE(ble_total_mutex_count, + ble_freertos_mutex_buf = bt_osi_mem_malloc_internal(OS_MEMPOOL_SIZE(ble_total_mutex_count, sizeof (struct ble_npl_mutex_freertos)) * sizeof(os_membuf_t)); if (!ble_freertos_mutex_buf) { @@ -1200,27 +1203,27 @@ int npl_freertos_mempool_init(void) return 0; _error: if (ble_freertos_ev_buf) { - free(ble_freertos_ev_buf); + bt_osi_mem_free(ble_freertos_ev_buf); ble_freertos_ev_buf = NULL; } if (ble_freertos_evq_buf) { - free(ble_freertos_evq_buf); + bt_osi_mem_free(ble_freertos_evq_buf); ble_freertos_evq_buf = NULL; } if (ble_freertos_co_buf) { - free(ble_freertos_co_buf); + bt_osi_mem_free(ble_freertos_co_buf); ble_freertos_co_buf = NULL; } if (ble_freertos_sem_buf) { - free(ble_freertos_sem_buf); + bt_osi_mem_free(ble_freertos_sem_buf); ble_freertos_sem_buf = NULL; } if (ble_freertos_mutex_buf) { - free(ble_freertos_mutex_buf); + bt_osi_mem_free(ble_freertos_mutex_buf); ble_freertos_mutex_buf = NULL; } return -1; @@ -1229,23 +1232,23 @@ _error: void npl_freertos_mempool_deinit(void) { if (ble_freertos_ev_buf) { - free(ble_freertos_ev_buf); + bt_osi_mem_free(ble_freertos_ev_buf); ble_freertos_ev_buf = NULL; } if (ble_freertos_evq_buf) { - free(ble_freertos_evq_buf); + bt_osi_mem_free(ble_freertos_evq_buf); ble_freertos_evq_buf = NULL; } if (ble_freertos_co_buf) { - free(ble_freertos_co_buf); + bt_osi_mem_free(ble_freertos_co_buf); ble_freertos_co_buf = NULL; } if (ble_freertos_sem_buf) { - free(ble_freertos_sem_buf); + bt_osi_mem_free(ble_freertos_sem_buf); ble_freertos_sem_buf = NULL; } if (ble_freertos_mutex_buf) { - free(ble_freertos_mutex_buf); + bt_osi_mem_free(ble_freertos_mutex_buf); ble_freertos_mutex_buf = NULL; } } @@ -1253,7 +1256,7 @@ void npl_freertos_mempool_deinit(void) void npl_freertos_funcs_deinit(void) { if (npl_funcs) { - free(npl_funcs); + bt_osi_mem_free(npl_funcs); } npl_funcs = NULL; } diff --git a/lib/bt/porting/transport/driver/common/hci_driver_h4.c b/lib/bt/porting/transport/driver/common/hci_driver_h4.c new file mode 100644 index 00000000..2911289c --- /dev/null +++ b/lib/bt/porting/transport/driver/common/hci_driver_h4.c @@ -0,0 +1,421 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include "esp_hci_driver.h" +#include "common/hci_driver_h4.h" +#include "common/hci_driver_util.h" + +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#define HCI_H4_SM_W4_PKT_TYPE 0 +#define HCI_H4_SM_W4_HEADER 1 +#define HCI_H4_SM_W4_PAYLOAD 2 +#define HCI_H4_SM_COMPLETED 3 + +struct hci_h4_input_buffer { + const uint8_t *buf; + uint16_t len; +}; + +static int +hci_h4_frame_start(struct hci_h4_sm *rxs, uint8_t pkt_type) +{ + rxs->pkt_type = pkt_type; + rxs->len = 0; + rxs->exp_len = 0; + + switch (rxs->pkt_type) { + case HCI_H4_CMD: + rxs->min_len = 3; + break; + case HCI_H4_ACL: + case HCI_H4_ISO: + rxs->min_len = 4; + break; +#if (!CONFIG_BT_CONTROLLER_ENABLED) + case HCI_H4_EVT: + rxs->min_len = 2; + break; +#endif // (!CONFIG_BT_CONTROLLER_ENABLED) + default: + /* !TODO: Sync loss. Need to wait for reset. */ + return -1; + } + + return 0; +} + +static int +hci_h4_ib_consume(struct hci_h4_input_buffer *ib, uint16_t len) +{ + HCI_TRANS_ASSERT((ib->len >= len), ib->len, len); + + ib->buf += len; + ib->len -= len; + + return len; +} + +static int +hci_h4_ib_pull_min_len(struct hci_h4_sm *rxs, + struct hci_h4_input_buffer *ib) +{ + uint16_t len; + + len = min(ib->len, rxs->min_len - rxs->len); + memcpy(&rxs->hdr[rxs->len], ib->buf, len); + + rxs->len += len; + hci_h4_ib_consume(ib, len); + + + return rxs->len != rxs->min_len; +} + +static int +hci_h4_sm_w4_header(struct hci_h4_sm *h4sm, struct hci_h4_input_buffer *ib) +{ + int rc; + + rc = hci_h4_ib_pull_min_len(h4sm, ib); + if (rc) { + /* need more data */ + return 1; + } + + switch (h4sm->pkt_type) { + case HCI_H4_CMD: + HCI_TRANS_ASSERT(h4sm->allocs && h4sm->allocs->cmd, 0, 0); + h4sm->buf = h4sm->allocs->cmd(); + if (!h4sm->buf) { + return -1; + } + + memcpy(h4sm->buf, h4sm->hdr, h4sm->len); + h4sm->exp_len = h4sm->hdr[2] + 3; + + break; + case HCI_H4_ACL: + HCI_TRANS_ASSERT(h4sm->allocs && h4sm->allocs->acl, 0, 0); + h4sm->om = h4sm->allocs->acl(); + if (!h4sm->om) { + return -1; + } + + os_mbuf_append(h4sm->om, h4sm->hdr, h4sm->len); + h4sm->exp_len = get_le16(&h4sm->hdr[2]) + 4; + break; +#if !CONFIG_BT_CONTROLLER_ENABLED + case HCI_H4_EVT: + if (h4sm->hdr[0] == BLE_HCI_EVCODE_LE_META) { + /* For LE Meta event we need 3 bytes to parse header */ + h4sm->min_len = 3; + rc = hci_h4_ib_pull_min_len(h4sm, ib); + if (rc) { + /* need more data */ + return 1; + } + } + + HCI_TRANS_ASSERT(h4sm->allocs && h4sm->allocs->evt, 0, 0); + + /* We can drop legacy advertising events if there's no free buffer in + * discardable pool. + */ + if (h4sm->hdr[2] == BLE_HCI_LE_SUBEV_ADV_RPT) { + h4sm->buf = h4sm->allocs->evt(1); + } else { + h4sm->buf = h4sm->allocs->evt(0); + if (!h4sm->buf) { + return -1; + } + } + + if (h4sm->buf) { + memcpy(h4sm->buf, h4sm->hdr, h4sm->len); + } + + h4sm->exp_len = h4sm->hdr[1] + 2; + break; +#endif // !CONFIG_BT_CONTROLLER_ENABLED + case HCI_H4_ISO: + HCI_TRANS_ASSERT(h4sm->allocs && h4sm->allocs->iso, 0, 0); + h4sm->om = h4sm->allocs->iso(); + if (!h4sm->om) { + return -1; + } + + os_mbuf_append(h4sm->om, h4sm->hdr, h4sm->len); + h4sm->exp_len = (get_le16(&h4sm->hdr[2]) & 0x7fff) + 4; + break; + default: + return -2; + } + + return 0; +} + +static int +hci_h4_sm_w4_payload(struct hci_h4_sm *h4sm, + struct hci_h4_input_buffer *ib) +{ + uint16_t mbuf_len; + uint16_t len; + int rc; + + len = min(ib->len, h4sm->exp_len - h4sm->len); + switch (h4sm->pkt_type) { + case HCI_H4_CMD: +#if (!CONFIG_BT_CONTROLLER_ENABLED) + case HCI_H4_EVT: +#endif // (!CONFIG_BT_CONTROLLER_ENABLED) + if (h4sm->buf) { + memcpy(&h4sm->buf[h4sm->len], ib->buf, len); + } + break; + case HCI_H4_ACL: + case HCI_H4_ISO: + HCI_TRANS_ASSERT(h4sm->om, h4sm->pkt_type, len); + mbuf_len = OS_MBUF_PKTLEN(h4sm->om); + rc = os_mbuf_append(h4sm->om, ib->buf, len); + if (rc) { + /* Some data may already be appended so need to adjust h4sm only by + * the size of appended data. + */ + len = OS_MBUF_PKTLEN(h4sm->om) - mbuf_len; + h4sm->len += len; + hci_h4_ib_consume(ib, len); + return -1; + } + break; + default: + return -2; + } + + h4sm->len += len; + hci_h4_ib_consume(ib, len); + + /* return 1 if need more data */ + return h4sm->len != h4sm->exp_len; +} + +static void +hci_h4_sm_completed(struct hci_h4_sm *h4sm) +{ + int rc; + + switch (h4sm->pkt_type) { +#if CONFIG_BT_CONTROLLER_ENABLED + case HCI_H4_CMD: + if (h4sm->buf) { + HCI_TRANS_ASSERT(h4sm->frame_cb, 0, 0); + rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->buf); + HCI_TRANS_ASSERT(rc == 0, rc, 0); + h4sm->buf = NULL; + } + break; + case HCI_H4_ACL: + case HCI_H4_ISO: + if (h4sm->om) { + HCI_TRANS_ASSERT(h4sm->frame_cb, 0, 0); + rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->om); + HCI_TRANS_ASSERT(rc == 0, rc, 0); + h4sm->om = NULL; + } + break; +#else + case HCI_H4_CMD: + if (h4sm->buf) { + HCI_TRANS_ASSERT(h4sm->frame_cb, 0, 0); + rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->buf); + if (rc != 0) { + HCI_TRANS_ASSERT(h4sm->frees && h4sm->frees->cmd, rc, (uint32_t)h4sm->frees); + h4sm->frees->cmd(h4sm->buf); + } + h4sm->buf = NULL; + } + break; + case HCI_H4_EVT: + if (h4sm->buf) { + HCI_TRANS_ASSERT(h4sm->frame_cb, 0, 0); + rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->buf); + if (rc != 0) { + HCI_TRANS_ASSERT(h4sm->frees && h4sm->frees->evt, rc, (uint32_t)h4sm->frees); + h4sm->frees->evt(h4sm->buf); + } + h4sm->buf = NULL; + } + break; + case HCI_H4_ACL: + if (h4sm->om) { + HCI_TRANS_ASSERT(h4sm->frame_cb, 0, 0); + rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->om); + if (rc != 0) { + HCI_TRANS_ASSERT(h4sm->frees && h4sm->frees->acl, rc, (uint32_t)h4sm->frees); + h4sm->frees->acl(h4sm->om); + } + h4sm->om = NULL; + } + break; + case HCI_H4_ISO: + if (h4sm->om) { + HCI_TRANS_ASSERT(h4sm->frame_cb, 0, 0); + rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->om); + if (rc != 0) { + HCI_TRANS_ASSERT(h4sm->frees && h4sm->frees->iso, rc, (uint32_t)h4sm->frees); + h4sm->frees->iso(h4sm->om); + } + h4sm->om = NULL; + } + break; +#endif // CONFIG_BT_CONTROLLER_ENABLED + default: + HCI_TRANS_ASSERT(0, h4sm->pkt_type, 0); + break; + } +} + +static int +hci_h4_sm_free_buf(struct hci_h4_sm *h4sm) +{ + switch (h4sm->pkt_type) { + case HCI_H4_CMD: + if (h4sm->buf) { + h4sm->frees->cmd(h4sm->buf); + h4sm->buf = NULL; + } + break; +#if (!CONFIG_BT_CONTROLLER_ENABLED) + case HCI_H4_EVT: + if (h4sm->buf) { + h4sm->frees->evt(h4sm->buf); + h4sm->buf = NULL; + } + break; +#endif // (!CONFIG_BT_CONTROLLER_ENABLED) + case HCI_H4_ACL: + if (h4sm->om) { + h4sm->frees->acl(h4sm->om); + h4sm->om = NULL; + } + break; + case HCI_H4_ISO: + if (h4sm->om) { + h4sm->frees->iso(h4sm->om); + h4sm->om = NULL; + } + break; + default: + break; + } + + return 0; +} + +int +hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len) +{ + struct hci_h4_input_buffer ib = { + .buf = buf, + .len = len, + }; + + int rc = 0; + while (ib.len && (rc >= 0)) { + rc = 0; + switch (h4sm->state) { + case HCI_H4_SM_W4_PKT_TYPE: + if (hci_h4_frame_start(h4sm, ib.buf[0]) < 0) { + return -1; + } + + hci_h4_ib_consume(&ib, 1); + h4sm->state = HCI_H4_SM_W4_HEADER; + /* no break */ + case HCI_H4_SM_W4_HEADER: + rc = hci_h4_sm_w4_header(h4sm, &ib); + if (rc) { + break; + } + + h4sm->state = HCI_H4_SM_W4_PAYLOAD; + /* no break */ + case HCI_H4_SM_W4_PAYLOAD: + rc = hci_h4_sm_w4_payload(h4sm, &ib); + if (rc) { + break; + } + + h4sm->state = HCI_H4_SM_COMPLETED; + /* no break */ + case HCI_H4_SM_COMPLETED: + hci_h4_sm_completed(h4sm); + h4sm->state = HCI_H4_SM_W4_PKT_TYPE; + break; + default: + return -1; + } + } + + if (rc < 0) { + hci_h4_sm_free_buf(h4sm); + h4sm->state = HCI_H4_SM_W4_PKT_TYPE; + return -1; + } + /* Calculate consumed bytes + * + * Note: we should always consume some bytes unless there is an oom error. + * It's also possible that we have an oom error but already consumed some + * data, in such case just return success and error will be returned on next + * pass. + */ + len = len - ib.len; + if (len == 0) { + HCI_TRANS_ASSERT((rc < 0), rc, ib.len); + return -1; + } + + return len; +} + +void +hci_h4_sm_init(struct hci_h4_sm *h4sm, const struct hci_h4_allocators *allocs, const struct hci_h4_frees *frees, + hci_h4_frame_cb *frame_cb) +{ + memset(h4sm, 0, sizeof(*h4sm)); + h4sm->allocs = allocs; + h4sm->frees = frees; + h4sm->frame_cb = frame_cb; +} diff --git a/lib/bt/porting/transport/driver/common/hci_driver_mem.c b/lib/bt/porting/transport/driver/common/hci_driver_mem.c new file mode 100644 index 00000000..3505fa62 --- /dev/null +++ b/lib/bt/porting/transport/driver/common/hci_driver_mem.c @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "common/hci_driver_mem.h" +#include "common/hci_driver_h4.h" +#include "esp_hci_internal.h" + +void * +hci_driver_mem_cmd_alloc(void) +{ + return r_ble_hci_trans_buf_alloc(ESP_HCI_INTERNAL_BUF_CMD); +} + +void * +hci_driver_mem_evt_alloc(int discardable) +{ + /* The controller shouldn't invoke this. */ + assert(0); + return NULL; +} + +struct os_mbuf * +hci_driver_mem_acl_alloc(void) +{ + return os_msys_get_pkthdr(0, ESP_HCI_INTERNAL_ACL_MBUF_LEADINGSPCAE); +} + +struct os_mbuf * +hci_driver_mem_acl_len_alloc(uint32_t len) +{ + return os_msys_get_pkthdr(len, ESP_HCI_INTERNAL_ACL_MBUF_LEADINGSPCAE); +} + +struct os_mbuf * +hci_driver_mem_iso_alloc(void) +{ + return os_msys_get_pkthdr(0, ESP_HCI_INTERNAL_ACL_MBUF_LEADINGSPCAE); +} + +struct os_mbuf * +hci_driver_mem_iso_len_alloc(uint32_t len) +{ + return os_msys_get_pkthdr(len, ESP_HCI_INTERNAL_ACL_MBUF_LEADINGSPCAE); +} + +const struct hci_h4_allocators s_hci_driver_mem_alloc = { + .cmd = hci_driver_mem_cmd_alloc, + .evt = hci_driver_mem_evt_alloc, + .acl = hci_driver_mem_acl_alloc, + .iso = hci_driver_mem_iso_alloc, +}; + +const struct hci_h4_frees s_hci_driver_mem_free = { + .cmd = r_ble_hci_trans_buf_free, + .evt = r_ble_hci_trans_buf_free, + .acl = os_mbuf_free_chain, + .iso = os_mbuf_free_chain, +}; diff --git a/lib/bt/porting/transport/driver/common/hci_driver_util.c b/lib/bt/porting/transport/driver/common/hci_driver_util.c new file mode 100644 index 00000000..3c3a49cd --- /dev/null +++ b/lib/bt/porting/transport/driver/common/hci_driver_util.c @@ -0,0 +1,232 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "esp_log.h" +#include "os/os.h" +#include "os/os_mempool.h" +#include "esp_hci_driver.h" +#include "esp_hci_internal.h" +#include "common/hci_driver_util.h" + +#define TAG "HCI_UTIL" +#define HCI_DRIVER_UTIL_TX_POOL_NUM \ + (CONFIG_BT_LE_ACL_BUF_COUNT + CONFIG_BT_LE_HCI_EVT_HI_BUF_COUNT + CONFIG_BT_LE_HCI_EVT_LO_BUF_COUNT) + +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + +/** + * @brief Structure representing HCI TX data. + */ +typedef struct hci_driver_util_tx_entry { + hci_driver_data_type_t data_type; ///< Type of the HCI TX data. + uint8_t *data; ///< Pointer to the TX data. + uint32_t length; ///< Length of the TX data. + STAILQ_ENTRY(hci_driver_util_tx_entry) next; ///< Next element in the linked list. +} hci_driver_util_tx_entry_t; + +/* The list for hci_driver_util_tx_entry */ +STAILQ_HEAD(hci_driver_util_tx_list, hci_driver_util_tx_entry); + +typedef struct { + struct hci_driver_util_tx_list tx_head; + struct hci_driver_util_tx_entry *cur_tx_entry; + uint32_t cur_tx_off; + struct os_mempool *tx_entry_pool; + uint8_t *tx_entry_mem; +} hci_driver_util_env_t; + +static hci_driver_util_env_t s_hci_driver_util_env; + +static void +hci_driver_util_memory_deinit(void) +{ + if (s_hci_driver_util_env.tx_entry_pool) { + free(s_hci_driver_util_env.tx_entry_pool); + s_hci_driver_util_env.tx_entry_pool = NULL; + } + if (s_hci_driver_util_env.tx_entry_mem) { + free(s_hci_driver_util_env.tx_entry_mem); + s_hci_driver_util_env.tx_entry_mem = NULL; + } +} + +static int +hci_driver_util_memory_init(void) +{ + int rc; + + s_hci_driver_util_env.tx_entry_pool = (struct os_mempool *)malloc(sizeof(struct os_mempool)); + if (!s_hci_driver_util_env.tx_entry_pool) { + ESP_LOGE(TAG, "No memory for tx pool"); + goto init_err; + } + + s_hci_driver_util_env.tx_entry_mem = malloc(OS_MEMPOOL_SIZE(HCI_DRIVER_UTIL_TX_POOL_NUM, + sizeof(hci_driver_util_tx_entry_t)) * sizeof(os_membuf_t)); + if (!s_hci_driver_util_env.tx_entry_mem) { + ESP_LOGE(TAG, "No memory for tx pool buffer"); + goto init_err; + } + + rc = os_mempool_init(s_hci_driver_util_env.tx_entry_pool, HCI_DRIVER_UTIL_TX_POOL_NUM, + sizeof(hci_driver_util_tx_entry_t), s_hci_driver_util_env.tx_entry_mem, + "hci_tx_entry_pool"); + if (rc) { + ESP_LOGE(TAG, "Failed to initialize tx pool"); + goto init_err; + } + + return 0; + +init_err: + hci_driver_util_memory_deinit(); + return -1; +} + +void +hci_driver_util_tx_list_enqueue(hci_driver_data_type_t type, uint8_t *data, uint32_t len) +{ + os_sr_t sr; + hci_driver_util_tx_entry_t *tx_entry; + + tx_entry = os_memblock_get(s_hci_driver_util_env.tx_entry_pool); + HCI_TRANS_ASSERT((tx_entry != NULL), 0, 0); + tx_entry->data_type = type; + tx_entry->data = data; + tx_entry->length = len; + /* If the txbuf is command status event or command complete event, we should send firstly. + * The tx list maybe used in the controller task and hci task. Therefore, enter critical area. + */ + if ((type == HCI_DRIVER_TYPE_EVT) && ((data[0] == 0x0E) || (data[0] == 0x0F))) { + OS_ENTER_CRITICAL(sr); + STAILQ_INSERT_HEAD(&s_hci_driver_util_env.tx_head, tx_entry, next); + OS_EXIT_CRITICAL(sr); + } else { + OS_ENTER_CRITICAL(sr); + STAILQ_INSERT_TAIL(&s_hci_driver_util_env.tx_head, tx_entry, next); + OS_EXIT_CRITICAL(sr); + } +} + +uint32_t +hci_driver_util_tx_list_dequeue(uint32_t max_tx_len, void **tx_data, bool *last_frame) +{ + os_sr_t sr; + uint32_t tx_len; + uint32_t data_len; + uint16_t out_off; + struct os_mbuf *om; + hci_driver_util_tx_entry_t *tx_entry; + + /* Check if there is any remaining data that hasn't been sent completely. If it has been completed, + * free the corresponding memory. Therefore, the HCI TX entry needs to be sent one by one; multiple + * entries cannot be sent together. + */ + tx_len = 0; + tx_entry = s_hci_driver_util_env.cur_tx_entry; + if (tx_entry) { + data_len = tx_entry->length; + if (tx_entry->data_type == HCI_DRIVER_TYPE_ACL) { + om = (struct os_mbuf *)tx_entry->data; + if (s_hci_driver_util_env.cur_tx_off >= data_len) { + os_mbuf_free_chain(om); + } else { + om = os_mbuf_off(om, s_hci_driver_util_env.cur_tx_off, &out_off); + tx_len = min(max_tx_len, om->om_len - out_off); + *tx_data = (void *)&om->om_data[out_off]; + } + } else if (tx_entry->data_type == HCI_DRIVER_TYPE_EVT) { + if (s_hci_driver_util_env.cur_tx_off >= data_len) { + r_ble_hci_trans_buf_free(tx_entry->data); + } else { + tx_len = min(max_tx_len, data_len - s_hci_driver_util_env.cur_tx_off); + *tx_data = &tx_entry->data[s_hci_driver_util_env.cur_tx_off]; + } + } else { + HCI_TRANS_ASSERT(0, tx_entry->data_type, data_len); + } + /* If this is the last frame, inform the invoker not to call this API until the current data + * has been completely sent. + */ + if (tx_len) { + s_hci_driver_util_env.cur_tx_off += tx_len; + + if (s_hci_driver_util_env.cur_tx_off >= data_len) { + *last_frame = true; + } else { + *last_frame = false; + } + } else { + os_memblock_put(s_hci_driver_util_env.tx_entry_pool, (void *)tx_entry); + s_hci_driver_util_env.cur_tx_entry = NULL; + } + } + + /* Find a new entry. */ + if (!tx_len && !STAILQ_EMPTY(&s_hci_driver_util_env.tx_head)) { + OS_ENTER_CRITICAL(sr); + tx_entry = STAILQ_FIRST(&s_hci_driver_util_env.tx_head); + STAILQ_REMOVE_HEAD(&s_hci_driver_util_env.tx_head, next); + OS_EXIT_CRITICAL(sr); + + *tx_data = &tx_entry->data_type; + s_hci_driver_util_env.cur_tx_entry = tx_entry; + s_hci_driver_util_env.cur_tx_off = 0; + tx_len = 1; + *last_frame = false; + } + + return tx_len; +} + +int +hci_driver_util_init(void) +{ + memset(&s_hci_driver_util_env, 0, sizeof(hci_driver_util_env_t)); + + if (hci_driver_util_memory_init()) { + return -1; + } + + STAILQ_INIT(&s_hci_driver_util_env.tx_head); + + return 0; +} + +void +hci_driver_util_deinit(void) +{ + hci_driver_util_tx_entry_t *tx_entry; + hci_driver_util_tx_entry_t *next_entry; + + /* Free all of controller buffers which haven't been sent yet. The whole mempool will be freed. + * Therefore, it's unnecessary to put the tx_entry into mempool. + */ + tx_entry = STAILQ_FIRST(&s_hci_driver_util_env.tx_head); + while (tx_entry) { + next_entry = STAILQ_NEXT(tx_entry, next); + if (tx_entry->data_type == HCI_DRIVER_TYPE_ACL) { + os_mbuf_free_chain((struct os_mbuf *)tx_entry->data); + } else if (tx_entry->data_type == HCI_DRIVER_TYPE_EVT) { + r_ble_hci_trans_buf_free(tx_entry->data); + } + tx_entry = next_entry; + } + + hci_driver_util_memory_deinit(); + + memset(&s_hci_driver_util_env, 0, sizeof(hci_driver_util_env_t)); +} + + +void +hci_driver_util_assert_check(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2) +{ + ESP_LOGE(TAG, "hci driver assert: line %d in function %s, param: 0x%x, 0x%x", ln, fn, param1, param2); +} diff --git a/lib/bt/porting/transport/driver/uart/hci_driver_uart.c b/lib/bt/porting/transport/driver/uart/hci_driver_uart.c new file mode 100644 index 00000000..e78f5d27 --- /dev/null +++ b/lib/bt/porting/transport/driver/uart/hci_driver_uart.c @@ -0,0 +1,239 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_log.h" +#include "driver/uart.h" +#include "esp_hci_transport.h" +#include "esp_hci_internal.h" +#include "common/hci_driver_h4.h" +#include "common/hci_driver_util.h" +#include "common/hci_driver_mem.h" +#include "hci_driver_uart.h" + +static const char *TAG = "hci_uart"; + +#define CONFIG_BT_LE_HCI_RX_PROC_DATA_LEN (256) + +typedef struct { + TaskHandle_t tx_task_handler; + TaskHandle_t rx_task_handler; + hci_driver_uart_params_config_t *hci_uart_params; + SemaphoreHandle_t tx_sem; + QueueHandle_t rx_event_queue; + uint8_t *rx_data; + struct hci_h4_sm *h4_sm; + hci_driver_forward_fn *forward_cb; +} hci_driver_uart_env_t; + +static hci_driver_uart_env_t s_hci_driver_uart_env; +static struct hci_h4_sm s_hci_driver_uart_h4_sm; +static uint8_t s_hci_driver_uart_rx_data[CONFIG_BT_LE_HCI_RX_PROC_DATA_LEN]; + +static int +hci_driver_uart_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir) +{ + /* By now, this layer is only used by controller. */ + assert(dir == HCI_DRIVER_DIR_C2H); + ESP_LOGD(TAG, "controller tx len:%d\n", length); + + hci_driver_util_tx_list_enqueue(data_type, data, length); + xSemaphoreGive(s_hci_driver_uart_env.tx_sem); + + return 0; +} + +static int +hci_driver_uart_h4_frame_cb(uint8_t pkt_type, void *data) +{ + hci_driver_forward_fn *forward_cb; + + forward_cb = s_hci_driver_uart_env.forward_cb; + if (!forward_cb) { + return -1; + } + ESP_LOGD(TAG, "h4 frame\n"); + return forward_cb(pkt_type, data, 0, HCI_DRIVER_DIR_H2C); +} + +static void +hci_driver_uart_tx_task(void *p) +{ + void *data; + bool last_frame; + uint32_t tx_len; + uart_port_t port; + + port = s_hci_driver_uart_env.hci_uart_params->hci_uart_port; + while (true) { + xSemaphoreTake(s_hci_driver_uart_env.tx_sem, portMAX_DELAY); + while (true) { + tx_len = hci_driver_util_tx_list_dequeue(0xffffff, &data, &last_frame); + if (tx_len == 0) { + break; + } + ESP_LOGD(TAG, "uart tx"); + ESP_LOG_BUFFER_HEXDUMP(TAG, data, tx_len, ESP_LOG_DEBUG); + uart_write_bytes(port, data, tx_len); + } + } +} + +static void +hci_driver_uart_rx_task(void *p) +{ + void *data; + int read_len; + int ret; + uart_port_t port; + uart_event_t uart_event; + + port = s_hci_driver_uart_env.hci_uart_params->hci_uart_port; + while (true) { + xQueueReceive(s_hci_driver_uart_env.rx_event_queue, &uart_event, portMAX_DELAY); + data = s_hci_driver_uart_env.rx_data; + while (true) { + read_len = uart_read_bytes(port, data, CONFIG_BT_LE_HCI_RX_PROC_DATA_LEN, 0); + if (read_len == 0) { + break; + } + ESP_LOGD(TAG, "uart rx"); + ESP_LOG_BUFFER_HEXDUMP(TAG, data, read_len, ESP_LOG_DEBUG); + ret = hci_h4_sm_rx(s_hci_driver_uart_env.h4_sm, data, read_len); + if (ret < 0) { + ESP_LOGE(TAG, "parse rx data error! sm_state:%d\n", s_hci_driver_uart_env.h4_sm->state); + r_ble_ll_hci_ev_hw_err(ESP_HCI_SYNC_LOSS_ERR); + } + } + } +} + +static int +hci_driver_uart_task_create(void) +{ + /* !TODO: Set the core id by menuconfig */ + xTaskCreatePinnedToCore(hci_driver_uart_tx_task, "hci_driver_uart_tx_task", + CONFIG_BT_LE_HCI_TRANS_TASK_STACK_SIZE, NULL, + ESP_TASK_BT_CONTROLLER_PRIO, &s_hci_driver_uart_env.tx_task_handler, + 0); + assert(s_hci_driver_uart_env.tx_task_handler); + + xTaskCreatePinnedToCore(hci_driver_uart_rx_task, "hci_driver_uart_rx_task", + CONFIG_BT_LE_HCI_TRANS_TASK_STACK_SIZE, NULL, + ESP_TASK_BT_CONTROLLER_PRIO, &s_hci_driver_uart_env.rx_task_handler, + 0); + assert(s_hci_driver_uart_env.rx_task_handler); + + ESP_LOGI(TAG, "hci transport task create successfully, prio:%d, stack size: %ld", + ESP_TASK_BT_CONTROLLER_PRIO, CONFIG_BT_LE_HCI_TRANS_TASK_STACK_SIZE); + + return 0; +} + +static void +hci_driver_uart_task_delete(void) +{ + if (s_hci_driver_uart_env.tx_task_handler) { + vTaskDelete(s_hci_driver_uart_env.tx_task_handler); + s_hci_driver_uart_env.tx_task_handler = NULL; + } + + if (s_hci_driver_uart_env.rx_task_handler) { + vTaskDelete(s_hci_driver_uart_env.rx_task_handler); + s_hci_driver_uart_env.rx_task_handler = NULL; + } +} + +static void +hci_driver_uart_deinit(void) +{ + hci_driver_uart_task_delete(); + + ESP_ERROR_CHECK(uart_driver_delete(s_hci_driver_uart_env.hci_uart_params->hci_uart_port)); + + if (s_hci_driver_uart_env.tx_sem) { + vSemaphoreDelete(s_hci_driver_uart_env.tx_sem); + } + + hci_driver_util_deinit(); + memset(&s_hci_driver_uart_env, 0, sizeof(hci_driver_uart_env_t)); +} + +static int +hci_driver_uart_init(hci_driver_forward_fn *cb) +{ + int rc; + memset(&s_hci_driver_uart_env, 0, sizeof(hci_driver_uart_env_t)); + + s_hci_driver_uart_env.h4_sm = &s_hci_driver_uart_h4_sm; + hci_h4_sm_init(s_hci_driver_uart_env.h4_sm, &s_hci_driver_mem_alloc, &s_hci_driver_mem_free, hci_driver_uart_h4_frame_cb); + + rc = hci_driver_util_init(); + if (rc) { + goto error; + } + + s_hci_driver_uart_env.tx_sem = xSemaphoreCreateBinary(); + if (!s_hci_driver_uart_env.tx_sem) { + goto error; + } + + s_hci_driver_uart_env.rx_data = s_hci_driver_uart_rx_data; + s_hci_driver_uart_env.forward_cb = cb; + s_hci_driver_uart_env.hci_uart_params = hci_driver_uart_config_param_get(); + hci_driver_uart_config(s_hci_driver_uart_env.hci_uart_params); + /* Currently, the queue size is set to 1. It will be considered as semaphore. */ + ESP_ERROR_CHECK(uart_driver_install(s_hci_driver_uart_env.hci_uart_params->hci_uart_port, + CONFIG_BT_LE_HCI_UART_RX_BUFFER_SIZE, + CONFIG_BT_LE_HCI_UART_TX_BUFFER_SIZE, + 1, &s_hci_driver_uart_env.rx_event_queue, + 0)); + + rc = hci_driver_uart_task_create(); + if (rc) { + goto error; + } + + return 0; + +error: + hci_driver_uart_deinit(); + return rc; +} + +int +hci_driver_uart_reconfig_pin(int tx_pin, int rx_pin, int cts_pin, int rts_pin) +{ + int rc; + + hci_driver_uart_task_delete(); + hci_driver_uart_pin_update(tx_pin, rx_pin, cts_pin, rts_pin); + /* Currently, the queue size is set to 1. It will be considered as semaphore. */ + ESP_ERROR_CHECK(uart_driver_install(s_hci_driver_uart_env.hci_uart_params->hci_uart_port, + CONFIG_BT_LE_HCI_UART_RX_BUFFER_SIZE, + CONFIG_BT_LE_HCI_UART_TX_BUFFER_SIZE, + 1, &s_hci_driver_uart_env.rx_event_queue, + 0)); + rc = hci_driver_uart_task_create(); + if (rc) { + hci_driver_uart_task_delete(); + return -2; + } + + return 0; +} + +hci_driver_ops_t hci_driver_uart_ops = { + .hci_driver_tx = hci_driver_uart_tx, + .hci_driver_init = hci_driver_uart_init, + .hci_driver_deinit = hci_driver_uart_deinit, +}; diff --git a/lib/bt/porting/transport/driver/uart/hci_driver_uart.h b/lib/bt/porting/transport/driver/uart/hci_driver_uart.h new file mode 100644 index 00000000..1cefb1d8 --- /dev/null +++ b/lib/bt/porting/transport/driver/uart/hci_driver_uart.h @@ -0,0 +1,87 @@ +/* + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include "driver/uart.h" +#include "os/os_mbuf.h" +#include "esp_bt.h" +#include "esp_hci_transport.h" + +/** + * @brief UART configuration parameters for the HCI driver + */ +typedef struct hci_driver_uart_params_config +{ + uint8_t hci_uart_port; /*!< Port of UART for HCI */ + uint8_t hci_uart_data_bits; /*!< Data bits of UART for HCI */ + uint8_t hci_uart_stop_bits; /*!< Stop bits of UART for HCI */ + uint8_t hci_uart_flow_ctrl; /*!< Flow control of UART for HCI */ + uint8_t hci_uart_parity; /*!< UART parity */ + uint8_t hci_uart_driver_mode; /*!< UART driver mode */ + uint32_t hci_uart_baud; /*!< Baudrate of UART for HCI */ + int hci_uart_tx_pin; /*!< Tx Pin number of UART for HCI */ + int hci_uart_rx_pin; /*!< Rx Pin number of UART for HCI */ + int hci_uart_rts_pin; /*!< RTS Pin number of UART for HCI */ + int hci_uart_cts_pin; /*!< CTS Pin number of UART for HCI */ +} hci_driver_uart_params_config_t; + +#define BT_HCI_DRIVER_UART_CONFIG_DEFAULT() { \ + .hci_uart_port = DEFAULT_BT_LE_HCI_UART_PORT, \ + .hci_uart_baud = DEFAULT_BT_LE_HCI_UART_BAUD, \ + .hci_uart_tx_pin = DEFAULT_BT_LE_HCI_UART_TX_PIN , \ + .hci_uart_rx_pin = DEFAULT_BT_LE_HCI_UART_RX_PIN, \ + .hci_uart_cts_pin = DEFAULT_BT_LE_HCI_UART_CTS_PIN, \ + .hci_uart_rts_pin = DEFAULT_BT_LE_HCI_UART_RTS_PIN, \ + .hci_uart_data_bits = DEFAULT_BT_LE_HCI_UART_DATA_BITS, \ + .hci_uart_stop_bits = DEFAULT_BT_LE_HCI_UART_STOP_BITS, \ + .hci_uart_flow_ctrl = DEFAULT_BT_LE_HCI_UART_FLOW_CTRL, \ + .hci_uart_parity = DEFAULT_BT_LE_HCI_UART_PARITY, \ +} + +/** + * @brief Configures the HCI driver UART parameters. + * This function sets up the UART interface according to the specified configuration parameters. + * + * @param uart_config A pointer to a structure containing the UART configuration parameters. + * The structure should include details such as baud rate, parity, stop bits, and flow control. + * Ensure that the uart_config structure is correctly initialized before calling this function. + * + * @return int Returns 0 on success, or a non-zero error code on failure. + * + * @note This function should be called before any UART communication is initiated. + */ +int hci_driver_uart_config(hci_driver_uart_params_config_t *uart_config); + +/** + * @brief Update the UART pin configuration for the HCI driver. + * + * This function updates the TX, RX, CTS, and RTS pin assignments for the HCI driver operating over UART. + * It allows dynamic reconfiguration of UART pins as needed. + * + * @param tx_pin The GPIO number assigned to the UART TX pin. + * @param rx_pin The GPIO number assigned to the UART RX pin. + * @param cts_pin The GPIO number assigned to the UART CTS pin. + * @param rts_pin The GPIO number assigned to the UART RTS pin. + * + * @return 0 on success, or a negative error code on failure. + */ +int hci_driver_uart_pin_update(int tx_pin, int rx_pin, int cts_pin, int rts_pin); + +/** + * @brief Retrieves the current UART configuration parameters for the HCI driver. + * + * @return hci_driver_uart_params_config_t* Pointer to the structure with UART configuration parameters. + */ +hci_driver_uart_params_config_t * hci_driver_uart_config_param_get(void); + +#ifdef __cplusplus +} +#endif diff --git a/lib/bt/porting/transport/driver/uart/hci_driver_uart_config.c b/lib/bt/porting/transport/driver/uart/hci_driver_uart_config.c new file mode 100644 index 00000000..ada3310b --- /dev/null +++ b/lib/bt/porting/transport/driver/uart/hci_driver_uart_config.c @@ -0,0 +1,68 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "esp_log.h" +#include "driver/uart.h" +#include "hci_driver_uart.h" +#include "esp_private/esp_gpio_reserve.h" + +static const char *TAG = "hci_uart_config"; +static uart_config_t s_uart_cfg; +static hci_driver_uart_params_config_t s_hci_driver_uart_params = BT_HCI_DRIVER_UART_CONFIG_DEFAULT(); + +int hci_driver_uart_config(hci_driver_uart_params_config_t *uart_config) +{ + uart_config_t *uart_cfg; + uart_cfg = &s_uart_cfg; + uart_cfg->baud_rate = uart_config->hci_uart_baud; + uart_cfg->data_bits = uart_config->hci_uart_data_bits; + uart_cfg->stop_bits = uart_config->hci_uart_stop_bits; + uart_cfg->parity = uart_config->hci_uart_parity; + uart_cfg->flow_ctrl = uart_config->hci_uart_flow_ctrl; + uart_cfg->source_clk= UART_SCLK_DEFAULT; + uart_cfg->rx_flow_ctrl_thresh = UART_HW_FIFO_LEN(uart_config->hci_uart_port) - 1; + + ESP_LOGI(TAG,"set uart pin tx:%d, rx:%d.\n", uart_config->hci_uart_tx_pin, uart_config->hci_uart_rx_pin); + ESP_LOGI(TAG,"set rts:%d, cts:%d.\n", uart_config->hci_uart_rts_pin, uart_config->hci_uart_cts_pin); + ESP_LOGI(TAG,"set baud_rate:%d.\n", uart_config->hci_uart_baud); + ESP_LOGI(TAG,"set flow_ctrl:%d.\n", uart_config->hci_uart_flow_ctrl); + + ESP_ERROR_CHECK(uart_driver_delete(uart_config->hci_uart_port)); + ESP_ERROR_CHECK(uart_param_config(uart_config->hci_uart_port, uart_cfg)); + ESP_ERROR_CHECK(uart_set_pin(uart_config->hci_uart_port, uart_config->hci_uart_tx_pin, uart_config->hci_uart_rx_pin, + uart_config->hci_uart_rts_pin, uart_config->hci_uart_cts_pin)); + return 0; +} + +int +hci_driver_uart_pin_update(int tx_pin, int rx_pin, int cts_pin, int rts_pin) +{ + hci_driver_uart_params_config_t *uart_param = &s_hci_driver_uart_params; + /* Fixed warning that the gpio is not usable, may be used by others */ + esp_gpio_revoke(BIT64(uart_param->hci_uart_tx_pin)); + esp_gpio_revoke(BIT64(uart_param->hci_uart_rx_pin)); + if (uart_param->hci_uart_cts_pin != -1) { + esp_gpio_revoke(BIT64(uart_param->hci_uart_cts_pin)); + } + + if (uart_param->hci_uart_rts_pin != -1) { + esp_gpio_revoke(BIT64(uart_param->hci_uart_rts_pin)); + } + + uart_param->hci_uart_tx_pin = tx_pin; + uart_param->hci_uart_rx_pin = rx_pin; + uart_param->hci_uart_rts_pin = rts_pin; + uart_param->hci_uart_cts_pin = cts_pin; + return hci_driver_uart_config(uart_param); +} + +hci_driver_uart_params_config_t * +hci_driver_uart_config_param_get(void) +{ + return &s_hci_driver_uart_params; +} diff --git a/lib/bt/porting/transport/driver/uart/hci_driver_uart_dma.c b/lib/bt/porting/transport/driver/uart/hci_driver_uart_dma.c new file mode 100644 index 00000000..7bc3cc7c --- /dev/null +++ b/lib/bt/porting/transport/driver/uart/hci_driver_uart_dma.c @@ -0,0 +1,664 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_log.h" +#include "driver/uart.h" +#include "esp_hci_transport.h" +#include "esp_hci_internal.h" +#include "common/hci_driver_h4.h" +#include "common/hci_driver_util.h" +#include "common/hci_driver_mem.h" +#include "hci_driver_uart.h" + +#include "esp_private/periph_ctrl.h" +#include "esp_private/gdma.h" +#include "hal/uhci_ll.h" + +/* + * UART DMA Desc struct + * + * -------------------------------------------------------------- + * | own | EoF | sub_sof | 5'b0 | length [11:0] | size [11:0] | + * -------------------------------------------------------------- + * | buf_ptr [31:0] | + * -------------------------------------------------------------- + * | next_desc_ptr [31:0] | + * -------------------------------------------------------------- + */ + +/* this bitfield is start from the LSB!!! */ +typedef struct uhci_lldesc_s { + volatile uint32_t size : 12, + length: 12, + offset: 5, /* h/w reserved 5bit, s/w use it as offset in buffer */ + sosf : 1, /* start of sub-frame */ + eof : 1, /* end of frame */ + owner : 1; /* hw or sw */ + volatile const uint8_t *buf; /* point to buffer data */ + union { + volatile uint32_t empty; + STAILQ_ENTRY(uhci_lldesc_s) qe; /* pointing to the next desc */ + }; +} uhci_lldesc_t; + +/** + * @brief Enumeration of HCI transport transmission states. + */ +typedef enum { + HCI_TRANS_TX_IDLE, ///< HCI Transport TX is in idle state. + HCI_TRANS_TX_START, ///< HCI Transport TX is starting transmission. + HCI_TRANS_TX_END, ///< HCI Transport TX has completed transmission. +} hci_trans_tx_state_t; + +typedef struct { + TaskHandle_t task_handler; + hci_driver_uart_params_config_t *hci_uart_params; + SemaphoreHandle_t process_sem; + struct hci_h4_sm *h4_sm; + hci_driver_forward_fn *forward_cb; + struct os_mempool *hci_rx_data_pool; /*!< Init a memory pool for rx_data cache */ + uint8_t *hci_rx_data_buffer; + struct os_mempool *hci_rxinfo_pool; /*!< Init a memory pool for rxinfo cache */ + os_membuf_t *hci_rxinfo_buffer; + volatile bool rxinfo_mem_exhausted; /*!< Indicate rxinfo memory does not exist */ + volatile bool is_continue_rx; /*!< Continue to rx */ + volatile hci_trans_tx_state_t hci_tx_state; /*!< HCI Tx State */ + struct os_mempool lldesc_mem_pool;/*!< Init a memory pool for uhci_lldesc_t */ + uhci_lldesc_t *lldesc_mem; +} hci_driver_uart_dma_env_t; + +#define ESP_BT_HCI_TL_STATUS_OK (0) /*!< HCI_TL Tx/Rx operation status OK */ +/* The number of lldescs pool */ +#define HCI_LLDESCS_POOL_NUM (CONFIG_BT_LE_HCI_LLDESCS_POOL_NUM) +/* Default block size for HCI RX data */ +#define HCI_RX_DATA_BLOCK_SIZE (DEFAULT_BT_LE_ACL_BUF_SIZE + HCI_TRANSPORT_CMD_SZ) +#define HCI_RX_DATA_POOL_NUM (CONFIG_BT_LE_HCI_TRANS_RX_MEM_NUM) +#define HCI_RX_INFO_POOL_NUM (CONFIG_BT_LE_HCI_TRANS_RX_MEM_NUM + 1) + +/** + * @brief callback function for HCI Transport Layer send/receive operations + */ +typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status); + +struct uart_txrxchannel { + esp_bt_hci_tl_callback_t callback; + void *arg; + uhci_lldesc_t *link_head; +}; + +struct uart_env_tag { + struct uart_txrxchannel tx; + struct uart_txrxchannel rx; +}; + +typedef struct hci_message { + void *ptr; ///< Pointer to the message data. + uint32_t length; ///< Length of the message data. + STAILQ_ENTRY(hci_message) next; ///< Next element in the linked list. +} hci_message_t; + +static void hci_driver_uart_dma_recv_async(uint8_t *buf, uint32_t size, esp_bt_hci_tl_callback_t callback, void *arg); +int hci_driver_uart_dma_rx_start(uint8_t *rx_data, uint32_t length); +int hci_driver_uart_dma_tx_start(esp_bt_hci_tl_callback_t callback, void *arg); + +static const char *TAG = "uart_dma"; +static hci_driver_uart_dma_env_t s_hci_driver_uart_dma_env; +static struct hci_h4_sm s_hci_driver_uart_h4_sm; + +/* The list for hci_rx_data */ +STAILQ_HEAD(g_hci_rxinfo_list, hci_message); + +DRAM_ATTR struct g_hci_rxinfo_list g_hci_rxinfo_head; +static DRAM_ATTR struct uart_env_tag uart_env; +static uhci_dev_t *s_uhci_hw = &UHCI0; +static DRAM_ATTR gdma_channel_handle_t s_rx_channel; +static DRAM_ATTR gdma_channel_handle_t s_tx_channel; + +static int hci_driver_uart_dma_memory_deinit(void) +{ + + if (s_hci_driver_uart_dma_env.hci_rxinfo_buffer) { + free(s_hci_driver_uart_dma_env.hci_rxinfo_buffer); + s_hci_driver_uart_dma_env.hci_rxinfo_buffer = NULL; + } + + if (s_hci_driver_uart_dma_env.hci_rxinfo_pool) { + free(s_hci_driver_uart_dma_env.hci_rxinfo_pool); + s_hci_driver_uart_dma_env.hci_rxinfo_pool = NULL; + } + + if (s_hci_driver_uart_dma_env.hci_rx_data_buffer) { + free(s_hci_driver_uart_dma_env.hci_rx_data_buffer); + s_hci_driver_uart_dma_env.hci_rx_data_buffer = NULL; + } + + if (s_hci_driver_uart_dma_env.hci_rx_data_pool) { + free(s_hci_driver_uart_dma_env.hci_rx_data_pool); + s_hci_driver_uart_dma_env.hci_rx_data_pool = NULL; + } + + if (s_hci_driver_uart_dma_env.lldesc_mem) { + free(s_hci_driver_uart_dma_env.lldesc_mem); + s_hci_driver_uart_dma_env.lldesc_mem = NULL; + } + + return 0; +} + +static int hci_driver_uart_dma_memory_init(void) +{ + int rc = 0; + + s_hci_driver_uart_dma_env.lldesc_mem = malloc(OS_MEMPOOL_SIZE(HCI_LLDESCS_POOL_NUM, + sizeof (uhci_lldesc_t)) * sizeof(os_membuf_t)); + if (!s_hci_driver_uart_dma_env.lldesc_mem) { + return -1; + } + + rc = os_mempool_init(&s_hci_driver_uart_dma_env.lldesc_mem_pool, HCI_LLDESCS_POOL_NUM, + sizeof (uhci_lldesc_t), s_hci_driver_uart_dma_env.lldesc_mem, "hci_lldesc_pool"); + if (rc) { + goto init_err; + } + + s_hci_driver_uart_dma_env.hci_rx_data_pool = (struct os_mempool *)malloc(sizeof(struct os_mempool)); + if (!s_hci_driver_uart_dma_env.hci_rx_data_pool) { + goto init_err; + } + + memset(s_hci_driver_uart_dma_env.hci_rx_data_pool, 0, sizeof(struct os_mempool)); + s_hci_driver_uart_dma_env.hci_rx_data_buffer = malloc(OS_MEMPOOL_SIZE(HCI_RX_DATA_POOL_NUM, + HCI_RX_DATA_BLOCK_SIZE) * sizeof(os_membuf_t)); + if (!s_hci_driver_uart_dma_env.hci_rx_data_buffer) { + goto init_err; + } + + memset(s_hci_driver_uart_dma_env.hci_rx_data_buffer, 0, OS_MEMPOOL_SIZE(HCI_RX_DATA_POOL_NUM, + HCI_RX_DATA_BLOCK_SIZE) * sizeof(os_membuf_t)); + rc = os_mempool_init(s_hci_driver_uart_dma_env.hci_rx_data_pool, HCI_RX_DATA_POOL_NUM, + HCI_RX_DATA_BLOCK_SIZE, s_hci_driver_uart_dma_env.hci_rx_data_buffer, + "hci_rx_data_pool"); + if (rc) { + goto init_err; + } + + + /* Malloc hci rxinfo pool */ + s_hci_driver_uart_dma_env.hci_rxinfo_pool = (struct os_mempool *)malloc(sizeof(struct os_mempool)); + if (!s_hci_driver_uart_dma_env.hci_rxinfo_pool) { + goto init_err; + } + + memset(s_hci_driver_uart_dma_env.hci_rxinfo_pool, 0, sizeof(struct os_mempool)); + s_hci_driver_uart_dma_env.hci_rxinfo_buffer = malloc(OS_MEMPOOL_SIZE(HCI_RX_INFO_POOL_NUM, + sizeof(hci_message_t)) * sizeof(os_membuf_t)); + if (!s_hci_driver_uart_dma_env.hci_rxinfo_buffer) { + goto init_err; + } + + memset(s_hci_driver_uart_dma_env.hci_rxinfo_buffer, 0, OS_MEMPOOL_SIZE(HCI_RX_INFO_POOL_NUM, + sizeof(hci_message_t)) * sizeof(os_membuf_t)); + rc = os_mempool_init(s_hci_driver_uart_dma_env.hci_rxinfo_pool, HCI_RX_INFO_POOL_NUM, + sizeof(hci_message_t), s_hci_driver_uart_dma_env.hci_rxinfo_buffer, + "hci_rxinfo_pool"); + if (rc) { + goto init_err; + } + + return rc; +init_err: + hci_driver_uart_dma_memory_deinit(); + return rc; +} + +static IRAM_ATTR bool hci_uart_tl_rx_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data) +{ + esp_bt_hci_tl_callback_t callback = uart_env.rx.callback; + void *arg = uart_env.rx.arg; + assert(dma_chan == s_rx_channel); + assert(uart_env.rx.callback != NULL); + // clear callback pointer + uart_env.rx.callback = NULL; + uart_env.rx.arg = NULL; + // call handler + callback(arg, ESP_BT_HCI_TL_STATUS_OK); + return true; +} + +static IRAM_ATTR bool hci_uart_tl_tx_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data) +{ + esp_bt_hci_tl_callback_t callback = uart_env.tx.callback; + assert(dma_chan == s_tx_channel); + assert(uart_env.tx.callback != NULL); + // clear callback pointer + uart_env.tx.callback = NULL; + // call handler + callback(uart_env.tx.arg, ESP_BT_HCI_TL_STATUS_OK); + uart_env.tx.arg = NULL; + return true; +} + +uint8_t * IRAM_ATTR hci_driver_uart_dma_rxdata_memory_get(void) +{ + uint8_t *rx_data; + rx_data = os_memblock_get(s_hci_driver_uart_dma_env.hci_rx_data_pool); + return rx_data; +} + +hci_message_t * IRAM_ATTR hci_driver_uart_dma_rxinfo_memory_get(void) +{ + hci_message_t *rx_info; + rx_info = os_memblock_get(s_hci_driver_uart_dma_env.hci_rxinfo_pool); + return rx_info; +} + +void IRAM_ATTR hci_driver_uart_dma_cache_rxinfo(hci_message_t *hci_rxinfo) +{ + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + STAILQ_INSERT_TAIL(&g_hci_rxinfo_head, hci_rxinfo, next); + OS_EXIT_CRITICAL(sr); +} + +void IRAM_ATTR hci_driver_uart_dma_continue_rx_enable(bool enable) +{ + os_sr_t sr; + OS_ENTER_CRITICAL(sr); + s_hci_driver_uart_dma_env.is_continue_rx = enable; + OS_EXIT_CRITICAL(sr); +} + +void IRAM_ATTR hci_driver_uart_dma_rxinfo_mem_exhausted_set(bool is_exhausted) +{ + os_sr_t sr; + OS_ENTER_CRITICAL(sr); + s_hci_driver_uart_dma_env.rxinfo_mem_exhausted = is_exhausted; + OS_EXIT_CRITICAL(sr); +} + +void IRAM_ATTR hci_driver_uart_dma_recv_callback(void *arg, uint8_t status) +{ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + hci_message_t *hci_rxinfo; + uint8_t *rx_data; + + if (s_hci_driver_uart_dma_env.rxinfo_mem_exhausted) { + ESP_LOGE(TAG, "Will lost rx data, need adjust rxinfo memory count\n"); + assert(0); + } + + hci_rxinfo = hci_driver_uart_dma_rxinfo_memory_get(); + if (!hci_rxinfo) { + ESP_LOGW(TAG, "set rxinfo mem exhausted flag\n"); + hci_driver_uart_dma_rxinfo_mem_exhausted_set(true); + xSemaphoreGiveFromISR(s_hci_driver_uart_dma_env.process_sem, &xHigherPriorityTaskWoken); + return; + } + + hci_rxinfo->ptr = (void *)uart_env.rx.link_head->buf; + hci_rxinfo->length = uart_env.rx.link_head->length; + hci_driver_uart_dma_cache_rxinfo(hci_rxinfo); + xSemaphoreGiveFromISR(s_hci_driver_uart_dma_env.process_sem, &xHigherPriorityTaskWoken); + rx_data = hci_driver_uart_dma_rxdata_memory_get(); + if (!rx_data) { + hci_driver_uart_dma_continue_rx_enable(true); + }else { + hci_driver_uart_dma_rx_start(rx_data, HCI_RX_DATA_BLOCK_SIZE); + } +} + +void IRAM_ATTR hci_driver_uart_dma_txstate_set(hci_trans_tx_state_t tx_state) +{ + os_sr_t sr; + OS_ENTER_CRITICAL(sr); + s_hci_driver_uart_dma_env.hci_tx_state = tx_state; + OS_EXIT_CRITICAL(sr); +} + +void IRAM_ATTR hci_driver_uart_dma_send_callback(void *arg, uint8_t status) +{ + uhci_lldesc_t *lldesc_head; + uhci_lldesc_t *lldesc_nxt; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + lldesc_head = uart_env.tx.link_head; + while (lldesc_head) { + lldesc_nxt = lldesc_head->qe.stqe_next; + os_memblock_put(&s_hci_driver_uart_dma_env.lldesc_mem_pool, lldesc_head); + lldesc_head = lldesc_nxt; + } + + uart_env.tx.link_head = NULL; + hci_driver_uart_dma_txstate_set(HCI_TRANS_TX_IDLE); + xSemaphoreGiveFromISR(s_hci_driver_uart_dma_env.process_sem, &xHigherPriorityTaskWoken); +} + +static IRAM_ATTR void hci_driver_uart_dma_recv_async(uint8_t *buf, uint32_t size, esp_bt_hci_tl_callback_t callback, void *arg) +{ + uhci_lldesc_t *lldesc_head; + assert(buf != NULL); + assert(size != 0); + assert(callback != NULL); + uart_env.rx.callback = callback; + uart_env.rx.arg = arg; + lldesc_head = uart_env.rx.link_head; + + while (lldesc_head) { + os_memblock_put(&s_hci_driver_uart_dma_env.lldesc_mem_pool, lldesc_head), + lldesc_head = lldesc_head->qe.stqe_next; + } + + uart_env.rx.link_head = NULL; + lldesc_head = os_memblock_get(&s_hci_driver_uart_dma_env.lldesc_mem_pool); + assert(lldesc_head); + memset(lldesc_head, 0, sizeof(uhci_lldesc_t)); + lldesc_head->buf = buf; + lldesc_head->size = size; + lldesc_head->eof = 0; + s_uhci_hw->pkt_thres.pkt_thrs = size; + uart_env.rx.link_head = lldesc_head; + gdma_start(s_rx_channel, (intptr_t)(uart_env.rx.link_head)); +} + +int IRAM_ATTR hci_driver_uart_dma_rx_start(uint8_t *rx_data, uint32_t length) +{ + hci_driver_uart_dma_recv_async(rx_data, length, hci_driver_uart_dma_recv_callback, NULL); + return 0; +} + +int hci_driver_uart_dma_tx_start(esp_bt_hci_tl_callback_t callback, void *arg) +{ + void *data; + bool last_frame; + bool head_is_setted; + uint32_t tx_len; + uhci_lldesc_t *lldesc_data; + uhci_lldesc_t *lldesc_head; + uhci_lldesc_t *lldesc_tail; + + lldesc_head = NULL; + lldesc_tail = NULL; + head_is_setted = false; + last_frame = false; + while (true) { + tx_len = hci_driver_util_tx_list_dequeue(0xffffff, &data, &last_frame); + if (!tx_len) { + break; + } + + lldesc_data = os_memblock_get(&s_hci_driver_uart_dma_env.lldesc_mem_pool); + /* According to the current processing logic, It should not be empty */ + assert(lldesc_data); + memset(lldesc_data, 0, sizeof(uhci_lldesc_t)); + lldesc_data->length = tx_len; + lldesc_data->buf = data; + lldesc_data->eof = 0; + if (!head_is_setted) { + lldesc_head = lldesc_data; + head_is_setted = true; + } else { + lldesc_tail->qe.stqe_next = lldesc_data; + } + + lldesc_tail = lldesc_data; + if (last_frame) { + break; + } + } + + if (lldesc_head) { + lldesc_tail->eof = 1; + uart_env.tx.link_head = lldesc_head; + uart_env.tx.callback = callback; + uart_env.tx.arg = arg; + /* The DMA interrupt may have been triggered before setting the tx_state, + * So we set it first. + */ + hci_driver_uart_dma_txstate_set(HCI_TRANS_TX_START); + gdma_start(s_tx_channel, (intptr_t)(uart_env.tx.link_head)); + return 0; + } else { + return -1; + } +} + +static void hci_driver_uart_dma_install(void) +{ + periph_module_enable(PERIPH_UHCI0_MODULE); + periph_module_reset(PERIPH_UHCI0_MODULE); + // install DMA driver + gdma_channel_alloc_config_t tx_channel_config = { + .flags.reserve_sibling = 1, + .direction = GDMA_CHANNEL_DIRECTION_TX, + }; + + ESP_ERROR_CHECK(gdma_new_ahb_channel(&tx_channel_config, &s_tx_channel)); + gdma_channel_alloc_config_t rx_channel_config = { + .direction = GDMA_CHANNEL_DIRECTION_RX, + .sibling_chan = s_tx_channel, + }; + + ESP_ERROR_CHECK(gdma_new_ahb_channel(&rx_channel_config, &s_rx_channel)); + gdma_connect(s_tx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_UHCI, 0)); + gdma_connect(s_rx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_UHCI, 0)); + gdma_strategy_config_t strategy_config = { + .auto_update_desc = false, + .owner_check = false + }; + + gdma_apply_strategy(s_tx_channel, &strategy_config); + gdma_apply_strategy(s_rx_channel, &strategy_config); + gdma_rx_event_callbacks_t rx_cbs = { + .on_recv_eof = hci_uart_tl_rx_eof_callback + }; + + gdma_register_rx_event_callbacks(s_rx_channel, &rx_cbs, NULL); + gdma_tx_event_callbacks_t tx_cbs = { + .on_trans_eof = hci_uart_tl_tx_eof_callback + }; + + gdma_register_tx_event_callbacks(s_tx_channel, &tx_cbs, NULL); + // configure UHCI + uhci_ll_init((uhci_dev_t *)s_uhci_hw); + // uhci_ll_rx_set_eof_mode((uhci_dev_t *)s_uhci_hw, UHCI_RX_LEN_EOF); + uhci_ll_rx_set_eof_mode((uhci_dev_t *)s_uhci_hw, UHCI_RX_IDLE_EOF); + // disable software flow control + s_uhci_hw->escape_conf.val = 0; + uhci_ll_attach_uart_port((uhci_dev_t *)s_uhci_hw, s_hci_driver_uart_dma_env.hci_uart_params->hci_uart_port); +} + +static int +hci_driver_uart_dma_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir) +{ + /* By now, this layer is only used by controller. */ + assert(dir == HCI_DRIVER_DIR_C2H); + ESP_LOGD(TAG, "dma tx:"); + ESP_LOG_BUFFER_HEXDUMP(TAG, data, length, ESP_LOG_DEBUG); + + hci_driver_util_tx_list_enqueue(data_type, data, length); + xSemaphoreGive(s_hci_driver_uart_dma_env.process_sem); + return 0; +} + +static int +hci_driver_uart_dma_h4_frame_cb(uint8_t pkt_type, void *data) +{ + hci_driver_forward_fn *forward_cb; + forward_cb = s_hci_driver_uart_dma_env.forward_cb; + if (!forward_cb) { + return -1; + } + ESP_LOGD(TAG, "h4 frame\n"); + return forward_cb(pkt_type, data, 0, HCI_DRIVER_DIR_H2C); +} + +static void +hci_driver_uart_dma_process_task(void *p) +{ + hci_message_t *rxinfo_container; + os_sr_t sr; + int ret; + uint8_t* rx_data; + uint32_t rx_len; + + while (true) { + xSemaphoreTake(s_hci_driver_uart_dma_env.process_sem, portMAX_DELAY); + ESP_LOGD(TAG, "task run:%d\n",s_hci_driver_uart_dma_env.hci_tx_state); + /* Process Tx data */ + if (s_hci_driver_uart_dma_env.hci_tx_state == HCI_TRANS_TX_IDLE) { + hci_driver_uart_dma_tx_start(hci_driver_uart_dma_send_callback, (void*)&uart_env); + } + + if (s_hci_driver_uart_dma_env.rxinfo_mem_exhausted) { + rx_data = (void *)uart_env.rx.link_head->buf; + rx_len = uart_env.rx.link_head->length; + ESP_LOGD(TAG, "rxinfo exhausted:"); + ESP_LOG_BUFFER_HEXDUMP(TAG, rx_data, rx_len, ESP_LOG_DEBUG); + ret = hci_h4_sm_rx(s_hci_driver_uart_dma_env.h4_sm, rx_data, rx_len); + hci_driver_uart_dma_rx_start(rx_data, HCI_RX_DATA_BLOCK_SIZE); + hci_driver_uart_dma_rxinfo_mem_exhausted_set(false); + if (ret < 0) { + ESP_LOGW(TAG, "parse rx data error!\n"); + r_ble_ll_hci_ev_hw_err(ESP_HCI_SYNC_LOSS_ERR); + } + } + + while (!STAILQ_EMPTY(&g_hci_rxinfo_head)) { + OS_ENTER_CRITICAL(sr); + rxinfo_container = STAILQ_FIRST(&g_hci_rxinfo_head); + STAILQ_REMOVE_HEAD(&g_hci_rxinfo_head, next); + OS_EXIT_CRITICAL(sr); + + rx_data = rxinfo_container->ptr; + rx_len = rxinfo_container->length; + ESP_LOGD(TAG, "uart rx"); + ESP_LOG_BUFFER_HEXDUMP(TAG, rx_data, rx_len, ESP_LOG_DEBUG); + ret = hci_h4_sm_rx(s_hci_driver_uart_dma_env.h4_sm, rx_data, rx_len); + if (ret < 0) { + ESP_LOGW(TAG, "parse rx data error!\n"); + r_ble_ll_hci_ev_hw_err(ESP_HCI_SYNC_LOSS_ERR); + } + + os_memblock_put(s_hci_driver_uart_dma_env.hci_rxinfo_pool, rxinfo_container); + /* No need to enter CRITICAL */ + if (s_hci_driver_uart_dma_env.is_continue_rx) { + /* We should set continux rx flag first, RX interrupted may happened when rx start soon */ + hci_driver_uart_dma_continue_rx_enable(false); + hci_driver_uart_dma_rx_start(rx_data, HCI_RX_DATA_BLOCK_SIZE); + } else { + os_memblock_put(s_hci_driver_uart_dma_env.hci_rx_data_pool, rx_data); + } + } + } +} + +static int +hci_driver_uart_dma_task_create(void) +{ + /* !TODO: Set the core id by menuconfig */ + xTaskCreatePinnedToCore(hci_driver_uart_dma_process_task, "hci_driver_uart_dma_process_task", + CONFIG_BT_LE_HCI_TRANS_TASK_STACK_SIZE, NULL, + ESP_TASK_BT_CONTROLLER_PRIO, &s_hci_driver_uart_dma_env.task_handler, + 0); + assert(s_hci_driver_uart_dma_env.task_handler); + + ESP_LOGI(TAG, "hci transport task create successfully, prio:%d, stack size: %ld", + ESP_TASK_BT_CONTROLLER_PRIO, CONFIG_BT_LE_HCI_TRANS_TASK_STACK_SIZE); + + return 0; +} + + +static void +hci_driver_uart_dma_deinit(void) +{ + if (s_hci_driver_uart_dma_env.task_handler) { + vTaskDelete(s_hci_driver_uart_dma_env.task_handler); + s_hci_driver_uart_dma_env.task_handler = NULL; + } + + ESP_ERROR_CHECK(uart_driver_delete(s_hci_driver_uart_dma_env.hci_uart_params->hci_uart_port)); + hci_driver_uart_dma_memory_deinit(); + if (!s_hci_driver_uart_dma_env.process_sem) { + vSemaphoreDelete(s_hci_driver_uart_dma_env.process_sem); + } + + hci_driver_util_deinit(); + memset(&s_hci_driver_uart_dma_env, 0, sizeof(hci_driver_uart_dma_env_t)); +} + + +static int +hci_driver_uart_dma_init(hci_driver_forward_fn *cb) +{ + int rc; + + memset(&s_hci_driver_uart_dma_env, 0, sizeof(hci_driver_uart_dma_env_t)); + + s_hci_driver_uart_dma_env.h4_sm = &s_hci_driver_uart_h4_sm; + hci_h4_sm_init(s_hci_driver_uart_dma_env.h4_sm, &s_hci_driver_mem_alloc, &s_hci_driver_mem_free, hci_driver_uart_dma_h4_frame_cb); + + rc = hci_driver_util_init(); + if (rc) { + goto error; + } + + s_hci_driver_uart_dma_env.process_sem = xSemaphoreCreateBinary(); + if (!s_hci_driver_uart_dma_env.process_sem) { + goto error; + } + + rc = hci_driver_uart_dma_memory_init(); + if (rc) { + goto error; + } + + s_hci_driver_uart_dma_env.forward_cb = cb; + s_hci_driver_uart_dma_env.hci_uart_params = hci_driver_uart_config_param_get(); + hci_driver_uart_config(s_hci_driver_uart_dma_env.hci_uart_params); + + ESP_LOGI(TAG, "uart attach uhci!"); + hci_driver_uart_dma_install(); + + STAILQ_INIT(&g_hci_rxinfo_head); + + rc = hci_driver_uart_dma_task_create(); + if (rc) { + goto error; + } + + s_hci_driver_uart_dma_env.hci_tx_state = HCI_TRANS_TX_IDLE; + s_hci_driver_uart_dma_env.rxinfo_mem_exhausted = false; + s_hci_driver_uart_dma_env.is_continue_rx = false; + hci_driver_uart_dma_rx_start(os_memblock_get(s_hci_driver_uart_dma_env.hci_rx_data_pool), + HCI_RX_DATA_BLOCK_SIZE); + return 0; + +error: + hci_driver_uart_dma_deinit(); + return rc; +} + +int +hci_driver_uart_dma_reconfig_pin(int tx_pin, int rx_pin, int cts_pin, int rts_pin) +{ + return hci_driver_uart_pin_update(tx_pin, rx_pin, cts_pin, rts_pin); +} + + +hci_driver_ops_t hci_driver_uart_dma_ops = { + .hci_driver_tx = hci_driver_uart_dma_tx, + .hci_driver_init = hci_driver_uart_dma_init, + .hci_driver_deinit = hci_driver_uart_dma_deinit, +}; diff --git a/lib/bt/porting/transport/driver/vhci/hci_driver_nimble.c b/lib/bt/porting/transport/driver/vhci/hci_driver_nimble.c new file mode 100644 index 00000000..9a117eb8 --- /dev/null +++ b/lib/bt/porting/transport/driver/vhci/hci_driver_nimble.c @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "esp_hci_internal.h" +#include "esp_hci_driver.h" + +typedef struct { + hci_driver_forward_fn *forward_cb; +} hci_driver_vhci_env_t; + +static hci_driver_vhci_env_t s_hci_driver_vhci_env; + +static int +hci_driver_vhci_controller_tx(hci_driver_data_type_t data_type, uint8_t *data) +{ + /* The length is contained in the data. */ + return s_hci_driver_vhci_env.forward_cb(data_type, data, 0, HCI_DRIVER_DIR_C2H); +} + +static int +hci_driver_vhci_host_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length) +{ + return s_hci_driver_vhci_env.forward_cb(data_type, data, length, HCI_DRIVER_DIR_H2C); +} + +static int +hci_driver_vhci_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir) +{ + int rc; + + if (dir == HCI_DRIVER_DIR_C2H) { + rc = hci_driver_vhci_controller_tx(data_type, data); + } else { + rc = hci_driver_vhci_host_tx(data_type, data, length); + } + return rc; +} + +static int +hci_driver_vhci_init(hci_driver_forward_fn *cb) +{ + s_hci_driver_vhci_env.forward_cb = cb; + return 0; +} + +static void +hci_driver_vhci_deinit(void) +{ + memset(&s_hci_driver_vhci_env, 0, sizeof(hci_driver_vhci_env_t)); +} + +hci_driver_ops_t hci_driver_vhci_ops = { + .hci_driver_tx = hci_driver_vhci_tx, + .hci_driver_init = hci_driver_vhci_init, + .hci_driver_deinit = hci_driver_vhci_deinit, +}; diff --git a/lib/bt/porting/transport/driver/vhci/hci_driver_standard.c b/lib/bt/porting/transport/driver/vhci/hci_driver_standard.c new file mode 100644 index 00000000..82626057 --- /dev/null +++ b/lib/bt/porting/transport/driver/vhci/hci_driver_standard.c @@ -0,0 +1,161 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "os/os_mbuf.h" +#include "esp_hci_transport.h" +#include "esp_hci_internal.h" +#include "esp_hci_driver.h" +#include "esp_bt.h" + +typedef struct { + hci_driver_forward_fn *forward_cb; + const esp_vhci_host_callback_t *host_recv_cb; +} hci_driver_vhci_env_t; + +static hci_driver_vhci_env_t s_hci_driver_vhci_env; + +static int +hci_driver_vhci_controller_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length) +{ + int rc; + uint16_t buf_len = 0; + uint8_t *buf = NULL; + struct os_mbuf *om; + + if (data_type == HCI_DRIVER_TYPE_ACL) { + om = (struct os_mbuf *)data; + buf_len = length + 1; + buf = malloc(buf_len); + /* TODO: If there is no memory, should handle it in the controller. */ + assert(buf); + buf[0] = HCI_DRIVER_TYPE_ACL; + os_mbuf_copydata(om, 0, length, &buf[1]); + os_mbuf_free_chain(om); + } else if (data_type == HCI_DRIVER_TYPE_EVT) { + buf_len = length + 1; + buf = malloc(buf_len); + /* TODO: If there is no memory, should handle it in the controller. */ + assert(buf != NULL); + buf[0] = HCI_DRIVER_TYPE_EVT; + memcpy(&buf[1], data, length); + r_ble_hci_trans_buf_free(data); + } else if (data_type == HCI_DRIVER_TYPE_ISO) { + buf_len = length + 1; + buf = malloc(buf_len); + /* TODO: If there is no memory, should handle it in the controller. */ + assert(buf); + buf[0] = HCI_DRIVER_TYPE_ISO; + memcpy(&buf[1], data, length); + free(data); + } + + rc = s_hci_driver_vhci_env.forward_cb(data_type, buf, buf_len, HCI_DRIVER_DIR_C2H); + free(buf); + + return rc; +} + +static int +hci_driver_vhci_host_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length) +{ + uint8_t *cmd; + struct os_mbuf *om; + + if (data_type == HCI_DRIVER_TYPE_ACL) { + om = os_msys_get_pkthdr(length, ESP_HCI_INTERNAL_ACL_MBUF_LEADINGSPCAE); + assert(om); + assert(os_mbuf_append(om, &data[1], length - 1) == 0); + data = (uint8_t *)om; + } else if (data_type == HCI_DRIVER_TYPE_CMD) { + cmd = r_ble_hci_trans_buf_alloc(ESP_HCI_INTERNAL_BUF_CMD); + assert(cmd); + memcpy(cmd, data + 1, length - 1); + data = cmd; + } + + return s_hci_driver_vhci_env.forward_cb(data_type, data, length, HCI_DRIVER_DIR_H2C); +} + +static int +hci_driver_vhci_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir) +{ + int rc; + + if (dir == HCI_DRIVER_DIR_C2H) { + rc = hci_driver_vhci_controller_tx(data_type, data, length); + } else { + rc = hci_driver_vhci_host_tx(data_type, data, length); + } + return rc; +} + +static int +hci_driver_vhci_init(hci_driver_forward_fn *cb) +{ + memset(&s_hci_driver_vhci_env, 0, sizeof(hci_driver_vhci_env_t)); + s_hci_driver_vhci_env.forward_cb = cb; + return 0; +} + +static void +hci_driver_vhci_deinit(void) +{ + memset(&s_hci_driver_vhci_env, 0, sizeof(hci_driver_vhci_env_t)); +} + +hci_driver_ops_t hci_driver_vhci_ops = { + .hci_driver_tx = hci_driver_vhci_tx, + .hci_driver_init = hci_driver_vhci_init, + .hci_driver_deinit = hci_driver_vhci_deinit, +}; + +/* Special APIs declared in the `esp_bt.h'. */ +static int +hci_driver_vhci_host_recv_cb(hci_trans_pkt_ind_t type, uint8_t *data, uint16_t len) +{ + static const esp_vhci_host_callback_t *host_recv_cb; + + host_recv_cb = s_hci_driver_vhci_env.host_recv_cb; + if (host_recv_cb) { + return host_recv_cb->notify_host_recv(data, len); + } + + return -1; +} + +esp_err_t +esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback) +{ + if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return ESP_FAIL; + } + + s_hci_driver_vhci_env.host_recv_cb = callback; + if(hci_transport_host_callback_register(hci_driver_vhci_host_recv_cb)) { + s_hci_driver_vhci_env.host_recv_cb = NULL; + return ESP_FAIL; + } + + return ESP_OK; +} + +void +esp_vhci_host_send_packet(uint8_t *data, uint16_t len) +{ + if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return; + } + + hci_driver_vhci_tx(data[0], data, len, HCI_DRIVER_DIR_H2C); +} + +bool +esp_vhci_host_check_send_available(void) +{ + return true; +} diff --git a/lib/bt/porting/transport/driver/vhci/hci_driver_tamplete.c b/lib/bt/porting/transport/driver/vhci/hci_driver_tamplete.c new file mode 100644 index 00000000..63feb934 --- /dev/null +++ b/lib/bt/porting/transport/driver/vhci/hci_driver_tamplete.c @@ -0,0 +1,133 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "os/os_mbuf.h" +#include "esp_hci_transport.h" +#include "esp_hci_internal.h" +#include "esp_hci_driver.h" + +typedef struct { + hci_driver_forward_fn *forward_cb; +} hci_driver_vhci_env_t; + +static hci_driver_vhci_env_t s_hci_driver_vhci_env; + +static int +hci_driver_vhci_controller_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length) +{ + int rc; + uint16_t len = 0; + uint8_t *buf = NULL; + struct os_mbuf *om; + + if (data_type == HCI_DRIVER_TYPE_ACL) { + /* The ACL data will be packaged as structure of `os_mbuf`. + * 1. Allocate a buffer suitable for the host. Use the following method to copy the data + * from the os_mbuf to the newly allocated memory. + * ```c + * buf = malloc(length); + * os_mbuf_copydata(om, 0, length, buf); + * ``` + * 2. Free the controller's os_mbuf + * ```c + * os_mbuf_free_chain(om); + * ``` + */ + } else if (data_type == HCI_DRIVER_TYPE_EVT) { + /* The event data will be packaged as an array. + * 1. Allocate a buffer suitable for the host. Use the following method to copy the data + * from the controller buffer to the newly allocated memory. + * ```c + * buf = malloc(length); + * memcpy(buf, data, length); + * ``` + * 2. Free the controller's buffer. + * ```c + * r_ble_hci_trans_buf_free(data); + * ``` + */ + } else { + assert(0); + } + + rc = s_hci_driver_vhci_env.forward_cb(data_type, buf, len, HCI_DRIVER_DIR_C2H); + free(buf); + + return rc; +} + +static int +hci_driver_vhci_host_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length) +{ + uint8_t *hci_data; + struct os_mbuf *om; + + if (data_type == HCI_DRIVER_TYPE_ACL) { + /* The ACL data needs to be packaged as structure of `os_mbuf`. + * 1. Get an os_mbuf in the following way. + * ```c + * om = os_msys_get_pkthdr(length, ESP_HCI_INTERNAL_ACL_MBUF_LEADINGSPCAE); + * ``` + * 2. Copy the host's data into this os_mbuf using the following method. + * ```c + * assert(os_mbuf_append(om, data, length) == 0); + * hci_data = (uint8_t *)om; + * ``` + * 3. Free the host's buffer if needed. + */ + } else if (data_type == HCI_DRIVER_TYPE_CMD) { + /* The COMMAND data needs to be packaged as an array. + * 1. Get a command buffer from the controller. + * ```c + * hci_data = r_ble_hci_trans_buf_alloc(ESP_HCI_INTERNAL_BUF_CMD); + * ``` + * 2. Copy the host's data into this buffer. + * ```c + * memcpy(hci_data, data, length); + * ``` + * 3. Free the host's buffer if needed. + */ + } else { + assert(0); + } + + return s_hci_driver_vhci_env.forward_cb(data_type, hci_data, length, HCI_DRIVER_DIR_H2C); +} + +static int +hci_driver_vhci_tx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir) +{ + int rc; + + if (dir == HCI_DRIVER_DIR_C2H) { + rc = hci_driver_vhci_controller_tx(data_type, data, length); + } else { + rc = hci_driver_vhci_host_tx(data_type, data, length); + } + return rc; +} + +static int +hci_driver_vhci_init(hci_driver_forward_fn *cb) +{ + memset(&s_hci_driver_vhci_env, 0, sizeof(hci_driver_vhci_env_t)); + s_hci_driver_vhci_env.forward_cb = cb; + return 0; +} + +static void +hci_driver_vhci_deinit(void) +{ + memset(&s_hci_driver_vhci_env, 0, sizeof(hci_driver_vhci_env_t)); +} + +hci_driver_ops_t hci_driver_vhci_ops = { + .hci_driver_tx = hci_driver_vhci_tx, + .hci_driver_init = hci_driver_vhci_init, + .hci_driver_deinit = hci_driver_vhci_deinit, +}; diff --git a/lib/bt/porting/transport/include/common/hci_driver_h4.h b/lib/bt/porting/transport/include/common/hci_driver_h4.h new file mode 100644 index 00000000..4c8424c7 --- /dev/null +++ b/lib/bt/porting/transport/include/common/hci_driver_h4.h @@ -0,0 +1,88 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _HCI_H4_H_ +#define _HCI_H4_H_ + +#include + +#define HCI_H4_NONE 0x00 +#define HCI_H4_CMD 0x01 +#define HCI_H4_ACL 0x02 +#define HCI_H4_EVT 0x04 +#define HCI_H4_ISO 0x05 + +typedef void *(hci_h4_alloc_cmd)(void); +typedef void *(hci_h4_alloc_evt)(int); +typedef struct os_mbuf *(hci_h4_alloc_acl)(void); +typedef struct os_mbuf *(hci_h4_alloc_iso)(void); + +struct hci_h4_allocators { + hci_h4_alloc_cmd *cmd; + hci_h4_alloc_acl *acl; + hci_h4_alloc_evt *evt; + hci_h4_alloc_iso *iso; +}; + +extern const struct hci_h4_allocators hci_h4_allocs_from_ll; +extern const struct hci_h4_allocators hci_h4_allocs_from_hs; + +typedef void (hci_h4_free_cmd)(uint8_t *buf); +typedef void (hci_h4_free_evt)(uint8_t *buf); +typedef int (hci_h4_free_acl)(struct os_mbuf *om); +typedef int (hci_h4_free_iso)(struct os_mbuf *om); +struct hci_h4_frees { + hci_h4_free_cmd *cmd; + hci_h4_free_acl *acl; + hci_h4_free_evt *evt; + hci_h4_free_iso *iso; +}; + +typedef int (hci_h4_frame_cb)(uint8_t pkt_type, void *data); + +struct hci_h4_sm { + uint8_t state; + uint8_t pkt_type; + uint8_t min_len; + uint16_t len; + uint16_t exp_len; + uint8_t hdr[4]; + union { + uint8_t *buf; + struct os_mbuf *om; + }; + + const struct hci_h4_allocators *allocs; + const struct hci_h4_frees *frees; + hci_h4_frame_cb *frame_cb; +}; + +void hci_h4_sm_init(struct hci_h4_sm *h4sm, + const struct hci_h4_allocators *allocs, + const struct hci_h4_frees *frees, + hci_h4_frame_cb *frame_cb); + +int hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len); + +#endif /* _HCI_H4_H_ */ diff --git a/lib/bt/porting/transport/include/common/hci_driver_mem.h b/lib/bt/porting/transport/include/common/hci_driver_mem.h new file mode 100644 index 00000000..8a2180e5 --- /dev/null +++ b/lib/bt/porting/transport/include/common/hci_driver_mem.h @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _H_HCI_DRIVER_MEM_ +#define _H_HCI_DRIVER_MEM_ +#include +#include "os/os_mbuf.h" + +void *hci_driver_mem_cmd_alloc(void); + +void *hci_driver_mem_evt_alloc(int discardable); + +struct os_mbuf *hci_driver_mem_acl_alloc(void); + +struct os_mbuf *hci_driver_mem_acl_len_alloc(uint32_t len); + +struct os_mbuf *hci_driver_mem_iso_alloc(void); + +struct os_mbuf *hci_driver_mem_iso_len_alloc(uint32_t len); + +extern const struct hci_h4_allocators s_hci_driver_mem_alloc; +extern const struct hci_h4_frees s_hci_driver_mem_free; +#endif // _H_HCI_DRIVER_MEM_ diff --git a/lib/bt/porting/transport/include/common/hci_driver_util.h b/lib/bt/porting/transport/include/common/hci_driver_util.h new file mode 100644 index 00000000..2e186e11 --- /dev/null +++ b/lib/bt/porting/transport/include/common/hci_driver_util.h @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _H_HCI_DRIVER_UTIL_ +#define _H_HCI_DRIVER_UTIL_ +#include + +int hci_driver_util_init(void); + +void hci_driver_util_deinit(void); + +void hci_driver_util_tx_list_enqueue(hci_driver_data_type_t type, uint8_t *data, uint32_t len); + +uint32_t hci_driver_util_tx_list_dequeue(uint32_t max_tx_len, void **tx_data, bool *last_frame); + +void hci_driver_util_assert_check(const uint32_t ln, const char *fn, uint32_t param1, uint32_t param2); +#define HCI_TRANS_ASSERT(cond, p1, p2) \ + if (!(cond)) { \ + hci_driver_util_assert_check(__LINE__, __func__, p1, p2); \ + } +#endif // _H_HCI_DRIVER_UTIL_ diff --git a/lib/bt/porting/transport/include/esp_hci_driver.h b/lib/bt/porting/transport/include/esp_hci_driver.h new file mode 100644 index 00000000..04bf9297 --- /dev/null +++ b/lib/bt/porting/transport/include/esp_hci_driver.h @@ -0,0 +1,81 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef H_ESP_HCI_DRIVER_ +#define H_ESP_HCI_DRIVER_ +#include + +/** + * @brief Enumeration of HCI transport direction. + */ +typedef enum { + HCI_DRIVER_DIR_C2H = 0x00, ///< From controller to host. + HCI_DRIVER_DIR_H2C, ///< From host to controller. +} hci_driver_direction_t; + +typedef enum { + HCI_DRIVER_TYPE_CMD = 0x01, ///< HCI Command Indicator. + HCI_DRIVER_TYPE_ACL, ///< HCI ACL Data Indicator. + HCI_DRIVER_TYPE_SYNC, ///< HCI Synchronous Data Indicator. + HCI_DRIVER_TYPE_EVT, ///< HCI Event Indicator. + HCI_DRIVER_TYPE_ISO, ///< HCI Isochronous Data Indicator. + HCI_DRIVER_TYPE_VENDOR, ///< HCI Vendor data Indicator. +} hci_driver_data_type_t; + +typedef int hci_driver_forward_fn(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir); + +/** + * @brief Structure of HCI driver operations. + */ +typedef struct hci_driver_ops { + int (*hci_driver_tx)(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir); + int (*hci_driver_init)(hci_driver_forward_fn *cb); + void (*hci_driver_deinit)(void); +} hci_driver_ops_t; + + +#if CONFIG_BT_LE_HCI_INTERFACE_USE_RAM +extern hci_driver_ops_t hci_driver_vhci_ops; +#endif // CONFIG_BT_LE_HCI_INTERFACE_USE_RAM + +#if CONFIG_BT_LE_HCI_INTERFACE_USE_UART +#if CONFIG_BT_LE_UART_HCI_DMA_MODE +extern hci_driver_ops_t hci_driver_uart_dma_ops; +/** + * @brief Reconfigure the UART pins for the HCI driver. + * + * This function changes the UART pin configuration for the HCI driver. + * + * @param tx_pin The pin number for the UART TX (transmit) line. + * @param rx_pin The pin number for the UART RX (receive) line. + * @param cts_pin The pin number for the UART CTS (clear to send) line. + * @param rts_pin The pin number for the UART RTS (request to send) line. + * + * @return int Returns 0 on success, or a negative error code on failure. + */ +int hci_driver_uart_dma_reconfig_pin(int tx_pin, int rx_pin, int cts_pin, int rts_pin); +#define hci_uart_reconfig_pin hci_driver_uart_dma_reconfig_pin +#else +extern hci_driver_ops_t hci_driver_uart_ops; +/** + * @brief Reconfigure the UART pins for the HCI driver. + * + * This function changes the UART pin configuration for the HCI driver. + * + * @param tx_pin The pin number for the UART TX (transmit) line. + * @param rx_pin The pin number for the UART RX (receive) line. + * @param cts_pin The pin number for the UART CTS (clear to send) line. + * @param rts_pin The pin number for the UART RTS (request to send) line. + * + * @return int Returns 0 on success, or a negative error code on failure. + */ +int hci_driver_uart_reconfig_pin(int tx_pin, int rx_pin, int cts_pin, int rts_pin); +#define hci_uart_reconfig_pin hci_driver_uart_reconfig_pin +#endif // CONFIG_BT_LE_UART_HCI_DMA_MODE +#endif // CONFIG_BT_LE_HCI_INTERFACE_USE_UART + +#endif // H_ESP_HCI_DRIVER_ diff --git a/lib/bt/porting/transport/include/esp_hci_internal.h b/lib/bt/porting/transport/include/esp_hci_internal.h new file mode 100644 index 00000000..2b1c3353 --- /dev/null +++ b/lib/bt/porting/transport/include/esp_hci_internal.h @@ -0,0 +1,121 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef H_ESP_HCI_INTERNAL_ +#define H_ESP_HCI_INTERNAL_ + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include "os/os_mbuf.h" + + +/* The leadingspace in user info header for ACL data */ +#define ESP_HCI_INTERNAL_ACL_MBUF_LEADINGSPCAE (4) + +#define ESP_HCI_INTERNAL_BUF_CMD (3) + +/** + * @brief Define the HCI hardware error code for synchronization loss. + * This error code is used to indicate a loss of synchronization between the controller and the host. + */ +#define ESP_HCI_SYNC_LOSS_ERR (0x1) +/** Callback function types; executed when HCI packets are received. */ +typedef int esp_hci_internal_rx_cmd_fn(uint8_t *cmd, void *arg); +typedef int esp_hci_internal_rx_acl_fn(struct os_mbuf *om, void *arg); + +/** + * Configures the HCI transport to operate with a host. The transport will + * execute specified callbacks upon receiving HCI packets from the controller. + * + * @param evt_cb The callback to execute upon receiving an HCI + * event. + * @param evt_arg Optional argument to pass to the event + * callback. + * @param acl_cb The callback to execute upon receiving ACL + * data. + * @param acl_arg Optional argument to pass to the ACL + * callback. + */ +void r_ble_hci_trans_cfg_hs(esp_hci_internal_rx_cmd_fn *evt_cb, void *evt_arg, + esp_hci_internal_rx_acl_fn *acl_cb, void *acl_arg); +/** + * Sends ACL data from host to controller. + * + * @param om The ACL data packet to send. + * + * @return 0 on success; + * A BLE_ERR_[...] error code on failure. + */ +int r_ble_hci_trans_hs_acl_tx(struct os_mbuf *om); + +/** + * Sends an HCI command from the host to the controller. + * + * @param cmd The HCI command to send. This buffer must be + * allocated via ble_hci_trans_buf_alloc(). + * + * @return 0 on success; + * A BLE_ERR_[...] error code on failure. + */ +int r_ble_hci_trans_hs_cmd_tx(uint8_t *cmd); + +/** + * Allocates a flat buffer of the specified type. + * + * @param type The type of buffer to allocate; one of the + * BLE_HCI_TRANS_BUF_[...] constants. + * + * @return The allocated buffer on success; + * NULL on buffer exhaustion. + */ +uint8_t * r_ble_hci_trans_buf_alloc(int type); + +/** + * Frees the specified flat buffer. The buffer must have been allocated via + * ble_hci_trans_buf_alloc(). + * + * @param buf The buffer to free. + */ +void r_ble_hci_trans_buf_free(uint8_t *buf); + +/** + * Configures a callback to get executed whenever an ACL data packet is freed. + * The function is called immediately before the free occurs. + * + * @param cb The callback to configure. + * @param arg An optional argument to pass to the callback. + * + * @return 0 on success; + * BLE_ERR_UNSUPPORTED if the transport does not + * support this operation. + */ +int r_ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg); + +/** + * @brief Handle an HCI hardware error event. + * This function processes a hardware error code and generates the appropriate HCI hardware error event. + * + * @param hw_err The hardware error code that needs to be processed. The specific meaning of the error code + * depends on the implementation and the hardware. + * + * @return int Returns 0 on success, or a non-zero error code on failure. + * + * @note This function should be called whenever a hardware error is detected in the HCI Layer. + */ +int r_ble_ll_hci_ev_hw_err(uint8_t hw_err); + +//!TODO: Check what this API is used for +int r_ble_hci_trans_reset(void); + +//!TODO: Should we initialize the hci layer in IDF ? +void esp_ble_hci_trans_init(uint8_t); + +#ifdef __cplusplus +} +#endif +#endif /* H_ESP_HCI_INTERNAL_ */ diff --git a/lib/bt/porting/transport/include/esp_hci_transport.h b/lib/bt/porting/transport/include/esp_hci_transport.h new file mode 100644 index 00000000..c811a09a --- /dev/null +++ b/lib/bt/porting/transport/include/esp_hci_transport.h @@ -0,0 +1,83 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef H_ESP_HCI_TRANSPORT_ +#define H_ESP_HCI_TRANSPORT_ + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include "os/os_mbuf.h" +#include "esp_hci_driver.h" + +/** + * @brief Enumeration of HCI packet indicators + */ +typedef enum { + HCI_CMD_IND = 0x01, /*!< HCI Command Indicator */ + HCI_ACL_IND, /*!< HCI ACL Data Indicator */ + HCI_SYNC_IND, /*!< HCI Synchronous Data Indicator */ + HCI_EVT_IND, /*!< HCI Event Indicator */ + HCI_ISO_IND, /*!< HCI Isochronous Data Indicator */ + HCI_VENDOR_IND, /*!< HCI Vendor data Indicator */ +} hci_trans_pkt_ind_t; + +/** + * @brief Enumeration of HCI Transport Mode + */ +typedef enum { + HCI_TRANSPORT_VHCI, /*!< VHCI Transport Mode */ + HCI_TRANSPORT_UART_NO_DMA, /*!< UART_NO_DMA Transport Mode */ + HCI_TRANSPORT_UART_UHCI, /*!< UART_UHCI Transport Mode */ + HCI_TRANSPORT_SDIO, /*!< SDIO Transport Mode */ + HCI_TRANSPORT_USB, /*!< USB Transport Mode */ +} hci_trans_mode_t; + +typedef int hci_transport_host_recv_fn(hci_trans_pkt_ind_t type, uint8_t *data, uint16_t len); +#define HCI_TRANSPORT_CMD_SZ (260) +/** + * @brief Initialize the HCI transport layer. + * It should be called before using any other functions in the transport layer. + * + * @param hci_transport_mode The mode in which the HCI transport should operate. + * + * @return int Returns 0 on success, or a non-zero error code on failure. + */ +int hci_transport_init(uint8_t hci_transport_mode); + +/** + * @brief Deinitialize the HCI transport layer for releasing any allocated resources. + */ +void hci_transport_deinit(void); + +/** + * @brief Set the host's HCI callback which will be invoked when receiving ACL/Events from controller. + * @param callback hci_transport_host_recv_fn type variable + * @return int 0 on success, non-zero error code on failure. + */ +int hci_transport_host_callback_register(hci_transport_host_recv_fn *callback); + +/** + * @brief Called to send HCI commands form host to controller. + * @param data Point to the commands data + * @param length Length of data + * @return int 0 on success, non-zero error code on failure. + */ +int hci_transport_host_cmd_tx(uint8_t *data, uint32_t length); + +/** + * @brief Called to send HCI ACL form host to controller. + * @param data Point to the ACL data + * @param length Length of data + * @return int 0 on success, non-zero error code on failure. + */ +int hci_transport_host_acl_tx(uint8_t *data, uint32_t length); + +#ifdef __cplusplus +} +#endif +#endif /* H_ESP_HCI_TRANSPORT_ */ diff --git a/lib/bt/porting/transport/include/hci_uart.h b/lib/bt/porting/transport/include/hci_uart.h deleted file mode 100644 index 02bc91b4..00000000 --- a/lib/bt/porting/transport/include/hci_uart.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "driver/uart.h" - -/** - * Function prototype for UART driver to ask for more data to send. - * Returns -1 if no more data is available for TX. - * Driver must call this with interrupts disabled. - */ -typedef int (*hci_uart_tx_char)(void *arg); - -/** - * Function prototype for UART driver to report that transmission is - * complete. This should be called when transmission of last byte is - * finished. - * Driver must call this with interrupts disabled. - */ -typedef void (*hci_uart_tx_done)(void *arg); - -/** - * Function prototype for UART driver to report incoming byte of data. - * Returns -1 if data was dropped. - * Driver must call this with interrupts disabled. - */ -typedef int (*hci_uart_rx_char)(void *arg, uint8_t byte); - - -/** - * Initializes given uart. Mapping of logical UART number to physical - * UART/GPIO pins is in BSP. - */ -int hci_uart_init_cbs(int uart, hci_uart_tx_char tx_func, - hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg); - - -/** - * Applies given configuration to UART. - * - * @param port_num The UART number to configure - * @param speed The baudrate in bps to configure - * @param databits The number of databits to send per byte - * @param stopbits The number of stop bits to send - * @param parity The UART parity - * @param flow_ctl Flow control settings on the UART - * - * @return 0 on success, non-zero error code on failure - */ -int hci_uart_config(int port_num, int32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, - uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl); - -/** - * Close UART port. Can call hal_uart_config() with different settings after - * calling this. - * - * @param port_num The UART number to close - */ -int hci_uart_close(int port_num); - -/** - * More data queued for transmission. UART driver will start asking for that - * data. - * - * @param port_num The UART number to start TX on - */ -void hci_uart_start_tx(int port_num); - -/** - * Upper layers have consumed some data, and are now ready to receive more. - * This is meaningful after uart_rx_char callback has returned -1 telling - * that no more data can be accepted. - * - * @param port_num The UART number to begin RX on - */ -void hci_uart_start_rx(int port_num); - -/** - * @brief reconfig hci uart pin - * - * @param tx_pin The Tx pin - * @param rx_pin The Rx pin - * @param cts_pin The CTS pin - * @param rts_pin The RTS pin - * @return int 0 on success, non-zero error code on failure - */ -int hci_uart_reconfig_pin(int tx_pin, int rx_pin, int cts_pin, int rts_pin); - -#ifdef __cplusplus -} -#endif diff --git a/lib/bt/porting/transport/src/hci_transport.c b/lib/bt/porting/transport/src/hci_transport.c new file mode 100644 index 00000000..29c2e001 --- /dev/null +++ b/lib/bt/porting/transport/src/hci_transport.c @@ -0,0 +1,177 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "esp_log.h" +#include "esp_hci_transport.h" +#include "esp_hci_internal.h" +#include "esp_bt.h" + +typedef struct hci_transport_env +{ + hci_transport_host_recv_fn *host_recv_cb; + hci_driver_ops_t *driver_ops; +} hci_transport_env_t; + +static hci_transport_env_t s_hci_transport_env; + +/* Functions for packets Rx. */ +static int +hci_transport_controller_packet_rx(hci_driver_data_type_t data_type, uint8_t *data) +{ + if (data_type == HCI_DRIVER_TYPE_CMD) { + r_ble_hci_trans_hs_cmd_tx(data); + } + + if (data_type == HCI_DRIVER_TYPE_ACL) { + r_ble_hci_trans_hs_acl_tx((struct os_mbuf *) data); + } + return 0; +} + +static int +hci_transport_host_packet_rx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length) +{ + if (!s_hci_transport_env.host_recv_cb) { + return -1; + } + return s_hci_transport_env.host_recv_cb((hci_trans_pkt_ind_t)data_type, data, length); +} + +static int +hci_transport_packet_rx(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir) +{ + int rc; + if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return -1; + } + + if (dir == HCI_DRIVER_DIR_C2H) { + rc = hci_transport_host_packet_rx(data_type, data, length); + } else { + rc = hci_transport_controller_packet_rx(data_type, data); + } + + return rc; +} + +/* Functions for controller Tx. */ +static int +hci_transport_controller_tx_dummy(void *data, void *arg) +{ + return -1; +} + +static int +hci_transport_controller_evt_tx(uint8_t *hci_ev, void *arg) +{ + uint32_t len; + + if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { + r_ble_hci_trans_buf_free(hci_ev); + return -1; + } + + len = hci_ev[1] + 2; + return s_hci_transport_env.driver_ops->hci_driver_tx(HCI_DRIVER_TYPE_EVT, hci_ev, len, + HCI_DRIVER_DIR_C2H); +} + +static int +hci_transport_controller_acl_tx(struct os_mbuf *om, void *arg) +{ + uint16_t len; + if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) { + os_mbuf_free_chain(om); + return -1; + } + + len = OS_MBUF_PKTHDR(om)->omp_len; + return s_hci_transport_env.driver_ops->hci_driver_tx(HCI_DRIVER_TYPE_ACL, (uint8_t *)om, len, + HCI_DRIVER_DIR_C2H); +} + +/* Functions for host Tx. */ +int +hci_transport_host_cmd_tx(uint8_t *data, uint32_t length) +{ + return s_hci_transport_env.driver_ops->hci_driver_tx(HCI_DRIVER_TYPE_CMD, data, length, + HCI_DRIVER_DIR_H2C); +} + +int +hci_transport_host_acl_tx(uint8_t *data, uint32_t length) +{ + return s_hci_transport_env.driver_ops->hci_driver_tx(HCI_DRIVER_TYPE_ACL, data, length, + HCI_DRIVER_DIR_H2C); +} + +int +hci_transport_host_callback_register(hci_transport_host_recv_fn *callback) +{ + s_hci_transport_env.host_recv_cb = callback; + return 0; +} + +int +hci_transport_init(uint8_t hci_transport_mode) +{ + int rc; + hci_driver_ops_t *ops; + + memset(&s_hci_transport_env, 0, sizeof(hci_transport_env_t)); + + switch(hci_transport_mode) { +#if CONFIG_BT_LE_HCI_INTERFACE_USE_RAM + case HCI_TRANSPORT_VHCI: + ops = &hci_driver_vhci_ops; + break; +#endif // CONFIG_BT_LE_HCI_INTERFACE_USE_RAM +#if CONFIG_BT_LE_HCI_INTERFACE_USE_UART +#if CONFIG_BT_LE_UART_HCI_DMA_MODE + case HCI_TRANSPORT_UART_UHCI: + ops = &hci_driver_uart_dma_ops; + break; +#else + case HCI_TRANSPORT_UART_NO_DMA: + ops = &hci_driver_uart_ops; + break; +#endif // CONFIG_BT_LE_UART_HCI_DMA_MODE +#endif // CONFIG_BT_LE_HCI_INTERFACE_USE_UART + default: + assert(0); + } + + rc = ops->hci_driver_init(hci_transport_packet_rx); + if (rc) { + goto error; + } + + s_hci_transport_env.driver_ops = ops; + r_ble_hci_trans_cfg_hs(hci_transport_controller_evt_tx, NULL, hci_transport_controller_acl_tx, NULL); + + return 0; + +error: + hci_transport_deinit(); + return rc; +} + +void +hci_transport_deinit(void) +{ + hci_driver_ops_t *ops; + + r_ble_hci_trans_cfg_hs((esp_hci_internal_rx_cmd_fn *)hci_transport_controller_tx_dummy, NULL, + (esp_hci_internal_rx_acl_fn *)hci_transport_controller_tx_dummy, NULL); + + ops = s_hci_transport_env.driver_ops; + if (ops) { + ops->hci_driver_deinit(); + } + memset(&s_hci_transport_env, 0, sizeof(hci_transport_env_t)); +} diff --git a/lib/bt/porting/transport/uart/hci_uart.c b/lib/bt/porting/transport/uart/hci_uart.c deleted file mode 100644 index c202e0a5..00000000 --- a/lib/bt/porting/transport/uart/hci_uart.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/queue.h" -#include "driver/uart.h" -#include "hci_uart.h" -#include "esp_log.h" -#include "esp_attr.h" - -#ifdef CONFIG_BT_LE_HCI_INTERFACE_USE_UART - -static const char *TAG = "hci_uart"; - -#define BUF_SIZE (1024) -#define RD_BUF_SIZE (BUF_SIZE) - -#define HCI_UART_TX_PIN CONFIG_BT_LE_HCI_UART_TX_PIN -#define HCI_UART_RX_PIN CONFIG_BT_LE_HCI_UART_RX_PIN - - -#ifdef CONFIG_BT_LE_HCI_UART_FLOWCTRL -#define HCI_UART_FLOWCTRL UART_HW_FLOWCTRL_CTS_RTS -#define HCI_UART_RTS_PIN CONFIG_BT_LE_HCI_UART_RTS_PIN -#define HCI_UART_CTS_PIN CONFIG_BT_LE_HCI_UART_CTS_PIN -#else -#define HCI_UART_FLOWCTRL UART_HW_FLOWCTRL_DISABLE -#define HCI_UART_RTS_PIN (-1) -#define HCI_UART_CTS_PIN (-1) -#endif - - -typedef struct { - bool uart_opened; - uart_port_t port; - uart_config_t cfg; - QueueHandle_t evt_queue; - TaskHandle_t rx_task_handler; - hci_uart_tx_char tx_char; - hci_uart_tx_done tx_done; - hci_uart_rx_char rx_char; - void *u_func_arg; - -} hci_uart_t; - -static hci_uart_t hci_uart; - -static void IRAM_ATTR hci_uart_rx_task(void *pvParameters) -{ - uart_event_t event; - uint8_t *dtmp = (uint8_t *) malloc(RD_BUF_SIZE); - while (hci_uart.uart_opened) { - //Waiting for UART event. - if (xQueueReceive(hci_uart.evt_queue, (void * )&event, (TickType_t)portMAX_DELAY)) { - bzero(dtmp, RD_BUF_SIZE); - ESP_LOGD(TAG, "uart[%d] event:", hci_uart.port); - switch (event.type) { - //Event of UART receving data - /*We'd better handler data event fast, there would be much more data events than - other types of events. If we take too much time on data event, the queue might - be full.*/ - case UART_DATA: - // ESP_LOGI(TAG, "[UART DATA]: %d", event.size); - uart_read_bytes(hci_uart.port, dtmp, event.size, portMAX_DELAY); - for (int i = 0 ; i < event.size; i++) { - hci_uart.rx_char(hci_uart.u_func_arg, dtmp[i]); - } - break; - //Event of HW FIFO overflow detected - case UART_FIFO_OVF: - ESP_LOGI(TAG, "hw fifo overflow"); - // If fifo overflow happened, you should consider adding flow control for your application. - // The ISR has already reset the rx FIFO, - uart_flush_input(hci_uart.port); - xQueueReset(hci_uart.evt_queue); - break; - //Event of UART ring buffer full - case UART_BUFFER_FULL: - ESP_LOGI(TAG, "ring buffer full"); - // If buffer full happened, you should consider encreasing your buffer size - uart_flush_input(hci_uart.port); - xQueueReset(hci_uart.evt_queue); - break; - //Event of UART RX break detected - case UART_BREAK: - ESP_LOGI(TAG, "uart rx break"); - break; - //Event of UART parity check error - case UART_PARITY_ERR: - ESP_LOGI(TAG, "uart parity error"); - break; - //Event of UART frame error - case UART_FRAME_ERR: - ESP_LOGI(TAG, "uart frame error"); - break; - //Others - default: - ESP_LOGI(TAG, "uart event type: %d", event.type); - break; - } - } - } - free(dtmp); - dtmp = NULL; - hci_uart.rx_task_handler = NULL; - vTaskDelete(NULL); -} - -int hci_uart_config(int port_num, int32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, - uart_parity_t parity, uart_hw_flowcontrol_t flow_ctl) -{ - uart_config_t uart_cfg = { - .baud_rate = baud_rate, - .data_bits = data_bits, - .parity = parity, - .stop_bits = stop_bits, - .flow_ctrl = HCI_UART_FLOWCTRL, - .source_clk = UART_SCLK_DEFAULT, - .rx_flow_ctrl_thresh = UART_HW_FIFO_LEN(port_num) - 1, - }; - hci_uart.port = port_num; - hci_uart.cfg = uart_cfg; - - int intr_alloc_flags = 0; - intr_alloc_flags = ESP_INTR_FLAG_IRAM; - - printf("set uart pin tx:%d, rx:%d.\n", HCI_UART_TX_PIN, HCI_UART_RX_PIN); - printf("set rts:%d, cts:%d.\n", HCI_UART_RTS_PIN, HCI_UART_CTS_PIN); - printf("set baud_rate:%d.\n", baud_rate); - - ESP_ERROR_CHECK(uart_driver_delete(port_num)); - ESP_ERROR_CHECK(uart_driver_install(port_num, BUF_SIZE * 2, BUF_SIZE * 2, 20, &hci_uart.evt_queue, intr_alloc_flags)); - ESP_ERROR_CHECK(uart_param_config(port_num, &hci_uart.cfg)); - ESP_ERROR_CHECK(uart_set_pin(port_num, HCI_UART_TX_PIN, HCI_UART_RX_PIN, HCI_UART_RTS_PIN, HCI_UART_CTS_PIN)); - - hci_uart.uart_opened = true; - - //Create a task to handler UART event from ISR - xTaskCreate(hci_uart_rx_task, "hci_uart_rx_task", 2048, NULL, 12, &hci_uart.rx_task_handler); - return 0; -} - -void IRAM_ATTR hci_uart_start_tx(int port_num) -{ - int data; - uint8_t u8_data = 0; - while (1) { - data = hci_uart.tx_char(hci_uart.u_func_arg); - if (data >= 0) { - u8_data = data; - uart_write_bytes(port_num, (char *)&u8_data, 1); - } else { - break; - } - } - if (hci_uart.tx_done) { - hci_uart.tx_done(hci_uart.u_func_arg); - } -} - -int hci_uart_init_cbs(int port_num, hci_uart_tx_char tx_func, - hci_uart_tx_done tx_done, hci_uart_rx_char rx_func, void *arg) -{ - hci_uart.tx_char = tx_func; - hci_uart.rx_char = rx_func; - hci_uart.tx_done = tx_done; - hci_uart.u_func_arg = arg; - return 0; -} - -int hci_uart_close(int port_num) -{ - uart_event_t uart_event; - uart_event.type = UART_BREAK; - hci_uart.uart_opened = false; - // Stop uart rx task - if (hci_uart.rx_task_handler != NULL) { - xQueueSend(hci_uart.evt_queue, (void *)&uart_event, 1000); - ESP_LOGW(TAG, "Waiting for uart task finish..."); - } - while (hci_uart.rx_task_handler != NULL); - - uart_driver_delete(port_num); - ESP_LOGI(TAG, "hci uart close success."); - return 0; -} - -int hci_uart_reconfig_pin(int tx_pin, int rx_pin, int cts_pin, int rts_pin) -{ - int port_num = hci_uart.port; - int32_t baud_rate = hci_uart.cfg.baud_rate; - uint8_t data_bits = hci_uart.cfg.data_bits; - uint8_t stop_bits = hci_uart.cfg.stop_bits; - uart_parity_t parity = hci_uart.cfg.parity; - uart_hw_flowcontrol_t flow_ctl = hci_uart.cfg.flow_ctrl; - hci_uart_close(port_num); - hci_uart_config(port_num, baud_rate, data_bits, stop_bits, parity, flow_ctl); - ESP_ERROR_CHECK(uart_set_pin(port_num, tx_pin, rx_pin, rts_pin, cts_pin)); - return 0; -} -#endif //CONFIG_BT_LE_HCI_INTERFACE_USE_UART diff --git a/lib/bt/sdkconfig.rename b/lib/bt/sdkconfig.rename index 0d38d15e..7e3b5e3e 100644 --- a/lib/bt/sdkconfig.rename +++ b/lib/bt/sdkconfig.rename @@ -220,7 +220,6 @@ CONFIG_BLUFI_TRACE_LEVEL_EVENT CONFIG_BT_LOG_BLUFI_ CONFIG_BLUFI_TRACE_LEVEL_DEBUG CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_DEBUG CONFIG_BLUFI_TRACE_LEVEL_VERBOSE CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_VERBOSE -CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK CONFIG_SMP_ENABLE CONFIG_BT_SMP_ENABLE CONFIG_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT diff --git a/lib/bt/test_apps/CMakeLists.txt b/lib/bt/test_apps/CMakeLists.txt deleted file mode 100644 index ab61d4b6..00000000 --- a/lib/bt/test_apps/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -cmake_minimum_required(VERSION 3.16) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -set(COMPONENTS main) -list(PREPEND SDKCONFIG_DEFAULTS - "$ENV{IDF_PATH}/tools/test_apps/configs/sdkconfig.debug_helpers" - "sdkconfig.defaults") - -project(bt_test) diff --git a/lib/bt/test_apps/README.md b/lib/bt/test_apps/README.md deleted file mode 100644 index fc828476..00000000 --- a/lib/bt/test_apps/README.md +++ /dev/null @@ -1,21 +0,0 @@ -| Supported Targets | ESP32 | ESP32-C3 | -| ----------------- | ----- | -------- | - -# `bt` component unit tests - -When adding new test cases, check if the `depends_components` list in `.build-test-rules.yml` needs to be updated to include additional components. The test app will only be built and tested when these components are modified. - -To build and run this test app, using esp32c3 target for example: - -```bash -idf.py set-target esp32c3 -idf.py build flash monitor -``` - -To run tests using pytest: - -```bash -idf.py set-target esp32c3 -idf.py build -pytest --target=esp32c3 -``` diff --git a/lib/bt/test_apps/basic_unit_test/pytest_basic_unit_test.py b/lib/bt/test_apps/basic_unit_test/pytest_basic_unit_test.py index de3d235b..98e7cd8a 100644 --- a/lib/bt/test_apps/basic_unit_test/pytest_basic_unit_test.py +++ b/lib/bt/test_apps/basic_unit_test/pytest_basic_unit_test.py @@ -1,11 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize @pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.esp32c3 +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_bt(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/lib/bt/test_apps/main/CMakeLists.txt b/lib/bt/test_apps/main/CMakeLists.txt deleted file mode 100644 index 6aecb24e..00000000 --- a/lib/bt/test_apps/main/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -idf_component_register(SRCS "test_bt_main.c" - "test_bt_common.c" - "test_smp.c" - INCLUDE_DIRS "." - PRIV_REQUIRES unity bt - WHOLE_ARCHIVE) diff --git a/lib/bt/test_apps/main/test_bt_common.c b/lib/bt/test_apps/main/test_bt_common.c deleted file mode 100644 index 402633d0..00000000 --- a/lib/bt/test_apps/main/test_bt_common.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ - -/* - Tests for the BT common things implementation -*/ - -#include - -#include "unity.h" -#include "sdkconfig.h" - -// btdm_controller_compile_version_check defined only for ESP32 -#ifdef CONFIG_IDF_TARGET_ESP32 -extern bool btdm_controller_compile_version_check(void); - -TEST_CASE("bt_controller_git_commit_check", "[bt_common]") -{ - TEST_ASSERT(btdm_controller_compile_version_check() == true); -} -#endif diff --git a/lib/bt/test_apps/main/test_bt_main.c b/lib/bt/test_apps/main/test_bt_main.c deleted file mode 100644 index 53a93c95..00000000 --- a/lib/bt/test_apps/main/test_bt_main.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "unity.h" -#include "unity_test_runner.h" -#include "esp_heap_caps.h" - -#define TEST_MEMORY_LEAK_THRESHOLD_DEFAULT 0 -static int leak_threshold = TEST_MEMORY_LEAK_THRESHOLD_DEFAULT; -void set_leak_threshold(int threshold) -{ - leak_threshold = threshold; -} - -static size_t before_free_8bit; -static size_t before_free_32bit; - -static void check_leak(size_t before_free, size_t after_free, const char *type) -{ - ssize_t delta = after_free - before_free; - printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta); - TEST_ASSERT_MESSAGE(delta >= leak_threshold, "memory leak"); -} - -void setUp(void) -{ - before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); - before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); -} - -void tearDown(void) -{ - size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT); - size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT); - check_leak(before_free_8bit, after_free_8bit, "8BIT"); - check_leak(before_free_32bit, after_free_32bit, "32BIT"); - - leak_threshold = TEST_MEMORY_LEAK_THRESHOLD_DEFAULT; -} - -void app_main(void) -{ - printf("Running bt component tests\n"); - unity_run_menu(); -} diff --git a/lib/bt/test_apps/main/test_smp.c b/lib/bt/test_apps/main/test_smp.c deleted file mode 100644 index ea89ec26..00000000 --- a/lib/bt/test_apps/main/test_smp.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ - -/* - * Tests for the BLE SMP implementation - */ - -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "unity.h" -#include "esp_random.h" - -#include "esp_bt_main.h" -#include "esp_bt_device.h" -#include "esp_gap_ble_api.h" - -#define KEY_LENGTH_DWORDS_P256 8 - -typedef unsigned long DWORD; -typedef uint32_t UINT32; - -typedef struct { - DWORD x[KEY_LENGTH_DWORDS_P256]; - DWORD y[KEY_LENGTH_DWORDS_P256]; - DWORD z[KEY_LENGTH_DWORDS_P256]; -} Point; - -typedef struct { - // curve's coefficients - DWORD a[KEY_LENGTH_DWORDS_P256]; - DWORD b[KEY_LENGTH_DWORDS_P256]; - - //whether a is -3 - int a_minus3; - - // prime modulus - DWORD p[KEY_LENGTH_DWORDS_P256]; - - // Omega, p = 2^m -omega - DWORD omega[KEY_LENGTH_DWORDS_P256]; - - // base point, a point on E of order r - Point G; - -} elliptic_curve_t; - -extern void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength); -extern bool ECC_CheckPointIsInElliCur_P256(Point *p); -extern void p_256_init_curve(UINT32 keyLength); -extern elliptic_curve_t curve_p256; - -static void bt_rand(void *buf, size_t len) -{ - if (!len) { - return; - } - // Reset the buf value to the fixed value. - memset(buf, 0x55, len); - - for (int i = 0; i < (int)(len / sizeof(uint32_t)); i++) { - uint32_t rand = esp_random(); - memcpy(buf + i * sizeof(uint32_t), &rand, sizeof(uint32_t)); - } - - return; -} - -TEST_CASE("ble_smp_public_key_check", "[ble_smp]") -{ - /* We wait init finish 200ms here */ - vTaskDelay(200 / portTICK_PERIOD_MS); - Point public_key; - DWORD private_key[KEY_LENGTH_DWORDS_P256] = {[0 ... (KEY_LENGTH_DWORDS_P256 - 1)] = 0x12345678}; - p_256_init_curve(KEY_LENGTH_DWORDS_P256); - ECC_PointMult_Bin_NAF(&public_key, &(curve_p256.G), private_key, KEY_LENGTH_DWORDS_P256); - /* Check Is the public key generated by the system on the given elliptic curve */ - TEST_ASSERT(ECC_CheckPointIsInElliCur_P256(&public_key)); - /* We simulate the attacker and set the y coordinate of the public key to 0. */ - for (int i = 0; i < KEY_LENGTH_DWORDS_P256; i++) { - public_key.y[i] = 0x0; - } - /* At this point the public key should not be on the given elliptic curve. */ - TEST_ASSERT(!ECC_CheckPointIsInElliCur_P256(&public_key)); - /* Test whether the G point on the protocol is on a given elliptic curve */ - TEST_ASSERT(ECC_CheckPointIsInElliCur_P256(&(curve_p256.G))); - /* test 100 times when the private key is generated by the random number. */ - for (int j = 0; j < 100; j++) { - bt_rand(private_key, sizeof(DWORD)*KEY_LENGTH_DWORDS_P256); - ECC_PointMult_Bin_NAF(&public_key, &(curve_p256.G), private_key, KEY_LENGTH_DWORDS_P256); - /* Check Is the public key generated by the system on the given elliptic curve */ - TEST_ASSERT(ECC_CheckPointIsInElliCur_P256(&public_key)); - } -} - -TEST_CASE("ble_smp_set_clear_static_passkey", "[ble_smp]") -{ - /* We wait init finish 200ms here */ - vTaskDelay(200 / portTICK_PERIOD_MS); - esp_ble_auth_req_t auth_req = ESP_LE_AUTH_BOND; - uint32_t passkey = 123456; - /* test len = 0 when type != ESP_BLE_SM_CLEAR_STATIC_PASSKEY */ - TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, 0) == ESP_ERR_INVALID_ARG); - /* test function */ - TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(esp_ble_auth_req_t)) != ESP_ERR_INVALID_ARG); - /* test type >= ESP_BLE_SM_MAX_PARAM */ - TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_PARAM, &passkey, sizeof(uint32_t)) == ESP_ERR_INVALID_ARG); - /* test len < sizeof(uint32_t) when type is ESP_BLE_SM_SET_STATIC_PASSKEY */ - TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint8_t)) != ESP_ERR_INVALID_ARG); - /* test value is NULL when type != ESP_BLE_SM_CLEAR_STATIC_PASSKEY */ - TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, NULL, sizeof(uint8_t)) == ESP_ERR_INVALID_ARG); - /* test value is NULL and len is 0 when type != ESP_BLE_SM_CLEAR_STATIC_PASSKEY */ - TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, NULL, 0) == ESP_ERR_INVALID_ARG); - /* test function */ - TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t)) != ESP_ERR_INVALID_ARG); - /* test function */ - TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_CLEAR_STATIC_PASSKEY, &passkey, sizeof(uint32_t)) != ESP_ERR_INVALID_ARG); - /* test function */ - TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_CLEAR_STATIC_PASSKEY, NULL, sizeof(uint32_t)) != ESP_ERR_INVALID_ARG); - /* test function */ - TEST_ASSERT(esp_ble_gap_set_security_param(ESP_BLE_SM_CLEAR_STATIC_PASSKEY, NULL, 0) != ESP_ERR_INVALID_ARG); -} diff --git a/lib/bt/test_apps/memory_release/main/test_app_main.c b/lib/bt/test_apps/memory_release/main/test_app_main.c index 562d1d97..909a730d 100644 --- a/lib/bt/test_apps/memory_release/main/test_app_main.c +++ b/lib/bt/test_apps/memory_release/main/test_app_main.c @@ -11,6 +11,7 @@ #include "nvs_flash.h" #include "multi_heap.h" +#include "esp_heap_caps.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -127,5 +128,7 @@ void app_main(void) } ESP_LOGI(tag, "Free heap size increased by %"PRIu32" bytes", free_after - free_before); - ESP_LOGI(tag, "SUCCESS"); + if (heap_caps_check_integrity_all(true)) { + ESP_LOGI(tag, "Comprehensive heap check: SUCCESS"); + } } diff --git a/lib/bt/test_apps/memory_release/pytest_memory_release.py b/lib/bt/test_apps/memory_release/pytest_memory_release.py index dbefc908..d5d70fcd 100644 --- a/lib/bt/test_apps/memory_release/pytest_memory_release.py +++ b/lib/bt/test_apps/memory_release/pytest_memory_release.py @@ -1,15 +1,21 @@ -# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.parametrize('config', [ - pytest.param('default', marks=[pytest.mark.esp32, pytest.mark.esp32c2, pytest.mark.generic]), - pytest.param('iram', marks=[pytest.mark.esp32c2, pytest.mark.generic]), - pytest.param('psram', marks=[pytest.mark.esp32, pytest.mark.psram]), -], indirect=True) +@idf_parametrize( + 'config,target,markers', + [ + ('default', 'esp32', (pytest.mark.generic,)), + ('default', 'esp32c2', (pytest.mark.generic,)), + ('iram', 'esp32c2', (pytest.mark.generic,)), + ('psram', 'esp32', (pytest.mark.psram,)), + ], + indirect=['config', 'target'], +) def test_bt_memory_release(dut: Dut) -> None: dut.expect_exact('BLE Host Task Started', timeout=6) dut.expect_exact('BLE Host Task Stopped', timeout=8) - dut.expect_exact('SUCCESS', timeout=10) + dut.expect_exact('Comprehensive heap check: SUCCESS', timeout=10) diff --git a/lib/bt/test_apps/memory_release/sdkconfig.defaults b/lib/bt/test_apps/memory_release/sdkconfig.defaults index a22d8109..fc2b04c1 100644 --- a/lib/bt/test_apps/memory_release/sdkconfig.defaults +++ b/lib/bt/test_apps/memory_release/sdkconfig.defaults @@ -1,2 +1,4 @@ +CONFIG_HEAP_POISONING_COMPREHENSIVE=y + CONFIG_BT_ENABLED=y CONFIG_BT_NIMBLE_ENABLED=y diff --git a/lib/bt/test_apps/pytest_bt.py b/lib/bt/test_apps/pytest_bt.py deleted file mode 100644 index 74b0a76a..00000000 --- a/lib/bt/test_apps/pytest_bt.py +++ /dev/null @@ -1,12 +0,0 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: CC0-1.0 - -import pytest -from pytest_embedded import Dut - - -@pytest.mark.generic -@pytest.mark.esp32 -@pytest.mark.esp32c3 -def test_bt(dut: Dut) -> None: - dut.run_all_single_board_cases() diff --git a/lib/bt/test_apps/sdkconfig.defaults b/lib/bt/test_apps/sdkconfig.defaults deleted file mode 100644 index 5847dd3c..00000000 --- a/lib/bt/test_apps/sdkconfig.defaults +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_BT_ENABLED=y -CONFIG_UNITY_FREERTOS_STACK_SIZE=12288 -CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n diff --git a/lib/fatfs/.build-test-rules.yml b/lib/fatfs/.build-test-rules.yml deleted file mode 100644 index 737e82b7..00000000 --- a/lib/fatfs/.build-test-rules.yml +++ /dev/null @@ -1,7 +0,0 @@ -# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps - -components/fatfs/test_apps/sdcard: - disable_test: - - if: IDF_TARGET in ["esp32s3", "esp32c2", "esp32c6", "esp32h2"] - temporary: true - reason: No sdspi runners for these targets diff --git a/lib/fatfs/Kconfig b/lib/fatfs/Kconfig index f2c737a6..1a35dc4e 100644 --- a/lib/fatfs/Kconfig +++ b/lib/fatfs/Kconfig @@ -64,7 +64,7 @@ menu "FAT Filesystem support" config FATFS_CODEPAGE_857 bool "Turkish (CP857)" config FATFS_CODEPAGE_860 - bool "Portugese (CP860)" + bool "Portuguese (CP860)" config FATFS_CODEPAGE_861 bool "Icelandic (CP861)" config FATFS_CODEPAGE_862 @@ -161,7 +161,7 @@ menu "FAT Filesystem support" help This option sets FATFS configuration value _FS_TIMEOUT, scaled to milliseconds. Sets the number of milliseconds FATFS will wait to acquire a mutex when - operating on an open file. For example, if one task is performing a lenghty + operating on an open file. For example, if one task is performing a lengthy operation, another task will wait for the first task to release the lock, and time out after amount of time set by this option. @@ -184,7 +184,7 @@ menu "FAT Filesystem support" config FATFS_ALLOC_PREFER_EXTRAM - bool "Perfer external RAM when allocating FATFS buffers" + bool "Prefer external RAM when allocating FATFS buffers" default y depends on SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC help @@ -205,6 +205,63 @@ menu "FAT Filesystem support" file is opened in write-mode, the seek mechanism will automatically fallback to the default implementation. + choice FATFS_USE_STRFUNC_CHOICE + prompt "Enable string functions, f_gets(), f_putc(), f_puts() and f_printf()" + default FATFS_USE_STRFUNC_NONE + help + These are specialized alternatives to stdio functions for working + directly with FATFS without VFS. Legacy code may need functions, + but for new development, it is advised to use stdio under VFS. + + 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect. + 1: Enable without LF-CRLF conversion. + 2: Enable with LF-CRLF conversion. + + config FATFS_USE_STRFUNC_NONE + bool "0:Disable" + + config FATFS_USE_STRFUNC_WITHOUT_CRLF_CONV + bool "1:Enable without LF-CRLF conversion" + + config FATFS_USE_STRFUNC_WITH_CRLF_CONV + bool "2:Enable with LF-CRLF conversion" + endchoice + + config FATFS_PRINT_LLI + depends on !FATFS_USE_STRFUNC_NONE + bool "Make fatfs f_printf() support long long argument" + default 0 + + config FATFS_PRINT_FLOAT + depends on !FATFS_USE_STRFUNC_NONE + bool "Make fatfs f_printf() support floating point argument" + default 0 + + choice FATFS_STRF_ENCODE_CHOICE + prompt "FatFS string functions: convert character encoding" + depends on !FATFS_LFN_NONE && !FATFS_USE_STRFUNC_NONE + default FATFS_STRF_ENCODE_UTF8 + help + When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character + encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE + to be read/written via those functions. + 0: ANSI/OEM in current CP + 1: Unicode in UTF-16LE + 2: Unicode in UTF-16BE + 3: Unicode in UTF-8 + + config FATFS_STRF_ENCODE_ANSI + bool "0:ANSI/OEM in current CP" + + config FATFS_STRF_ENCODE_UTF16LE + bool "1:Unicode in UTF-16LE" + + config FATFS_STRF_ENCODE_UTF16BE + bool "2:Unicode in UTF-16BE" + + config FATFS_STRF_ENCODE_UTF8 + bool "3:Unicode in UTF-8" + endchoice config FATFS_FAST_SEEK_BUFFER_SIZE int "Fast seek CLMT buffer size" @@ -239,4 +296,52 @@ menu "FAT Filesystem support" vfs_fat_pwrite(), vfs_fat_link(), vfs_fat_truncate() and vfs_fat_ftruncate() functions. This feature improves file-consistency and size reporting accuracy for the FatFS, at a price on decreased performance due to frequent disk operations + + config FATFS_USE_LABEL + bool "Use FATFS volume label" + default n + help + Allows FATFS volume label to be specified using f_setlabel + + config FATFS_LINK_LOCK + bool "Perform the whole link operation under lock" + default y + help + If enabled, the whole link operation (including file copying) is performed under lock. + This ensures that the link operation is atomic, but may cause performance for large files. + It may create less fragmented file copy. + + config FATFS_USE_DYN_BUFFERS + bool "Use dynamic buffers" + default n + help + If enabled, the buffers used by FATFS will be allocated separately from the rest of the structure. + This option is useful when using multiple FATFS instances with different + sector sizes, as the buffers will be allocated according to the sector size. + If disabled, the greatest sector size will be used for all FATFS instances. + (In most cases, this would be the sector size of Wear Levelling library) + This might cause more memory to be used than necessary. + + menu "File system free space calculation behavior" + help + Controls if the file system does or does not trust cached data like free cluster count and allocated + cluster number. Setting these to do not trust the data may result of more accurate output from + `f_getfree()` function but increased overhead (forces a full FAT scan, etc.). + + config FATFS_DONT_TRUST_FREE_CLUSTER_CNT + int "Don't trust free cluster count" + default 0 + range 0 1 + help + If 1, the file system will not trust the free cluster count in the FSINFO (in FATFS struct). + This may result in more accurate output from `f_getfree()` function but increased overhead. + + config FATFS_DONT_TRUST_LAST_ALLOC + int "Don't trust allocated cluster number" + default 0 + range 0 1 + help + If 1, the file system will not trust the last allocated cluster number in the FSINFO (in FATFS struct). + This may result in more accurate output from `f_getfree()` function but increased overhead. + endmenu endmenu diff --git a/lib/fatfs/diskio/diskio.c b/lib/fatfs/diskio/diskio.c index 4bafa7ea..7d39835f 100644 --- a/lib/fatfs/diskio/diskio.c +++ b/lib/fatfs/diskio/diskio.c @@ -1,10 +1,10 @@ /*-----------------------------------------------------------------------*/ /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */ -/* ESP-IDF port Copyright 2016 Espressif Systems (Shanghai) PTE LTD */ +/* ESP-IDF port Copyright 2016-2025 Espressif Systems (Shanghai) PTE LTD */ /*-----------------------------------------------------------------------*/ /* If a working storage control module is available, it should be */ /* attached to the FatFs via a glue function rather than modifying it. */ -/* This is an example of glue functions to attach various exsisting */ +/* This is an example of glue functions to attach various existing */ /* storage control modules to the FatFs module with a defined API. */ /*-----------------------------------------------------------------------*/ @@ -19,7 +19,7 @@ static ff_diskio_impl_t * s_impls[FF_VOLUMES] = { NULL }; #if FF_MULTI_PARTITION /* Multiple partition configuration */ -const PARTITION VolToPart[FF_VOLUMES] = { +PARTITION VolToPart[FF_VOLUMES] = { {0, 0}, /* Logical drive 0 ==> Physical drive 0, auto detection */ #if FF_VOLUMES > 1 {1, 0}, /* Logical drive 1 ==> Physical drive 1, auto detection */ diff --git a/lib/fatfs/diskio/diskio_rawflash.c b/lib/fatfs/diskio/diskio_rawflash.c index 313aacec..4bc3eb8e 100644 --- a/lib/fatfs/diskio/diskio_rawflash.c +++ b/lib/fatfs/diskio/diskio_rawflash.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,7 +25,7 @@ static uint8_t s_initialized[FF_VOLUMES]; #define BPB_TotSec32 32 -DSTATUS ff_raw_initialize (BYTE pdrv) +static DSTATUS ff_raw_initialize (BYTE pdrv) { uint16_t sector_size_tmp; @@ -61,7 +61,7 @@ DSTATUS ff_raw_initialize (BYTE pdrv) return STA_PROTECT; } -DSTATUS ff_raw_status (BYTE pdrv) +static DSTATUS ff_raw_status (BYTE pdrv) { DSTATUS status = STA_PROTECT; if (!s_initialized[pdrv]) { @@ -70,7 +70,7 @@ DSTATUS ff_raw_status (BYTE pdrv) return status; } -DRESULT ff_raw_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count) +static DRESULT ff_raw_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count) { ESP_LOGV(TAG, "ff_raw_read - pdrv=%i, sector=%i, count=%in", (unsigned int)pdrv, (unsigned int)sector, (unsigned int)count); const esp_partition_t* part = s_ff_raw_handles[pdrv]; @@ -84,16 +84,16 @@ DRESULT ff_raw_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count) } -DRESULT ff_raw_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) +static DRESULT ff_raw_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) { return RES_WRPRT; } -DRESULT ff_raw_ioctl (BYTE pdrv, BYTE cmd, void *buff) +static DRESULT ff_raw_ioctl (BYTE pdrv, BYTE cmd, void *buff) { - const esp_partition_t* part = s_ff_raw_handles[pdrv]; ESP_LOGV(TAG, "ff_raw_ioctl: cmd=%in", cmd); - assert(part); + assert(s_ff_raw_handles[pdrv]); + switch (cmd) { case CTRL_SYNC: return RES_OK; diff --git a/lib/fatfs/diskio/diskio_sdmmc.c b/lib/fatfs/diskio/diskio_sdmmc.c index 3e61eb00..689a07bc 100644 --- a/lib/fatfs/diskio/diskio_sdmmc.c +++ b/lib/fatfs/diskio/diskio_sdmmc.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -34,12 +34,12 @@ static DSTATUS ff_sdmmc_card_available(BYTE pdrv) * fails. This error value is checked throughout the FATFS code. * Both functions return 0 on success. */ -DSTATUS ff_sdmmc_initialize (BYTE pdrv) +static DSTATUS ff_sdmmc_initialize (BYTE pdrv) { return ff_sdmmc_card_available(pdrv); } -DSTATUS ff_sdmmc_status(BYTE pdrv) +static DSTATUS ff_sdmmc_status(BYTE pdrv) { if (s_disk_status_check_en[pdrv]) { return ff_sdmmc_card_available(pdrv); @@ -47,32 +47,32 @@ DSTATUS ff_sdmmc_status(BYTE pdrv) return 0; } -DRESULT ff_sdmmc_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count) +static DRESULT ff_sdmmc_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count) { sdmmc_card_t* card = s_cards[pdrv]; assert(card); esp_err_t err = sdmmc_read_sectors(card, buff, sector, count); if (unlikely(err != ESP_OK)) { - ESP_LOGE(TAG, "sdmmc_read_blocks failed (%d)", err); + ESP_LOGE(TAG, "sdmmc_read_blocks failed (0x%x)", err); return RES_ERROR; } return RES_OK; } -DRESULT ff_sdmmc_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) +static DRESULT ff_sdmmc_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) { sdmmc_card_t* card = s_cards[pdrv]; assert(card); esp_err_t err = sdmmc_write_sectors(card, buff, sector, count); if (unlikely(err != ESP_OK)) { - ESP_LOGE(TAG, "sdmmc_write_blocks failed (%d)", err); + ESP_LOGE(TAG, "sdmmc_write_blocks failed (0x%x)", err); return RES_ERROR; } return RES_OK; } #if FF_USE_TRIM -DRESULT ff_sdmmc_trim (BYTE pdrv, DWORD start_sector, DWORD sector_count) +static DRESULT ff_sdmmc_trim (BYTE pdrv, DWORD start_sector, DWORD sector_count) { sdmmc_card_t* card = s_cards[pdrv]; assert(card); @@ -88,7 +88,7 @@ DRESULT ff_sdmmc_trim (BYTE pdrv, DWORD start_sector, DWORD sector_count) } #endif //FF_USE_TRIM -DRESULT ff_sdmmc_ioctl (BYTE pdrv, BYTE cmd, void* buff) +static DRESULT ff_sdmmc_ioctl (BYTE pdrv, BYTE cmd, void* buff) { sdmmc_card_t* card = s_cards[pdrv]; assert(card); diff --git a/lib/fatfs/diskio/diskio_sdmmc.h b/lib/fatfs/diskio/diskio_sdmmc.h index 2ba4c2d9..d6c881ae 100644 --- a/lib/fatfs/diskio/diskio_sdmmc.h +++ b/lib/fatfs/diskio/diskio_sdmmc.h @@ -7,7 +7,7 @@ #pragma once #include "sdmmc_cmd.h" -#include "driver/sdmmc_defs.h" +#include "sd_protocol_defs.h" #ifdef __cplusplus extern "C" { diff --git a/lib/fatfs/diskio/diskio_wl.c b/lib/fatfs/diskio/diskio_wl.c index 8e20290e..4852ca7a 100644 --- a/lib/fatfs/diskio/diskio_wl.c +++ b/lib/fatfs/diskio/diskio_wl.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,52 +19,52 @@ wl_handle_t ff_wl_handles[FF_VOLUMES] = { [0 ... FF_VOLUMES - 1] = WL_INVALID_HANDLE }; -DSTATUS ff_wl_initialize (BYTE pdrv) +static DSTATUS ff_wl_initialize (BYTE pdrv) { return 0; } -DSTATUS ff_wl_status (BYTE pdrv) +static DSTATUS ff_wl_status (BYTE pdrv) { return 0; } -DRESULT ff_wl_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count) +static DRESULT ff_wl_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count) { ESP_LOGV(TAG, "ff_wl_read - pdrv=%i, sector=%i, count=%i", (unsigned int)pdrv, (unsigned int)sector, (unsigned int)count); wl_handle_t wl_handle = ff_wl_handles[pdrv]; - assert(wl_handle + 1); + assert(wl_handle != WL_INVALID_HANDLE); esp_err_t err = wl_read(wl_handle, sector * wl_sector_size(wl_handle), buff, count * wl_sector_size(wl_handle)); if (unlikely(err != ESP_OK)) { - ESP_LOGE(TAG, "wl_read failed (%d)", err); + ESP_LOGE(TAG, "wl_read failed (0x%x)", err); return RES_ERROR; } return RES_OK; } -DRESULT ff_wl_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) +static DRESULT ff_wl_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count) { ESP_LOGV(TAG, "ff_wl_write - pdrv=%i, sector=%i, count=%i", (unsigned int)pdrv, (unsigned int)sector, (unsigned int)count); wl_handle_t wl_handle = ff_wl_handles[pdrv]; - assert(wl_handle + 1); + assert(wl_handle != WL_INVALID_HANDLE); esp_err_t err = wl_erase_range(wl_handle, sector * wl_sector_size(wl_handle), count * wl_sector_size(wl_handle)); if (unlikely(err != ESP_OK)) { - ESP_LOGE(TAG, "wl_erase_range failed (%d)", err); + ESP_LOGE(TAG, "wl_erase_range failed (0x%x)", err); return RES_ERROR; } err = wl_write(wl_handle, sector * wl_sector_size(wl_handle), buff, count * wl_sector_size(wl_handle)); if (unlikely(err != ESP_OK)) { - ESP_LOGE(TAG, "wl_write failed (%d)", err); + ESP_LOGE(TAG, "wl_write failed (0x%x)", err); return RES_ERROR; } return RES_OK; } -DRESULT ff_wl_ioctl (BYTE pdrv, BYTE cmd, void *buff) +static DRESULT ff_wl_ioctl (BYTE pdrv, BYTE cmd, void *buff) { wl_handle_t wl_handle = ff_wl_handles[pdrv]; ESP_LOGV(TAG, "ff_wl_ioctl: cmd=%i", cmd); - assert(wl_handle + 1); + assert(wl_handle != WL_INVALID_HANDLE); switch (cmd) { case CTRL_SYNC: return RES_OK; diff --git a/lib/fatfs/fatfs_utils/boot_sector.py b/lib/fatfs/fatfs_utils/boot_sector.py index 615dd065..2809c033 100644 --- a/lib/fatfs/fatfs_utils/boot_sector.py +++ b/lib/fatfs/fatfs_utils/boot_sector.py @@ -1,9 +1,9 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 from inspect import getmembers, isroutine from typing import Optional -from construct import Const, Int8ul, Int16ul, Int32ul, PaddedString, Struct, core +from construct import Bytes, Const, Int8ul, Int16ul, Int32ul, PaddedString, Padding, Struct, core from .exceptions import InconsistentFATAttributes, NotInitialized from .fatfs_state import BootSectorState @@ -29,8 +29,7 @@ class BootSector: BOOT_HEADER_SIZE = 512 BOOT_SECTOR_HEADER = Struct( - # this value reflects BS_jmpBoot used for ESP32 boot sector (any other accepted) - 'BS_jmpBoot' / Const(b'\xeb\xfe\x90'), + 'BS_jmpBoot' / Bytes(3), 'BS_OEMName' / PaddedString(MAX_OEM_NAME_SIZE, SHORT_NAMES_ENCODING), 'BPB_BytsPerSec' / Int16ul, 'BPB_SecPerClus' / Int8ul, @@ -45,12 +44,12 @@ class BootSector: 'BPB_HiddSec' / Int32ul, 'BPB_TotSec32' / Int32ul, # zero if the FAT type is 12/16, otherwise number of sectors 'BS_DrvNum' / Const(b'\x80'), - 'BS_Reserved1' / Const(EMPTY_BYTE), + 'BS_Reserved1' / Padding(1), 'BS_BootSig' / Const(b'\x29'), 'BS_VolID' / Int32ul, 'BS_VolLab' / PaddedString(MAX_VOL_LAB_SIZE, SHORT_NAMES_ENCODING), 'BS_FilSysType' / PaddedString(MAX_FS_TYPE_SIZE, SHORT_NAMES_ENCODING), - 'BS_EMPTY' / Const(448 * EMPTY_BYTE), + 'BS_EMPTY' / Padding(448), 'Signature_word' / Const(FATDefaults.SIGNATURE_WORD) ) assert BOOT_SECTOR_HEADER.sizeof() == BOOT_HEADER_SIZE @@ -65,15 +64,17 @@ class BootSector: raise NotInitialized('The BootSectorState instance is not initialized!') volume_uuid = generate_4bytes_random() pad_header: bytes = (boot_sector_state.sector_size - BootSector.BOOT_HEADER_SIZE) * EMPTY_BYTE - data_content: bytes = boot_sector_state.data_sectors * boot_sector_state.sector_size * FULL_BYTE - root_dir_content: bytes = boot_sector_state.root_dir_sectors_cnt * boot_sector_state.sector_size * EMPTY_BYTE fat_tables_content: bytes = (boot_sector_state.sectors_per_fat_cnt * boot_sector_state.fat_tables_cnt * boot_sector_state.sector_size * EMPTY_BYTE) + root_dir_content: bytes = boot_sector_state.root_dir_sectors_cnt * boot_sector_state.sector_size * EMPTY_BYTE + data_content: bytes = boot_sector_state.data_sectors * boot_sector_state.sector_size * FULL_BYTE + self.boot_sector_state.binary_image = ( BootSector.BOOT_SECTOR_HEADER.build( - dict(BS_OEMName=pad_string(boot_sector_state.oem_name, size=BootSector.MAX_OEM_NAME_SIZE), + dict(BS_jmpBoot=(b'\xeb\xfe\x90'), + BS_OEMName=pad_string(boot_sector_state.oem_name, size=BootSector.MAX_OEM_NAME_SIZE), BPB_BytsPerSec=boot_sector_state.sector_size, BPB_SecPerClus=boot_sector_state.sectors_per_cluster, BPB_RsvdSecCnt=boot_sector_state.reserved_sectors_cnt, @@ -91,8 +92,7 @@ class BootSector: BS_VolLab=pad_string(boot_sector_state.volume_label, size=BootSector.MAX_VOL_LAB_SIZE), BS_FilSysType=pad_string(boot_sector_state.file_sys_type, - size=BootSector.MAX_FS_TYPE_SIZE) - ) + size=BootSector.MAX_FS_TYPE_SIZE)) ) + pad_header + fat_tables_content + root_dir_content + data_content ) diff --git a/lib/fatfs/fatfs_utils/fatfs_state.py b/lib/fatfs/fatfs_utils/fatfs_state.py index 22af7bfb..4ba57132 100644 --- a/lib/fatfs/fatfs_utils/fatfs_state.py +++ b/lib/fatfs/fatfs_utils/fatfs_state.py @@ -152,6 +152,7 @@ class BootSectorState: def non_data_sectors(self) -> int: non_data_sectors_: int = get_non_data_sectors_cnt(self.reserved_sectors_cnt, self.sectors_per_fat_cnt, + self.fat_tables_cnt, self.root_dir_sectors_cnt) return non_data_sectors_ @@ -166,5 +167,5 @@ class BootSectorState: @property def root_directory_start(self) -> int: - root_dir_start: int = (self.reserved_sectors_cnt + self.sectors_per_fat_cnt) * self.sector_size + root_dir_start: int = (self.reserved_sectors_cnt + self.sectors_per_fat_cnt * self.fat_tables_cnt) * self.sector_size return root_dir_start diff --git a/lib/fatfs/fatfs_utils/utils.py b/lib/fatfs/fatfs_utils/utils.py index d2180c76..662586a5 100644 --- a/lib/fatfs/fatfs_utils/utils.py +++ b/lib/fatfs/fatfs_utils/utils.py @@ -1,15 +1,18 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import argparse import binascii import os import re import uuid from datetime import datetime -from typing import List, Optional, Tuple +from typing import List +from typing import Optional +from typing import Tuple -from construct import BitsInteger, BitStruct, Int16ul +from construct import BitsInteger +from construct import BitStruct +from construct import Int16ul # the regex pattern defines symbols that are allowed by long file names but not by short file names INVALID_SFN_CHARS_PATTERN = re.compile(r'[.+,;=\[\]]') @@ -68,8 +71,8 @@ def number_of_clusters(number_of_sectors: int, sectors_per_cluster: int) -> int: return number_of_sectors // sectors_per_cluster -def get_non_data_sectors_cnt(reserved_sectors_cnt: int, sectors_per_fat_cnt: int, root_dir_sectors_cnt: int) -> int: - return reserved_sectors_cnt + sectors_per_fat_cnt + root_dir_sectors_cnt +def get_non_data_sectors_cnt(reserved_sectors_cnt: int, sectors_per_fat_cnt: int, fat_tables_cnt: int, root_dir_sectors_cnt: int) -> int: + return reserved_sectors_cnt + sectors_per_fat_cnt * fat_tables_cnt + root_dir_sectors_cnt def get_fatfs_type(clusters_count: int) -> int: @@ -203,9 +206,19 @@ def get_args_for_partition_generator(desc: str, wl: bool) -> argparse.Namespace: type=int, choices=[FAT12, FAT16, 0], help=""" - Type of fat. Select 12 for fat12, 16 for fat16. Don't set, or set to 0 for automatic - calculation using cluster size and partition size. + Type of the FAT file-system. Select '12' for FAT12, '16' for FAT16. + Leave unset or select 0 for automatic file-system type detection. """) + parser.add_argument('--fat_count', + default=FATDefaults.FAT_TABLES_COUNT, + type=int, + choices=[1, 2], + help='Number of file allocation tables (FATs) in the filesystem.') + parser.add_argument('--wl_mode', + default=None, + type=str, + choices=['safe', 'perf'], + help='Wear levelling mode to use. Safe or performance. Only for sector size of 512') args = parser.parse_args() if args.fat_type == 0: @@ -215,6 +228,9 @@ def get_args_for_partition_generator(desc: str, wl: bool) -> argparse.Namespace: args.partition_size = int(str(args.partition_size), 0) if not os.path.isdir(args.input_directory): raise NotADirectoryError(f'The target directory `{args.input_directory}` does not exist!') + if args.wl_mode is not None: + if args.sector_size != 512: + raise ValueError('Wear levelling mode can be set only for sector size 512') return args @@ -276,7 +292,7 @@ class FATDefaults: # FATFS defaults SIZE: int = 1024 * 1024 RESERVED_SECTORS_COUNT: int = 1 - FAT_TABLES_COUNT: int = 1 + FAT_TABLES_COUNT: int = 2 SECTORS_PER_CLUSTER: int = 1 SECTOR_SIZE: int = 0x1000 HIDDEN_SECTORS: int = 0 diff --git a/lib/fatfs/fatfsgen.py b/lib/fatfs/fatfsgen.py index 199916ef..30d274f5 100755 --- a/lib/fatfs/fatfsgen.py +++ b/lib/fatfs/fatfsgen.py @@ -1,10 +1,11 @@ #!/usr/bin/env python -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import os from datetime import datetime -from typing import Any, List, Optional +from typing import Any +from typing import List +from typing import Optional from fatfs_utils.boot_sector import BootSector from fatfs_utils.exceptions import NoFreeClusterException @@ -12,10 +13,24 @@ from fatfs_utils.fat import FAT from fatfs_utils.fatfs_state import FATFSState from fatfs_utils.fs_object import Directory from fatfs_utils.long_filename_utils import get_required_lfn_entries_count -from fatfs_utils.utils import (BYTES_PER_DIRECTORY_ENTRY, FATFS_INCEPTION, FATFS_MIN_ALLOC_UNIT, - RESERVED_CLUSTERS_COUNT, FATDefaults, get_args_for_partition_generator, - get_fat_sectors_count, get_non_data_sectors_cnt, read_filesystem, - required_clusters_count) +from fatfs_utils.utils import BYTES_PER_DIRECTORY_ENTRY +from fatfs_utils.utils import FATDefaults +from fatfs_utils.utils import FATFS_INCEPTION +from fatfs_utils.utils import FATFS_MIN_ALLOC_UNIT +from fatfs_utils.utils import get_args_for_partition_generator +from fatfs_utils.utils import get_fat_sectors_count +from fatfs_utils.utils import get_non_data_sectors_cnt +from fatfs_utils.utils import read_filesystem +from fatfs_utils.utils import required_clusters_count +from fatfs_utils.utils import RESERVED_CLUSTERS_COUNT + + +def duplicate_fat_decorator(func): # type: ignore + def wrapper(self, *args, **kwargs) -> None: # type: ignore + func(self, *args, **kwargs) + if isinstance(self, FATFS): + self.duplicate_fat() + return wrapper class FATFS: @@ -40,14 +55,15 @@ class FATFS: volume_label: str = FATDefaults.VOLUME_LABEL, file_sys_type: str = FATDefaults.FILE_SYS_TYPE, root_entry_count: int = FATDefaults.ROOT_ENTRIES_COUNT, - explicit_fat_type: int = None, + explicit_fat_type: Optional[int] = None, media_type: int = FATDefaults.MEDIA_TYPE) -> None: # root directory bytes should be aligned by sector size - assert (root_entry_count * BYTES_PER_DIRECTORY_ENTRY) % sector_size == 0 + assert (int(root_entry_count) * BYTES_PER_DIRECTORY_ENTRY) % sector_size == 0 # number of bytes in the root dir must be even multiple of BPB_BytsPerSec - assert ((root_entry_count * BYTES_PER_DIRECTORY_ENTRY) // sector_size) % 2 == 0 + if (int(root_entry_count) > 128): + assert ((int(root_entry_count) * BYTES_PER_DIRECTORY_ENTRY) // sector_size) % 2 == 0 - root_dir_sectors_cnt: int = (root_entry_count * BYTES_PER_DIRECTORY_ENTRY) // sector_size + root_dir_sectors_cnt: int = (int(root_entry_count) * BYTES_PER_DIRECTORY_ENTRY) // sector_size self.state: FATFSState = FATFSState(sector_size=sector_size, explicit_fat_type=explicit_fat_type, @@ -79,6 +95,7 @@ class FATFS: fatfs_state=self.state) self.root_directory.init_directory() + @duplicate_fat_decorator def create_file(self, name: str, extension: str = '', path_from_root: Optional[List[str]] = None, @@ -102,6 +119,7 @@ class FATFS: object_timestamp_=object_timestamp_, is_empty=is_empty) + @duplicate_fat_decorator def create_directory(self, name: str, path_from_root: Optional[List[str]] = None, object_timestamp_: datetime = FATFS_INCEPTION) -> None: @@ -126,6 +144,7 @@ class FATFS: path_from_root=path_from_root, object_timestamp_=object_timestamp_) + @duplicate_fat_decorator def write_content(self, path_from_root: List[str], content: bytes) -> None: """ fat fs invokes root directory to recursively find the required file and writes the content @@ -137,10 +156,24 @@ class FATFS: boot_sector_.generate_boot_sector() return boot_sector_.binary_image + def duplicate_fat(self) -> None: + """ + Duplicate FAT table if 2 FAT tables are required + """ + boot_sec_st = self.state.boot_sector_state + if boot_sec_st.fat_tables_cnt == 2: + fat_start = boot_sec_st.reserved_sectors_cnt * boot_sec_st.sector_size + fat_end = fat_start + boot_sec_st.sectors_per_fat_cnt * boot_sec_st.sector_size + second_fat_shift = boot_sec_st.sectors_per_fat_cnt * boot_sec_st.sector_size + self.state.binary_image[fat_start + second_fat_shift: fat_end + second_fat_shift] = ( + self.state.binary_image[fat_start: fat_end] + ) + def write_filesystem(self, output_path: str) -> None: with open(output_path, 'wb') as output: output.write(bytearray(self.state.binary_image)) + @duplicate_fat_decorator def _generate_partition_from_folder(self, folder_relative_path: str, folder_path: str = '', @@ -225,17 +258,19 @@ def main() -> None: args.partition_size = max(FATFS_MIN_ALLOC_UNIT * args.sector_size, (clusters + fats + get_non_data_sectors_cnt(RESERVED_CLUSTERS_COUNT, fats, + args.fat_count, root_dir_sectors) ) * args.sector_size ) - fatfs = FATFS(sector_size=args.sector_size, + fatfs = FATFS(size=args.partition_size, + fat_tables_cnt=args.fat_count, sectors_per_cluster=args.sectors_per_cluster, - size=args.partition_size, - root_entry_count=args.root_entry_count, - explicit_fat_type=args.fat_type, + sector_size=args.sector_size, long_names_enabled=args.long_name_support, - use_default_datetime=args.use_default_datetime) + use_default_datetime=args.use_default_datetime, + root_entry_count=args.root_entry_count, + explicit_fat_type=args.fat_type) fatfs.generate(args.input_directory) fatfs.write_filesystem(args.output_file) diff --git a/lib/fatfs/fatfsparse.py b/lib/fatfs/fatfsparse.py index de50f2fe..13c9a056 100755 --- a/lib/fatfs/fatfsparse.py +++ b/lib/fatfs/fatfsparse.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import argparse import os @@ -100,7 +100,7 @@ def remove_wear_levelling_if_exists(fs_: bytes) -> bytes: boot_sector__.parse_boot_sector(fs_) if boot_sector__.boot_sector_state.size == len(fs_): return fs_ - except construct.core.ConstError: + except (UnicodeDecodeError, construct.core.StringError): pass plain_fs: bytes = remove_wl(fs_) return plain_fs @@ -124,6 +124,9 @@ if __name__ == '__main__': default=None, help="If detection doesn't work correctly, " 'you can force analyzer to or not to assume WL.') + argument_parser.add_argument('--verbose', + action='store_true', + help='Prints details about FAT image.') args = argument_parser.parse_args() @@ -157,6 +160,10 @@ if __name__ == '__main__': boot_sector_ = BootSector() boot_sector_.parse_boot_sector(fs) + + if args.verbose: + print(str(boot_sector_)) + fat = FAT(boot_sector_.boot_sector_state, init_=False) boot_dir_start_ = boot_sector_.boot_sector_state.root_directory_start diff --git a/lib/fatfs/host_test/.build-test-rules.yml b/lib/fatfs/host_test/.build-test-rules.yml new file mode 100644 index 00000000..17714e9c --- /dev/null +++ b/lib/fatfs/host_test/.build-test-rules.yml @@ -0,0 +1,7 @@ +components/fatfs/host_test: + enable: + - if: IDF_TARGET == "linux" + disable_test: + - if: IDF_TARGET == "esp32p4" + temporary: true + reason: test not pass, should be re-enable # TODO: IDF-8980 diff --git a/lib/fatfs/host_test/CMakeLists.txt b/lib/fatfs/host_test/CMakeLists.txt index 48267da8..7bf861b1 100644 --- a/lib/fatfs/host_test/CMakeLists.txt +++ b/lib/fatfs/host_test/CMakeLists.txt @@ -2,9 +2,7 @@ cmake_minimum_required(VERSION 3.16) include($ENV{IDF_PATH}/tools/cmake/project.cmake) set(COMPONENTS main) -# Freertos is included via common components. However, CATCH isn't compatible with the FreeRTOS component yet, hence -# using the FreeRTOS mock component. -# target. +# This test doesn't require FreeRTOS, uses a mock instead list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/") project(fatfs_host_test) diff --git a/lib/fatfs/host_test/main/CMakeLists.txt b/lib/fatfs/host_test/main/CMakeLists.txt index ef8aeb43..046433c1 100644 --- a/lib/fatfs/host_test/main/CMakeLists.txt +++ b/lib/fatfs/host_test/main/CMakeLists.txt @@ -1,6 +1,8 @@ -idf_component_register(SRCS "main.cpp" - "test_fatfs.cpp" - INCLUDE_DIRS "$ENV{IDF_PATH}/tools/catch" +idf_component_register(SRCS "test_fatfs.cpp" REQUIRES fatfs WHOLE_ARCHIVE ) + +# Currently 'main' for IDF_TARGET=linux is defined in freertos component. +# Since we are using a freertos mock here, need to let Catch2 provide 'main'. +target_link_libraries(${COMPONENT_LIB} PRIVATE Catch2WithMain) diff --git a/lib/fatfs/host_test/main/idf_component.yml b/lib/fatfs/host_test/main/idf_component.yml new file mode 100644 index 00000000..f7982136 --- /dev/null +++ b/lib/fatfs/host_test/main/idf_component.yml @@ -0,0 +1,2 @@ +dependencies: + espressif/catch2: "^3.4.0" diff --git a/lib/fatfs/host_test/main/main.cpp b/lib/fatfs/host_test/main/main.cpp deleted file mode 100644 index cd66dc30..00000000 --- a/lib/fatfs/host_test/main/main.cpp +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#define CATCH_CONFIG_MAIN -#include "catch.hpp" diff --git a/lib/fatfs/host_test/main/test_fatfs.cpp b/lib/fatfs/host_test/main/test_fatfs.cpp index 77af2e70..88aa16e1 100644 --- a/lib/fatfs/host_test/main/test_fatfs.cpp +++ b/lib/fatfs/host_test/main/test_fatfs.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,7 +12,7 @@ #include "diskio_impl.h" #include "diskio_wl.h" -#include "catch.hpp" +#include TEST_CASE("Create volume, open file, write and read back data", "[fatfs]") { @@ -44,7 +44,10 @@ TEST_CASE("Create volume, open file, write and read back data", "[fatfs]") fr_result = f_fdisk(pdrv, part_list, work_area); REQUIRE(fr_result == FR_OK); - const MKFS_PARM opt = {(BYTE)FM_ANY, 0, 0, 0, 0}; + + // For host tests, include FM_SFD flag when formatting partitions smaller than 128KB. + // if n_root field of MKFS_PARM is set to 128 => 1 root directory sec and if set to 0(default 512) => 4 root directory sectors. + const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 128, 0}; fr_result = f_mkfs("", &opt, work_area, sizeof(work_area)); // Use default volume // Mount the volume @@ -56,7 +59,7 @@ TEST_CASE("Create volume, open file, write and read back data", "[fatfs]") REQUIRE(fr_result == FR_OK); // Generate data - uint32_t data_size = 100000; + uint32_t data_size = 1000; char *data = (char*) malloc(data_size); char *read = (char*) malloc(data_size); @@ -130,7 +133,7 @@ static void prepare_fatfs(const char* partition_label, const esp_partition_t** p fr_result = f_fdisk(_pdrv, part_list, work_area); REQUIRE(fr_result == FR_OK); - const MKFS_PARM opt = {(BYTE)FM_ANY, 0, 0, 0, 0}; + const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 128, 0}; fr_result = f_mkfs(drv, &opt, work_area, sizeof(work_area)); // Use default volume REQUIRE(fr_result == FR_OK); } @@ -141,7 +144,7 @@ static void prepare_fatfs(const char* partition_label, const esp_partition_t** p * at the time of writing this - therefore there also is a device test_apps test in * `components/fatfs/test_apps/flash_wl/main/test_fatfs_flash_wl.c` which tests our VFS FATFS SPIFLASH API. */ -TEST_CASE("Test mounting 2 volumes, writing data and formating the 2nd one, reading data", "[fatfs]") +TEST_CASE("Test mounting 2 volumes, writing data and formatting the 2nd one, reading data", "[fatfs]") { FRESULT fr_result; esp_err_t esp_result; @@ -158,7 +161,6 @@ TEST_CASE("Test mounting 2 volumes, writing data and formating the 2nd one, read FATFS fs1; wl_handle_t wl_handle1 = WL_INVALID_HANDLE; - size_t allocation_unit_size = CONFIG_WL_SECTOR_SIZE; size_t data_size = 10; @@ -223,7 +225,7 @@ TEST_CASE("Test mounting 2 volumes, writing data and formating the 2nd one, read const size_t workbuf_size = 4096; void *workbuf = ff_memalloc(workbuf_size); REQUIRE(workbuf != NULL); - const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 0, CONFIG_WL_SECTOR_SIZE}; + const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 128, CONFIG_WL_SECTOR_SIZE}; fr_result = f_mkfs(drv1, &opt, workbuf, workbuf_size); free(workbuf); workbuf = NULL; @@ -241,7 +243,7 @@ TEST_CASE("Test mounting 2 volumes, writing data and formating the 2nd one, read fr_result = f_read(&file1, read1, data_size, &bw1); REQUIRE(fr_result == FR_OK); REQUIRE(bw1 != data_size); - // Comapre data + // Compare data printf("data1=%s, read1=%s\n", data1, read1); REQUIRE(strncmp(data1, read1, data_size-1) != 0); // 987654321 should be ersead due to formatting // Close file from file1 @@ -259,7 +261,7 @@ TEST_CASE("Test mounting 2 volumes, writing data and formating the 2nd one, read fr_result = f_read(&file0, read0, data_size, &bw0); REQUIRE(fr_result == FR_OK); REQUIRE(bw0 == data_size); - // Comapre data + // Compare data printf("data0=%s, read0=%s\n", data0, read0); REQUIRE(strncmp(data0, read0, data_size-1) == 0); // should match since the partition was not formatted // Close file from file0 diff --git a/lib/fatfs/host_test/partition_table.csv b/lib/fatfs/host_test/partition_table.csv index 30d2d909..777a3e67 100644 --- a/lib/fatfs/host_test/partition_table.csv +++ b/lib/fatfs/host_test/partition_table.csv @@ -3,5 +3,5 @@ nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 1M, -storage, data, fat, , 1M, -storage2, data, fat, , 1M, +storage, data, fat, , 32k, +storage2, data, fat, , 32k, diff --git a/lib/fatfs/host_test/pytest_fatfs_linux.py b/lib/fatfs/host_test/pytest_fatfs_linux.py index 7b12c361..e14e927a 100644 --- a/lib/fatfs/host_test/pytest_fatfs_linux.py +++ b/lib/fatfs/host_test/pytest_fatfs_linux.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.linux @pytest.mark.host_test +@idf_parametrize('target', ['linux'], indirect=['target']) def test_fatfs_linux(dut: Dut) -> None: dut.expect_exact('All tests passed', timeout=120) diff --git a/lib/fatfs/host_test/sdkconfig.defaults b/lib/fatfs/host_test/sdkconfig.defaults index e0d9a692..53e7687b 100644 --- a/lib/fatfs/host_test/sdkconfig.defaults +++ b/lib/fatfs/host_test/sdkconfig.defaults @@ -6,7 +6,6 @@ CONFIG_LOG_DEFAULT_LEVEL=3 CONFIG_PARTITION_TABLE_OFFSET=0x8000 CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partition_table.csv" -CONFIG_ESPTOOLPY_FLASHSIZE="8MB" CONFIG_MMU_PAGE_SIZE=0X10000 CONFIG_ESP_PARTITION_ENABLE_STATS=y CONFIG_FATFS_VOLUME_COUNT=3 diff --git a/lib/fatfs/port/freertos/ffsystem.c b/lib/fatfs/port/freertos/ffsystem.c index 7ca7ecc5..37c31de3 100644 --- a/lib/fatfs/port/freertos/ffsystem.c +++ b/lib/fatfs/port/freertos/ffsystem.c @@ -58,7 +58,7 @@ static mtxid Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */ #elif OS_TYPE == 2 /* uc/OS-II */ #include "includes.h" -static OS_EVENT *Mutex[FF_VOLUMES + 1]; /* Table of mutex pinter */ +static OS_EVENT *Mutex[FF_VOLUMES + 1]; /* Table of mutex pointers */ #elif OS_TYPE == 3 /* FreeRTOS */ #include "freertos/FreeRTOS.h" diff --git a/lib/fatfs/project_include.cmake b/lib/fatfs/project_include.cmake index d945c0e9..aa0edf2a 100644 --- a/lib/fatfs/project_include.cmake +++ b/lib/fatfs/project_include.cmake @@ -3,7 +3,7 @@ # Create a fatfs image of the specified directory on the host during build and optionally # have the created image flashed using `idf.py flash` function(fatfs_create_partition_image partition base_dir) - set(options FLASH_IN_PROJECT WL_INIT PRESERVE_TIME) + set(options FLASH_IN_PROJECT WL_INIT PRESERVE_TIME ONE_FAT) cmake_parse_arguments(arg "${options}" "" "${multi}" "${ARGN}") @@ -22,6 +22,12 @@ function(fatfs_create_partition_image partition base_dir) set(default_datetime_option --use_default_datetime) endif() + if(arg_ONE_FAT) + set(fatfsgen_fat_count --fat_count=1) + else() + set(fatfsgen_fat_count) + endif() + if("${CONFIG_FATFS_SECTOR_512}") set(fatfs_sector_size 512) elseif("${CONFIG_FATFS_SECTOR_1024}") @@ -52,6 +58,7 @@ function(fatfs_create_partition_image partition base_dir) COMMAND ${fatfsgen_py} ${base_dir_full_path} ${fatfs_long_names_option} ${default_datetime_option} + ${fatfsgen_fat_count} --partition_size ${size} --output_file ${image_file} --sector_size "${fatfs_sector_size}" @@ -81,39 +88,39 @@ endfunction() function(fatfs_create_rawflash_image partition base_dir) - set(options FLASH_IN_PROJECT PRESERVE_TIME) + set(options FLASH_IN_PROJECT PRESERVE_TIME ONE_FAT) cmake_parse_arguments(arg "${options}" "" "${multi}" "${ARGN}") + set(argument_list) + if(arg_FLASH_IN_PROJECT) - if(arg_PRESERVE_TIME) - fatfs_create_partition_image(${partition} ${base_dir} FLASH_IN_PROJECT PRESERVE_TIME) - else() - fatfs_create_partition_image(${partition} ${base_dir} FLASH_IN_PROJECT) - endif() - else() - if(arg_PRESERVE_TIME) - fatfs_create_partition_image(${partition} ${base_dir} PRESERVE_TIME) - else() - fatfs_create_partition_image(${partition} ${base_dir}) - endif() + list(APPEND argument_list FLASH_IN_PROJECT) + endif() + if(arg_PRESERVE_TIME) + list(APPEND argument_list PRESERVE_TIME) + endif() + if(arg_ONE_FAT) + list(APPEND argument_list ONE_FAT) endif() + + fatfs_create_partition_image(${partition} ${base_dir} ${argument_list}) endfunction() function(fatfs_create_spiflash_image partition base_dir) - set(options FLASH_IN_PROJECT PRESERVE_TIME) + set(options FLASH_IN_PROJECT PRESERVE_TIME ONE_FAT) cmake_parse_arguments(arg "${options}" "" "${multi}" "${ARGN}") + set(argument_list WL_INIT) + if(arg_FLASH_IN_PROJECT) - if(arg_PRESERVE_TIME) - fatfs_create_partition_image(${partition} ${base_dir} FLASH_IN_PROJECT WL_INIT PRESERVE_TIME) - else() - fatfs_create_partition_image(${partition} ${base_dir} FLASH_IN_PROJECT WL_INIT) - endif() - else() - if(arg_PRESERVE_TIME) - fatfs_create_partition_image(${partition} ${base_dir} WL_INIT PRESERVE_TIME) - else() - fatfs_create_partition_image(${partition} ${base_dir} WL_INIT) - endif() + list(APPEND argument_list FLASH_IN_PROJECT) endif() + if(arg_PRESERVE_TIME) + list(APPEND argument_list PRESERVE_TIME) + endif() + if(arg_ONE_FAT) + list(APPEND argument_list ONE_FAT) + endif() + + fatfs_create_partition_image(${partition} ${base_dir} ${argument_list}) endfunction() diff --git a/lib/fatfs/src/ff.c b/lib/fatfs/src/ff.c index 52adc2ab..3c3f1ace 100644 --- a/lib/fatfs/src/ff.c +++ b/lib/fatfs/src/ff.c @@ -34,7 +34,6 @@ #error Wrong include file (ff.h). #endif - /* Limits and boundaries */ #define MAX_DIR 0x200000 /* Max size of FAT directory */ #define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */ @@ -43,6 +42,10 @@ #define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */ #define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */ +#define MIN_FAT12_SEC_VOL 4 /* Min size of the FAT sector volume + 1 FAT, 1 root dir, 1 reserved, 1 data sector */ +#define MIN_FAT12_DATA_SEC 1 /* Min FAT data sectors */ + /* Character code support macros */ #define IsUpper(c) ((c) >= 'A' && (c) <= 'Z') @@ -1118,7 +1121,7 @@ static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */ if (res == FR_OK) { if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */ /* Create FSInfo structure */ - memset(fs->win, 0, sizeof fs->win); + memset(fs->win, 0, SS(fs)); st_word(fs->win + BS_55AA, 0xAA55); /* Boot signature */ st_dword(fs->win + FSI_LeadSig, 0x41615252); /* Leading signature */ st_dword(fs->win + FSI_StrucSig, 0x61417272); /* Structure signature */ @@ -1670,7 +1673,7 @@ static FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */ sect = clst2sect(fs, clst); /* Top of the cluster */ fs->winsect = sect; /* Set window to top of the cluster */ - memset(fs->win, 0, sizeof fs->win); /* Clear window buffer */ + memset(fs->win, 0, SS(fs)); /* Clear window buffer */ #if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */ /* Allocate a temporary buffer */ for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ; @@ -3318,7 +3321,7 @@ static UINT check_fs ( /* 0:FAT/FAT32 VBR, 1:exFAT VBR, 2:Not FAT and valid BS, && ld_word(fs->win + BPB_RsvdSecCnt) != 0 /* Properness of reserved sectors (MNBZ) */ && (UINT)fs->win[BPB_NumFATs] - 1 <= 1 /* Properness of FATs (1 or 2) */ && ld_word(fs->win + BPB_RootEntCnt) != 0 /* Properness of root dir entries (MNBZ) */ - && (ld_word(fs->win + BPB_TotSec16) >= 128 || ld_dword(fs->win + BPB_TotSec32) >= 0x10000) /* Properness of volume sectors (>=128) */ + && (ld_word(fs->win + BPB_TotSec16) >= MIN_FAT12_SEC_VOL || ld_dword(fs->win + BPB_TotSec32) >= 0x10000) /* Properness of volume sectors (>=MIN_FAT12_SEC_VOL) */ && ld_word(fs->win + BPB_FATSz16) != 0) { /* Properness of FAT size (MNBZ) */ return 0; /* It can be presumed an FAT VBR */ } @@ -3438,6 +3441,10 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ if (disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR; if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR; #endif +#if FF_USE_DYN_BUFFER + fs->win = ff_memalloc(SS(fs)); /* Allocate memory for sector buffer */ + if (!fs->win) return FR_NOT_ENOUGH_CORE; +#endif /* Find an FAT volume on the hosting drive */ fmt = find_volume(fs, LD2PT(vol)); @@ -3680,6 +3687,10 @@ FRESULT f_mount ( #endif #if FF_FS_REENTRANT /* Discard mutex of the current volume */ ff_mutex_delete(vol); +#endif +#if FF_USE_DYN_BUFFER + if (cfs->fs_type) /* Check if the buffer was ever allocated */ + ff_memfree(cfs->win); /* Deallocate buffer allocated for the filesystem object */ #endif cfs->fs_type = 0; /* Invalidate the filesystem object to be unregistered */ } @@ -3868,7 +3879,19 @@ FRESULT f_open ( fp->fptr = 0; /* Set file pointer top of the file */ #if !FF_FS_READONLY #if !FF_FS_TINY - memset(fp->buf, 0, sizeof fp->buf); /* Clear sector buffer */ +#if FF_USE_DYN_BUFFER + fp->buf = NULL; + if (res == FR_OK) { + fp->buf = ff_memalloc(SS(fs)); + if (!fp->buf) { + res = FR_NOT_ENOUGH_CORE; /* Not enough memory */ + goto fail; + } + memset(fp->buf, 0, SS(fs)); /* Clear sector buffer */ + } +#else + memset(fp->buf, 0, SS(fs)); /* Clear sector buffer */ +#endif #endif if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */ fp->fptr = fp->obj.objsize; /* Offset to seek */ @@ -3901,7 +3924,19 @@ FRESULT f_open ( FREE_NAMBUF(); } - if (res != FR_OK) fp->obj.fs = 0; /* Invalidate file object on error */ + if (res != FR_OK) { + fp->obj.fs = 0; /* Invalidate file object on error */ +#if !FF_FS_TINY && FF_USE_DYN_BUFFER + if (fp->buf) { + ff_memfree(fp->buf); + fp->buf = NULL; + } +#endif + } + +#if FF_USE_DYN_BUFFER +fail: +#endif LEAVE_FF(fs, res); } @@ -4235,6 +4270,10 @@ FRESULT f_close ( #else fp->obj.fs = 0; /* Invalidate file object */ #endif +#if !FF_FS_TINY && FF_USE_DYN_BUFFER + ff_memfree(fp->buf); + fp->buf = NULL; +#endif #if FF_FS_REENTRANT unlock_volume(fs, FR_OK); /* Unlock volume */ #endif @@ -5998,7 +6037,11 @@ FRESULT f_mkfs ( } } } - if (sz_vol < 128) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >=128s */ + if (n_fat == 1) { + if (sz_vol < MIN_FAT12_SEC_VOL) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >= MIN_FAT12_SEC_VOLs */ + } else { + if (sz_vol < (MIN_FAT12_SEC_VOL + 1)) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >= (MIN_FAT12_SEC_VOL+1)s */ + } /* Now start to create an FAT volume at b_vol and sz_vol */ @@ -6229,7 +6272,7 @@ FRESULT f_mkfs ( } /* Determine number of clusters and final check of validity of the FAT sub-type */ - if (sz_vol < b_data + pau * 16 - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ + if (sz_vol < b_data + pau * MIN_FAT12_DATA_SEC - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ n_clst = ((DWORD)sz_vol - sz_rsv - sz_fat * n_fat - sz_dir) / pau; if (fsty == FS_FAT32) { if (n_clst <= MAX_FAT16) { /* Too few clusters for FAT32? */ diff --git a/lib/fatfs/src/ff.h b/lib/fatfs/src/ff.h index 19854705..f4493e03 100644 --- a/lib/fatfs/src/ff.h +++ b/lib/fatfs/src/ff.h @@ -116,7 +116,7 @@ typedef struct { BYTE pd; /* Physical drive number */ BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ } PARTITION; -extern const PARTITION VolToPart[]; /* Volume - Partition mapping table */ +extern PARTITION VolToPart[]; /* Volume - Partition mapping table */ #endif #if FF_STR_VOLUME_ID @@ -170,7 +170,11 @@ typedef struct { LBA_t bitbase; /* Allocation bitmap base sector */ #endif LBA_t winsect; /* Current sector appearing in the win[] */ +#if FF_USE_DYN_BUFFER + BYTE* win; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ +#else BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ +#endif } FATFS; @@ -215,8 +219,12 @@ typedef struct { DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ #endif #if !FF_FS_TINY +#if FF_USE_DYN_BUFFER + BYTE* buf; /* File private data read/write window */ +#else BYTE buf[FF_MAX_SS]; /* File private data read/write window */ #endif +#endif } FIL; @@ -289,7 +297,7 @@ typedef enum { FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */ FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ - FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FR_NOT_ENOUGH_CORE, /* (17) Buffer could not be allocated */ FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ } FRESULT; diff --git a/lib/fatfs/src/ffconf.h b/lib/fatfs/src/ffconf.h index a5a4ae17..d378ee6d 100644 --- a/lib/fatfs/src/ffconf.h +++ b/lib/fatfs/src/ffconf.h @@ -1,3 +1,6 @@ +#ifndef _FFCONF_DEFINED +#define _FFCONF_DEFINED + #include "sdkconfig.h" /*---------------------------------------------------------------------------/ @@ -40,7 +43,7 @@ /* This option switches fast seek function. (0:Disable or 1:Enable) */ -#define FF_USE_EXPAND 0 +#define FF_USE_EXPAND 1 /* This option switches f_expand function. (0:Disable or 1:Enable) */ @@ -57,11 +60,36 @@ #define FF_USE_FORWARD 1 /* This option switches f_forward() function. (0:Disable or 1:Enable) */ +#if defined(CONFIG_FATFS_USE_STRFUNC_WITHOUT_CRLF_CONV) +#define FF_USE_STRFUNC 1 +#elif defined(CONFIG_FATFS_USE_STRFUNC_WITH_CRLF_CONV) +#define FF_USE_STRFUNC 2 +#else /* CONFIG_FATFS_USE_STRFUNC_NONE */ +#define FF_USE_STRFUNC 0 +#endif -#define FF_USE_STRFUNC 1 +#ifdef CONFIG_FATFS_PRINT_LLI +#define FF_PRINT_LLI 1 +#else #define FF_PRINT_LLI 0 +#endif + +#ifdef CONFIG_FATFS_PRINT_FLOAT +#define FF_PRINT_FLOAT 1 +#else #define FF_PRINT_FLOAT 0 +#endif + +#if defined(CONFIG_FATFS_STRF_ENCODE_ANSI) +#define FF_STRF_ENCODE 0 +#elif defined(CONFIG_FATFS_STRF_ENCODE_UTF16LE) +#define FF_STRF_ENCODE 1 +#elif defined(CONFIG_FATFS_STRF_ENCODE_UTF16BE) +#define FF_STRF_ENCODE 2 +#else /* CONFIG_FATFS_STRF_ENCODE_UTF8 */ #define FF_STRF_ENCODE 3 +#endif + /* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and / f_printf(). / @@ -271,7 +299,7 @@ / These options have no effect in read-only configuration (FF_FS_READONLY = 1). */ -#define FF_FS_NOFSINFO 0 +#define FF_FS_NOFSINFO (CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT << 0 | CONFIG_FATFS_DONT_TRUST_LAST_ALLOC << 1) /* If you need to know correct free space on the FAT32 volume, set bit 0 of this / option, and f_getfree() function at the first time after volume mount will force / a full FAT scan. Bit 1 controls the use of last allocated cluster number. @@ -311,6 +339,13 @@ / The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick. */ +#define FF_USE_DYN_BUFFER CONFIG_FATFS_USE_DYN_BUFFERS +/* The option FF_USE_DYN_BUFFER controls source of size used for buffers in the FS and FIL objects. +/ +/ 0: Disable dynamic buffer size and use static size buffers defined by FF_MAX_SS. +/ 1: Enable dynamic buffer size and use ff_memmalloc() to allocate buffers. +*/ + #include #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" @@ -330,3 +365,5 @@ void ff_memfree(void*); #define disk_read ff_disk_read #define disk_write ff_disk_write #define disk_ioctl ff_disk_ioctl + +#endif /* _FFCONF_DEFINED */ diff --git a/lib/fatfs/test_apps/.build-test-rules.yml b/lib/fatfs/test_apps/.build-test-rules.yml index d8277804..86cfac0d 100644 --- a/lib/fatfs/test_apps/.build-test-rules.yml +++ b/lib/fatfs/test_apps/.build-test-rules.yml @@ -1,11 +1,47 @@ # Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps -components/fatfs/test_apps/sdcard: +components/fatfs/test_apps/dyn_buffers: disable_test: - - if: IDF_TARGET in ["esp32s3", "esp32c2", "esp32c6", "esp32h2"] - temporary: true - reason: No sdspi runners for these targets + - if: IDF_TARGET != "esp32" + reason: only one target required + + depends_components: + - fatfs + +components/fatfs/test_apps/flash_ro: + disable_test: + - if: IDF_TARGET not in ["esp32", "esp32c3"] + reason: only one target per arch needed + + depends_components: + - esp_partition + - spi_flash + - fatfs + - vfs + +components/fatfs/test_apps/flash_wl: + disable_test: + - if: IDF_TARGET not in ["esp32", "esp32c3", "linux"] + reason: only one target per arch needed + depends_components: + - esp_partition + - spi_flash + - fatfs + - vfs + - wear_leveling + +components/fatfs/test_apps/sdcard: disable: - - if: IDF_TARGET == "esp32p4" + - if: IDF_TARGET in ["esp32h21", "esp32h4"] + temporary: true + reason: not supported yet # TODO: [esp32h21] IDF-11593 [ESP32H4] IDF-12372 + disable_test: + - if: IDF_TARGET not in ["esp32", "esp32c3"] temporary: true - reason: target esp32p4 is not supported yet # TODO: IDF-7501 + reason: lack of runners + depends_components: + - esp_driver_sdmmc + - esp_driver_spi + - sdmmc + - fatfs + - vfs diff --git a/lib/fatfs/test_apps/README.md b/lib/fatfs/test_apps/README.md index 2140e8c4..78a9dcd9 100644 --- a/lib/fatfs/test_apps/README.md +++ b/lib/fatfs/test_apps/README.md @@ -1,3 +1,6 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | + # fatfs component target tests This directory contains tests for `fatfs` component which are run on chip targets. @@ -9,6 +12,7 @@ Fatfs tests can be executed with different `diskio` backends: `diskio_sdmmc` (SD - [sdcard](sdcard/) — runs fatfs tests with an SD card over SDMMC or SDSPI interface - [flash_wl](flash_wl/) - runs fatfs test in a wear_levelling partition in SPI flash - [flash_ro](flash_ro/) - runs fatfs test in a read-only (no wear levelling) partition in SPI flash +- [dyn_buffers](dyn_buffers/) - check if enabling dynamic buffers in FATFS has an effect These test apps define: - test functions diff --git a/lib/fatfs/test_apps/dyn_buffers/CMakeLists.txt b/lib/fatfs/test_apps/dyn_buffers/CMakeLists.txt new file mode 100644 index 00000000..4e6f01d2 --- /dev/null +++ b/lib/fatfs/test_apps/dyn_buffers/CMakeLists.txt @@ -0,0 +1,7 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +idf_build_set_property(MINIMAL_BUILD ON) +project(dyn_buffers) diff --git a/lib/fatfs/test_apps/dyn_buffers/README.md b/lib/fatfs/test_apps/dyn_buffers/README.md new file mode 100644 index 00000000..261aeee2 --- /dev/null +++ b/lib/fatfs/test_apps/dyn_buffers/README.md @@ -0,0 +1,8 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | + +This test app checks if `CONFIG_FATFS_USE_DYN_BUFFERS` has any effect. + +These tests should be possible to run on any ESP development board, not extra hardware is necessary. + +See [../README.md](../README.md) for more information about FATFS test apps. diff --git a/lib/fatfs/test_apps/dyn_buffers/main/CMakeLists.txt b/lib/fatfs/test_apps/dyn_buffers/main/CMakeLists.txt new file mode 100644 index 00000000..c3cd1aa7 --- /dev/null +++ b/lib/fatfs/test_apps/dyn_buffers/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "test_fatfs_dyn_buffers.c" + INCLUDE_DIRS "." + REQUIRES wear_levelling fatfs vfs) diff --git a/lib/fatfs/test_apps/dyn_buffers/main/test_fatfs_dyn_buffers.c b/lib/fatfs/test_apps/dyn_buffers/main/test_fatfs_dyn_buffers.c new file mode 100644 index 00000000..c945d97b --- /dev/null +++ b/lib/fatfs/test_apps/dyn_buffers/main/test_fatfs_dyn_buffers.c @@ -0,0 +1,101 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include +#include +#include "wear_levelling.h" +#include "esp_partition.h" +#include "esp_vfs.h" +#include "esp_vfs_fat.h" +#include "esp_heap_caps.h" +#include "sdkconfig.h" +#include "ff.h" +#include "esp_debug_helpers.h" + +static const char* TAG = "Test dynamic buffers"; + +static volatile bool g_alloc_count_enable = false; +static volatile int g_buffer_alloc_count = 0; + +static esp_vfs_fat_mount_config_t g_mount_config = { + .format_if_mount_failed = true, + .max_files = 5, +}; + +void esp_heap_trace_alloc_hook(void* ptr, size_t size, uint32_t caps) +{ + (void) ptr; + (void) caps; + + if (!g_alloc_count_enable) { + return; + } + + // This will work only on SPI flash + // Different flash types might break this check + if (size == FF_MAX_SS) { + g_buffer_alloc_count++; + } +} + +void app_main(void) +{ + esp_err_t err = ESP_OK; + + wl_handle_t wl_handle; + + err = esp_vfs_fat_spiflash_format_cfg_rw_wl("/spiflash", NULL, &g_mount_config); + + ESP_LOGI(TAG, "Mounting FATFS"); + + g_mount_config.format_if_mount_failed = false, + + g_alloc_count_enable = true; + + err = esp_vfs_fat_spiflash_mount_rw_wl("/spiflash", NULL, &g_mount_config, &wl_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "FATFS mount failed with error: %d", err); + return; + } + + ESP_LOGI(TAG, "Mounted"); + + int fd = open("/spiflash/test.txt", O_RDWR|O_CREAT); + if (fd < 0) { + ESP_LOGE(TAG, "Failed opening file"); + } + + close(fd); + + g_alloc_count_enable = false; + + ESP_LOGI(TAG, "Unmounting FATFS"); + + esp_vfs_fat_spiflash_unmount_rw_wl("/spiflash", wl_handle); + + ESP_LOGI(TAG, "Unmounted"); + + ESP_LOGI(TAG, "Allocs called:\n\tBuffer: %d" + , g_buffer_alloc_count); + +#if CONFIG_FATFS_USE_DYN_BUFFERS + + if (g_buffer_alloc_count != 2) { + ESP_LOGE(TAG, "FATFS buffer should have been allocated once for each context (file and fatfs)"); + return; + } +#else + + if (g_buffer_alloc_count != 0) { + ESP_LOGE(TAG, "FATFS buffer should not have been allocated"); + return; + } + +#endif + + ESP_LOGI(TAG, "Done"); +} diff --git a/lib/fatfs/test_apps/dyn_buffers/partitions.csv b/lib/fatfs/test_apps/dyn_buffers/partitions.csv new file mode 100644 index 00000000..d68a9de0 --- /dev/null +++ b/lib/fatfs/test_apps/dyn_buffers/partitions.csv @@ -0,0 +1,5 @@ +# Name, Type, SubType, Offset, Size, Flags +factory, app, factory, 0x10000, 768k, +storage, data, fat, , 528k, +storage2, data, fat, , 528k, +storage1, data, fat, , 32k, diff --git a/lib/fatfs/test_apps/dyn_buffers/pytest_fatfs_dyn_buffers.py b/lib/fatfs/test_apps/dyn_buffers/pytest_fatfs_dyn_buffers.py new file mode 100644 index 00000000..a60ac87e --- /dev/null +++ b/lib/fatfs/test_apps/dyn_buffers/pytest_fatfs_dyn_buffers.py @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 +import pytest +from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize + + +@pytest.mark.generic +@pytest.mark.parametrize( + 'config', + [ + 'dyn_buffers', + 'no_dyn_buffers', + ], +) +@idf_parametrize('target', ['esp32'], indirect=['target']) +def test_fatfs_flash_dyn_buffers(config: str, dut: Dut) -> None: + dut.expect('Mounting FATFS') + dut.expect('Mounted') + dut.expect('Unmounting FATFS') + dut.expect('Unmounted') + dut.expect('Done') diff --git a/lib/fatfs/test_apps/dyn_buffers/sdkconfig.ci.dyn_buffers b/lib/fatfs/test_apps/dyn_buffers/sdkconfig.ci.dyn_buffers new file mode 100644 index 00000000..380dafbf --- /dev/null +++ b/lib/fatfs/test_apps/dyn_buffers/sdkconfig.ci.dyn_buffers @@ -0,0 +1 @@ +CONFIG_FATFS_USE_DYN_BUFFERS=y diff --git a/lib/fatfs/test_apps/dyn_buffers/sdkconfig.ci.no_dyn_buffers b/lib/fatfs/test_apps/dyn_buffers/sdkconfig.ci.no_dyn_buffers new file mode 100644 index 00000000..bc9b68f3 --- /dev/null +++ b/lib/fatfs/test_apps/dyn_buffers/sdkconfig.ci.no_dyn_buffers @@ -0,0 +1 @@ +CONFIG_FATFS_USE_DYN_BUFFERS=n diff --git a/lib/fatfs/test_apps/dyn_buffers/sdkconfig.defaults b/lib/fatfs/test_apps/dyn_buffers/sdkconfig.defaults new file mode 100644 index 00000000..8b57aacd --- /dev/null +++ b/lib/fatfs/test_apps/dyn_buffers/sdkconfig.defaults @@ -0,0 +1,14 @@ +# General options for additional checks +CONFIG_HEAP_POISONING_COMPREHENSIVE=y +CONFIG_COMPILER_WARN_WRITE_STRINGS=y +CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y +CONFIG_COMPILER_STACK_CHECK_MODE_STRONG=y +CONFIG_COMPILER_STACK_CHECK=y + +# use custom partition table +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" + +# to measure allocations +CONFIG_HEAP_USE_HOOKS=y diff --git a/lib/fatfs/test_apps/flash_ro/README.md b/lib/fatfs/test_apps/flash_ro/README.md index 4d341fbc..90297186 100644 --- a/lib/fatfs/test_apps/flash_ro/README.md +++ b/lib/fatfs/test_apps/flash_ro/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | This test app runs a few FATFS test cases in a read-only FAT partition. diff --git a/lib/fatfs/test_apps/flash_ro/main/test_fatfs_flash_ro.c b/lib/fatfs/test_apps/flash_ro/main/test_fatfs_flash_ro.c index 61786bfe..cca3dc0d 100644 --- a/lib/fatfs/test_apps/flash_ro/main/test_fatfs_flash_ro.c +++ b/lib/fatfs/test_apps/flash_ro/main/test_fatfs_flash_ro.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "sdkconfig.h" #include #include #include @@ -263,7 +264,7 @@ TEST_CASE("(raw) multiple tasks can use same volume", "[fatfs]") read_test_arg_t args4 = READ_TEST_ARG_INIT(names[3], 0x34343434); const int cpuid_0 = 0; - const int cpuid_1 = portNUM_PROCESSORS - 1; + const int cpuid_1 = CONFIG_FREERTOS_NUMBER_OF_CORES - 1; const int stack_size = 4096; printf("reading files 1.txt 2.txt 3.txt 4.txt \n"); diff --git a/lib/fatfs/test_apps/flash_ro/pytest_fatfs_flash_ro.py b/lib/fatfs/test_apps/flash_ro/pytest_fatfs_flash_ro.py index eda296ef..0339f8b6 100644 --- a/lib/fatfs/test_apps/flash_ro/pytest_fatfs_flash_ro.py +++ b/lib/fatfs/test_apps/flash_ro/pytest_fatfs_flash_ro.py @@ -1,15 +1,11 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_fatfs_flash_ro(dut: Dut) -> None: - dut.expect_exact('Press ENTER to see the list of tests') - dut.write('') - dut.expect_exact('Enter test for running.') - dut.write('*') - dut.expect_unity_test_output() + dut.run_all_single_board_cases() diff --git a/lib/fatfs/test_apps/flash_wl/README.md b/lib/fatfs/test_apps/flash_wl/README.md index 9112db39..a90777a3 100644 --- a/lib/fatfs/test_apps/flash_wl/README.md +++ b/lib/fatfs/test_apps/flash_wl/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | This test app runs a few FATFS test cases in a wear levelling FAT partition. diff --git a/lib/fatfs/test_apps/flash_wl/main/CMakeLists.txt b/lib/fatfs/test_apps/flash_wl/main/CMakeLists.txt index 20b600fc..f6501bda 100644 --- a/lib/fatfs/test_apps/flash_wl/main/CMakeLists.txt +++ b/lib/fatfs/test_apps/flash_wl/main/CMakeLists.txt @@ -1,4 +1,4 @@ -idf_component_register(SRCS "test_fatfs_flash_wl.c" +idf_component_register(SRCS "test_fatfs_flash_wl.c" "test_fatfs_small_partition.c" INCLUDE_DIRS "." PRIV_REQUIRES unity spi_flash fatfs vfs test_fatfs_common WHOLE_ARCHIVE) diff --git a/lib/fatfs/test_apps/flash_wl/main/Kconfig.projbuild b/lib/fatfs/test_apps/flash_wl/main/Kconfig.projbuild new file mode 100644 index 00000000..c7292513 --- /dev/null +++ b/lib/fatfs/test_apps/flash_wl/main/Kconfig.projbuild @@ -0,0 +1,10 @@ +menu "Test configuration" + config SPI_WL_TEST_ERASE_PARTITION + bool "Erase partition" + default y if IDF_TARGET_LINUX + help + Erase the partition before each format operation. + This will destroy the flash fairly quickly in CI, but is necessary to + ensure that the test is not affected by previous test runs. + Run with caution. +endmenu diff --git a/lib/fatfs/test_apps/flash_wl/main/test_fatfs_flash_wl.c b/lib/fatfs/test_apps/flash_wl/main/test_fatfs_flash_wl.c index 1af50fe6..fa383803 100644 --- a/lib/fatfs/test_apps/flash_wl/main/test_fatfs_flash_wl.c +++ b/lib/fatfs/test_apps/flash_wl/main/test_fatfs_flash_wl.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,6 +23,7 @@ #include "wear_levelling.h" #include "esp_partition.h" #include "esp_memory_utils.h" +#include "vfs_fat_internal.h" void app_main(void) { @@ -32,7 +33,7 @@ void app_main(void) static wl_handle_t s_test_wl_handle; static void test_setup(void) { - esp_vfs_fat_sdmmc_mount_config_t mount_config = { + esp_vfs_fat_mount_config_t mount_config = { .format_if_mount_failed = true, .max_files = 5, }; @@ -45,14 +46,47 @@ static void test_teardown(void) TEST_ESP_OK(esp_vfs_fat_spiflash_unmount_rw_wl("/spiflash", s_test_wl_handle)); } -TEST_CASE("(WL) can format partition", "[fatfs][wear_levelling][timeout=180]") +#ifdef CONFIG_SPI_WL_TEST_ERASE_PARTITION +static void corrupt_wl_data(void) { + const esp_partition_t* part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, NULL); + TEST_ASSERT_NOT_NULL(part); + TEST_ESP_OK(esp_partition_erase_range(part, 0, part->size)); +} +#endif + +TEST_CASE("(WL) can format partition", "[fatfs][wear_levelling][timeout=120]") +{ +#ifdef CONFIG_SPI_WL_TEST_ERASE_PARTITION + corrupt_wl_data(); +#endif TEST_ESP_OK(esp_vfs_fat_spiflash_format_rw_wl("/spiflash", NULL)); test_setup(); + vfs_fat_spiflash_ctx_t* ctx = get_vfs_fat_spiflash_ctx(s_test_wl_handle); + TEST_ASSERT_NOT_NULL(ctx); + TEST_ASSERT_TRUE(ctx->fs->n_fats == 2); // 2 FATs are created by default + test_teardown(); +} + +TEST_CASE("(WL) can format partition with config", "[fatfs][wear_levelling][timeout=120]") +{ +#ifdef CONFIG_SPI_WL_TEST_ERASE_PARTITION + corrupt_wl_data(); +#endif + esp_vfs_fat_mount_config_t format_config = { + .format_if_mount_failed = true, + .max_files = 5, + .use_one_fat = true, + }; + TEST_ESP_OK(esp_vfs_fat_spiflash_format_cfg_rw_wl("/spiflash", NULL, &format_config)); + test_setup(); + vfs_fat_spiflash_ctx_t* ctx = get_vfs_fat_spiflash_ctx(s_test_wl_handle); + TEST_ASSERT_NOT_NULL(ctx); + TEST_ASSERT_TRUE(ctx->fs->n_fats == 1); test_teardown(); } -TEST_CASE("(WL) can format when the FAT is mounted already", "[fatfs][wear_levelling][timeout=180]") +TEST_CASE("(WL) can format when the FAT is mounted already", "[fatfs][wear_levelling][timeout=120]") { test_setup(); TEST_ESP_OK(esp_vfs_fat_spiflash_format_rw_wl("/spiflash", NULL)); @@ -61,9 +95,28 @@ TEST_CASE("(WL) can format when the FAT is mounted already", "[fatfs][wear_level test_teardown(); } -TEST_CASE("(WL) can format specified FAT when more are mounted", "[fatfs][wear_levelling][timeout=180]") +TEST_CASE("(WL) can format when the FAT is mounted already with config", "[fatfs][wear_levelling][timeout=120]") +{ + TEST_ESP_OK(esp_vfs_fat_spiflash_format_rw_wl("/spiflash", NULL)); // To reset the FAT number to 2 + test_setup(); + vfs_fat_spiflash_ctx_t* ctx = get_vfs_fat_spiflash_ctx(s_test_wl_handle); + TEST_ASSERT_NOT_NULL(ctx); + TEST_ASSERT_TRUE(ctx->fs->n_fats == 2); + esp_vfs_fat_mount_config_t format_config = { + .format_if_mount_failed = true, + .max_files = 5, + .use_one_fat = true, + }; + TEST_ESP_OK(esp_vfs_fat_spiflash_format_cfg_rw_wl("/spiflash", NULL, &format_config)); + TEST_ASSERT_TRUE(ctx->fs->n_fats == 1); + test_fatfs_create_file_with_text("/spiflash/hello.txt", fatfs_test_hello_str); + test_fatfs_pread_file("/spiflash/hello.txt"); + test_teardown(); +} + +TEST_CASE("(WL) can format specified FAT when more are mounted", "[fatfs][wear_levelling][timeout=120]") { - esp_vfs_fat_sdmmc_mount_config_t mount_config = { + esp_vfs_fat_mount_config_t mount_config = { .format_if_mount_failed = true, .max_files = 5, }; @@ -126,7 +179,7 @@ TEST_CASE("(WL) pwrite() works well", "[fatfs][wear_levelling]") TEST_CASE("(WL) can open maximum number of files", "[fatfs][wear_levelling]") { size_t max_files = FOPEN_MAX - 3; /* account for stdin, stdout, stderr */ - esp_vfs_fat_sdmmc_mount_config_t mount_config = { + esp_vfs_fat_mount_config_t mount_config = { .format_if_mount_failed = true, .max_files = max_files }; @@ -152,9 +205,25 @@ TEST_CASE("(WL) can lseek", "[fatfs][wear_levelling]") TEST_CASE("(WL) can truncate", "[fatfs][wear_levelling]") { test_setup(); - test_fatfs_truncate_file("/spiflash/truncate.txt"); + test_fatfs_truncate_file("/spiflash/truncate.txt", true); + test_teardown(); +} + +TEST_CASE("(WL) can ftruncate", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_ftruncate_file("/spiflash/ftrunc.txt", true); + test_teardown(); +} + +#if FF_USE_EXPAND +TEST_CASE("(WL) can esp_vfs_fat_create_contiguous_file", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_create_contiguous_file("/spiflash", "/spiflash/expand.txt"); test_teardown(); } +#endif TEST_CASE("(WL) stat returns correct values", "[fatfs][wear_levelling]") { @@ -205,6 +274,13 @@ TEST_CASE("(WL) can opendir root directory of FS", "[fatfs][wear_levelling]") test_teardown(); } +TEST_CASE("(WL) readdir, stat work as expected", "[fatfs][wear_levelling]") +{ + test_setup(); + test_fatfs_readdir_stat("/spiflash/dir"); + test_teardown(); +} + TEST_CASE("(WL) opendir, readdir, rewinddir, seekdir work as expected", "[fatfs][wear_levelling]") { test_setup(); diff --git a/lib/fatfs/test_apps/flash_wl/main/test_fatfs_small_partition.c b/lib/fatfs/test_apps/flash_wl/main/test_fatfs_small_partition.c new file mode 100644 index 00000000..fd65a4db --- /dev/null +++ b/lib/fatfs/test_apps/flash_wl/main/test_fatfs_small_partition.c @@ -0,0 +1,76 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "unity.h" +#include "esp_vfs_fat.h" + +static wl_handle_t s_test_wl_handle; +static void test_setup(void) +{ + // With this configuration, for 32k partition size, + // 4 sectors will be used for WL and 4 sectors for FATFS + // (1 FAT, 1 root directory, 1 reserved and 1 data sector) + esp_vfs_fat_mount_config_t mount_config = { + .format_if_mount_failed = true, + .max_files = 5, + .use_one_fat = true, + }; + + TEST_ESP_OK(esp_vfs_fat_spiflash_format_cfg_rw_wl("/spiflash", "storage1", &mount_config)); + TEST_ESP_OK(esp_vfs_fat_spiflash_mount_rw_wl("/spiflash", "storage1", &mount_config, &s_test_wl_handle)); +} + +static void test_teardown(void) +{ + TEST_ESP_OK(esp_vfs_fat_spiflash_unmount_rw_wl("/spiflash", s_test_wl_handle)); +} + +static void test_write_data_sec(int num_data_sec) +{ + int fd = open("/spiflash/test.txt", O_CREAT | O_WRONLY); + TEST_ASSERT_NOT_EQUAL(-1, fd); + + // Generate data + uint32_t data_size = 4096*num_data_sec; + + char *data = (char*) malloc(data_size); + char *read_data = (char*) malloc(data_size); + + for(uint32_t i = 0; i < (data_size); i += sizeof(i)) + { + *((uint32_t*)(data + i)) = i; + } + ssize_t wr = write(fd, data, data_size); + if (num_data_sec == 1) { + TEST_ASSERT_EQUAL(data_size, wr); + } else { + TEST_ASSERT_NOT_EQUAL(data_size, wr); + } + TEST_ASSERT_EQUAL(0, close(fd)); + + fd = open("/spiflash/test.txt", O_RDONLY); + int r = read(fd, read_data, data_size); + if (num_data_sec == 1) { + TEST_ASSERT_EQUAL(data_size, r); + } else { + TEST_ASSERT_NOT_EQUAL(data_size, r); + } + TEST_ASSERT_EQUAL(0, strcmp(data, read_data)); + TEST_ASSERT_EQUAL(0, close(fd)); +} + +TEST_CASE("(WL) can format small partition and read-write data", "[fatfs][wear_levelling][timeout=120]") +{ + test_setup(); + test_write_data_sec(1); //for 1 data sectors, write and read func should work + test_write_data_sec(2); //for 2 data sectors, write and read func should fail + test_teardown(); +} diff --git a/lib/fatfs/test_apps/flash_wl/partitions.csv b/lib/fatfs/test_apps/flash_wl/partitions.csv index d1dcbae6..d68a9de0 100644 --- a/lib/fatfs/test_apps/flash_wl/partitions.csv +++ b/lib/fatfs/test_apps/flash_wl/partitions.csv @@ -2,3 +2,4 @@ factory, app, factory, 0x10000, 768k, storage, data, fat, , 528k, storage2, data, fat, , 528k, +storage1, data, fat, , 32k, diff --git a/lib/fatfs/test_apps/flash_wl/pytest_fatfs_flash_wl.py b/lib/fatfs/test_apps/flash_wl/pytest_fatfs_flash_wl.py index af8c5db6..a9863635 100644 --- a/lib/fatfs/test_apps/flash_wl/pytest_fatfs_flash_wl.py +++ b/lib/fatfs/test_apps/flash_wl/pytest_fatfs_flash_wl.py @@ -1,11 +1,10 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.supported_targets @pytest.mark.generic @pytest.mark.parametrize( 'config', @@ -13,27 +12,23 @@ from pytest_embedded import Dut 'default', 'release', 'fastseek', - ] + 'auto_fsync', + 'dyn_buffers', + ], ) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_fatfs_flash_wl_generic(dut: Dut) -> None: - dut.expect_exact('Press ENTER to see the list of tests') - dut.write('') - dut.expect_exact('Enter test for running.') - dut.write('*') - dut.expect_unity_test_output(timeout=180) + dut.run_all_single_board_cases(timeout=240) -@pytest.mark.supported_targets +@pytest.mark.generic @pytest.mark.psram @pytest.mark.parametrize( 'config', [ 'psram', - ] + ], ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_fatfs_flash_wl_psram(dut: Dut) -> None: - dut.expect_exact('Press ENTER to see the list of tests') - dut.write('') - dut.expect_exact('Enter test for running.') - dut.write('*') - dut.expect_unity_test_output(timeout=180) + dut.run_all_single_board_cases(timeout=180) diff --git a/lib/fatfs/test_apps/flash_wl/sdkconfig.ci.auto_fsync b/lib/fatfs/test_apps/flash_wl/sdkconfig.ci.auto_fsync index b74d5124..9ab32baa 100644 --- a/lib/fatfs/test_apps/flash_wl/sdkconfig.ci.auto_fsync +++ b/lib/fatfs/test_apps/flash_wl/sdkconfig.ci.auto_fsync @@ -1 +1,3 @@ CONFIG_FATFS_IMMEDIATE_FSYNC=y +CONFIG_ESP_MAIN_TASK_STACK_SIZE=4096 +CONFIG_FATFS_VFS_FSTAT_BLKSIZE=2048 diff --git a/lib/fatfs/test_apps/flash_wl/sdkconfig.ci.dyn_buffers b/lib/fatfs/test_apps/flash_wl/sdkconfig.ci.dyn_buffers new file mode 100644 index 00000000..380dafbf --- /dev/null +++ b/lib/fatfs/test_apps/flash_wl/sdkconfig.ci.dyn_buffers @@ -0,0 +1 @@ +CONFIG_FATFS_USE_DYN_BUFFERS=y diff --git a/lib/fatfs/test_apps/flash_wl/sdkconfig.ci.psram b/lib/fatfs/test_apps/flash_wl/sdkconfig.ci.psram deleted file mode 100644 index b3b45db9..00000000 --- a/lib/fatfs/test_apps/flash_wl/sdkconfig.ci.psram +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_SPIRAM=y -CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0 -CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y diff --git a/lib/fatfs/test_apps/flash_wl/sdkconfig.ci.psram.esp32 b/lib/fatfs/test_apps/flash_wl/sdkconfig.ci.psram.esp32 new file mode 100644 index 00000000..5becfb94 --- /dev/null +++ b/lib/fatfs/test_apps/flash_wl/sdkconfig.ci.psram.esp32 @@ -0,0 +1,4 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0 +CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y diff --git a/lib/fatfs/test_apps/sdcard/README.md b/lib/fatfs/test_apps/sdcard/README.md index 639f1d38..381b38a9 100644 --- a/lib/fatfs/test_apps/sdcard/README.md +++ b/lib/fatfs/test_apps/sdcard/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | This test app runs a few FATFS test cases in a FAT-formatted SD card. diff --git a/lib/fatfs/test_apps/sdcard/main/CMakeLists.txt b/lib/fatfs/test_apps/sdcard/main/CMakeLists.txt index be2a969a..e4a519cb 100644 --- a/lib/fatfs/test_apps/sdcard/main/CMakeLists.txt +++ b/lib/fatfs/test_apps/sdcard/main/CMakeLists.txt @@ -1,6 +1,6 @@ idf_component_register(SRCS "test_fatfs_sdcard_main.c" "test_fatfs_sdspi.c" INCLUDE_DIRS "." - PRIV_REQUIRES unity fatfs vfs sdmmc driver test_fatfs_common + PRIV_REQUIRES unity fatfs vfs sdmmc driver test_fatfs_common esp_timer WHOLE_ARCHIVE) if(CONFIG_SOC_SDMMC_HOST_SUPPORTED) diff --git a/lib/fatfs/test_apps/sdcard/main/test_fatfs_sdmmc.c b/lib/fatfs/test_apps/sdcard/main/test_fatfs_sdmmc.c index 4504a5d6..e6478ad9 100644 --- a/lib/fatfs/test_apps/sdcard/main/test_fatfs_sdmmc.c +++ b/lib/fatfs/test_apps/sdcard/main/test_fatfs_sdmmc.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,7 @@ #include "unity.h" #include "esp_log.h" #include "esp_random.h" +#include "esp_timer.h" #include "esp_vfs.h" #include "esp_vfs_fat.h" #include "freertos/FreeRTOS.h" @@ -22,6 +23,7 @@ #include "ff.h" #include "test_fatfs_common.h" #include "soc/soc_caps.h" +#include "vfs_fat_internal.h" #if CONFIG_IDF_TARGET_ESP32 #define SDSPI_MISO_PIN 2 @@ -50,6 +52,7 @@ #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3) // No runner #include "driver/sdmmc_host.h" +const char* base_path = "/sdcard"; static void test_setup_sdmmc(sdmmc_card_t **out_card) { @@ -61,7 +64,7 @@ static void test_setup_sdmmc(sdmmc_card_t **out_card) .max_files = 5, .allocation_unit_size = 16 * 1024 }; - TEST_ESP_OK(esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card)); + TEST_ESP_OK(esp_vfs_fat_sdmmc_mount(base_path, &host, &slot_config, &mount_config, &card)); *out_card = card; } @@ -102,6 +105,35 @@ TEST_CASE("(SD) can format partition", "[fatfs][sdmmc][timeout=180]") test_teardown_sdmmc(card); } +TEST_CASE("(SD) can format partition with config", "[fatfs][sdmmc][timeout=180]") +{ + sdmmc_card_t *card = NULL; + test_setup_sdmmc(&card); + vfs_fat_sd_ctx_t* ctx = get_vfs_fat_get_sd_ctx(card); + TEST_ASSERT_NOT_NULL(ctx); + + esp_vfs_fat_mount_config_t format_config = { + .format_if_mount_failed = true, + .max_files = 5, + .allocation_unit_size = 16 * 1024, + .use_one_fat = true, + }; + TEST_ESP_OK(esp_vfs_fat_sdcard_format_cfg("/sdcard", card, &format_config)); + TEST_ASSERT_TRUE(ctx->fs->n_fats == 1); + + test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str); + test_fatfs_read_file(test_filename); + + format_config.use_one_fat = false; + TEST_ESP_OK(esp_vfs_fat_sdcard_format_cfg("/sdcard", card, &format_config)); + TEST_ASSERT_TRUE(ctx->fs->n_fats == 2); + + test_fatfs_create_file_with_text(test_filename, fatfs_test_hello_str); + test_fatfs_read_file(test_filename); + + test_teardown_sdmmc(card); +} + TEST_CASE("(SD) can create and write file", "[fatfs][sdmmc]") { sdmmc_card_t *card = NULL; @@ -156,7 +188,7 @@ TEST_CASE("(SD) can truncate", "[fatfs][sdmmc]") { sdmmc_card_t *card = NULL; test_setup_sdmmc(&card); - test_fatfs_truncate_file("/sdcard/truncate.txt"); + test_fatfs_truncate_file("/sdcard/truncate.txt", true); test_teardown_sdmmc(card); } @@ -164,9 +196,19 @@ TEST_CASE("(SD) can ftruncate", "[fatfs][sdmmc]") { sdmmc_card_t *card = NULL; test_setup_sdmmc(&card); - test_fatfs_ftruncate_file("/sdcard/ftrunc.txt"); + test_fatfs_ftruncate_file("/sdcard/ftrunc.txt", true); + test_teardown_sdmmc(card); +} + +#if FF_USE_EXPAND +TEST_CASE("(SD) can esp_vfs_fat_create_contiguous_file", "[fatfs][sdmmc]") +{ + sdmmc_card_t *card = NULL; + test_setup_sdmmc(&card); + test_fatfs_create_contiguous_file("/sdcard", "/sdcard/expand.txt"); test_teardown_sdmmc(card); } +#endif TEST_CASE("(SD) stat returns correct values", "[fatfs][sdmmc]") { @@ -275,6 +317,231 @@ static void sdmmc_speed_test(void *buf, size_t buf_size, size_t file_size, bool TEST_ESP_OK(esp_vfs_fat_sdcard_unmount("/sdcard", card)); } +TEST_CASE("(SD) mount FAT partitions and readdir to get stat structure", "[fatfs][sdmmc]") +{ + char name_dir_file[64]; + char name_dir_stat[64] = {0}; + const char* dir_prefix = "/sdcard"; + int dir_prefix_len = strlen(dir_prefix); + int file_num = 300; + + /* Mount FATFS in SD can WL at the same time. Create a file on each FS */ + sdmmc_card_t* card = NULL; + test_setup_sdmmc(&card); + TEST_ESP_OK(esp_vfs_fat_sdcard_format("/sdcard", card)); + + //Create multiple files with text on sdcard. Each file size is 14 bytes + //Total files created are file_num (300 in this case) + //So directory size will be 300*14 bytes + for(int i=0;id_name)+1, "%s/%s", dir_prefix, de->d_name); + TEST_ASSERT_EQUAL(0, stat(name_dir_stat, &st)); + dir_size += st.st_size; + } + TEST_ASSERT_EQUAL(0, closedir(dir)); + int64_t end = esp_timer_get_time(); + int64_t total_time_readdir = end-start; + printf("Time in us for calculating directory size by calling readdir first and then stat func: %lld \n",total_time_readdir); + printf("Size of the directory %s is %"PRIu32"Kb\n", dir_prefix, (dir_size/1000)); + TEST_ASSERT_EQUAL(file_num*strlen(fatfs_test_hello_str), dir_size); //each file size is 14 bytes + + // Call stat function directly without calling readdir and record the time needed to calculate the directory size + dir_size = 0; + start = esp_timer_get_time(); + for(int i=0;idir); + TEST_ASSERT_NOT_NULL(dir); + while(1) { + de = readdir(dir); + if (!de) { + break; + } + //Intentionally introduced a delay to ensure that the second task is triggered simultaneously. + vTaskDelay(10 / portTICK_PERIOD_MS); + snprintf(name_dir_stat, sizeof(test_task_param->dir)+sizeof(de->d_name), "%s/%s", test_task_param->dir, de->d_name); + TEST_ASSERT_EQUAL(0, stat(name_dir_stat, &st)); + if (strcasecmp(de->d_name, test_task_param->filename) == 0) { + TEST_ASSERT_FALSE(st.st_mode & S_IFDIR); + TEST_ASSERT_EQUAL(strlen(test_task_param->str), st.st_size); + } else { + TEST_FAIL_MESSAGE("unexpected directory entry"); + } + } + + if (test_task_param->sem) { + xSemaphoreGive(test_task_param->sem); + } + vTaskDelete(NULL); +} + +TEST_CASE("(SD) mount two FAT partitions, SDMMC and WL, at the same time and readdir to get stat structure", "[fatfs][sdmmc]") +{ + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = true, + .max_files = 5 + }; + + const char *dir_prefix[FF_VOLUMES] = {"/sdcard", "/spiflash"}; + const char *dir_filename[FF_VOLUMES] = {"sd.txt", "wl.txt"}; + const char* str[FF_VOLUMES] = {"this is sd\n", "this is spiflash\n"}; + const char* filename_sd = "/sdcard/sd.txt"; + const char* filename_wl = "/spiflash/wl.txt"; + + /* Erase flash before the first use */ + const esp_partition_t *test_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, NULL); + TEST_ASSERT_NOT_NULL(test_partition); + esp_partition_erase_range(test_partition, 0, test_partition->size); + + /* Mount FATFS in SD can WL at the same time. Create a file on each FS */ + wl_handle_t wl_handle = WL_INVALID_HANDLE; + sdmmc_card_t *card = NULL; + test_setup_sdmmc(&card); + TEST_ESP_OK(esp_vfs_fat_spiflash_mount_rw_wl("/spiflash", NULL, &mount_config, &wl_handle)); + unlink(filename_sd); + unlink(filename_wl); + test_fatfs_create_file_with_text(filename_sd, str[0]); + test_fatfs_create_file_with_text(filename_wl, str[1]); + + test_task_param_t test_task_param_sd = { + .dir = dir_prefix[0], + .filename = dir_filename[0], + .str = str[0], + .sem = xSemaphoreCreateBinary(), + }; + + test_task_param_t test_task_param_spiflash = { + .dir = dir_prefix[1], + .filename = dir_filename[1], + .str = str[1], + .sem = xSemaphoreCreateBinary(), + }; + + //Create two tasks with same priority to check file size on two different FAT partitions at the same time + xTaskCreate(test_task, "test_task_1", 8*1024, (void *) &test_task_param_sd, 5, NULL); + xTaskCreate(test_task, "test_task_2", 8*1024, (void *) &test_task_param_spiflash, 5, NULL); + + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(test_task_param_sd.sem, 1000 / portTICK_PERIOD_MS)); + vSemaphoreDelete(test_task_param_sd.sem); + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(test_task_param_spiflash.sem, 1000 / portTICK_PERIOD_MS)); + vSemaphoreDelete(test_task_param_spiflash.sem); + TEST_ESP_OK(esp_vfs_fat_spiflash_unmount_rw_wl("/spiflash", wl_handle)); + test_teardown_sdmmc(card); +} + +TEST_CASE("(SD) read two directories and get stat structure for respective file at the same time", "[fatfs][sdmmc]") +{ + char name_dir_file[64]; + char name_dir1_stat[64] = {0}; + char name_dir2_stat[64] = {0}; + const char* dir1_prefix = "/sdcard/dir1"; + const char* dir2_prefix = "/sdcard/dir2"; + int dir1_prefix_len = strlen(dir1_prefix); + int dir2_prefix_len = strlen(dir2_prefix); + const char* test_str1 = "Hello, World!\n"; + const char* test_str2 = "Hello, ESP Community\n"; + + /* Mount FATFS in SD can WL at the same time. Create a file on each FS */ + sdmmc_card_t* card = NULL; + test_setup_sdmmc(&card); + + TEST_ASSERT_EQUAL(0, mkdir(dir1_prefix, 0755)); + TEST_ASSERT_EQUAL(0, mkdir(dir2_prefix, 0755)); + + snprintf(name_dir_file, sizeof(name_dir_file), "%s/boo_1.bin", dir1_prefix); + test_fatfs_create_file_with_text(name_dir_file, test_str1); + snprintf(name_dir_file, sizeof(name_dir_file), "%s/boo_1.bin", dir2_prefix); + test_fatfs_create_file_with_text(name_dir_file, test_str2); + + DIR* dir1 = opendir(dir1_prefix); + TEST_ASSERT_NOT_NULL(dir1); + DIR* dir2 = opendir(dir2_prefix); + TEST_ASSERT_NOT_NULL(dir2); + struct dirent* de1; + struct dirent* de2; + struct stat st1; + struct stat st2; + + while(1) { + de1 = readdir(dir1); + if (!de1) { + break; + } + de2 = readdir(dir2); + if (!de2) { + break; + } + snprintf(name_dir1_stat, dir1_prefix_len+sizeof(de1->d_name)+1, "%s/%s", dir1_prefix, de1->d_name); + snprintf(name_dir2_stat, dir2_prefix_len+sizeof(de2->d_name)+1, "%s/%s", dir2_prefix, de2->d_name); + TEST_ASSERT_EQUAL(0, stat(name_dir1_stat, &st1)); + TEST_ASSERT_EQUAL(0, stat(name_dir2_stat, &st2)); + TEST_ASSERT_EQUAL(strlen(test_str1), st1.st_size); //size of dir1/boo_1.bin is 14 + TEST_ASSERT_EQUAL(strlen(test_str2), st2.st_size); //size of dir2/boo_1.bin is 21 + } + TEST_ASSERT_EQUAL(0, closedir(dir1)); + TEST_ASSERT_EQUAL(0, closedir(dir2)); + + snprintf(name_dir_file, sizeof(name_dir_file), "%s/boo_1.bin", dir1_prefix); + unlink(name_dir_file); + snprintf(name_dir_file, sizeof(name_dir_file), "%s/boo_1.bin", dir2_prefix); + unlink(name_dir_file); + rmdir(dir1_prefix); + rmdir(dir2_prefix); + + test_teardown_sdmmc(card); +} + TEST_CASE("(SD) mount two FAT partitions, SDMMC and WL, at the same time", "[fatfs][sdmmc]") { esp_vfs_fat_sdmmc_mount_config_t mount_config = { diff --git a/lib/fatfs/test_apps/sdcard/main/test_fatfs_sdspi.c b/lib/fatfs/test_apps/sdcard/main/test_fatfs_sdspi.c index c1d567c0..a3247bd2 100644 --- a/lib/fatfs/test_apps/sdcard/main/test_fatfs_sdspi.c +++ b/lib/fatfs/test_apps/sdcard/main/test_fatfs_sdspi.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,6 +22,7 @@ #include "ff.h" #include "test_fatfs_common.h" #include "soc/soc_caps.h" +#include "vfs_fat_internal.h" #if CONFIG_IDF_TARGET_ESP32 #define SDSPI_MISO_PIN 2 @@ -34,13 +35,13 @@ #define SDSPI_MOSI_PIN 35 #define SDSPI_CLK_PIN 36 #define SDSPI_CS_PIN 34 -#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6 +#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C61 #define SDSPI_MISO_PIN 6 #define SDSPI_MOSI_PIN 4 #define SDSPI_CLK_PIN 5 #define SDSPI_CS_PIN 1 #define SPI_DMA_CHAN SPI_DMA_CH_AUTO -#elif CONFIG_IDF_TARGET_ESP32H2 +#elif CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32P4 #define SDSPI_MISO_PIN 0 #define SDSPI_MOSI_PIN 5 #define SDSPI_CLK_PIN 4 @@ -89,7 +90,7 @@ static void test_teardown_sdspi(sdspi_mem_t* mem) HEAP_SIZE_CHECK(mem->heap_size, 0); } -TEST_CASE("(SDSPI) write/read speed test", "[fatfs][sdspi]") +TEST_CASE("(SDSPI) write/read speed test", "[fatfs][sdspi][timeout=120]") { sdspi_mem_t mem; size_t file_size = 1 * 1024 * 1024; @@ -197,3 +198,55 @@ TEST_CASE("(SDSPI) can format card", "[fatfs][sdspi][timeout=180]") TEST_ESP_OK(esp_vfs_fat_sdcard_unmount(path, card)); test_teardown_sdspi(&mem); } + + +TEST_CASE("(SDSPI) can format card with config", "[fatfs][sdspi][timeout=180]") +{ + sdspi_mem_t mem; + test_setup_sdspi(&mem); + + const char path[] = "/sdcard"; + sdmmc_card_t *card; + card = NULL; + sdspi_device_config_t device_cfg = { + .gpio_cs = SDSPI_CS_PIN, + .host_id = SDSPI_HOST_ID, + .gpio_cd = SDSPI_SLOT_NO_CD, + .gpio_wp = SDSPI_SLOT_NO_WP, + .gpio_int = SDSPI_SLOT_NO_INT, + }; + + sdmmc_host_t host = SDSPI_HOST_DEFAULT(); + host.slot = SDSPI_HOST_ID; + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = true, + .max_files = 5, + .allocation_unit_size = 64 * 1024, + }; + TEST_ESP_OK(esp_vfs_fat_sdspi_mount(path, &host, &device_cfg, &mount_config, &card)); + + vfs_fat_sd_ctx_t* ctx = get_vfs_fat_get_sd_ctx(card); + TEST_ASSERT_NOT_NULL(ctx); + + esp_vfs_fat_mount_config_t format_config = { + .format_if_mount_failed = true, + .max_files = 5, + .allocation_unit_size = 64 * 1024, + .use_one_fat = true, + }; + TEST_ESP_OK(esp_vfs_fat_sdcard_format_cfg("/sdcard", card, &format_config)); + TEST_ASSERT_TRUE(ctx->fs->n_fats == 1); + + test_fatfs_create_file_with_text(s_test_filename, fatfs_test_hello_str); + test_fatfs_read_file(s_test_filename); + + format_config.use_one_fat = false; + TEST_ESP_OK(esp_vfs_fat_sdcard_format_cfg("/sdcard", card, &format_config)); + TEST_ASSERT_TRUE(ctx->fs->n_fats == 2); + + test_fatfs_create_file_with_text(s_test_filename, fatfs_test_hello_str); + test_fatfs_read_file(s_test_filename); + + TEST_ESP_OK(esp_vfs_fat_sdcard_unmount(path, card)); + test_teardown_sdspi(&mem); +} diff --git a/lib/fatfs/test_apps/sdcard/pytest_fatfs_sdcard.py b/lib/fatfs/test_apps/sdcard/pytest_fatfs_sdcard.py index fe720a02..b0657186 100644 --- a/lib/fatfs/test_apps/sdcard/pytest_fatfs_sdcard.py +++ b/lib/fatfs/test_apps/sdcard/pytest_fatfs_sdcard.py @@ -1,75 +1,59 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 - import pytest from pytest_embedded import Dut +from pytest_embedded_idf.utils import idf_parametrize -@pytest.mark.esp32 @pytest.mark.sdcard_sdmode @pytest.mark.parametrize( 'config', [ 'default', 'release', - ] + ], ) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_fatfs_sdcard_generic_sdmmc(dut: Dut) -> None: - dut.expect_exact('Press ENTER to see the list of tests') - dut.write('') - dut.expect_exact('Enter test for running.') - dut.write('[sdmmc]') - dut.expect_unity_test_output(timeout=180) + dut.run_all_single_board_cases(group='sdmmc', timeout=180) -@pytest.mark.esp32 -@pytest.mark.esp32s2 -@pytest.mark.esp32c3 +@pytest.mark.temp_skip_ci(targets=['esp32'], reason='IDFCI-2058, temporary lack runner') @pytest.mark.sdcard_spimode @pytest.mark.parametrize( 'config', [ 'default', 'release', - ] + ], ) +@idf_parametrize('target', ['esp32', 'esp32c3'], indirect=['target']) def test_fatfs_sdcard_generic_sdspi(dut: Dut) -> None: - dut.expect_exact('Press ENTER to see the list of tests') - dut.write('') - dut.expect_exact('Enter test for running.') - dut.write('[sdspi]') - dut.expect_unity_test_output(timeout=180) + dut.run_all_single_board_cases(group='sdspi', timeout=180) -@pytest.mark.esp32 @pytest.mark.sdcard_sdmode @pytest.mark.psram @pytest.mark.parametrize( 'config', [ 'psram', - ] + ], ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_fatfs_sdcard_psram_sdmmc(dut: Dut) -> None: - dut.expect_exact('Press ENTER to see the list of tests') - dut.write('') - dut.expect_exact('Enter test for running.') - dut.write('[sdmmc]') - dut.expect_unity_test_output(timeout=180) + dut.run_all_single_board_cases(group='sdmmc', timeout=180) -@pytest.mark.esp32 +@pytest.mark.temp_skip_ci(targets=['esp32'], reason='IDFCI-2058, temporary lack runner') @pytest.mark.sdcard_spimode @pytest.mark.psram @pytest.mark.parametrize( 'config', [ 'psram', - ] + ], ) +@idf_parametrize('target', ['esp32'], indirect=['target']) def test_fatfs_sdcard_psram_sdspi(dut: Dut) -> None: - dut.expect_exact('Press ENTER to see the list of tests') - dut.write('') - dut.expect_exact('Enter test for running.') - dut.write('[sdspi]') - dut.expect_unity_test_output(timeout=180) + dut.run_all_single_board_cases(group='sdspi', timeout=180) diff --git a/lib/fatfs/test_apps/sdcard/sdkconfig.ci.psram b/lib/fatfs/test_apps/sdcard/sdkconfig.ci.psram deleted file mode 100644 index b3b45db9..00000000 --- a/lib/fatfs/test_apps/sdcard/sdkconfig.ci.psram +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_SPIRAM=y -CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0 -CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y diff --git a/lib/fatfs/test_apps/sdcard/sdkconfig.ci.psram.esp32 b/lib/fatfs/test_apps/sdcard/sdkconfig.ci.psram.esp32 new file mode 100644 index 00000000..5becfb94 --- /dev/null +++ b/lib/fatfs/test_apps/sdcard/sdkconfig.ci.psram.esp32 @@ -0,0 +1,4 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0 +CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y diff --git a/lib/fatfs/test_apps/test_fatfs_common/CMakeLists.txt b/lib/fatfs/test_apps/test_fatfs_common/CMakeLists.txt index 8f06878d..74ec85e7 100644 --- a/lib/fatfs/test_apps/test_fatfs_common/CMakeLists.txt +++ b/lib/fatfs/test_apps/test_fatfs_common/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS "test_fatfs_common.c" INCLUDE_DIRS "." - PRIV_REQUIRES unity fatfs vfs unity) + PRIV_REQUIRES unity fatfs vfs unity esp_timer) diff --git a/lib/fatfs/test_apps/test_fatfs_common/test_fatfs_common.c b/lib/fatfs/test_apps/test_fatfs_common/test_fatfs_common.c index 77372fbb..887123cb 100644 --- a/lib/fatfs/test_apps/test_fatfs_common/test_fatfs_common.c +++ b/lib/fatfs/test_apps/test_fatfs_common/test_fatfs_common.c @@ -1,9 +1,10 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include "sdkconfig.h" #include #include #include @@ -16,10 +17,12 @@ #include #include "unity.h" #include "esp_vfs.h" +#include "esp_timer.h" #include "esp_vfs_fat.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "test_fatfs_common.h" +#include "ff.h" const char* fatfs_test_hello_str = "Hello, World!\n"; const char* fatfs_test_hello_str_utf = "世界,你好!\n"; @@ -252,7 +255,7 @@ void test_fatfs_lseek(const char* filename) } -void test_fatfs_truncate_file(const char* filename) +void test_fatfs_truncate_file(const char* filename, bool allow_expanding_files) { int read = 0; int truncated_len = 0; @@ -267,14 +270,44 @@ void test_fatfs_truncate_file(const char* filename) TEST_ASSERT_EQUAL(0, fclose(f)); + struct stat st; + size_t size; - // Extending file beyond size is not supported - TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input) + 1)); - TEST_ASSERT_EQUAL(errno, EPERM); + stat(filename, &st); + size = st.st_size; + TEST_ASSERT_EQUAL(strlen(input), size); - TEST_ASSERT_EQUAL(-1, truncate(filename, -1)); - TEST_ASSERT_EQUAL(errno, EINVAL); + if (allow_expanding_files) { + size_t trunc_add = 2; + size_t new_size = strlen(input) + trunc_add; + TEST_ASSERT_EQUAL(0, truncate(filename, new_size)); + + stat(filename, &st); + size = st.st_size; + TEST_ASSERT_EQUAL(new_size, size); + + f = fopen(filename, "rb"); + TEST_ASSERT_NOT_NULL(f); + + char expanded_output[sizeof(input) + trunc_add]; + memset(expanded_output, 42, sizeof(expanded_output)); // set to something else than 0 (42) + + read = fread(expanded_output, 1, sizeof(input) + trunc_add, f); + TEST_ASSERT_EQUAL(new_size, read); + + TEST_ASSERT_EQUAL('Z', expanded_output[strlen(input) - 1]); // 'Z' character + TEST_ASSERT_EQUAL('\0', expanded_output[sizeof(input) + trunc_add - 3]); // zeroed expanded space + TEST_ASSERT_EQUAL('\0', expanded_output[sizeof(input) + trunc_add - 2]); // zeroed expanded space + TEST_ASSERT_EQUAL(42, expanded_output[sizeof(input) + trunc_add - 1]); // 42 set with memset, end of the array + TEST_ASSERT_EQUAL(0, fclose(f)); + } else { + TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input) + 1)); + TEST_ASSERT_EQUAL(errno, EPERM); + + TEST_ASSERT_EQUAL(-1, truncate(filename, -1)); + TEST_ASSERT_EQUAL(errno, EINVAL); + } // Truncating should succeed const char truncated_1[] = "ABCDEFGHIJ"; @@ -282,6 +315,10 @@ void test_fatfs_truncate_file(const char* filename) TEST_ASSERT_EQUAL(0, truncate(filename, truncated_len)); + stat(filename, &st); + size = st.st_size; + TEST_ASSERT_EQUAL(strlen(truncated_1), size); + f = fopen(filename, "rb"); TEST_ASSERT_NOT_NULL(f); @@ -293,28 +330,34 @@ void test_fatfs_truncate_file(const char* filename) TEST_ASSERT_EQUAL(0, fclose(f)); + if (allow_expanding_files) { + TEST_ASSERT_EQUAL(0, truncate(filename, truncated_len + 1)); + } else { + // Once truncated, the new file size should be the basis + // whether truncation should succeed or not when `allow_expanding_files == false` + TEST_ASSERT_EQUAL(-1, truncate(filename, truncated_len + 1)); + TEST_ASSERT_EQUAL(EPERM, errno); - // Once truncated, the new file size should be the basis - // whether truncation should succeed or not - TEST_ASSERT_EQUAL(-1, truncate(filename, truncated_len + 1)); - TEST_ASSERT_EQUAL(EPERM, errno); - - TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input))); - TEST_ASSERT_EQUAL(EPERM, errno); + TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input))); + TEST_ASSERT_EQUAL(EPERM, errno); - TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input) + 1)); - TEST_ASSERT_EQUAL(EPERM, errno); + TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input) + 1)); + TEST_ASSERT_EQUAL(EPERM, errno); + } TEST_ASSERT_EQUAL(-1, truncate(filename, -1)); TEST_ASSERT_EQUAL(EINVAL, errno); - // Truncating a truncated file should succeed const char truncated_2[] = "ABCDE"; truncated_len = strlen(truncated_2); TEST_ASSERT_EQUAL(0, truncate(filename, truncated_len)); + stat(filename, &st); + size = st.st_size; + TEST_ASSERT_EQUAL(strlen(truncated_2), size); + f = fopen(filename, "rb"); TEST_ASSERT_NOT_NULL(f); @@ -327,29 +370,63 @@ void test_fatfs_truncate_file(const char* filename) TEST_ASSERT_EQUAL(0, fclose(f)); } -void test_fatfs_ftruncate_file(const char* filename) +void test_fatfs_ftruncate_file(const char* filename, bool allow_expanding_files) { int truncated_len = 0; const char input[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char output[sizeof(input)]; - int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC); + int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC); TEST_ASSERT_NOT_EQUAL(-1, fd); TEST_ASSERT_EQUAL(strlen(input), write(fd, input, strlen(input))); - // Extending file beyond size is not supported - TEST_ASSERT_EQUAL(-1, ftruncate(fd, strlen(input) + 1)); - TEST_ASSERT_EQUAL(errno, EPERM); - - TEST_ASSERT_EQUAL(-1, ftruncate(fd, -1)); - TEST_ASSERT_EQUAL(errno, EINVAL); + struct stat st; + size_t size; + + fstat(fd, &st); + size = st.st_size; + TEST_ASSERT_EQUAL(strlen(input), size); + + if (allow_expanding_files) { + size_t trunc_add = 2; + size_t new_size = strlen(input) + trunc_add; + TEST_ASSERT_EQUAL(0, ftruncate(fd, new_size)); + + fstat(fd, &st); + size = st.st_size; + TEST_ASSERT_EQUAL(new_size, size); + + char expanded_output[sizeof(input) + trunc_add]; + memset(expanded_output, 42, sizeof(expanded_output)); // set to something else than 0 (42) + + lseek(fd, 0, SEEK_SET); + int r = read(fd, expanded_output, sizeof(input) + trunc_add); + TEST_ASSERT_NOT_EQUAL(-1, r); + TEST_ASSERT_EQUAL(new_size, r); + + TEST_ASSERT_EQUAL('Z', expanded_output[strlen(input) - 1]); // 'Z' character + TEST_ASSERT_EQUAL('\0', expanded_output[sizeof(input) + trunc_add - 3]); // zeroed expanded space + TEST_ASSERT_EQUAL('\0', expanded_output[sizeof(input) + trunc_add - 2]); // zeroed expanded space + TEST_ASSERT_EQUAL(42, expanded_output[sizeof(input) + trunc_add - 1]); // 42 set with memset, end of the array + } else { + TEST_ASSERT_EQUAL(-1, ftruncate(fd, strlen(input) + 1)); + TEST_ASSERT_EQUAL(errno, EPERM); + + TEST_ASSERT_EQUAL(-1, ftruncate(fd, -1)); + TEST_ASSERT_EQUAL(errno, EINVAL); + } // Truncating should succeed const char truncated_1[] = "ABCDEFGHIJ"; truncated_len = strlen(truncated_1); TEST_ASSERT_EQUAL(0, ftruncate(fd, truncated_len)); + + fstat(fd, &st); + size = st.st_size; + TEST_ASSERT_EQUAL(truncated_len, size); + TEST_ASSERT_EQUAL(0, close(fd)); // open file for reading and validate the content @@ -367,25 +444,35 @@ void test_fatfs_ftruncate_file(const char* filename) // further truncate the file fd = open(filename, O_WRONLY); TEST_ASSERT_NOT_EQUAL(-1, fd); - // Once truncated, the new file size should be the basis - // whether truncation should succeed or not - TEST_ASSERT_EQUAL(-1, ftruncate(fd, truncated_len + 1)); - TEST_ASSERT_EQUAL(EPERM, errno); - TEST_ASSERT_EQUAL(-1, ftruncate(fd, strlen(input))); - TEST_ASSERT_EQUAL(EPERM, errno); + if (allow_expanding_files) { + TEST_ASSERT_EQUAL(0, ftruncate(fd, truncated_len + 1)); + } else { + // Once truncated, the new file size should be the basis + // whether truncation should succeed or not when `allow_expanding_files == false` + TEST_ASSERT_EQUAL(-1, ftruncate(fd, truncated_len + 1)); + TEST_ASSERT_EQUAL(EPERM, errno); - TEST_ASSERT_EQUAL(-1, ftruncate(fd, strlen(input) + 1)); - TEST_ASSERT_EQUAL(EPERM, errno); + TEST_ASSERT_EQUAL(-1, ftruncate(fd, strlen(input))); + TEST_ASSERT_EQUAL(EPERM, errno); - TEST_ASSERT_EQUAL(-1, ftruncate(fd, -1)); - TEST_ASSERT_EQUAL(EINVAL, errno); + TEST_ASSERT_EQUAL(-1, ftruncate(fd, strlen(input) + 1)); + TEST_ASSERT_EQUAL(EPERM, errno); + + TEST_ASSERT_EQUAL(-1, ftruncate(fd, -1)); + TEST_ASSERT_EQUAL(EINVAL, errno); + } // Truncating a truncated file should succeed const char truncated_2[] = "ABCDE"; truncated_len = strlen(truncated_2); TEST_ASSERT_EQUAL(0, ftruncate(fd, truncated_len)); + + fstat(fd, &st); + size = st.st_size; + TEST_ASSERT_EQUAL(truncated_len, size); + TEST_ASSERT_EQUAL(0, close(fd)); // open file for reading and validate the content @@ -556,7 +643,7 @@ void test_fatfs_utime(const char* filename, const char* root_dir) TEST_ASSERT_EQUAL(0, stat(filename, &achieved_stat)); TEST_ASSERT_EQUAL_UINT32(desired_time.modtime, achieved_stat.st_mtime); - //WARNING: it has the Unix Millenium bug (Y2K38) + //WARNING: it has the Unix Millennium bug (Y2K38) // 00:00:00. January 1st, 1970 - FATFS cannot handle years before 1980 desired_tm.tm_mon = 1 - 1; @@ -670,6 +757,65 @@ void test_fatfs_can_opendir(const char* path) unlink(name_dir_file); } +void test_fatfs_readdir_stat(const char* dir_prefix) +{ + char name_dir_file[64]; + char name_dir_stat[64]; + int file_num = 25; + + rmdir(dir_prefix); + TEST_ASSERT_EQUAL(0, mkdir(dir_prefix, 0755)); + + for(int i=0;id_name), "%s/%s", dir_prefix, de->d_name); + TEST_ASSERT_EQUAL(0, stat(name_dir_stat, &st)); + dir_size += st.st_size; + } + TEST_ASSERT_EQUAL(0, closedir(dir)); + int64_t end = esp_timer_get_time(); + int64_t total_time_readdir = end-start; + printf("Time in us for calculating directory size by calling readdir first and then stat func: %lld \n",total_time_readdir); + printf("Size of the directory %s is %"PRIu32"bytes\n", dir_prefix, dir_size); + TEST_ASSERT_EQUAL(file_num*14, dir_size); //each file size is 14 bytes + + // Call stat function directly and record the time needed to calculate the directory size + dir_size = 0; + start = esp_timer_get_time(); + for(int i=0;i -#include - -#include "ff.h" -#include "esp_partition.h" -#include "wear_levelling.h" -#include "diskio_impl.h" -#include "diskio_wl.h" - -#include "catch.hpp" - -extern "C" void _spi_flash_init(const char* chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin); - -TEST_CASE("create volume, open file, write and read back data", "[fatfs]") -{ - _spi_flash_init(CONFIG_ESPTOOLPY_FLASHSIZE, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin"); - - FRESULT fr_result; - BYTE pdrv; - FATFS fs; - FIL file; - UINT bw; - - esp_err_t esp_result; - - const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, "storage"); - - // Mount wear-levelled partition - wl_handle_t wl_handle; - esp_result = wl_mount(partition, &wl_handle); - REQUIRE(esp_result == ESP_OK); - - // Get a physical drive - esp_result = ff_diskio_get_drive(&pdrv); - REQUIRE(esp_result == ESP_OK); - - // Register physical drive as wear-levelled partition - esp_result = ff_diskio_register_wl_partition(pdrv, wl_handle); - - // Create FAT volume on the entire disk - LBA_t part_list[] = {100, 0, 0, 0}; - BYTE work_area[FF_MAX_SS]; - - fr_result = f_fdisk(pdrv, part_list, work_area); - REQUIRE(fr_result == FR_OK); - const MKFS_PARM opt = {(BYTE)FM_ANY, 0, 0, 0, 0}; - fr_result = f_mkfs("", &opt, work_area, sizeof(work_area)); // Use default volume - - // Mount the volume - fr_result = f_mount(&fs, "", 0); - REQUIRE(fr_result == FR_OK); - - // Open, write and read data - fr_result = f_open(&file, "test.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE); - REQUIRE(fr_result == FR_OK); - - // Generate data - uint32_t data_size = 100000; - - char *data = (char*) malloc(data_size); - char *read = (char*) malloc(data_size); - - for(uint32_t i = 0; i < data_size; i += sizeof(i)) - { - *((uint32_t*)(data + i)) = i; - } - - // Write generated data - fr_result = f_write(&file, data, data_size, &bw); - REQUIRE(fr_result == FR_OK); - REQUIRE(bw == data_size); - - // Move to beginning of file - fr_result = f_lseek(&file, 0); - REQUIRE(fr_result == FR_OK); - - // Read written data - fr_result = f_read(&file, read, data_size, &bw); - REQUIRE(fr_result == FR_OK); - REQUIRE(bw == data_size); - - REQUIRE(memcmp(data, read, data_size) == 0); - - // Close file - fr_result = f_close(&file); - REQUIRE(fr_result == FR_OK); - - // Unmount default volume - fr_result = f_mount(0, "", 0); - REQUIRE(fr_result == FR_OK); - - free(read); - free(data); -} diff --git a/lib/fatfs/test_fatfsgen/test_fatfsgen.py b/lib/fatfs/test_fatfsgen/test_fatfsgen.py index 5816991c..0e73ec29 100755 --- a/lib/fatfs/test_fatfsgen/test_fatfsgen.py +++ b/lib/fatfs/test_fatfsgen/test_fatfsgen.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import os @@ -39,7 +39,17 @@ class FatFSGen(unittest.TestCase): os.remove('fatfs_image.img') def test_empty_file_sn_fat12(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) + fatfs.create_file('TESTFILE') + + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + + self.assertEqual(file_system[0x3000:0x300c], b'TESTFILE \x20') # check entry name and type + self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat + + def test_empty_file_sn_fat12_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs.create_file('TESTFILE') fatfs.write_filesystem(CFG['output_file']) @@ -49,7 +59,18 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat def test_directory_sn_fat12(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) + fatfs.create_directory('TESTFOLD') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + + self.assertEqual(file_system[0x3000:0x300c], b'TESTFOLD \x10') # check entry name and type + self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat + self.assertEqual(file_system[0x7000:0x700c], b'. \x10') # reference to itself + self.assertEqual(file_system[0x7020:0x702c], b'.. \x10') # reference to parent + + def test_directory_sn_fat12_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs.create_directory('TESTFOLD') fatfs.write_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file']) @@ -60,7 +81,15 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x6020:0x602c], b'.. \x10') # reference to parent def test_empty_file_with_extension_sn_fat12(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) + fatfs.create_file('TESTF', extension='TXT') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x3000:0x300c], b'TESTF TXT\x20') # check entry name and type + self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat + + def test_empty_file_with_extension_sn_fat12_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs.create_file('TESTF', extension='TXT') fatfs.write_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file']) @@ -68,7 +97,19 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat def test_write_to_file_with_extension_sn_fat12(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) + fatfs.create_file('WRITEF', extension='TXT') + fatfs.write_content(path_from_root=['WRITEF.TXT'], content=b'testcontent') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + + self.assertEqual(file_system[0x3000:0x300c], b'WRITEF TXT\x20') # check entry name and type + self.assertEqual(file_system[0x301a:0x3020], b'\x02\x00\x0b\x00\x00\x00') # check size and cluster ref + self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat + self.assertEqual(file_system[0x7000:0x700f], b'testcontent\x00\x00\x00\x00') # check file content + + def test_write_to_file_with_extension_sn_fat12_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs.create_file('WRITEF', extension='TXT') fatfs.write_content(path_from_root=['WRITEF.TXT'], content=b'testcontent') fatfs.write_filesystem(CFG['output_file']) @@ -80,7 +121,23 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x6000:0x600f], b'testcontent\x00\x00\x00\x00') # check file content def test_write_to_file_in_folder_sn_fat12(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) + fatfs.create_directory('TESTFOLD') + fatfs.create_file('WRITEF', extension='TXT', path_from_root=['TESTFOLD']) + fatfs.write_content(path_from_root=['TESTFOLD', 'WRITEF.TXT'], content=b'testcontent') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + + self.assertEqual(file_system[0x3000:0x300c], b'TESTFOLD \x10') + self.assertEqual( + file_system[0x1000:0x1010], + b'\xf8\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x7040:0x7050], b'WRITEF TXT\x20\x00\x00\x00\x00') + self.assertEqual(file_system[0x705a:0x7060], b'\x03\x00\x0b\x00\x00\x00') + self.assertEqual(file_system[0x8000:0x800b], b'testcontent') # check file content + + def test_write_to_file_in_folder_sn_fat12_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs.create_directory('TESTFOLD') fatfs.create_file('WRITEF', extension='TXT', path_from_root=['TESTFOLD']) fatfs.write_content(path_from_root=['TESTFOLD', 'WRITEF.TXT'], content=b'testcontent') @@ -96,7 +153,7 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x7000:0x700b], b'testcontent') # check file content def test_cluster_setting_values(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) fatfs.create_file('TESTFIL1') fatfs.create_file('TESTFIL2') fatfs.create_file('TESTFIL3') @@ -112,7 +169,16 @@ class FatFSGen(unittest.TestCase): b'\xf8\xff\xff\xe8\x43\x00\x05\xf0\xff\xff\x0f\x00\x00\x00\x00\x00') def test_full_sector_file(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) + fatfs.create_file('WRITEF', extension='TXT') + fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x1000: 0x100e], b'\xf8\xff\xff\xff\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x7000: 0x8000], CFG['sector_size'] * b'a') + + def test_full_sector_file_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs.create_file('WRITEF', extension='TXT') fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a') fatfs.write_filesystem(CFG['output_file']) @@ -121,7 +187,16 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x6000: 0x7000], CFG['sector_size'] * b'a') def test_file_chaining(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) + fatfs.create_file('WRITEF', extension='TXT') + fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x1000: 0x100e], b'\xf8\xff\xff\x03\xf0\xff\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x8000: 0x9000], b'a' + (CFG['sector_size'] - 1) * b'\x00') + + def test_file_chaining_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs.create_file('WRITEF', extension='TXT') fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a') fatfs.write_filesystem(CFG['output_file']) @@ -130,7 +205,22 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x7000: 0x8000], b'a' + (CFG['sector_size'] - 1) * b'\x00') def test_full_sector_folder(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) + fatfs.create_directory('TESTFOLD') + + fill_sector(fatfs) + fatfs.write_content(path_from_root=['TESTFOLD', 'A0'], content=b'first') + fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x1000: 0x10d0], + b'\xf8\xff\xff\x82\xf0\xff' + 192 * b'\xff' + 10 * b'\x00') + self.assertEqual(file_system[0x86000:0x86005], b'later') + self.assertEqual(file_system[0x87000:0x87010], b'A126 \x00\x00\x00\x00') + self.assertEqual(file_system[0x87020:0x87030], b'A127 \x00\x00\x00\x00') + + def test_full_sector_folder_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs.create_directory('TESTFOLD') fill_sector(fatfs) @@ -145,21 +235,21 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x86020:0x86030], b'A127 \x00\x00\x00\x00') def test_write_to_folder_in_folder_sn_fat12(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) fatfs.create_directory('TESTFOLD') fatfs.create_directory('TESTFOLL', path_from_root=['TESTFOLD']) self.assertRaises(WriteDirectoryException, fatfs.write_content, path_from_root=['TESTFOLD', 'TESTFOLL'], content=b'testcontent') def test_write_non_existing_file_in_folder_sn_fat12(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) fatfs.create_directory('TESTFOLD') self.assertRaises(FileNotFoundError, fatfs.write_content, path_from_root=['TESTFOLD', 'AHOJ'], content=b'testcontent') @staticmethod def create_too_many_files() -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) fatfs.create_directory('TESTFOLD') for i in range(2 * CFG['sector_size'] // CFG['entry_size']): fatfs.create_file(f'A{str(i).upper()}', path_from_root=['TESTFOLD']) @@ -168,7 +258,20 @@ class FatFSGen(unittest.TestCase): self.assertRaises(NoFreeClusterException, self.create_too_many_files) def test_full_two_sectors_folder(self) -> None: - fatfs = fatfsgen.FATFS(size=2 * 1024 * 1024) + fatfs = fatfsgen.FATFS(fat_tables_cnt=2, size=2 * 1024 * 1024) + fatfs.create_directory('TESTFOLD') + + for i in range(2 * CFG['sector_size'] // CFG['entry_size']): + fatfs.create_file(f'A{str(i).upper()}', path_from_root=['TESTFOLD']) + fatfs.write_content(path_from_root=['TESTFOLD', 'A253'], content=b'later') + fatfs.write_content(path_from_root=['TESTFOLD', 'A255'], content=b'last') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x106000:0x106010], b'later\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x109000:0x109010], b'last\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + + def test_full_two_sectors_folder_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1, size=2 * 1024 * 1024) fatfs.create_directory('TESTFOLD') for i in range(2 * CFG['sector_size'] // CFG['entry_size']): @@ -181,26 +284,38 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x108000:0x108010], b'last\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') def test_lower_case_dir_short_names(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) self.assertRaises(LowerCaseException, fatfs.create_directory, 'testfold') def test_lower_case_file_short_names(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) self.assertRaises(LowerCaseException, fatfs.create_file, 'newfile') def test_too_long_name_dir_short_names(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) self.assertRaises(TooLongNameException, fatfs.create_directory, 'TOOLONGNAME') def test_fatfs16_detection(self) -> None: - fatfs = fatfsgen.FATFS(size=16 * 1024 * 1024) + fatfs = fatfsgen.FATFS(fat_tables_cnt=2, size=16 * 1024 * 1024) self.assertEqual(fatfs.state.boot_sector_state.fatfs_type, 16) def test_fatfs32_detection(self) -> None: self.assertRaises(NotImplementedError, fatfsgen.FATFS, size=256 * 1024 * 1024) def test_deep_structure(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) + fatfs.create_directory('TESTFOLD') + fatfs.create_directory('TESTFOLL', path_from_root=['TESTFOLD']) + fatfs.create_directory('TESTFOLO', path_from_root=['TESTFOLD', 'TESTFOLL']) + fatfs.create_file('WRITEF', extension='TXT', path_from_root=['TESTFOLD', 'TESTFOLL', 'TESTFOLO']) + fatfs.write_content(path_from_root=['TESTFOLD', 'TESTFOLL', 'TESTFOLO', 'WRITEF.TXT'], content=b'later') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + + self.assertEqual(file_system[0xa000:0xa010], b'later\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + + def test_deep_structure_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs.create_directory('TESTFOLD') fatfs.create_directory('TESTFOLL', path_from_root=['TESTFOLD']) fatfs.create_directory('TESTFOLO', path_from_root=['TESTFOLD', 'TESTFOLL']) @@ -212,7 +327,26 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x9000:0x9010], b'later\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') def test_same_name_deep_structure(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) + fatfs.create_directory('TESTFOLD') + fatfs.create_directory('TESTFOLD', path_from_root=['TESTFOLD']) + fatfs.create_directory('TESTFOLD', path_from_root=['TESTFOLD', 'TESTFOLD']) + fatfs.create_file('WRITEF', extension='TXT', path_from_root=['TESTFOLD', 'TESTFOLD', 'TESTFOLD']) + fatfs.write_content(path_from_root=['TESTFOLD', 'TESTFOLD', 'TESTFOLD', 'WRITEF.TXT'], content=b'later') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + + self.assertEqual(file_system[0x3000:0x3010], b'TESTFOLD \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x3010:0x3020], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x7040:0x7050], b'TESTFOLD \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x7040:0x7050], b'TESTFOLD \x10\x00\x00\x00\x00') + + self.assertEqual(file_system[0x8040:0x8050], b'TESTFOLD \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x9040:0x9050], b'WRITEF TXT \x00\x00\x00\x00') + self.assertEqual(file_system[0xa000:0xa010], b'later\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + + def test_same_name_deep_structure_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs.create_directory('TESTFOLD') fatfs.create_directory('TESTFOLD', path_from_root=['TESTFOLD']) fatfs.create_directory('TESTFOLD', path_from_root=['TESTFOLD', 'TESTFOLD']) @@ -231,7 +365,19 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x9000:0x9010], b'later\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') def test_e2e_deep_folder_into_image(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) + fatfs.generate(CFG['test_dir']) + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x7060:0x7070], b'TESTFIL2 \x00\x00\x00\x00') + self.assertEqual(file_system[0x7070:0x7080], b'!\x00!\x00\x00\x00\x00\x00!\x00\x05\x00\x0b\x00\x00\x00') + self.assertEqual(file_system[0x8040:0x8050], b'LASTFILE \x00\x00\x00\x00') + self.assertEqual(file_system[0x9000:0x9010], b'deeptest\n\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xa000:0xa010], b'thisistest\n\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xb000:0xb010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + + def test_e2e_deep_folder_into_image_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs.generate(CFG['test_dir']) fatfs.write_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file']) @@ -243,7 +389,22 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0xa000:0xa010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') def test_e2e_deep_folder_into_image_ext(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) + fatfs.generate(CFG['test_dir2']) + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + + self.assertEqual(file_system[0x3020:0x3030], b'TESTFILE \x00\x00\x00\x00') + self.assertEqual(file_system[0x7060:0x7070], b'TESTFIL2 \x00\x00\x00\x00') + self.assertEqual(file_system[0x8000:0x8010], b'. \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x8040:0x8050], b'LASTFILETXT \x00\x00\x00\x00') + self.assertEqual(file_system[0x9000:0x9010], b'deeptest\n\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xa000:0xa010], b'thisistest\n\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xb000:0xb010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xc000:0xc009], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff') + + def test_e2e_deep_folder_into_image_ext_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1) fatfs.generate(CFG['test_dir2']) fatfs.write_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file']) @@ -258,20 +419,29 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0xb000:0xb009], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff') def test_empty_fat16(self) -> None: - fatfs = fatfsgen.FATFS(size=17 * 1024 * 1024) + fatfs = fatfsgen.FATFS(fat_tables_cnt=2, size=17 * 1024 * 1024) fatfs.write_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file']) self.assertEqual(file_system[0x1000:0x1007], b'\xf8\xff\xff\xff\x00\x00\x00') def test_simple_fat16(self) -> None: - fatfs = fatfsgen.FATFS(size=17 * 1024 * 1024) + fatfs = fatfsgen.FATFS(fat_tables_cnt=2, size=17 * 1024 * 1024) fatfs.create_directory('TESTFOLD') fatfs.write_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file']) self.assertEqual(file_system[0x1000:0x1007], b'\xf8\xff\xff\xff\xff\xff\x00') def test_chaining_fat16(self) -> None: - fatfs = fatfsgen.FATFS(size=17 * 1024 * 1024) + fatfs = fatfsgen.FATFS(fat_tables_cnt=2, size=17 * 1024 * 1024) + fatfs.create_file('WRITEF', extension='TXT') + fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x1000: 0x100e], b'\xf8\xff\xff\xff\x03\x00\xff\xff\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xc000: 0xd000], b'a' + (CFG['sector_size'] - 1) * b'\x00') + + def test_chaining_fat16_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1, size=17 * 1024 * 1024) fatfs.create_file('WRITEF', extension='TXT') fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a') fatfs.write_filesystem(CFG['output_file']) @@ -280,7 +450,22 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x9000: 0xa000], b'a' + (CFG['sector_size'] - 1) * b'\x00') def test_full_sector_folder_fat16(self) -> None: - fatfs = fatfsgen.FATFS(size=17 * 1024 * 1024) + fatfs = fatfsgen.FATFS(fat_tables_cnt=2, size=17 * 1024 * 1024) + fatfs.create_directory('TESTFOLD') + + fill_sector(fatfs) + fatfs.write_content(path_from_root=['TESTFOLD', 'A0'], content=b'first') + fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x1000: 0x1110], + b'\xf8\xff\xff\xff\x82\x00' + 258 * b'\xff' + 8 * b'\x00') + self.assertEqual(file_system[0x8a000:0x8a005], b'later') + self.assertEqual(file_system[0x8b000:0x8b010], b'A126 \x00\x00\x00\x00') + self.assertEqual(file_system[0x8b020:0x8b030], b'A127 \x00\x00\x00\x00') + + def test_full_sector_folder_fat16_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1, size=17 * 1024 * 1024) fatfs.create_directory('TESTFOLD') fill_sector(fatfs) @@ -295,14 +480,31 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x88020:0x88030], b'A127 \x00\x00\x00\x00') def test_empty_lfn_short_name(self) -> None: - fatfs = fatfsgen.FATFS(long_names_enabled=True) + fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) + fatfs.create_file('HELLO', extension='TXT') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x3000: 0x3019], b'HELLO TXT \x18\x00\x00\x00!\x00!\x00\x00\x00\x00\x00!') + + def test_empty_lfn_short_name_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs.create_file('HELLO', extension='TXT') fatfs.write_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file']) self.assertEqual(file_system[0x2000: 0x2019], b'HELLO TXT \x18\x00\x00\x00!\x00!\x00\x00\x00\x00\x00!') def test_lfn_short_name(self) -> None: - fatfs = fatfsgen.FATFS(long_names_enabled=True) + fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) + fatfs.create_file('HELLO', extension='TXT') + fatfs.write_content(path_from_root=['HELLO.TXT'], content=b'this is a test') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x3000: 0x3010], b'HELLO TXT \x18\x00\x00\x00') + self.assertEqual(file_system[0x3010: 0x3020], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x0e\x00\x00\x00') + self.assertEqual(file_system[0x7000: 0x7010], b'this is a test\x00\x00') + + def test_lfn_short_name_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs.create_file('HELLO', extension='TXT') fatfs.write_content(path_from_root=['HELLO.TXT'], content=b'this is a test') fatfs.write_filesystem(CFG['output_file']) @@ -312,7 +514,19 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x6000: 0x6010], b'this is a test\x00\x00') def test_lfn_empty_name(self) -> None: - fatfs = fatfsgen.FATFS(long_names_enabled=True) + fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) + fatfs.create_file('HELLOHELLOHELLO', extension='TXT') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x3000: 0x3010], b'Bl\x00o\x00.\x00t\x00x\x00\x0f\x00\xadt\x00') + self.assertEqual(file_system[0x3012: 0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') + self.assertEqual(file_system[0x3020: 0x3030], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\xadh\x00') + self.assertEqual(file_system[0x3030: 0x3040], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00') + self.assertEqual(file_system[0x3040: 0x3050], b'HELLOH~\x01TXT \x00\x00\x00\x00') + self.assertEqual(file_system[0x3050: 0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') + + def test_lfn_empty_name_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs.create_file('HELLOHELLOHELLO', extension='TXT') fatfs.write_filesystem(CFG['output_file']) file_system = read_filesystem(CFG['output_file']) @@ -324,7 +538,21 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x2050: 0x2060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') def test_lfn_plain_name(self) -> None: - fatfs = fatfsgen.FATFS(long_names_enabled=True) + fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) + fatfs.create_file('HELLOHELLOHELLO', extension='TXT') + fatfs.write_content(path_from_root=['HELLOHELLOHELLO.TXT'], content=b'this is a test') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x3000: 0x3010], b'Bl\x00o\x00.\x00t\x00x\x00\x0f\x00\xadt\x00') + self.assertEqual(file_system[0x3012: 0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') + self.assertEqual(file_system[0x3020: 0x3030], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\xadh\x00') + self.assertEqual(file_system[0x3030: 0x3040], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00') + self.assertEqual(file_system[0x3040: 0x3050], b'HELLOH~\x01TXT \x00\x00\x00\x00') + self.assertEqual(file_system[0x3050: 0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x0e\x00\x00\x00') + self.assertEqual(file_system[0x7000: 0x7010], b'this is a test\x00\x00') + + def test_lfn_plain_name_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs.create_file('HELLOHELLOHELLO', extension='TXT') fatfs.write_content(path_from_root=['HELLOHELLOHELLO.TXT'], content=b'this is a test') fatfs.write_filesystem(CFG['output_file']) @@ -338,7 +566,21 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x6000: 0x6010], b'this is a test\x00\x00') def test_lfn_plain_name_no_ext(self) -> None: - fatfs = fatfsgen.FATFS(long_names_enabled=True) + fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) + fatfs.create_file('HELLOHELLOHELLO') + fatfs.write_content(path_from_root=['HELLOHELLOHELLO'], content=b'this is a test') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x3000: 0x3010], b'Bl\x00o\x00\x00\x00\xff\xff\xff\xff\x0f\x00P\xff\xff') + self.assertEqual(file_system[0x3012: 0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') + self.assertEqual(file_system[0x3020: 0x3030], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00Ph\x00') + self.assertEqual(file_system[0x3030: 0x3040], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00') + self.assertEqual(file_system[0x3040: 0x3050], b'HELLOH~\x01 \x00\x00\x00\x00') + self.assertEqual(file_system[0x3050: 0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x0e\x00\x00\x00') + self.assertEqual(file_system[0x7000: 0x7010], b'this is a test\x00\x00') + + def test_lfn_plain_name_no_ext_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs.create_file('HELLOHELLOHELLO') fatfs.write_content(path_from_root=['HELLOHELLOHELLO'], content=b'this is a test') fatfs.write_filesystem(CFG['output_file']) @@ -352,11 +594,31 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x6000: 0x6010], b'this is a test\x00\x00') def test_lfn_short_entry_exception(self) -> None: - fatfs = fatfsgen.FATFS(long_names_enabled=True) + fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) self.assertRaises(LowerCaseException, fatfs.create_file, 'hello', extension='txt') def test_lfn_nested_empty(self) -> None: - fatfs = fatfsgen.FATFS(long_names_enabled=True) + fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) + fatfs.create_directory('VERYLONGTESTFOLD') + fatfs.create_file('HELLO', extension='TXT', path_from_root=['VERYLONGTESTFOLD']) + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x3000: 0x3010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\xa0\xff\xff') + self.assertEqual(file_system[0x3012: 0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') + self.assertEqual(file_system[0x3020: 0x3030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\xa0o\x00') + self.assertEqual(file_system[0x3030: 0x3040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00') + self.assertEqual(file_system[0x3040: 0x3050], b'VERYLO~\x01 \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x3050: 0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') + + self.assertEqual(file_system[0x7000: 0x7010], b'. \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x7012: 0x7020], b'!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x7020: 0x7030], b'.. \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x7030: 0x7040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x7040: 0x7050], b'HELLO TXT \x18\x00\x00\x00') + self.assertEqual(file_system[0x7050: 0x7060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x00\x00\x00\x00') + + def test_lfn_nested_empty_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs.create_directory('VERYLONGTESTFOLD') fatfs.create_file('HELLO', extension='TXT', path_from_root=['VERYLONGTESTFOLD']) fatfs.write_filesystem(CFG['output_file']) @@ -376,7 +638,29 @@ class FatFSGen(unittest.TestCase): self.assertEqual(file_system[0x6050: 0x6060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x00\x00\x00\x00') def test_lfn_nested_long_empty(self) -> None: - fatfs: fatfsgen.FATFS = fatfsgen.FATFS(long_names_enabled=True) + fatfs: fatfsgen.fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) + fatfs.create_directory('verylongtestfold') + fatfs.create_file('hellohellohello', extension='txt', path_from_root=['verylongtestfold']) + fatfs.write_filesystem(CFG['output_file']) + + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x3000: 0x3010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\n\xff\xff') + self.assertEqual(file_system[0x3012: 0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') + self.assertEqual(file_system[0x3020: 0x3030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\no\x00') + self.assertEqual(file_system[0x3030: 0x3040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00') + self.assertEqual(file_system[0x3040: 0x3050], b'verylo~\x01 \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x3050: 0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') + + self.assertEqual(file_system[0x7000: 0x7010], b'. \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x7012: 0x7020], b'!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x7020: 0x7030], b'.. \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x7030: 0x7040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x7040: 0x7050], b'Bl\x00o\x00.\x00t\x00x\x00\x0f\x00\xcft\x00') + self.assertEqual(file_system[0x7050: 0x7060], + b'\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') + + def test_lfn_nested_long_empty_one_fat(self) -> None: + fatfs: fatfsgen.FATFS = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs.create_directory('verylongtestfold') fatfs.create_file('hellohellohello', extension='txt', path_from_root=['verylongtestfold']) fatfs.write_filesystem(CFG['output_file']) @@ -398,7 +682,30 @@ class FatFSGen(unittest.TestCase): b'\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') def test_lfn_nested_text(self) -> None: - fatfs: fatfsgen.FATFS = fatfsgen.FATFS(long_names_enabled=True) + fatfs: fatfsgen.fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) + fatfs.create_directory('VERYLONGTESTFOLD') + fatfs.create_file('HELLO', extension='TXT', path_from_root=['VERYLONGTESTFOLD']) + fatfs.write_content(path_from_root=['VERYLONGTESTFOLD', 'HELLO.TXT'], content=b'this is a test') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + self.assertEqual(file_system[0x3000: 0x3010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\xa0\xff\xff') + self.assertEqual(file_system[0x3012: 0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') + self.assertEqual(file_system[0x3020: 0x3030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\xa0o\x00') + self.assertEqual(file_system[0x3030: 0x3040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00') + self.assertEqual(file_system[0x3040: 0x3050], b'VERYLO~\x01 \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x3050: 0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') + + self.assertEqual(file_system[0x7000: 0x7010], b'. \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x7012: 0x7020], b'!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x7020: 0x7030], b'.. \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x7030: 0x7040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x7040: 0x7050], b'HELLO TXT \x18\x00\x00\x00') + self.assertEqual(file_system[0x7050: 0x7060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x0e\x00\x00\x00') + + self.assertEqual(file_system[0x8000: 0x8010], b'this is a test\x00\x00') + + def test_lfn_nested_text_one_fat(self) -> None: + fatfs: fatfsgen.FATFS = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs.create_directory('VERYLONGTESTFOLD') fatfs.create_file('HELLO', extension='TXT', path_from_root=['VERYLONGTESTFOLD']) fatfs.write_content(path_from_root=['VERYLONGTESTFOLD', 'HELLO.TXT'], content=b'this is a test') @@ -441,7 +748,45 @@ class FatFSGen(unittest.TestCase): self.assertRaises(InconsistentFATAttributes, fatfsgen.FATFS, size=20480000, explicit_fat_type=FAT12) def test_lfn_increasing(self) -> None: - fatfs: fatfsgen.FATFS = fatfsgen.FATFS(long_names_enabled=True) + fatfs: fatfsgen.fatfs = fatfsgen.FATFS(fat_tables_cnt=2, long_names_enabled=True) + fatfs.create_directory('VERYLONGTESTFOLD') + fatfs.create_file('HELLOHELLOHELLOOOOOOO', extension='TXT', path_from_root=['VERYLONGTESTFOLD']) + fatfs.create_file('HELLOHELLOHELLOOOOOOB', extension='TXT', path_from_root=['VERYLONGTESTFOLD']) + fatfs.write_content(path_from_root=['VERYLONGTESTFOLD', 'HELLOHELLOHELLOOOOOOO.TXT'], + content=b'this is a test A') + fatfs.write_content(path_from_root=['VERYLONGTESTFOLD', 'HELLOHELLOHELLOOOOOOB.TXT'], + content=b'this is a test B') + fatfs.write_filesystem(CFG['output_file']) + file_system = read_filesystem(CFG['output_file']) + + self.assertEqual(file_system[0x3000: 0x3010], b'Bo\x00l\x00d\x00\x00\x00\xff\xff\x0f\x00\xa0\xff\xff') + self.assertEqual(file_system[0x3011: 0x3020], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff') + self.assertEqual(file_system[0x3020: 0x3030], b'\x01v\x00e\x00r\x00y\x00l\x00\x0f\x00\xa0o\x00') + self.assertEqual(file_system[0x3030: 0x3040], b'n\x00g\x00t\x00e\x00s\x00\x00\x00t\x00f\x00') + self.assertEqual(file_system[0x3040: 0x3050], b'VERYLO~\x01 \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x3050: 0x3060], b'!\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') + + self.assertEqual(file_system[0x7000: 0x7010], b'. \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x7011: 0x7020], b'\x00!\x00\x00\x00\x00\x00!\x00\x02\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x7020: 0x7030], b'.. \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x7030: 0x7040], b'!\x00!\x00\x00\x00\x00\x00!\x00\x01\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x7040: 0x7050], b'Bl\x00o\x00o\x00o\x00o\x00\x0f\x00\xado\x00') + self.assertEqual(file_system[0x7050: 0x7060], b'o\x00o\x00.\x00t\x00x\x00\x00\x00t\x00\x00\x00') + + self.assertEqual(file_system[0x7050: 0x7060], b'o\x00o\x00.\x00t\x00x\x00\x00\x00t\x00\x00\x00') + self.assertEqual(file_system[0x7060: 0x7070], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\xadh\x00') + self.assertEqual(file_system[0x7070: 0x7080], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00') + self.assertEqual(file_system[0x7080: 0x7090], b'HELLOH~\x01TXT \x00\x00\x00\x00') + self.assertEqual(file_system[0x7090: 0x70a0], b'!\x00!\x00\x00\x00\x00\x00!\x00\x03\x00\x10\x00\x00\x00') + self.assertEqual(file_system[0x70a0: 0x70b0], b'Bl\x00o\x00o\x00o\x00o\x00\x0f\x00\x8do\x00') + + self.assertEqual(file_system[0x70b0: 0x70c0], b'o\x00b\x00.\x00t\x00x\x00\x00\x00t\x00\x00\x00') + self.assertEqual(file_system[0x70c0: 0x70d0], b'\x01h\x00e\x00l\x00l\x00o\x00\x0f\x00\x8dh\x00') + self.assertEqual(file_system[0x70d0: 0x70e0], b'e\x00l\x00l\x00o\x00h\x00\x00\x00e\x00l\x00') + self.assertEqual(file_system[0x70e0: 0x70f0], b'HELLOH~\x02TXT \x00\x00\x00\x00') + + def test_lfn_increasing_one_fat(self) -> None: + fatfs: fatfsgen.FATFS = fatfsgen.FATFS(fat_tables_cnt=1, long_names_enabled=True) fatfs.create_directory('VERYLONGTESTFOLD') fatfs.create_file('HELLOHELLOHELLOOOOOOO', extension='TXT', path_from_root=['VERYLONGTESTFOLD']) fatfs.create_file('HELLOHELLOHELLOOOOOOB', extension='TXT', path_from_root=['VERYLONGTESTFOLD']) @@ -484,7 +829,21 @@ class FatFSGen(unittest.TestCase): self.assertRaises(NotInitialized, lambda: BootSector().binary_image) # encapsulate property to callable def test_bs_str(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) + bs = BootSector(fatfs.state.boot_sector_state) + bs.generate_boot_sector() + bs.parse_boot_sector(bs.binary_image) + x = 'FATFS properties:,clusters: 251,data_region_start: 28672,data_sectors: ' \ + '249,entries_root_count: 512,fat_table_start_address: 4096,fat_tables_cnt: 2,' \ + 'fatfs_type: 12,file_sys_type: FAT ,hidden_sectors: 0,media_type: 248,' \ + 'non_data_sectors: 7,num_heads: 255,oem_name: MSDOS5.0,reserved_sectors_cnt: 1,' \ + 'root_dir_sectors_cnt: 4,root_directory_start: 12288,sec_per_track: 63,sector_size: 4096,' \ + 'sectors_count: 256,sectors_per_cluster: 1,sectors_per_fat_cnt: 1,size: 1048576,' \ + 'volume_label: Espressif ,volume_uuid: 1144419653,' + self.assertEqual(x.split(',')[:-2], str(bs).split('\n')[:-2]) # except for volume id + + def test_bs_str_one_fat(self) -> None: + fatfs = fatfsgen.FATFS(fat_tables_cnt=1) bs = BootSector(fatfs.state.boot_sector_state) bs.generate_boot_sector() bs.parse_boot_sector(bs.binary_image) @@ -508,19 +867,19 @@ class FatFSGen(unittest.TestCase): 2) def test_get_cluster_value_from_fat(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) self.assertEqual(fatfs.fat.get_cluster_value(1), 0xFFF) def test_is_cluster_last(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) self.assertEqual(fatfs.fat.is_cluster_last(2), False) def test_chain_in_fat(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) self.assertEqual(fatfs.fat.get_chained_content(1), b'\x00' * 0x1000) def test_retrieve_file_chaining(self) -> None: - fatfs = fatfsgen.FATFS() + fatfs = fatfsgen.FATFS(fat_tables_cnt=2) fatfs.create_file('WRITEF', extension='TXT') fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a') fatfs.write_filesystem(CFG['output_file']) diff --git a/lib/fatfs/test_fatfsgen/test_fatfsparse.py b/lib/fatfs/test_fatfsgen/test_fatfsparse.py index 15a7f3d8..43d62eb5 100755 --- a/lib/fatfs/test_fatfsgen/test_fatfsparse.py +++ b/lib/fatfs/test_fatfsgen/test_fatfsparse.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import os @@ -32,13 +32,13 @@ class FatFSGen(unittest.TestCase): @staticmethod def test_gen_parse() -> None: run([ - 'python', + sys.executable, f'{os.path.join(os.path.dirname(__file__), "..", "fatfsgen.py")}', 'output_data/tst_str' ], stderr=STDOUT) - run(['python', '../fatfsgen.py', 'output_data/tst_str'], stderr=STDOUT) - run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) + run([sys.executable, '../fatfsgen.py', 'output_data/tst_str'], stderr=STDOUT) + run([sys.executable, '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) assert set(os.listdir('Espressif')) == {'TEST', 'TESTFILE'} with open('Espressif/TESTFILE', 'rb') as in_: @@ -59,7 +59,7 @@ class FatFSGen(unittest.TestCase): fatfs.write_content(path_from_root=['WRITEF.TXT'], content=4096 * b'a' + b'a') fatfs.write_filesystem('fatfs_image.img') - run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) + run([sys.executable, '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) with open('Espressif/WRITEF.TXT', 'rb') as in_: assert in_.read() == 4097 * b'a' @@ -74,7 +74,7 @@ class FatFSGen(unittest.TestCase): fatfs.write_content(path_from_root=['TESTFOLD', 'A255'], content=b'last') fatfs.write_filesystem('fatfs_image.img') - run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) + run([sys.executable, '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) assert set(os.listdir('Espressif')) == {'TESTFOLD'} assert set(os.listdir('Espressif/TESTFOLD')) == {f'A{str(i).upper()}' for i in range(256)} @@ -88,7 +88,7 @@ class FatFSGen(unittest.TestCase): def test_empty_fat16() -> None: fatfs = fatfsgen.FATFS(size=17 * 1024 * 1024) fatfs.write_filesystem('fatfs_image.img') - run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) + run([sys.executable, '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) @staticmethod def test_chaining_fat16() -> None: @@ -96,7 +96,7 @@ class FatFSGen(unittest.TestCase): fatfs.create_file('WRITEF', extension='TXT') fatfs.write_content(path_from_root=['WRITEF.TXT'], content=4096 * b'a' + b'a') fatfs.write_filesystem('fatfs_image.img') - run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) + run([sys.executable, '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) with open('Espressif/WRITEF.TXT', 'rb') as in_: assert in_.read() == 4097 * b'a' @@ -109,7 +109,7 @@ class FatFSGen(unittest.TestCase): fatfs.write_content(path_from_root=['TESTFOLD', 'A0'], content=b'first') fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later') fatfs.write_filesystem('fatfs_image.img') - run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) + run([sys.executable, '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) assert set(os.listdir('Espressif')) == {'TESTFOLD'} assert set(os.listdir('Espressif/TESTFOLD')) == {f'A{str(i).upper()}' for i in range(128)} with open('Espressif/TESTFOLD/A0', 'rb') as in_: @@ -134,20 +134,20 @@ class FatFSGen(unittest.TestCase): } generate_local_folder_structure(struct_, path_='.') run([ - 'python', + sys.executable, f'{os.path.join(os.path.dirname(__file__), "..", "fatfsgen.py")}', 'testf' ], stderr=STDOUT) - run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) + run([sys.executable, '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) assert compare_folders('testf', 'Espressif') shutil.rmtree('Espressif', ignore_errors=True) run([ - 'python', + sys.executable, f'{os.path.join(os.path.dirname(__file__), "..", "wl_fatfsgen.py")}', 'testf' ], stderr=STDOUT) - run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) + run([sys.executable, '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) assert compare_folders('testf', 'Espressif') def test_e2e_deeper(self) -> None: @@ -173,20 +173,20 @@ class FatFSGen(unittest.TestCase): generate_local_folder_structure(struct_, path_='.') run([ - 'python', + sys.executable, f'{os.path.join(os.path.dirname(__file__), "..", "fatfsgen.py")}', 'testf' ], stderr=STDOUT) - run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) + run([sys.executable, '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) assert compare_folders('testf', 'Espressif') shutil.rmtree('Espressif', ignore_errors=True) run([ - 'python', + sys.executable, f'{os.path.join(os.path.dirname(__file__), "..", "wl_fatfsgen.py")}', 'testf' ], stderr=STDOUT) - run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) + run([sys.executable, '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) assert compare_folders('testf', 'Espressif') def test_e2e_deeper_large(self) -> None: @@ -229,20 +229,20 @@ class FatFSGen(unittest.TestCase): } generate_local_folder_structure(struct_, path_='.') run([ - 'python', + sys.executable, f'{os.path.join(os.path.dirname(__file__), "..", "fatfsgen.py")}', 'testf' ], stderr=STDOUT) - run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) + run([sys.executable, '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) assert compare_folders('testf', 'Espressif') shutil.rmtree('Espressif', ignore_errors=True) run([ - 'python', + sys.executable, f'{os.path.join(os.path.dirname(__file__), "..", "wl_fatfsgen.py")}', 'testf' ], stderr=STDOUT) - run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) + run([sys.executable, '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) assert compare_folders('testf', 'Espressif') def test_e2e_very_deep(self) -> None: @@ -287,11 +287,11 @@ class FatFSGen(unittest.TestCase): } generate_local_folder_structure(struct_, path_='.') run([ - 'python', + sys.executable, f'{os.path.join(os.path.dirname(__file__), "..", "fatfsgen.py")}', 'testf' ], stderr=STDOUT) - run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) + run([sys.executable, '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) assert compare_folders('testf', 'Espressif') def test_e2e_very_deep_long(self) -> None: @@ -317,11 +317,11 @@ class FatFSGen(unittest.TestCase): } generate_local_folder_structure(struct_, path_='.') run([ - 'python', + sys.executable, f'{os.path.join(os.path.dirname(__file__), "..", "fatfsgen.py")}', 'testf', '--long_name_support' ], stderr=STDOUT) - run(['python', '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) + run([sys.executable, '../fatfsparse.py', 'fatfs_image.img'], stderr=STDOUT) assert compare_folders('testf', 'Espressif') def test_parse_long_name(self) -> None: diff --git a/lib/fatfs/test_fatfsgen/test_wl_fatfsgen.py b/lib/fatfs/test_fatfsgen/test_wl_fatfsgen.py index 2b3e28c7..3179441d 100755 --- a/lib/fatfs/test_fatfsgen/test_wl_fatfsgen.py +++ b/lib/fatfs/test_fatfsgen/test_wl_fatfsgen.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import os @@ -7,7 +7,7 @@ import shutil import sys import unittest -from test_utils import CFG, generate_test_dir_1, generate_test_dir_2 +from test_utils import CFG, fill_sector, generate_test_dir_1, generate_test_dir_2 sys.path.append(os.path.join(os.path.dirname(__file__), '..')) import wl_fatfsgen # noqa E402 # pylint: disable=C0413 @@ -24,7 +24,18 @@ class WLFatFSGen(unittest.TestCase): shutil.rmtree('output_data') def test_empty_file_sn_fat12(self) -> None: - fatfs = wl_fatfsgen.WLFATFS() + fatfs = wl_fatfsgen.WLFATFS(fat_tables_cnt=2) + fatfs.plain_fatfs.create_file('TESTFILE') + fatfs.init_wl() + fatfs.wl_write_filesystem(CFG['output_file']) + with open(CFG['output_file'], 'rb') as fs_file: + file_system = fs_file.read() + + self.assertEqual(file_system[0x4000:0x400c], b'TESTFILE \x20') # check entry name and type + self.assertEqual(file_system[0x3000:0x3006], b'\xf8\xff\xff\xff\x0f\x00') # check fat + + def test_empty_file_sn_fat12_one_fat(self) -> None: + fatfs = wl_fatfsgen.WLFATFS(fat_tables_cnt=1) fatfs.plain_fatfs.create_file('TESTFILE') fatfs.init_wl() fatfs.wl_write_filesystem(CFG['output_file']) @@ -35,7 +46,44 @@ class WLFatFSGen(unittest.TestCase): self.assertEqual(file_system[0x2000:0x2006], b'\xf8\xff\xff\xff\x0f\x00') # check fat def test_directory_sn_fat12(self) -> None: - fatfs = wl_fatfsgen.WLFATFS(device_id=3750448905) + fatfs = wl_fatfsgen.WLFATFS(fat_tables_cnt=2, device_id=3750448905) + fatfs.plain_fatfs.create_directory('TESTFOLD') + fatfs.init_wl() + + fatfs.wl_write_filesystem(CFG['output_file']) + with open(CFG['output_file'], 'rb') as fs_file: + file_system = fs_file.read() + + # boot sector + self.assertEqual(file_system[0x1000:0x1010], b'\xeb\xfe\x90MSDOS5.0\x00\x10\x01\x01\x00') + self.assertEqual(file_system[0x1010:0x1020], b'\x02\x00\x02\xfa\x00\xf8\x01\x00?\x00\xff\x00\x00\x00\x00\x00') # two fats b'\x02...' + self.assertEqual(file_system[0x102b:0x1034], b'Espressif') + + self.assertEqual(file_system[0x4000:0x400c], b'TESTFOLD \x10') # check entry name and type + self.assertEqual(file_system[0x2000:0x2006], b'\xf8\xff\xff\xff\x0f\x00') # check fat + self.assertEqual(file_system[0x8000:0x800c], b'. \x10') # reference to itself + self.assertEqual(file_system[0x8020:0x802c], b'.. \x10') # reference to parent + + # check state1 + self.assertEqual(file_system[0xfb000:0xfb00f], b'\x00\x00\x00\x00\xfb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xfb010:0xfb020], b'\x10\x00\x00\x00\x00\x10\x00\x00\x02\x00\x00\x00\tO\x8b\xdf') + self.assertEqual(file_system[0xfb020:0xfb02f], b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xfb031:0xfb040], b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\xa1\x94i') + + # check state2 + self.assertEqual(file_system[0xfd000:0xfd00f], b'\x00\x00\x00\x00\xfb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xfd010:0xfd020], b'\x10\x00\x00\x00\x00\x10\x00\x00\x02\x00\x00\x00\tO\x8b\xdf') + self.assertEqual(file_system[0xfd020:0xfd02f], b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xfd031:0xfd040], b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd4\xa1\x94i') + + # check config + self.assertEqual(file_system[0xff001:0xff010], b'\x00\x00\x00\x00\x00\x10\x00\x00\x10\x00\x00\x00\x10\x00\x00') + self.assertEqual(file_system[0xff010:0xff01f], b'\x10\x00\x00\x00\x10\x00\x00\x00\x02\x00\x00\x00 \x00\x00') + self.assertEqual(file_system[0xff020:0xff030], b'\xe0b\xb5O\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xff030:0xff03f], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff') + + def test_directory_sn_fat12_one_fat(self) -> None: + fatfs = wl_fatfsgen.WLFATFS(fat_tables_cnt=1, device_id=3750448905) fatfs.plain_fatfs.create_directory('TESTFOLD') fatfs.init_wl() @@ -45,7 +93,7 @@ class WLFatFSGen(unittest.TestCase): # boot sector self.assertEqual(file_system[0x1000:0x1010], b'\xeb\xfe\x90MSDOS5.0\x00\x10\x01\x01\x00') - self.assertEqual(file_system[0x1010:0x1020], b'\x01\x00\x02\xfa\x00\xf8\x01\x00?\x00\xff\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x1010:0x1020], b'\x01\x00\x02\xfa\x00\xf8\x01\x00?\x00\xff\x00\x00\x00\x00\x00') # one fat b'\x01...' self.assertEqual(file_system[0x102b:0x1034], b'Espressif') self.assertEqual(file_system[0x3000:0x300c], b'TESTFOLD \x10') # check entry name and type @@ -72,7 +120,36 @@ class WLFatFSGen(unittest.TestCase): self.assertEqual(file_system[0xff030:0xff03f], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff') def test_directory_sn_fat122mb(self) -> None: - fatfs = wl_fatfsgen.WLFATFS(device_id=3750448905, size=2 * 1024 * 1024) + fatfs = wl_fatfsgen.WLFATFS(fat_tables_cnt=2, device_id=3750448905, size=2 * 1024 * 1024) + fatfs.plain_fatfs.create_directory('TESTFOLD') + fatfs.init_wl() + + fatfs.wl_write_filesystem(CFG['output_file']) + with open(CFG['output_file'], 'rb') as fs_file: + file_system = fs_file.read() + + # check state1 + self.assertEqual(file_system[0x1f9000:0x1f900e], b'\x00\x00\x00\x00\xf9\x01\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x1f9010:0x1f9020], + b'\x10\x00\x00\x00\x00\x10\x00\x00\x02\x00\x00\x00\tO\x8b\xdf') + self.assertEqual(file_system[0x1f9020:0x1f902e], b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x1f9030:0x1f9040], b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j5\xbdp') + + # check state2 + self.assertEqual(file_system[0x1fc000:0x1fc00e], b'\x00\x00\x00\x00\xf9\x01\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x1fc010:0x1fc020], + b'\x10\x00\x00\x00\x00\x10\x00\x00\x02\x00\x00\x00\tO\x8b\xdf') + self.assertEqual(file_system[0x1fc020:0x1fc02e], b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x1fc030:0x1fc040], b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00j5\xbdp') + + # check config + self.assertEqual(file_system[0x1ff000:0x1ff00f], b'\x00\x00\x00\x00\x00\x00 \x00\x00\x10\x00\x00\x00\x10\x00') + self.assertEqual(file_system[0x1ff010:0x1ff01f], b'\x10\x00\x00\x00\x10\x00\x00\x00\x02\x00\x00\x00 \x00\x00') + self.assertEqual(file_system[0x1ff020:0x1ff030], b')\x892j\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0x1ff030:0x1ff03e], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff') + + def test_directory_sn_fat122mb_one_fat(self) -> None: + fatfs = wl_fatfsgen.WLFATFS(fat_tables_cnt=1, device_id=3750448905, size=2 * 1024 * 1024) fatfs.plain_fatfs.create_directory('TESTFOLD') fatfs.init_wl() @@ -101,12 +178,29 @@ class WLFatFSGen(unittest.TestCase): self.assertEqual(file_system[0x1ff030:0x1ff03e], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff') def test_write_not_initialized_wlfatfs(self) -> None: - fatfs = wl_fatfsgen.WLFATFS() + fatfs = wl_fatfsgen.WLFATFS(fat_tables_cnt=2) fatfs.plain_fatfs.create_directory('TESTFOLD') self.assertRaises(WLNotInitialized, fatfs.wl_write_filesystem, CFG['output_file']) def test_e2e_deep_folder_into_image_ext(self) -> None: - fatfs = wl_fatfsgen.WLFATFS() + fatfs = wl_fatfsgen.WLFATFS(fat_tables_cnt=2) + fatfs.plain_fatfs.generate(CFG['test_dir2']) + fatfs.init_wl() + fatfs.wl_write_filesystem(CFG['output_file']) + with open(CFG['output_file'], 'rb') as fs_file: + file_system = bytearray(fs_file.read()) + + self.assertEqual(file_system[0x4020:0x4030], b'TESTFILE \x00\x00\x00\x00') + self.assertEqual(file_system[0x8060:0x8070], b'TESTFIL2 \x00\x00\x00\x00') + self.assertEqual(file_system[0x9000:0x9010], b'. \x10\x00\x00\x00\x00') + self.assertEqual(file_system[0x9040:0x9050], b'LASTFILETXT \x00\x00\x00\x00') + self.assertEqual(file_system[0xa000:0xa010], b'deeptest\n\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xb000:0xb010], b'thisistest\n\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xc000:0xc010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xd000:0xd009], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff') + + def test_e2e_deep_folder_into_image_ext_one_fat(self) -> None: + fatfs = wl_fatfsgen.WLFATFS(fat_tables_cnt=1) fatfs.plain_fatfs.generate(CFG['test_dir2']) fatfs.init_wl() fatfs.wl_write_filesystem(CFG['output_file']) @@ -123,7 +217,22 @@ class WLFatFSGen(unittest.TestCase): self.assertEqual(file_system[0xc000:0xc009], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff') def test_e2e_deep_folder_into_image(self) -> None: - fatfs = wl_fatfsgen.WLFATFS() + fatfs = wl_fatfsgen.WLFATFS(fat_tables_cnt=2) + fatfs.plain_fatfs.generate(CFG['test_dir']) + fatfs.init_wl() + fatfs.wl_write_filesystem(CFG['output_file']) + with open(CFG['output_file'], 'rb') as fs_file: + file_system = bytearray(fs_file.read()) + + self.assertEqual(file_system[0x8060:0x8070], b'TESTFIL2 \x00\x00\x00\x00') + self.assertEqual(file_system[0x8070:0x8080], b'!\x00!\x00\x00\x00\x00\x00!\x00\x05\x00\x0b\x00\x00\x00') + self.assertEqual(file_system[0x9040:0x9050], b'LASTFILE \x00\x00\x00\x00') + self.assertEqual(file_system[0xa000:0xa010], b'deeptest\n\x00\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xb000:0xb010], b'thisistest\n\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xc000:0xc010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + + def test_e2e_deep_folder_into_image_one_fat(self) -> None: + fatfs = wl_fatfsgen.WLFATFS(fat_tables_cnt=1) fatfs.plain_fatfs.generate(CFG['test_dir']) fatfs.init_wl() fatfs.wl_write_filesystem(CFG['output_file']) @@ -137,6 +246,66 @@ class WLFatFSGen(unittest.TestCase): self.assertEqual(file_system[0xa000:0xa010], b'thisistest\n\x00\x00\x00\x00\x00') self.assertEqual(file_system[0xb000:0xb010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + def test_chaining_wl_fat16(self) -> None: + fatfs = wl_fatfsgen.WLFATFS(fat_tables_cnt=2, size=17 * 1024 * 1024) + fatfs.plain_fatfs.create_file('WRITEF', extension='TXT') + fatfs.plain_fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a') + fatfs.init_wl() + fatfs.wl_write_filesystem(CFG['output_file']) + with open(CFG['output_file'], 'rb') as fs_file: + file_system = bytearray(fs_file.read()) + + self.assertEqual(file_system[0x2000: 0x200e], b'\xf8\xff\xff\xff\x03\x00\xff\xff\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xd000: 0xe000], b'a' + (CFG['sector_size'] - 1) * b'\x00') + + def test_chaining_wl_fat16_one_fat(self) -> None: + fatfs = wl_fatfsgen.WLFATFS(fat_tables_cnt=1, size=17 * 1024 * 1024) + fatfs.plain_fatfs.create_file('WRITEF', extension='TXT') + fatfs.plain_fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a') + fatfs.init_wl() + fatfs.wl_write_filesystem(CFG['output_file']) + with open(CFG['output_file'], 'rb') as fs_file: + file_system = bytearray(fs_file.read()) + + self.assertEqual(file_system[0x2000: 0x200e], b'\xf8\xff\xff\xff\x03\x00\xff\xff\x00\x00\x00\x00\x00\x00') + self.assertEqual(file_system[0xa000: 0xb000], b'a' + (CFG['sector_size'] - 1) * b'\x00') + + def test_full_sector_folder_wl_fat16(self) -> None: + fatfs = wl_fatfsgen.WLFATFS(fat_tables_cnt=2, size=17 * 1024 * 1024) + fatfs.plain_fatfs.create_directory('TESTFOLD') + + fill_sector(fatfs.plain_fatfs) + fatfs.plain_fatfs.write_content(path_from_root=['TESTFOLD', 'A0'], content=b'first') + fatfs.plain_fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later') + fatfs.init_wl() + fatfs.wl_write_filesystem(CFG['output_file']) + with open(CFG['output_file'], 'rb') as fs_file: + file_system = bytearray(fs_file.read()) + + self.assertEqual(file_system[0x2000: 0x2110], + b'\xf8\xff\xff\xff\x82\x00' + 258 * b'\xff' + 8 * b'\x00') + self.assertEqual(file_system[0x8b000:0x8b005], b'later') + self.assertEqual(file_system[0x8c000:0x8c010], b'A126 \x00\x00\x00\x00') + self.assertEqual(file_system[0x8c020:0x8c030], b'A127 \x00\x00\x00\x00') + + def test_full_sector_folder_wl_fat16_one_fat(self) -> None: + fatfs = wl_fatfsgen.WLFATFS(fat_tables_cnt=1, size=17 * 1024 * 1024) + fatfs.plain_fatfs.create_directory('TESTFOLD') + + fill_sector(fatfs.plain_fatfs) + fatfs.plain_fatfs.write_content(path_from_root=['TESTFOLD', 'A0'], content=b'first') + fatfs.plain_fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later') + fatfs.init_wl() + fatfs.wl_write_filesystem(CFG['output_file']) + with open(CFG['output_file'], 'rb') as fs_file: + file_system = bytearray(fs_file.read()) + + self.assertEqual(file_system[0x2000: 0x2110], + b'\xf8\xff\xff\xff\x82\x00' + 258 * b'\xff' + 8 * b'\x00') + self.assertEqual(file_system[0x88000:0x88005], b'later') + self.assertEqual(file_system[0x89000:0x89010], b'A126 \x00\x00\x00\x00') + self.assertEqual(file_system[0x89020:0x89030], b'A127 \x00\x00\x00\x00') + if __name__ == '__main__': unittest.main() diff --git a/lib/fatfs/vfs/esp_vfs_fat.h b/lib/fatfs/vfs/esp_vfs_fat.h index 3e7b165b..7b87818f 100644 --- a/lib/fatfs/vfs/esp_vfs_fat.h +++ b/lib/fatfs/vfs/esp_vfs_fat.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,8 +7,7 @@ #pragma once #include #include "esp_err.h" -#include "driver/gpio.h" -#include "driver/sdmmc_types.h" +#include "sd_protocol_types.h" #include "driver/sdspi_host.h" #include "ff.h" #include "wear_levelling.h" @@ -17,10 +16,20 @@ extern "C" { #endif +/** + * @brief Configuration structure for esp_vfs_fat_register + */ +typedef struct { + const char* base_path; /*!< Path prefix where FATFS should be registered, */ + const char* fat_drive; /*!< FATFS drive specification; if only one drive is used, can be an empty string. */ + size_t max_files; /*!< Maximum number of files which can be open at the same time. */ +} esp_vfs_fat_conf_t; + /** * @brief Register FATFS with VFS component * * This function registers given FAT drive in VFS, at the specified base path. + * Input arguments are held in esp_vfs_fat_conf_t structure. * If only one drive is used, fat_drive argument can be an empty string. * Refer to FATFS library documentation on how to specify FAT drive. * This function also allocates FATFS structure which should be used for f_mount @@ -30,17 +39,14 @@ extern "C" { * POSIX and C standard library IO function with FATFS. You need to mount * desired drive into FATFS separately. * - * @param base_path path prefix where FATFS should be registered - * @param fat_drive FATFS drive specification; if only one drive is used, can be an empty string - * @param max_files maximum number of files which can be open at the same time + * @param conf pointer to esp_vfs_fat_conf_t configuration structure * @param[out] out_fs pointer to FATFS structure which can be used for FATFS f_mount call is returned via this argument. * @return * - ESP_OK on success * - ESP_ERR_INVALID_STATE if esp_vfs_fat_register was already called * - ESP_ERR_NO_MEM if not enough memory or too many VFSes already registered */ -esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, - size_t max_files, FATFS** out_fs); +esp_err_t esp_vfs_fat_register_cfg(const esp_vfs_fat_conf_t* conf, FATFS** out_fs); /** * @brief Un-register FATFS from VFS @@ -96,8 +102,26 @@ typedef struct { * Doesn't do anything for other memory storage media. */ bool disk_status_check_enable; + /** + * Use 1 FAT (File Allocation Tables) instead of 2. + * This decreases reliability, but makes more space available + * (usually only one sector). + * Note that this option has effect only when the filesystem is formatted. + * When mounting an already-formatted partition, the actual number of FATs + * may be different. + */ + bool use_one_fat; } esp_vfs_fat_mount_config_t; +#define VFS_FAT_MOUNT_DEFAULT_CONFIG() \ + { \ + .format_if_mount_failed = false, \ + .max_files = 5, \ + .allocation_unit_size = 0, \ + .disk_status_check_enable = false, \ + .use_one_fat = false, \ + } + // Compatibility definition typedef esp_vfs_fat_mount_config_t esp_vfs_fat_sdmmc_mount_config_t; @@ -207,6 +231,25 @@ esp_err_t esp_vfs_fat_sdmmc_unmount(void) __attribute__((deprecated("Please use */ esp_err_t esp_vfs_fat_sdcard_unmount(const char* base_path, sdmmc_card_t *card); +/** + * @brief Format FAT filesystem with given configuration + * + * @note + * This API should be only called when the FAT is already mounted. + * + * @param base_path Path where partition should be registered (e.g. "/sdcard") + * @param card Pointer to the card handle, which should be initialised by calling `esp_vfs_fat_sdspi_mount` first + * @param cfg Pointer to structure with extra parameters for formatting FATFS (only relevant fields are used). + * If NULL, the previous configuration will be used. + * + * @return + * - ESP_OK + * - ESP_ERR_INVALID_STATE: FAT partition isn't mounted, call esp_vfs_fat_sdmmc_mount or esp_vfs_fat_sdspi_mount first + * - ESP_ERR_NO_MEM: if memory can not be allocated + * - ESP_FAIL: fail to format it, or fail to mount back + */ +esp_err_t esp_vfs_fat_sdcard_format_cfg(const char *base_path, sdmmc_card_t *card, esp_vfs_fat_mount_config_t *cfg); + /** * @brief Format FAT filesystem * @@ -267,6 +310,27 @@ esp_err_t esp_vfs_fat_spiflash_mount_rw_wl(const char* base_path, */ esp_err_t esp_vfs_fat_spiflash_unmount_rw_wl(const char* base_path, wl_handle_t wl_handle); +/** + * @brief Format FAT filesystem with given configuration + * + * @note + * This API can be called when the FAT is mounted / not mounted. + * If this API is called when the FAT isn't mounted (by calling esp_vfs_fat_spiflash_mount_rw_wl), + * this API will first mount the FAT then format it, then restore back to the original state. + * + * @param base_path Path where partition should be registered (e.g. "/spiflash") + * @param partition_label Label of the partition which should be used + * @param cfg Pointer to structure with extra parameters for formatting FATFS (only relevant fields are used). + * If NULL and mounted the previous configuration will be used. + * If NULL and unmounted the default configuration will be used. + * + * @return + * - ESP_OK + * - ESP_ERR_NO_MEM: if memory can not be allocated + * - Other errors from esp_vfs_fat_spiflash_mount_rw_wl + */ +esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const char* partition_label, esp_vfs_fat_mount_config_t *cfg); + /** * @brief Format FAT filesystem * @@ -337,7 +401,45 @@ esp_err_t esp_vfs_fat_spiflash_unmount_ro(const char* base_path, const char* par */ esp_err_t esp_vfs_fat_info(const char* base_path, uint64_t* out_total_bytes, uint64_t* out_free_bytes); +/** + * @brief Create a file with contiguous space at given path + * + * @note The file cannot exist before calling this function (or the file size has to be 0) + * For more information see documentation for `f_expand` from FATFS library + * + * @param base_path Base path of the partition examined (e.g. "/spiflash") + * @param full_path Full path of the file (e.g. "/spiflash/ABC.TXT") + * @param size File size expanded to, number of bytes in size to prepare or allocate for the file + * @param alloc_now True == allocate space now, false == prepare to allocate -- see `f_expand` from FATFS + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if invalid arguments (e.g. any of arguments are NULL or size lower or equal to 0) + * - ESP_ERR_INVALID_STATE if partition not found + * - ESP_FAIL if another FRESULT error (saved in errno) + */ +esp_err_t esp_vfs_fat_create_contiguous_file(const char* base_path, const char* full_path, uint64_t size, bool alloc_now); + +/** + * @brief Test if a file is contiguous in the FAT filesystem + * + * @param base_path Base path of the partition examined (e.g. "/spiflash") + * @param full_path Full path of the file (e.g. "/spiflash/ABC.TXT") + * @param[out] is_contiguous True == allocate space now, false == prepare to allocate -- see `f_expand` from FATFS + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_ARG if invalid arguments (e.g. any of arguments are NULL) + * - ESP_ERR_INVALID_STATE if partition not found + * - ESP_FAIL if another FRESULT error (saved in errno) + */ +esp_err_t esp_vfs_fat_test_contiguous_file(const char* base_path, const char* full_path, bool* is_contiguous); + /** @cond */ +/** + * @deprecated Please use `esp_vfs_fat_register_cfg` instead + */ +esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, + size_t max_files, FATFS** out_fs); + /** * @deprecated Please use `esp_vfs_fat_spiflash_mount_rw_wl` instead */ diff --git a/lib/fatfs/vfs/vfs_fat.c b/lib/fatfs/vfs/vfs_fat.c index 4ae04c3d..b0b32fa9 100644 --- a/lib/fatfs/vfs/vfs_fat.c +++ b/lib/fatfs/vfs/vfs_fat.c @@ -1,21 +1,40 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include #include +#include #include #include #include #include #include +#include "esp_vfs_fat.h" #include "esp_vfs.h" #include "esp_log.h" #include "ff.h" #include "diskio_impl.h" +#define F_WRITE_MALLOC_ZEROING_BUF_SIZE_LIMIT 512 + +#ifdef CONFIG_VFS_SUPPORT_DIR +struct cached_data{ +#if FF_USE_LFN + char file_path[FILENAME_MAX+1+FF_LFN_BUF+1]; //FILENAME_MAX+1: for dir_path, FF_LFN_BUF+1: for file name +#else + char file_path[FILENAME_MAX+1+FF_SFN_BUF+1]; //FILENAME_MAX+1: for dir_path, FF_LFN_BUF+1: for file name +#endif + FILINFO fileinfo; +}; +#endif // CONFIG_VFS_SUPPORT_DIR + +#if !defined(FILENAME_MAX) +#define FILENAME_MAX 255 +#endif + typedef struct { char fat_drive[8]; /* FAT drive name */ char base_path[ESP_VFS_PATH_MAX]; /* base path in VFS where partition is registered */ @@ -24,8 +43,12 @@ typedef struct { FATFS fs; /* fatfs library FS structure */ char tmp_path_buf[FILENAME_MAX+3]; /* temporary buffer used to prepend drive name to the path */ char tmp_path_buf2[FILENAME_MAX+3]; /* as above; used in functions which take two path arguments */ - bool *o_append; /* O_APPEND is stored here for each max_files entries (because O_APPEND is not compatible with FA_OPEN_APPEND) */ - FIL files[0]; /* array with max_files entries; must be the final member of the structure */ + uint32_t *flags; /* file descriptor flags, array of max_files size */ +#ifdef CONFIG_VFS_SUPPORT_DIR + char dir_path[FILENAME_MAX]; /* variable to store path of opened directory*/ + struct cached_data cached_fileinfo; +#endif + FIL files[]; /* array with max_files entries; must be the final member of the structure */ } vfs_fat_ctx_t; typedef struct { @@ -66,6 +89,7 @@ static int vfs_fat_open(void* ctx, const char * path, int flags, int mode); static int vfs_fat_close(void* ctx, int fd); static int vfs_fat_fstat(void* ctx, int fd, struct stat * st); static int vfs_fat_fsync(void* ctx, int fd); +static int vfs_fat_fcntl(void* ctx, int fd, int cmd, int arg); #ifdef CONFIG_VFS_SUPPORT_DIR static int vfs_fat_stat(void* ctx, const char * path, struct stat * st); static int vfs_fat_link(void* ctx, const char* n1, const char* n2); @@ -90,6 +114,7 @@ static vfs_fat_ctx_t* s_fat_ctxs[FF_VOLUMES] = { NULL }; //backwards-compatibility with esp_vfs_fat_unregister() static vfs_fat_ctx_t* s_fat_ctx = NULL; + static size_t find_context_index_by_path(const char* base_path) { for(size_t i=0; ibase_path); if (ctx < FF_VOLUMES) { return ESP_ERR_INVALID_STATE; } @@ -122,55 +194,30 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, siz return ESP_ERR_NO_MEM; } - const esp_vfs_t vfs = { - .flags = ESP_VFS_FLAG_CONTEXT_PTR, - .write_p = &vfs_fat_write, - .lseek_p = &vfs_fat_lseek, - .read_p = &vfs_fat_read, - .pread_p = &vfs_fat_pread, - .pwrite_p = &vfs_fat_pwrite, - .open_p = &vfs_fat_open, - .close_p = &vfs_fat_close, - .fstat_p = &vfs_fat_fstat, - .fsync_p = &vfs_fat_fsync, -#ifdef CONFIG_VFS_SUPPORT_DIR - .stat_p = &vfs_fat_stat, - .link_p = &vfs_fat_link, - .unlink_p = &vfs_fat_unlink, - .rename_p = &vfs_fat_rename, - .opendir_p = &vfs_fat_opendir, - .closedir_p = &vfs_fat_closedir, - .readdir_p = &vfs_fat_readdir, - .readdir_r_p = &vfs_fat_readdir_r, - .seekdir_p = &vfs_fat_seekdir, - .telldir_p = &vfs_fat_telldir, - .mkdir_p = &vfs_fat_mkdir, - .rmdir_p = &vfs_fat_rmdir, - .access_p = &vfs_fat_access, - .truncate_p = &vfs_fat_truncate, - .ftruncate_p = &vfs_fat_ftruncate, - .utime_p = &vfs_fat_utime, -#endif // CONFIG_VFS_SUPPORT_DIR - }; + size_t max_files = conf->max_files; + if (max_files < 1) { + max_files = 1; // ff_memalloc(max_files * sizeof(bool)) below will fail if max_files == 0 + } + size_t ctx_size = sizeof(vfs_fat_ctx_t) + max_files * sizeof(FIL); vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ff_memalloc(ctx_size); if (fat_ctx == NULL) { return ESP_ERR_NO_MEM; } memset(fat_ctx, 0, ctx_size); - fat_ctx->o_append = ff_memalloc(max_files * sizeof(bool)); - if (fat_ctx->o_append == NULL) { + fat_ctx->flags = ff_memalloc(max_files * sizeof(*fat_ctx->flags)); + if (fat_ctx->flags == NULL) { free(fat_ctx); return ESP_ERR_NO_MEM; } - memset(fat_ctx->o_append, 0, max_files * sizeof(bool)); + memset(fat_ctx->flags, 0, max_files * sizeof(*fat_ctx->flags)); fat_ctx->max_files = max_files; - strlcpy(fat_ctx->fat_drive, fat_drive, sizeof(fat_ctx->fat_drive) - 1); - strlcpy(fat_ctx->base_path, base_path, sizeof(fat_ctx->base_path) - 1); + strlcpy(fat_ctx->fat_drive, conf->fat_drive, sizeof(fat_ctx->fat_drive) - 1); + strlcpy(fat_ctx->base_path, conf->base_path, sizeof(fat_ctx->base_path) - 1); - esp_err_t err = esp_vfs_register(base_path, &vfs, fat_ctx); + esp_err_t err = esp_vfs_register_fs(conf->base_path, &s_vfs_fat, ESP_VFS_FLAG_CONTEXT_PTR | ESP_VFS_FLAG_STATIC, fat_ctx); if (err != ESP_OK) { - free(fat_ctx->o_append); + free(fat_ctx->flags); free(fat_ctx); return err; } @@ -198,7 +245,7 @@ esp_err_t esp_vfs_fat_unregister_path(const char* base_path) return err; } _lock_close(&fat_ctx->lock); - free(fat_ctx->o_append); + free(fat_ctx->flags); free(fat_ctx); s_fat_ctxs[ctx] = NULL; return ESP_OK; @@ -386,7 +433,7 @@ static int vfs_fat_open(void* ctx, const char * path, int flags, int mode) // Other VFS drivers handles O_APPEND well (to the best of my knowledge), // therefore this flag is stored here (at this VFS level) in order to save // memory. - fat_ctx->o_append[fd] = (flags & O_APPEND) == O_APPEND; + fat_ctx->flags[fd] = (flags & (O_APPEND | O_ACCMODE)); _lock_release(&fat_ctx->lock); return fd; } @@ -396,10 +443,12 @@ static ssize_t vfs_fat_write(void* ctx, int fd, const void * data, size_t size) vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; FIL* file = &fat_ctx->files[fd]; FRESULT res; - if (fat_ctx->o_append[fd]) { + _lock_acquire(&fat_ctx->lock); + if (fat_ctx->flags[fd] & O_APPEND) { if ((res = f_lseek(file, f_size(file))) != FR_OK) { ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); errno = fresult_to_errno(res); + _lock_release(&fat_ctx->lock); return -1; } } @@ -407,18 +456,19 @@ static ssize_t vfs_fat_write(void* ctx, int fd, const void * data, size_t size) res = f_write(file, data, size, &written); if (((written == 0) && (size != 0)) && (res == 0)) { errno = ENOSPC; + _lock_release(&fat_ctx->lock); return -1; } if (res != FR_OK) { ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); errno = fresult_to_errno(res); if (written == 0) { + _lock_release(&fat_ctx->lock); return -1; } } #if CONFIG_FATFS_IMMEDIATE_FSYNC - _lock_acquire(&fat_ctx->lock); if (written > 0) { res = f_sync(file); if (res != FR_OK) { @@ -428,9 +478,8 @@ static ssize_t vfs_fat_write(void* ctx, int fd, const void * data, size_t size) return -1; } } - _lock_release(&fat_ctx->lock); #endif - + _lock_release(&fat_ctx->lock); return written; } @@ -549,10 +598,8 @@ pwrite_release: static int vfs_fat_fsync(void* ctx, int fd) { vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; - _lock_acquire(&fat_ctx->lock); FIL* file = &fat_ctx->files[fd]; FRESULT res = f_sync(file); - _lock_release(&fat_ctx->lock); int rc = 0; if (res != FR_OK) { ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); @@ -631,6 +678,26 @@ static int vfs_fat_fstat(void* ctx, int fd, struct stat * st) return 0; } +static int vfs_fat_fcntl(void* ctx, int fd, int cmd, int arg) +{ + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + switch (cmd) { + case F_GETFL: + return fat_ctx->flags[fd]; + case F_SETFL: + fat_ctx->flags[fd] = arg; + return 0; + // no-ops: + case F_SETLK: + case F_SETLKW: + case F_GETLK: + return 0; + default: + errno = EINVAL; + return -1; + } +} + #ifdef CONFIG_VFS_SUPPORT_DIR static inline mode_t get_stat_mode(bool is_dir) @@ -639,6 +706,32 @@ static inline mode_t get_stat_mode(bool is_dir) ((is_dir) ? S_IFDIR : S_IFREG); } +static void update_stat_struct(struct stat *st, FILINFO *info) +{ + memset(st, 0, sizeof(*st)); + st->st_size = info->fsize; + st->st_mode = get_stat_mode((info->fattrib & AM_DIR) != 0); + fat_date_t fdate = { .as_int = info->fdate }; + fat_time_t ftime = { .as_int = info->ftime }; + struct tm tm = { + .tm_mday = fdate.mday, + .tm_mon = fdate.mon - 1, /* unlike tm_mday, tm_mon is zero-based */ + .tm_year = fdate.year + 80, + .tm_sec = ftime.sec * 2, + .tm_min = ftime.min, + .tm_hour = ftime.hour, + /* FAT doesn't keep track if the time was DST or not, ask the C library + * to try to figure this out. Note that this may yield incorrect result + * in the hour before the DST comes in effect, when the local time can't + * be converted to UTC uniquely. + */ + .tm_isdst = -1 + }; + st->st_mtime = mktime(&tm); + st->st_atime = 0; + st->st_ctime = 0; +} + static int vfs_fat_stat(void* ctx, const char * path, struct stat * st) { if (strcmp(path, "/") == 0) { @@ -651,6 +744,16 @@ static int vfs_fat_stat(void* ctx, const char * path, struct stat * st) } vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + + //If fileinfo is already cached by readdir for requested filename, + //then return the same info else obtain fileinfo with f_stat function + if (strcmp(path, fat_ctx->cached_fileinfo.file_path) == 0) { + update_stat_struct(st, &fat_ctx->cached_fileinfo.fileinfo); + memset(&fat_ctx->cached_fileinfo, 0 ,sizeof(FILINFO)); + return 0; + } + + memset(&fat_ctx->cached_fileinfo, 0 ,sizeof(fat_ctx->cached_fileinfo)); _lock_acquire(&fat_ctx->lock); prepend_drive_to_path(fat_ctx, &path, NULL); FILINFO info; @@ -662,28 +765,7 @@ static int vfs_fat_stat(void* ctx, const char * path, struct stat * st) return -1; } - memset(st, 0, sizeof(*st)); - st->st_size = info.fsize; - st->st_mode = get_stat_mode((info.fattrib & AM_DIR) != 0); - fat_date_t fdate = { .as_int = info.fdate }; - fat_time_t ftime = { .as_int = info.ftime }; - struct tm tm = { - .tm_mday = fdate.mday, - .tm_mon = fdate.mon - 1, /* unlike tm_mday, tm_mon is zero-based */ - .tm_year = fdate.year + 80, - .tm_sec = ftime.sec * 2, - .tm_min = ftime.min, - .tm_hour = ftime.hour, - /* FAT doesn't keep track if the time was DST or not, ask the C library - * to try to figure this out. Note that this may yield incorrect result - * in the hour before the DST comes in effect, when the local time can't - * be converted to UTC uniquely. - */ - .tm_isdst = -1 - }; - st->st_mtime = mktime(&tm); - st->st_atime = 0; - st->st_ctime = 0; + update_stat_struct(st, &info); return 0; } @@ -707,74 +789,85 @@ static int vfs_fat_link(void* ctx, const char* n1, const char* n2) vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; _lock_acquire(&fat_ctx->lock); prepend_drive_to_path(fat_ctx, &n1, &n2); - const size_t copy_buf_size = fat_ctx->fs.csize; - FRESULT res; + + FRESULT res = FR_OK; + int ret = 0; + FIL* pf1 = (FIL*) ff_memalloc(sizeof(FIL)); FIL* pf2 = (FIL*) ff_memalloc(sizeof(FIL)); + + const size_t copy_buf_size = fat_ctx->fs.csize; void* buf = ff_memalloc(copy_buf_size); if (buf == NULL || pf1 == NULL || pf2 == NULL) { - _lock_release(&fat_ctx->lock); ESP_LOGD(TAG, "alloc failed, pf1=%p, pf2=%p, buf=%p", pf1, pf2, buf); - free(pf1); - free(pf2); - free(buf); + _lock_release(&fat_ctx->lock); errno = ENOMEM; - return -1; + ret = -1; + goto cleanup; } + memset(pf1, 0, sizeof(*pf1)); memset(pf2, 0, sizeof(*pf2)); + res = f_open(pf1, n1, FA_READ | FA_OPEN_EXISTING); if (res != FR_OK) { _lock_release(&fat_ctx->lock); - goto fail1; + goto cleanup; } + res = f_open(pf2, n2, FA_WRITE | FA_CREATE_NEW); + +#if !CONFIG_FATFS_LINK_LOCK _lock_release(&fat_ctx->lock); +#endif + if (res != FR_OK) { - goto fail2; + goto close_old; } + size_t size_left = f_size(pf1); while (size_left > 0) { size_t will_copy = (size_left < copy_buf_size) ? size_left : copy_buf_size; size_t read; res = f_read(pf1, buf, will_copy, &read); if (res != FR_OK) { - goto fail3; + goto close_both; } else if (read != will_copy) { res = FR_DISK_ERR; - goto fail3; + goto close_both; } size_t written; res = f_write(pf2, buf, will_copy, &written); if (res != FR_OK) { - goto fail3; + goto close_both; } else if (written != will_copy) { res = FR_DISK_ERR; - goto fail3; + goto close_both; } size_left -= will_copy; } -#if CONFIG_FATFS_IMMEDIATE_FSYNC - _lock_acquire(&fat_ctx->lock); - res = f_sync(pf2); +close_both: + f_close(pf2); + +close_old: + f_close(pf1); + +#if CONFIG_FATFS_LINK_LOCK _lock_release(&fat_ctx->lock); #endif -fail3: - f_close(pf2); -fail2: - f_close(pf1); -fail1: +cleanup: free(buf); free(pf2); free(pf1); - if (res != FR_OK) { + if (ret == 0 && res != FR_OK) { ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); errno = fresult_to_errno(res); return -1; } - return 0; + + return ret; } static int vfs_fat_rename(void* ctx, const char *src, const char *dst) @@ -795,6 +888,7 @@ static int vfs_fat_rename(void* ctx, const char *src, const char *dst) static DIR* vfs_fat_opendir(void* ctx, const char* name) { vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + strlcpy(fat_ctx->dir_path, name, sizeof(fat_ctx->dir_path)); _lock_acquire(&fat_ctx->lock); prepend_drive_to_path(fat_ctx, &name, NULL); vfs_fat_dir_t* fat_dir = ff_memalloc(sizeof(vfs_fat_dir_t)); @@ -832,6 +926,9 @@ static int vfs_fat_closedir(void* ctx, DIR* pdir) static struct dirent* vfs_fat_readdir(void* ctx, DIR* pdir) { + assert(ctx); + assert(pdir); + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; vfs_fat_dir_t* fat_dir = (vfs_fat_dir_t*) pdir; struct dirent* out_dirent; int err = vfs_fat_readdir_r(ctx, pdir, &fat_dir->cur_dirent, &out_dirent); @@ -839,6 +936,25 @@ static struct dirent* vfs_fat_readdir(void* ctx, DIR* pdir) errno = err; return NULL; } + + //Store the FILEINFO in the cached_fileinfo. If the stat function is invoked immediately afterward, + //the cached_fileinfo will provide the FILEINFO directly, as it was already obtained during the readdir operation. + //During directory size calculation, this optimization can reduce the computation time. + memset(&fat_ctx->cached_fileinfo, 0 ,sizeof(fat_ctx->cached_fileinfo)); + if (strcmp(fat_ctx->dir_path, "/") == 0) { + snprintf(fat_ctx->cached_fileinfo.file_path, sizeof(fat_ctx->cached_fileinfo.file_path), + "/%s", fat_dir->filinfo.fname); + } else { + char *temp_file_path = (char*) ff_memalloc(sizeof(fat_ctx->cached_fileinfo.file_path)); + if (temp_file_path == NULL) { + return out_dirent; + } + snprintf(temp_file_path, sizeof(fat_ctx->cached_fileinfo.file_path), + "%s/%s", fat_ctx->dir_path, fat_dir->filinfo.fname); + memcpy(fat_ctx->cached_fileinfo.file_path, temp_file_path, sizeof(fat_ctx->cached_fileinfo.file_path)); + ff_memfree(temp_file_path); + } + fat_ctx->cached_fileinfo.fileinfo = fat_dir->filinfo; return out_dirent; } @@ -881,8 +997,10 @@ static long vfs_fat_telldir(void* ctx, DIR* pdir) static void vfs_fat_seekdir(void* ctx, DIR* pdir, long offset) { assert(pdir); + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; vfs_fat_dir_t* fat_dir = (vfs_fat_dir_t*) pdir; FRESULT res; + _lock_acquire(&fat_ctx->lock); if (offset < fat_dir->offset) { res = f_rewinddir(&fat_dir->ffdir); if (res != FR_OK) { @@ -901,6 +1019,7 @@ static void vfs_fat_seekdir(void* ctx, DIR* pdir, long offset) } fat_dir->offset++; } + _lock_release(&fat_ctx->lock); } static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode) @@ -962,6 +1081,49 @@ static int vfs_fat_access(void* ctx, const char *path, int amode) return ret; } +static FRESULT f_write_zero_mem(FIL* fp, FSIZE_t data_size, FSIZE_t buf_size, UINT* bytes_written) +{ + if (fp == NULL || data_size <= 0 || buf_size <= 0) { + return FR_INVALID_PARAMETER; + } + + void* buf = ff_memalloc(buf_size); + if (buf == NULL) { + return FR_DISK_ERR; + } + memset(buf, 0, buf_size); + + FRESULT res = FR_OK; + UINT bw = 0; + FSIZE_t i = 0; + if (bytes_written != NULL) { + *bytes_written = 0; + } + + if (data_size > buf_size) { // prevent unsigned underflow + for (; i < (data_size - buf_size); i += buf_size) { // write chunks of buf_size + res = f_write(fp, buf, (UINT) buf_size, &bw); + if (res != FR_OK) { + goto out; + } + if (bytes_written != NULL) { + *bytes_written += bw; + } + } + } + + if (i < data_size) { // write the remaining data + res = f_write(fp, buf, (UINT) (data_size - i), &bw); + if (res == FR_OK && bytes_written != NULL) { + *bytes_written += bw; + } + } + +out: + ff_memfree(buf); + return res; +} + static int vfs_fat_truncate(void* ctx, const char *path, off_t length) { FRESULT res; @@ -1000,31 +1162,55 @@ static int vfs_fat_truncate(void* ctx, const char *path, off_t length) goto out; } - long sz = f_size(file); - if (sz < length) { - _lock_release(&fat_ctx->lock); - ESP_LOGD(TAG, "truncate does not support extending size"); - errno = EPERM; - ret = -1; - goto close; - } + FSIZE_t seek_ptr_pos = (FSIZE_t) f_tell(file); // current seek pointer position + FSIZE_t sz = (FSIZE_t) f_size(file); // current file size (end of file position) res = f_lseek(file, length); - if (res != FR_OK) { - _lock_release(&fat_ctx->lock); - ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); - errno = fresult_to_errno(res); - ret = -1; - goto close; + if (res != FR_OK || f_tell(file) != length) { + goto lseek_or_write_fail; } - res = f_truncate(file); + if (sz < length) { + res = f_lseek(file, sz); // go to the previous end of file + if (res != FR_OK) { + goto lseek_or_write_fail; + } - if (res != FR_OK) { - ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); - errno = fresult_to_errno(res); - ret = -1; - goto close; + FSIZE_t new_free_space = ((FSIZE_t) length) - sz; + UINT written; + + if (new_free_space > UINT32_MAX) { + _lock_release(&fat_ctx->lock); + ESP_LOGE(TAG, "%s: Cannot extend the file more than 4GB at once", __func__); + ret = -1; + goto close; + } + + FSIZE_t buf_size_limit = F_WRITE_MALLOC_ZEROING_BUF_SIZE_LIMIT; + FSIZE_t buf_size = new_free_space < buf_size_limit ? new_free_space : buf_size_limit; + res = f_write_zero_mem(file, new_free_space, buf_size, &written); + + if (res != FR_OK) { + goto lseek_or_write_fail; + } else if (written != (UINT) new_free_space) { + res = FR_DISK_ERR; + goto lseek_or_write_fail; + } + + res = f_lseek(file, seek_ptr_pos); // return to the original position + if (res != FR_OK) { + goto lseek_or_write_fail; + } + } else { + res = f_truncate(file); + + if (res != FR_OK) { + _lock_release(&fat_ctx->lock); + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + ret = -1; + goto close; + } } #if CONFIG_FATFS_IMMEDIATE_FSYNC @@ -1052,6 +1238,13 @@ close: out: free(file); return ret; + +lseek_or_write_fail: + _lock_release(&fat_ctx->lock); + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + ret = -1; + goto close; } static int vfs_fat_ftruncate(void* ctx, int fd, off_t length) @@ -1078,29 +1271,50 @@ static int vfs_fat_ftruncate(void* ctx, int fd, off_t length) goto out; } - long sz = f_size(file); - if (sz < length) { - ESP_LOGD(TAG, "ftruncate does not support extending size"); - errno = EPERM; - ret = -1; - goto out; - } + FSIZE_t seek_ptr_pos = (FSIZE_t) f_tell(file); // current seek pointer position + FSIZE_t sz = (FSIZE_t) f_size(file); // current file size (end of file position) res = f_lseek(file, length); - if (res != FR_OK) { - ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); - errno = fresult_to_errno(res); - ret = -1; - goto out; + if (res != FR_OK || f_tell(file) != length) { + goto fail; } - res = f_truncate(file); + if (sz < length) { + res = f_lseek(file, sz); // go to the previous end of file + if (res != FR_OK) { + goto fail; + } - if (res != FR_OK) { - ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); - errno = fresult_to_errno(res); - ret = -1; - goto out; + FSIZE_t new_free_space = ((FSIZE_t) length) - sz; + UINT written; + + if (new_free_space > UINT32_MAX) { + ESP_LOGE(TAG, "%s: Cannot extend the file more than 4GB at once", __func__); + ret = -1; + goto out; + } + + FSIZE_t buf_size_limit = F_WRITE_MALLOC_ZEROING_BUF_SIZE_LIMIT; + FSIZE_t buf_size = new_free_space < buf_size_limit ? new_free_space : buf_size_limit; + res = f_write_zero_mem(file, new_free_space, buf_size, &written); + + if (res != FR_OK) { + goto fail; + } else if (written != (UINT) new_free_space) { + res = FR_DISK_ERR; + goto fail; + } + + res = f_lseek(file, seek_ptr_pos); // return to the original position + if (res != FR_OK) { + goto fail; + } + } else { + res = f_truncate(file); + + if (res != FR_OK) { + goto fail; + } } #if CONFIG_FATFS_IMMEDIATE_FSYNC @@ -1115,6 +1329,12 @@ static int vfs_fat_ftruncate(void* ctx, int fd, off_t length) out: _lock_release(&fat_ctx->lock); return ret; + +fail: + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + ret = -1; + goto out; } static int vfs_fat_utime(void *ctx, const char *path, const struct utimbuf *times) @@ -1142,7 +1362,7 @@ static int vfs_fat_utime(void *ctx, const char *path, const struct utimbuf *time fat_date_t fdate; fat_time_t ftime; - // this time transformation is esentially the reverse of the one in vfs_fat_stat() + // this time transformation is essentially the reverse of the one in vfs_fat_stat() fdate.mday = tm_time.tm_mday; fdate.mon = tm_time.tm_mon + 1; // January in fdate.mon is 1, and 0 in tm_time.tm_mon fdate.year = tm_time.tm_year - 80; // tm_time.tm_year=0 is 1900, tm_time.tm_year=0 is 1980 @@ -1170,3 +1390,142 @@ static int vfs_fat_utime(void *ctx, const char *path, const struct utimbuf *time } #endif // CONFIG_VFS_SUPPORT_DIR + +esp_err_t esp_vfs_fat_create_contiguous_file(const char* base_path, const char* full_path, uint64_t size, bool alloc_now) +{ + if (base_path == NULL || full_path == NULL || size <= 0) { + return ESP_ERR_INVALID_ARG; + } + + size_t ctx = find_context_index_by_path(base_path); + if (ctx == FF_VOLUMES) { + return ESP_ERR_INVALID_STATE; + } + vfs_fat_ctx_t* fat_ctx = s_fat_ctxs[ctx]; + + _lock_acquire(&fat_ctx->lock); + const char* file_path = full_path + strlen(base_path); // shift the pointer and omit the base_path + prepend_drive_to_path(fat_ctx, &file_path, NULL); + + FIL* file = (FIL*) ff_memalloc(sizeof(FIL)); + if (file == NULL) { + _lock_release(&fat_ctx->lock); + ESP_LOGD(TAG, "esp_vfs_fat_create_contiguous_file alloc failed"); + errno = ENOMEM; + return -1; + } + memset(file, 0, sizeof(*file)); + + FRESULT res = f_open(file, file_path, FA_WRITE | FA_OPEN_ALWAYS); + if (res != FR_OK) { + goto fail; + } + + res = f_expand(file, size, alloc_now ? 1 : 0); + if (res != FR_OK) { + f_close(file); + goto fail; + } + + res = f_close(file); + if (res != FR_OK) { + goto fail; + } + + _lock_release(&fat_ctx->lock); + free(file); + + return 0; +fail: + _lock_release(&fat_ctx->lock); + free(file); + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return -1; +} + +static FRESULT test_contiguous_file( // From FATFS examples + FIL* fp, /* [IN] Open file object to be checked */ + int* cont /* [OUT] 1:Contiguous, 0:Fragmented or zero-length */ +) { + DWORD clst, clsz, step; + FSIZE_t fsz; + FRESULT fr; + + *cont = 0; + fr = f_rewind(fp); /* Validates and prepares the file */ + if (fr != FR_OK) return fr; + +#if FF_MAX_SS == FF_MIN_SS + clsz = (DWORD)fp->obj.fs->csize * FF_MAX_SS; /* Cluster size */ +#else + clsz = (DWORD)fp->obj.fs->csize * fp->obj.fs->ssize; +#endif + fsz = f_size(fp); + if (fsz > 0) { + clst = fp->obj.sclust - 1; /* A cluster leading the first cluster for first test */ + while (fsz) { + step = (fsz >= clsz) ? clsz : (DWORD)fsz; + fr = f_lseek(fp, f_tell(fp) + step); /* Advances file pointer a cluster */ + if (fr != FR_OK) return fr; + if (clst + 1 != fp->clust) break; /* Is not the cluster next to previous one? */ + clst = fp->clust; fsz -= step; /* Get current cluster for next test */ + } + if (fsz == 0) *cont = 1; /* All done without fail? */ + } + + return FR_OK; +} + +esp_err_t esp_vfs_fat_test_contiguous_file(const char* base_path, const char* full_path, bool* is_contiguous) +{ + if (base_path == NULL || full_path == NULL || is_contiguous == NULL) { + return ESP_ERR_INVALID_ARG; + } + + size_t ctx = find_context_index_by_path(base_path); + if (ctx == FF_VOLUMES) { + return ESP_ERR_INVALID_STATE; + } + vfs_fat_ctx_t* fat_ctx = s_fat_ctxs[ctx]; + + _lock_acquire(&fat_ctx->lock); + const char* file_path = full_path + strlen(base_path); // shift the pointer and omit the base_path + prepend_drive_to_path(fat_ctx, &file_path, NULL); + + FIL* file = (FIL*) ff_memalloc(sizeof(FIL)); + if (file == NULL) { + _lock_release(&fat_ctx->lock); + ESP_LOGD(TAG, "esp_vfs_fat_test_contiguous_file alloc failed"); + errno = ENOMEM; + return -1; + } + memset(file, 0, sizeof(*file)); + + FRESULT res = f_open(file, file_path, FA_WRITE | FA_OPEN_ALWAYS); + if (res != FR_OK) { + goto fail; + } + + res = test_contiguous_file(file, (int*) is_contiguous); + if (res != FR_OK) { + f_close(file); + goto fail; + } + + res = f_close(file); + if (res != FR_OK) { + goto fail; + } + + _lock_release(&fat_ctx->lock); + free(file); + + return 0; +fail: + _lock_release(&fat_ctx->lock); + free(file); + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return -1; +} diff --git a/lib/fatfs/vfs/vfs_fat_internal.h b/lib/fatfs/vfs/vfs_fat_internal.h index dc3bae27..5b894604 100644 --- a/lib/fatfs/vfs/vfs_fat_internal.h +++ b/lib/fatfs/vfs/vfs_fat_internal.h @@ -1,23 +1,41 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once #include "esp_vfs_fat.h" +#include "diskio_impl.h" +#include "esp_partition.h" +#include "sdmmc_cmd.h" #include #include +typedef enum { + FORMATTED_DURING_LAST_MOUNT = 1 << 0, // The FATFS partition was formatted during the last mount +} vfs_fat_x_ctx_flags_t; + +typedef struct vfs_fat_spiflash_ctx_t { + const esp_partition_t *partition; //The partition where the FAT is located + bool by_label; //If the partition is mounted by label or not + BYTE pdrv; //Drive number that is mounted + FATFS *fs; //FAT structure pointer that is registered + wl_handle_t wlhandle; //WL handle + esp_vfs_fat_mount_config_t mount_config; //Mount configuration + vfs_fat_x_ctx_flags_t flags; //Flags +} vfs_fat_spiflash_ctx_t; + +typedef struct vfs_fat_sd_ctx_t { + BYTE pdrv; //Drive number that is mounted + esp_vfs_fat_mount_config_t mount_config; //Mount configuration + FATFS *fs; //FAT structure pointer that is registered + sdmmc_card_t *card; //Card info + char *base_path; //Path where partition is registered + vfs_fat_x_ctx_flags_t flags; //Flags +} vfs_fat_sd_ctx_t; + static inline size_t esp_vfs_fat_get_allocation_unit_size( size_t sector_size, size_t requested_size) { @@ -28,3 +46,6 @@ static inline size_t esp_vfs_fat_get_allocation_unit_size( alloc_unit_size = MIN(alloc_unit_size, max_size); return alloc_unit_size; } + +vfs_fat_spiflash_ctx_t* get_vfs_fat_spiflash_ctx(wl_handle_t wlhandle); +vfs_fat_sd_ctx_t* get_vfs_fat_get_sd_ctx(const sdmmc_card_t *card); diff --git a/lib/fatfs/vfs/vfs_fat_sdmmc.c b/lib/fatfs/vfs/vfs_fat_sdmmc.c index f62d6e7c..cd012d4d 100644 --- a/lib/fatfs/vfs/vfs_fat_sdmmc.c +++ b/lib/fatfs/vfs/vfs_fat_sdmmc.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,7 +16,7 @@ #include "diskio_impl.h" #include "diskio_sdmmc.h" #include "soc/soc_caps.h" -#include "driver/sdmmc_defs.h" +#include "sd_protocol_defs.h" #if SOC_SDMMC_HOST_SUPPORTED #include "driver/sdmmc_host.h" @@ -31,14 +31,6 @@ static const char* TAG = "vfs_fat_sdmmc"; } \ } while(0) -typedef struct vfs_fat_sd_ctx_t { - BYTE pdrv; //Drive number that is mounted - esp_vfs_fat_mount_config_t mount_config; //Mount configuration - FATFS *fs; //FAT structure pointer that is registered - sdmmc_card_t *card; //Card info - char *base_path; //Path where partition is registered -} vfs_fat_sd_ctx_t; - static vfs_fat_sd_ctx_t *s_ctx[FF_VOLUMES] = {}; /** * This `s_saved_ctx_id` is only used by `esp_vfs_fat_sdmmc_unmount`, which is deprecated. @@ -75,6 +67,15 @@ static uint32_t s_get_unused_context_id(void) return FF_VOLUMES; } +vfs_fat_sd_ctx_t* get_vfs_fat_get_sd_ctx(const sdmmc_card_t *card) +{ + uint32_t id = FF_VOLUMES; + if (s_get_context_id_by_card(card, &id)) { + return s_ctx[id]; + } + return NULL; +} + static esp_err_t mount_prepare_mem(const char *base_path, BYTE *out_pdrv, char **out_dup_path, @@ -116,7 +117,7 @@ cleanup: return err; } -static esp_err_t s_f_mount(sdmmc_card_t *card, FATFS *fs, const char *drv, uint8_t pdrv, const esp_vfs_fat_mount_config_t *mount_config) +static esp_err_t s_f_mount(sdmmc_card_t *card, FATFS *fs, const char *drv, uint8_t pdrv, const esp_vfs_fat_mount_config_t *mount_config, vfs_fat_x_ctx_flags_t *out_flags) { esp_err_t err = ESP_OK; FRESULT res = f_mount(fs, drv, 1); @@ -134,20 +135,28 @@ static esp_err_t s_f_mount(sdmmc_card_t *card, FATFS *fs, const char *drv, uint8 return err; } + if (out_flags) { + *out_flags |= FORMATTED_DURING_LAST_MOUNT; // set flag + } + ESP_LOGW(TAG, "mounting again"); - res = f_mount(fs, drv, 0); + res = f_mount(fs, drv, 1); if (res != FR_OK) { err = ESP_FAIL; ESP_LOGD(TAG, "f_mount failed after formatting (%d)", res); return err; } + } else { + if (out_flags) { + *out_flags &= ~FORMATTED_DURING_LAST_MOUNT; // reset flag + } } return ESP_OK; } static esp_err_t mount_to_vfs_fat(const esp_vfs_fat_mount_config_t *mount_config, sdmmc_card_t *card, uint8_t pdrv, - const char *base_path, FATFS **out_fs) + const char *base_path, FATFS **out_fs, vfs_fat_x_ctx_flags_t *out_flags) { FATFS *fs = NULL; esp_err_t err; @@ -157,17 +166,22 @@ static esp_err_t mount_to_vfs_fat(const esp_vfs_fat_mount_config_t *mount_config char drv[3] = {(char)('0' + pdrv), ':', 0}; // connect FATFS to VFS - err = esp_vfs_fat_register(base_path, drv, mount_config->max_files, &fs); + esp_vfs_fat_conf_t conf = { + .base_path = base_path, + .fat_drive = drv, + .max_files = mount_config->max_files, + }; + err = esp_vfs_fat_register_cfg(&conf, &fs); *out_fs = fs; if (err == ESP_ERR_INVALID_STATE) { // it's okay, already registered with VFS } else if (err != ESP_OK) { - ESP_LOGD(TAG, "esp_vfs_fat_register failed 0x(%x)", err); + ESP_LOGD(TAG, "esp_vfs_fat_register_cfg failed 0x(%x)", err); goto fail; } // Try to mount partition - err = s_f_mount(card, fs, drv, pdrv, mount_config); + err = s_f_mount(card, fs, drv, pdrv, mount_config, out_flags); if (err != ESP_OK) { goto fail; } @@ -207,7 +221,7 @@ static esp_err_t partition_card(const esp_vfs_fat_mount_config_t *mount_config, card->csd.sector_size, mount_config->allocation_unit_size); ESP_LOGW(TAG, "formatting card, allocation unit size=%d", alloc_unit_size); - const MKFS_PARM opt = {(BYTE)FM_ANY, 0, 0, 0, alloc_unit_size}; + const MKFS_PARM opt = {(BYTE)FM_ANY, (mount_config->use_one_fat ? 1 : 2), 0, 0, alloc_unit_size}; res = f_mkfs(drv, &opt, workbuf, workbuf_size); if (res != FR_OK) { err = ESP_FAIL; @@ -265,7 +279,9 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, err = sdmmc_card_init(host_config, card); CHECK_EXECUTE_RESULT(err, "sdmmc_card_init failed"); - err = mount_to_vfs_fat(mount_config, card, pdrv, dup_path, &fs); + vfs_fat_x_ctx_flags_t flags = 0; + + err = mount_to_vfs_fat(mount_config, card, pdrv, dup_path, &fs, &flags); CHECK_EXECUTE_RESULT(err, "mount_to_vfs failed"); if (out_card != NULL) { @@ -276,7 +292,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, s_saved_ctx_id = 0; } - ctx = calloc(sizeof(vfs_fat_sd_ctx_t), 1); + ctx = calloc(1, sizeof(vfs_fat_sd_ctx_t)); if (!ctx) { CHECK_EXECUTE_RESULT(ESP_ERR_NO_MEM, "no mem"); } @@ -285,6 +301,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, ctx->card = card; ctx->base_path = dup_path; ctx->fs = fs; + ctx->flags = flags; ctx_id = s_get_unused_context_id(); assert(ctx_id != FF_VOLUMES); s_ctx[ctx_id] = ctx; @@ -360,7 +377,9 @@ esp_err_t esp_vfs_fat_sdspi_mount(const char* base_path, err = sdmmc_card_init(host_config, card); CHECK_EXECUTE_RESULT(err, "sdmmc_card_init failed"); - err = mount_to_vfs_fat(mount_config, card, pdrv, dup_path, &fs); + vfs_fat_x_ctx_flags_t flags = 0; + + err = mount_to_vfs_fat(mount_config, card, pdrv, dup_path, &fs, &flags); CHECK_EXECUTE_RESULT(err, "mount_to_vfs failed"); if (out_card != NULL) { @@ -371,7 +390,7 @@ esp_err_t esp_vfs_fat_sdspi_mount(const char* base_path, s_saved_ctx_id = 0; } - ctx = calloc(sizeof(vfs_fat_sd_ctx_t), 1); + ctx = calloc(1, sizeof(vfs_fat_sd_ctx_t)); if (!ctx) { CHECK_EXECUTE_RESULT(ESP_ERR_NO_MEM, "no mem"); } @@ -380,6 +399,7 @@ esp_err_t esp_vfs_fat_sdspi_mount(const char* base_path, ctx->card = card; ctx->base_path = dup_path; ctx->fs = fs; + ctx->flags = flags; ctx_id = s_get_unused_context_id(); assert(ctx_id != FF_VOLUMES); s_ctx[ctx_id] = ctx; @@ -450,7 +470,7 @@ esp_err_t esp_vfs_fat_sdcard_unmount(const char *base_path, sdmmc_card_t *card) return err; } -esp_err_t esp_vfs_fat_sdcard_format(const char *base_path, sdmmc_card_t *card) +esp_err_t esp_vfs_fat_sdcard_format_cfg(const char *base_path, sdmmc_card_t *card, esp_vfs_fat_mount_config_t *cfg) { esp_err_t ret = ESP_OK; if (!card) { @@ -480,13 +500,22 @@ esp_err_t esp_vfs_fat_sdcard_format(const char *base_path, sdmmc_card_t *card) //format uint32_t id = FF_VOLUMES; - bool found = s_get_context_id_by_card(card, &id); - assert(found); + + { + const bool found = s_get_context_id_by_card(card, &id); + (void)found; + assert(found); + } + + if (cfg) { + s_ctx[id]->mount_config = *cfg; + } + size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size( card->csd.sector_size, s_ctx[id]->mount_config.allocation_unit_size); ESP_LOGI(TAG, "Formatting card, allocation unit size=%d", alloc_unit_size); - const MKFS_PARM opt = {(BYTE)FM_ANY, 0, 0, 0, alloc_unit_size}; + const MKFS_PARM opt = {(BYTE)FM_ANY, (s_ctx[id]->mount_config.use_one_fat ? 1 : 2), 0, 0, alloc_unit_size}; res = f_mkfs(drv, &opt, workbuf, workbuf_size); free(workbuf); if (res != FR_OK) { @@ -495,7 +524,7 @@ esp_err_t esp_vfs_fat_sdcard_format(const char *base_path, sdmmc_card_t *card) } //mount back - esp_err_t err = s_f_mount(card, s_ctx[id]->fs, drv, pdrv, &s_ctx[id]->mount_config); + esp_err_t err = s_f_mount(card, s_ctx[id]->fs, drv, pdrv, &s_ctx[id]->mount_config, NULL); if (err != ESP_OK) { unmount_card_core(base_path, card); ESP_LOGE(TAG, "failed to format, resources recycled, please mount again"); @@ -503,3 +532,7 @@ esp_err_t esp_vfs_fat_sdcard_format(const char *base_path, sdmmc_card_t *card) return ret; } + +esp_err_t esp_vfs_fat_sdcard_format(const char *base_path, sdmmc_card_t *card) { + return esp_vfs_fat_sdcard_format_cfg(base_path, card, NULL); +} diff --git a/lib/fatfs/vfs/vfs_fat_spiflash.c b/lib/fatfs/vfs/vfs_fat_spiflash.c index 98e4160f..0ee00e25 100644 --- a/lib/fatfs/vfs/vfs_fat_spiflash.c +++ b/lib/fatfs/vfs/vfs_fat_spiflash.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,16 +15,11 @@ #include "wear_levelling.h" #include "diskio_wl.h" -static const char* TAG = "vfs_fat_spiflash"; +// If the available sectors based on partition size are less than 128, +// the root directory sector should be set to 1. +#define MIN_REQ_SEC 128 -typedef struct vfs_fat_spiflash_ctx_t { - const esp_partition_t *partition; //The partition where the FAT is located - bool by_label; //If the partition is mounted by lable or not - BYTE pdrv; //Drive number that is mounted - FATFS *fs; //FAT structure pointer that is registered - wl_handle_t wlhandle; //WL handle - esp_vfs_fat_mount_config_t mount_config; //Mount configuration -} vfs_fat_spiflash_ctx_t; +static const char* TAG = "vfs_fat_spiflash"; static vfs_fat_spiflash_ctx_t *s_ctx[FF_VOLUMES] = {}; @@ -74,35 +69,78 @@ static uint32_t s_get_unused_context_id(void) return FF_VOLUMES; } -static esp_err_t s_f_mount_rw(FATFS *fs, const char *drv, const esp_vfs_fat_mount_config_t *mount_config) +vfs_fat_spiflash_ctx_t* get_vfs_fat_spiflash_ctx(wl_handle_t wlhandle) { - FRESULT fresult = f_mount(fs, drv, 1); - if (fresult != FR_OK) { - ESP_LOGW(TAG, "f_mount failed (%d)", fresult); + uint32_t id = FF_VOLUMES; + if (s_get_context_id_by_wl_handle(wlhandle, &id)) { + return s_ctx[id]; + } + return NULL; +} - bool need_mount_again = (fresult == FR_NO_FILESYSTEM || fresult == FR_INT_ERR) && mount_config->format_if_mount_failed; - if (!need_mount_again) { - return ESP_FAIL; +static esp_err_t s_f_mount_rw(FATFS *fs, const char *drv, const esp_vfs_fat_mount_config_t *mount_config, vfs_fat_x_ctx_flags_t *out_flags, size_t sec_num) +{ + FRESULT fresult = f_mount(fs, drv, 1); + if (fresult == FR_OK) { + if (out_flags) { + *out_flags &= ~FORMATTED_DURING_LAST_MOUNT; // reset flag } + return ESP_OK; + } - const size_t workbuf_size = 4096; - void *workbuf = ff_memalloc(workbuf_size); - if (workbuf == NULL) { - return ESP_ERR_NO_MEM; - } + const char *msg = "Unknown"; + const char *note = ""; + bool recoverable = false; + + switch (fresult) { + case FR_NO_FILESYSTEM: + msg = "No filesystem detected"; + note = "(This may indicate corrupt FS, or attempt to mount read-only fatfsgen image for write)"; + recoverable = true; + break; + case FR_INT_ERR: + msg = "Assertion failed"; + recoverable = true; + break; + default: + break; + } + + if (!recoverable || !mount_config->format_if_mount_failed) { + ESP_LOGE(TAG, "f_mount failed with error: \"%s\" [%d]. %s", msg, fresult, note); + return ESP_FAIL; + } + + ESP_LOGW(TAG, "FatFS mount (f_mount) failed with error: \"%s\" [%d]. Retrying after format...", msg, fresult); - size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(CONFIG_WL_SECTOR_SIZE, mount_config->allocation_unit_size); - ESP_LOGI(TAG, "Formatting FATFS partition, allocation unit size=%d", alloc_unit_size); - const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 0, alloc_unit_size}; - fresult = f_mkfs(drv, &opt, workbuf, workbuf_size); - free(workbuf); - workbuf = NULL; - ESP_RETURN_ON_FALSE(fresult == FR_OK, ESP_FAIL, TAG, "f_mkfs failed (%d)", fresult); - - ESP_LOGI(TAG, "Mounting again"); - fresult = f_mount(fs, drv, 0); - ESP_RETURN_ON_FALSE(fresult == FR_OK, ESP_FAIL, TAG, "f_mount failed after formatting (%d)", fresult); + const size_t workbuf_size = 4096; + void *workbuf = ff_memalloc(workbuf_size); + if (workbuf == NULL) { + return ESP_ERR_NO_MEM; } + + size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(CONFIG_WL_SECTOR_SIZE, mount_config->allocation_unit_size); + ESP_LOGI(TAG, "Formatting FATFS partition, allocation unit size=%d", alloc_unit_size); + UINT root_dir_entries; + if (CONFIG_WL_SECTOR_SIZE == 512) { + root_dir_entries = 16; + } else { + root_dir_entries = 128; + } + const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), (mount_config->use_one_fat ? 1 : 2), 0, (sec_num <= MIN_REQ_SEC ? root_dir_entries : 0), alloc_unit_size}; + fresult = f_mkfs(drv, &opt, workbuf, workbuf_size); + free(workbuf); + workbuf = NULL; + ESP_RETURN_ON_FALSE(fresult == FR_OK, ESP_FAIL, TAG, "f_mkfs failed (%d)", fresult); + + if (out_flags) { + *out_flags |= FORMATTED_DURING_LAST_MOUNT; // set flag + } + + ESP_LOGI(TAG, "Mounting again"); + fresult = f_mount(fs, drv, 1); + ESP_RETURN_ON_FALSE(fresult == FR_OK, ESP_FAIL, TAG, "f_mount failed after formatting (%d)", fresult); + return ESP_OK; } @@ -134,27 +172,36 @@ esp_err_t esp_vfs_fat_spiflash_mount_rw_wl(const char* base_path, ESP_GOTO_ON_ERROR(ff_diskio_register_wl_partition(pdrv, *wl_handle), fail, TAG, "ff_diskio_register_wl_partition failed pdrv=%i, error - 0x(%x)", pdrv, ret); FATFS *fs; - ret = esp_vfs_fat_register(base_path, drv, mount_config->max_files, &fs); + esp_vfs_fat_conf_t conf = { + .base_path = base_path, + .fat_drive = drv, + .max_files = mount_config->max_files, + }; + ret = esp_vfs_fat_register_cfg(&conf, &fs); if (ret == ESP_ERR_INVALID_STATE) { // it's okay, already registered with VFS } else if (ret != ESP_OK) { - ESP_LOGD(TAG, "esp_vfs_fat_register failed 0x(%x)", ret); + ESP_LOGD(TAG, "esp_vfs_fat_register_cfg failed 0x(%x)", ret); goto fail; } + vfs_fat_x_ctx_flags_t flags = 0; + + size_t sec_num = wl_size(*wl_handle) / wl_sector_size(*wl_handle); // Try to mount partition - ret = s_f_mount_rw(fs, drv, mount_config); + ret = s_f_mount_rw(fs, drv, mount_config, &flags, sec_num); if (ret != ESP_OK) { goto fail; } - ctx = calloc(sizeof(vfs_fat_spiflash_ctx_t), 1); + ctx = calloc(1, sizeof(vfs_fat_spiflash_ctx_t)); ESP_GOTO_ON_FALSE(ctx, ESP_ERR_NO_MEM, fail, TAG, "no mem"); ctx->partition = data_partition; ctx->by_label = (partition_label != NULL); ctx->pdrv = pdrv; ctx->fs = fs; ctx->wlhandle = *wl_handle; + ctx->flags = flags; memcpy(&ctx->mount_config, mount_config, sizeof(esp_vfs_fat_mount_config_t)); ctx_id = s_get_unused_context_id(); //At this stage, we should always get a free context, otherwise program should return already @@ -201,25 +248,43 @@ esp_err_t esp_vfs_fat_spiflash_unmount_rw_wl(const char* base_path, wl_handle_t return err; } -esp_err_t esp_vfs_fat_spiflash_format_rw_wl(const char* base_path, const char* partition_label) +esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const char* partition_label, esp_vfs_fat_mount_config_t *cfg) { esp_err_t ret = ESP_OK; bool partition_was_mounted = false; wl_handle_t temp_handle = WL_INVALID_HANDLE; uint32_t id = FF_VOLUMES; + size_t sec_num = 0; bool found = s_get_context_id_by_label(partition_label, &id); if (!found) { - const esp_vfs_fat_mount_config_t mount_config = { + esp_vfs_fat_mount_config_t default_mount_config = { .max_files = 1, .format_if_mount_failed = true, }; - ESP_RETURN_ON_ERROR(esp_vfs_fat_spiflash_mount_rw_wl(base_path, partition_label, &mount_config, &temp_handle), TAG, "Failed to mount"); + esp_vfs_fat_mount_config_t *mount_cfg = NULL; + if (cfg) { + mount_cfg = cfg; + } else { + mount_cfg = &default_mount_config; + } + ESP_RETURN_ON_ERROR(esp_vfs_fat_spiflash_mount_rw_wl(base_path, partition_label, mount_cfg, &temp_handle), TAG, "Failed to mount"); found = s_get_context_id_by_label(partition_label, &id); + sec_num = wl_size(temp_handle) / wl_sector_size(temp_handle); assert(found); + if (s_ctx[id]->flags & FORMATTED_DURING_LAST_MOUNT) { + ESP_LOGD(TAG, "partition was formatted during mounting, skipping another format"); + ret = ESP_OK; + goto mount_back; + } } else { partition_was_mounted = true; + if (cfg) { + s_ctx[id]->mount_config = *cfg; + } + temp_handle = s_ctx[id]->wlhandle; + sec_num = wl_size(temp_handle) / wl_sector_size(temp_handle); } //unmount @@ -236,7 +301,13 @@ esp_err_t esp_vfs_fat_spiflash_format_rw_wl(const char* base_path, const char* p } size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(CONFIG_WL_SECTOR_SIZE, s_ctx[id]->mount_config.allocation_unit_size); ESP_LOGI(TAG, "Formatting FATFS partition, allocation unit size=%d", alloc_unit_size); - const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), 0, 0, 0, alloc_unit_size}; + UINT root_dir_entries; + if (CONFIG_WL_SECTOR_SIZE == 512) { + root_dir_entries = 16; + } else { + root_dir_entries = 128; + } + const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), (s_ctx[id]->mount_config.use_one_fat ? 1 : 2), 0, (sec_num <= MIN_REQ_SEC ? root_dir_entries : 0), alloc_unit_size}; fresult = f_mkfs(drv, &opt, workbuf, workbuf_size); free(workbuf); workbuf = NULL; @@ -244,7 +315,7 @@ esp_err_t esp_vfs_fat_spiflash_format_rw_wl(const char* base_path, const char* p mount_back: if (partition_was_mounted) { - esp_err_t err = s_f_mount_rw(s_ctx[id]->fs, drv, &s_ctx[id]->mount_config); + esp_err_t err = s_f_mount_rw(s_ctx[id]->fs, drv, &s_ctx[id]->mount_config, NULL, sec_num); if (err != ESP_OK) { ESP_LOGE(TAG, "failed to mount back, go to recycle"); goto recycle; @@ -265,6 +336,10 @@ recycle: return ret; } +esp_err_t esp_vfs_fat_spiflash_format_rw_wl(const char* base_path, const char* partition_label) +{ + return esp_vfs_fat_spiflash_format_cfg_rw_wl(base_path, partition_label, NULL); +} esp_err_t esp_vfs_fat_spiflash_mount_ro(const char* base_path, const char* partition_label, @@ -287,11 +362,16 @@ esp_err_t esp_vfs_fat_spiflash_mount_ro(const char* base_path, ESP_GOTO_ON_ERROR(ff_diskio_register_raw_partition(pdrv, data_partition), fail, TAG, "ff_diskio_register_raw_partition failed pdrv=%i, error - 0x(%x)", pdrv, ret); FATFS *fs; - ret = esp_vfs_fat_register(base_path, drv, mount_config->max_files, &fs); + esp_vfs_fat_conf_t conf = { + .base_path = base_path, + .fat_drive = drv, + .max_files = mount_config->max_files, + }; + ret = esp_vfs_fat_register_cfg(&conf, &fs); if (ret == ESP_ERR_INVALID_STATE) { // it's okay, already registered with VFS } else if (ret != ESP_OK) { - ESP_LOGD(TAG, "esp_vfs_fat_register failed 0x(%x)", ret); + ESP_LOGD(TAG, "esp_vfs_fat_register_cfg failed 0x(%x)", ret); goto fail; } diff --git a/lib/fatfs/wl_fatfsgen.py b/lib/fatfs/wl_fatfsgen.py index 4a685434..13ef5168 100755 --- a/lib/fatfs/wl_fatfsgen.py +++ b/lib/fatfs/wl_fatfsgen.py @@ -1,11 +1,18 @@ #!/usr/bin/env python -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 +from typing import Optional -from construct import Const, Int32ul, Struct +from construct import Const +from construct import Int32ul +from construct import Struct from fatfs_utils.exceptions import WLNotInitialized -from fatfs_utils.utils import (FULL_BYTE, UINT32_MAX, FATDefaults, crc32, generate_4bytes_random, - get_args_for_partition_generator) +from fatfs_utils.utils import crc32 +from fatfs_utils.utils import FATDefaults +from fatfs_utils.utils import FULL_BYTE +from fatfs_utils.utils import generate_4bytes_random +from fatfs_utils.utils import get_args_for_partition_generator +from fatfs_utils.utils import UINT32_MAX from fatfsgen import FATFS @@ -53,6 +60,7 @@ class WLFATFS: WL_STATE_HEADER_SIZE = 64 WL_STATE_COPY_COUNT = 2 # always 2 copies for power failure safety WL_SECTOR_SIZE = 0x1000 + WL_SAFE_MODE_DUMP_SECTORS = 2 WL_STATE_T_DATA = Struct( 'pos' / Int32ul, @@ -97,7 +105,8 @@ class WLFATFS: temp_buff_size: int = FATDefaults.TEMP_BUFFER_SIZE, device_id: int = None, root_entry_count: int = FATDefaults.ROOT_ENTRIES_COUNT, - media_type: int = FATDefaults.MEDIA_TYPE) -> None: + media_type: int = FATDefaults.MEDIA_TYPE, + wl_mode: Optional[str] = None) -> None: self._initialized = False self._version = version self._temp_buff_size = temp_buff_size @@ -105,6 +114,7 @@ class WLFATFS: self.partition_size = size self.total_sectors = self.partition_size // FATDefaults.WL_SECTOR_SIZE self.wl_state_size = WLFATFS.WL_STATE_HEADER_SIZE + WLFATFS.WL_STATE_RECORD_SIZE * self.total_sectors + self.wl_mode = wl_mode # determine the number of required sectors (roundup to sector size) self.wl_state_sectors = (self.wl_state_size + FATDefaults.WL_SECTOR_SIZE - 1) // FATDefaults.WL_SECTOR_SIZE @@ -114,6 +124,9 @@ class WLFATFS: wl_sectors = (WLFATFS.WL_DUMMY_SECTORS_COUNT + WLFATFS.WL_CFG_SECTORS_COUNT + self.wl_state_sectors * WLFATFS.WL_STATE_COPY_COUNT) + if self.wl_mode is not None and self.wl_mode == 'safe': + wl_sectors += WLFATFS.WL_SAFE_MODE_DUMP_SECTORS + self.plain_fat_sectors = self.total_sectors - wl_sectors self.plain_fatfs = FATFS( explicit_fat_type=explicit_fat_type, @@ -202,13 +215,15 @@ class WLFATFS: if __name__ == '__main__': desc = 'Create a FAT filesystem with support for wear levelling and populate it with directory content' args = get_args_for_partition_generator(desc, wl=True) - wl_fatfs = WLFATFS(sectors_per_cluster=args.sectors_per_cluster, - size=args.partition_size, + wl_fatfs = WLFATFS(size=args.partition_size, sector_size=args.sector_size, - root_entry_count=args.root_entry_count, + fat_tables_cnt=args.fat_count, + sectors_per_cluster=args.sectors_per_cluster, explicit_fat_type=args.fat_type, long_names_enabled=args.long_name_support, - use_default_datetime=args.use_default_datetime) + use_default_datetime=args.use_default_datetime, + root_entry_count=args.root_entry_count, + wl_mode=args.wl_mode) wl_fatfs.plain_fatfs.generate(args.input_directory) wl_fatfs.init_wl() -- cgit v1.2.3