feat(bt/bluedroid): Add PBAP client sample code in hfp_hf example

This commit is contained in:
linruihao
2024-10-23 15:20:44 +08:00
parent 42c0f17b7d
commit 125b303720
7 changed files with 119 additions and 0 deletions

View File

@@ -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`.

View File

@@ -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 ".")

View File

@@ -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;
}

View File

@@ -0,0 +1,86 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#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;
}
}

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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