diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/README.md b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/README.md index ab8040e276d..9ed38dab29c 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/README.md +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/README.md @@ -64,6 +64,18 @@ PCM Signal supports three configurations in menuconfig: PCM Role, PCM Polar and - The default configuration is `Stereo Mode`, you can change the PCM Channel mode in `menuconfig` path: `Component config --> Bluetooth --> Controller Options --> PCM Signal Configurations --> PCM Signal Configurations: Role, Polar and Channel Mode(Stereo/Mono) --> Channel Mode(Stereo/Mono)` +### Special Configurations for PBA Client + +To use PBA Client function, we need to enable PBA Client in `menuconfig` path: `Component config --> Bluetooth --> Bluedroid Options --> Classic Bluetooth --> Classic BT PBA Client`, this example already enable PBA Client by `sdkconfig.defaults`. + +Step to initialize PBA Client connection: + +- Register user callback: `esp_pbac_register_callback(bt_app_pbac_cb)` +- Initialize PBA Client API: `esp_pbac_init()` +- Connect to peer device ... +- Call `esp_pbac_connect(peer_addr, supported_features, 0)`, this will initiate service discover and try to connect to PBA Server. +- After the operation done, whether success or not, we will receive a `ESP_PBAC_CONNECTION_STATE_EVT` event in user callback. + ### Codec Choice ESP32 supports two types of codec for HFP audio data: `CVSD` and `mSBC`. diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/CMakeLists.txt index 728e74c3529..d91b3279d0b 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/CMakeLists.txt +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/CMakeLists.txt @@ -2,6 +2,7 @@ idf_component_register(SRCS "app_hf_msg_set.c" "bt_app_core.c" "bt_app_hf.c" "gpio_pcm_config.c" + "bt_app_pbac.c" "main.c" PRIV_REQUIRES bt nvs_flash esp_driver_gpio console esp_ringbuf INCLUDE_DIRS ".") diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_hf.c b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_hf.c index 26f2af87d85..65169f18328 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_hf.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_hf.c @@ -17,6 +17,7 @@ #include "esp_bt_device.h" #include "esp_gap_bt_api.h" #include "esp_hf_client_api.h" +#include "esp_pbac_api.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" @@ -244,6 +245,9 @@ void bt_app_hf_client_cb(esp_hf_client_cb_event_t event, esp_hf_client_cb_param_ param->conn_stat.peer_feat, param->conn_stat.chld_feat); memcpy(peer_addr,param->conn_stat.remote_bda,ESP_BD_ADDR_LEN); + if (param->conn_stat.state == ESP_HF_CLIENT_CONNECTION_STATE_SLC_CONNECTED) { + esp_pbac_connect(peer_addr); + } break; } diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_pbac.c b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_pbac.c new file mode 100644 index 00000000000..09ac19811c9 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_pbac.c @@ -0,0 +1,86 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "esp_log.h" +#include "esp_bt.h" +#include "esp_pbac_api.h" +#include "bt_app_core.h" +#include "bt_app_pbac.h" + +#define BT_PBAC_TAG "BT_PBAC" + +esp_pbac_conn_hdl_t pba_conn_handle; + +void bt_app_pbac_cb(esp_pbac_event_t event, esp_pbac_param_t *param) +{ + switch (event) + { + case ESP_PBAC_CONNECTION_STATE_EVT: + ESP_LOGI(BT_PBAC_TAG, "PBA client connection event, state: %s, reason: 0x%x", (param->conn_stat.connected ? "Connected" : "Disconnected"), param->conn_stat.reason); + ESP_LOGI(BT_PBAC_TAG, "Peer supported repositories: 0x%x, supported features: 0x%lx", param->conn_stat.peer_supported_repo, param->conn_stat.peer_supported_feat); + if (param->conn_stat.connected) { + pba_conn_handle = param->conn_stat.handle; + /* set phone book to "telecom" folder, just to test set phone book function */ + esp_pbac_set_phone_book(pba_conn_handle, ESP_PBAC_SET_PHONE_BOOK_FLAGS_DOWN, "telecom"); + } + break; + case ESP_PBAC_PULL_PHONE_BOOK_RESPONSE_EVT: + /* if multiple PBA connection, we should check param->pull_phone_book_rsp.handle */ + ESP_LOGI(BT_PBAC_TAG, "PBA client pull phone book response, handle:%d, result: 0x%x", param->pull_phone_book_rsp.handle, param->pull_phone_book_rsp.result); + if (param->pull_phone_book_rsp.result == ESP_PBAC_SUCCESS && param->pull_phone_book_rsp.data_len > 0) { + printf("%.*s\n", param->pull_phone_book_rsp.data_len, param->pull_phone_book_rsp.data); + /* copy data to other buff before return, if phone book size is too large, it will be sent in multiple response event */ + } + if (param->pull_phone_book_rsp.final) { + ESP_LOGI(BT_PBAC_TAG, "PBA client pull phone book final response"); + /* pull phone book done, now we can perform other operation */ + if (param->pull_phone_book_rsp.result == ESP_PBAC_SUCCESS && param->pull_phone_book_rsp.include_phone_book_size) { + ESP_LOGI(BT_PBAC_TAG, "Phone Book Size:%d", param->pull_phone_book_rsp.phone_book_size); + esp_pbac_pull_phone_book_app_param_t app_param = {0}; + app_param.include_property_selector = 1; + /* property bit mask, filter out photo, refer to Phone Book Access Profile */ + app_param.property_selector = 0xFFFFFFF7; + /* pull again, without 'max_list_count = 0', then we can get the entire phone book */ + esp_pbac_pull_phone_book(pba_conn_handle, "telecom/pb.vcf", &app_param); + } + } + break; + case ESP_PBAC_SET_PHONE_BOOK_RESPONSE_EVT: + ESP_LOGI(BT_PBAC_TAG, "PBA client set phone book response, handle:%d, result: 0x%x", param->set_phone_book_rsp.handle, param->set_phone_book_rsp.result); + /* done, set phone book response will always be a final response */ + if (param->set_phone_book_rsp.result == ESP_PBAC_SUCCESS) { + esp_pbac_pull_phone_book_app_param_t app_param = {0}; + app_param.include_max_list_count = 1; + /* set max_list_count to zero, then we can get phone book size in peer response */ + app_param.max_list_count = 0; + /* pull phone book use a absolute path; if no app param, we can pass a NULL to API */ + esp_pbac_pull_phone_book(pba_conn_handle, "telecom/pb.vcf", &app_param); + } + break; + case ESP_PBAC_PULL_VCARD_LISTING_RESPONSE_EVT: + ESP_LOGI(BT_PBAC_TAG, "PBA client pull vCard listing response, handle:%d, result: 0x%x", param->pull_vcard_listing_rsp.handle, param->pull_vcard_listing_rsp.result); + if (param->pull_vcard_listing_rsp.result == ESP_PBAC_SUCCESS) { + printf("%.*s\n", param->pull_vcard_listing_rsp.data_len, param->pull_vcard_listing_rsp.data); + } + if (param->pull_vcard_listing_rsp.final) { + ESP_LOGI(BT_PBAC_TAG, "PBA client pull vCard listing final response"); + } + break; + case ESP_PBAC_PULL_VCARD_ENTRY_RESPONSE_EVT: + ESP_LOGI(BT_PBAC_TAG, "PBA client pull vCard entry response, handle:%d, result: 0x%x", param->pull_vcard_entry_rsp.handle, param->pull_vcard_entry_rsp.result); + if (param->pull_vcard_entry_rsp.result == ESP_PBAC_SUCCESS) { + printf("%.*s\n", param->pull_vcard_entry_rsp.data_len, param->pull_vcard_entry_rsp.data); + } + if (param->pull_vcard_entry_rsp.final) { + ESP_LOGI(BT_PBAC_TAG, "PBA client pull vCard entry final response"); + } + break; + default: + break; + } +} diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_pbac.h b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_pbac.h new file mode 100644 index 00000000000..2e0b87b53be --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_pbac.h @@ -0,0 +1,11 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "esp_bt.h" +#include "esp_pbac_api.h" + +void bt_app_pbac_cb(esp_pbac_event_t event, esp_pbac_param_t *param); diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/main.c b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/main.c index 984695aaaac..3e40498143d 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/main.c @@ -21,10 +21,12 @@ #include "esp_bt_device.h" #include "esp_gap_bt_api.h" #include "esp_hf_client_api.h" +#include "esp_pbac_api.h" #include "bt_app_hf.h" #include "gpio_pcm_config.h" #include "esp_console.h" #include "app_hf_msg_set.h" +#include "bt_app_pbac.h" esp_bd_addr_t peer_addr = {0}; static char peer_bdname[ESP_BT_GAP_MAX_BDNAME_LEN + 1]; @@ -251,6 +253,8 @@ static void bt_hf_client_hdl_stack_evt(uint16_t event, void *p_param) esp_bt_gap_register_callback(esp_bt_gap_cb); esp_hf_client_register_callback(bt_app_hf_client_cb); esp_hf_client_init(); + esp_pbac_register_callback(bt_app_pbac_cb); + esp_pbac_init(); #if (CONFIG_EXAMPLE_SSP_ENABLED == true) /* Set default parameters for Secure Simple Pairing */ diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/sdkconfig.defaults b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/sdkconfig.defaults index 351210d4f83..643ce88d5da 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/sdkconfig.defaults +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/sdkconfig.defaults @@ -8,3 +8,4 @@ CONFIG_BT_BLUEDROID_ENABLED=y CONFIG_BT_CLASSIC_ENABLED=y CONFIG_BT_HFP_ENABLE=y CONFIG_BT_HFP_CLIENT_ENABLE=y +CONFIG_BT_PBAC_ENABLED=y