LE Audio CAP Acceptor
The purpose of this document is to give an overview of the LE audio CAP acceptor sample. The LE audio CAP acceptor sample implements a very simple LE audio CAP acceptor device and it can be used as a framework to develop many different CAP acceptor-role applications.
The sample uses LE host, LE manager, and LE audio module. The above figure shows the relationships between several modules in the sample.
More information about these modules can be found in the LE Host, LE Manager and LE Audio Manager documentation.
Requirements
The sample supports the following development kits:
Hardware Platforms |
Board Name |
Build Target |
---|---|---|
RTL87x3E HDK |
RTL87x3E EVB |
lea_cap_acceptor_4M_bank0 lea_cap_acceptor_16M_bank0 |
RTL87x3EP HDK |
RTL87x3EP EVB |
lea_cap_acceptor_4M_bank0 lea_cap_acceptor_16M_bank0 |
RTL87x3D HDK |
RTL87x3D EVB |
lea_cap_acceptor_8M_bank0 lea_cap_acceptor_16M_bank0 lea_cap_acceptor_cs_16M_bank0 |
This sample project can be found under board\evb\lea_cap_acceptor
in SDK folder structure.
Developers can choose the project according to the Board Name
and choose the Build Target
according to the flash map.
When built for an xxx_4M_xxx
build target, the sample is configured to build and run with a 4M flash map.
When built for an xxx_8M_xxx
build target, the sample is configured to build and run with an 8M flash map.
When built for an xxx_16M_xxx
build target, the sample is configured to build and run with a 16M flash map.
For more requirements, please refer to Quick Start.
Wiring
The sample requires support for user command interface. For specific wiring instructions, please refer to Data UART Connection in User Command Interface.
Configurations
The configurations for the sample include Configurable Items and Generating System Config File.
Configurable Items
The sample’s configurable functions are defined in src\sample\lea_samples\lea_cap_acceptor\app_lea_cap_acc_flags.h
:
LE link number
The LE link number is configured by the macro definition
APP_MAX_BLE_LINK_NUM
./** * @brief Config APP LE link number * */ #define APP_MAX_BLE_LINK_NUM 1
Input audio data test
If the macro definition
APP_LEA_INPUT_AUDIO_DATA_TEST
is enabled, the sample will test the ISO data send procedure.#define APP_LEA_INPUT_AUDIO_DATA_TEST 1 /**< Input (Host to Controller).*/
EATT support
EATT is configured by the macro definition
APP_LEA_EATT_SUPPORT
. If the macroAPP_LEA_EATT_SUPPORT
is enabled, the sample will support EATT./** @brief Config EATT: 0-Disable EATT, 1-Enable EATT */ #define APP_LEA_EATT_SUPPORT 0
GATT client service table storage
The macro definition
GATTC_TBL_STORAGE_SUPPORT
is used to configure the sample to support GATT discovery result storage.0 - Do not store GATT discovery result.
1 - Store GATT discovery result to FTL.
#define GATTC_TBL_STORAGE_SUPPORT 1
CAP role component
#define BAP_UNICAST_CLIENT 0 #define BAP_UNICAST_SERVER 1 #define BAP_BROADCAST_SOURCE 0 #define BAP_BROADCAST_SINK 1 #define BAP_BROADCAST_ASSISTANT 0 #define BAP_SCAN_DELEGATOR 1 #define VCP_VOLUME_CONTROLLER 0 #define VCP_VOLUME_RENDERER 1 #define MICP_MIC_CONTROLLER 0 #define MICP_MIC_DEVICE 1 #define CCP_CALL_CONTROL_SERVER 0 #define CCP_CALL_CONTROL_CLIENT 1 #define MCP_MEDIA_CONTROL_SERVER 0 #define MCP_MEDIA_CONTROL_CLIENT 1 #define CSIP_SET_COORDINATOR 0 #define CSIP_SET_MEMBER 1
Generating System Config File
Developers shall configure the following items through MCUConfig Tool:
Configurable Item |
Value |
---|---|
LE Link Number |
≥ |
LE Slave Link Number |
≥ |
CCCD Count |
64 |
CCCD Per Link Count |
32 |
LE Bond Device number |
≥ |
Support LE Isochronous |
Enable |
LE CIG number |
2 |
LE CIS number |
4 |
LE BIG number |
2 |
LE BIS number |
4 |
Support LE PA |
Enable |
LE PA number |
2 |
Building and Downloading
Take the project rtl87x3e_lea_cap_acceptor.uvprojx
and target lea_cap_acceptor_4M_bank0
as an example,
to build and run the sample with the Keil development environment, follow the steps listed below:
Open
rtl87x3e_lea_cap_acceptor.uvprojx
.Choose the build target
lea_cap_acceptor_4M_bank0
.Building the target.
After a successful compilation, the sample bin file
lea_cap_acceptor_bank0_MP-v0.0.0.0-xxx.bin
will be generated in the directorybin\rtl87x3e\flash_4M_dualbank\bank0
.Download sample bin into EVB board.
Press reset button on the EVB board and it will start running.
Experimental Verification
After downloading the sample bin to the EVB board, the developer can test it either by using another kit that is running the LE Audio CAP Commander or the LE Audio CAP Initiator sample.
Testing with Another Kit
Testing with CAP Initiator
Please refer to Testing with Another Kit in LE Audio CAP Initiator.
Testing with CAP Commander
Please refer to Testing with Another Kit in LE Audio CAP Commander.
Code Overview
The main purpose of this chapter is to help sample developers become familiar with the development process related to the CAP Acceptor Role. LE audio CAP acceptor sample code overview will be introduced according to the following parts:
LE audio CAP acceptor sample project overview will be introduced in chapter Source Code Directory.
For CAP acceptor related parameters and Bluetooth Host initialization, please refer to the chapter Initialization.
For CAP acceptor related GAP message handler, please refer to the chapter GAP Message Handler.
For CAP acceptor related callback handler, please refer to the chapter Callback Message Handler.
For CAP acceptor related test flow, please refer to the chapter LE Audio Flow.
Source Code Directory
This section describes the project directory and project structure. Reference files directory is as follows:
Project directory:
board\evb\lea_cap_acceptor
.Project source code directory:
src\sample\lea_samples\lea_cap_acceptor
.
Source files in the sample project are currently categorized into several groups as below:
└── lea_cap_acceptor_4M_bank0
├── include ROM UUID header files. Developers do not need to modify it.
├── lib The protocol stack and GAP library file. Developers do not need to modify it.
├── gap_utils.lib
├── ROM.lib
├── upperstack_4M.lib
├── hal_utils.lib
├── ble_mgr.lib
├── leaudio.lib
└── sysm.lib
├── cmsis The cmsis source code. Developers do not need to modify it.
├── APP The sample source code.
├── data_uart.c
├── user_cmd_parse.c
├── bt_ext_ftl.c GATT discovery result storage
├── gattc_tbl_storage.c
├── app_lea_cap_acc_main.c Main entry
├── app_lea_cap_acc_gap.c LE GAP initialization and message handler
├── app_lea_cap_acc_profile.c LE audio profile initialization
├── app_lea_cap_acc_cfg.c NV config
├── app_lea_cap_acc_link.c LE link utility
├── app_lea_cap_acc_user_cmd.c User Command
├── app_lea_cap_acc_adv.c Advertising manager
├── app_lea_cap_acc_scan.c Scan manager
├── app_lea_cap_acc_csis.c CSIS message handler
├── app_lea_cap_acc_bap.c BAP message handler
├── app_lea_cap_acc_vc_mic.c VCS and MISC message handler
├── app_lea_cap_acc_audio_data.c Audio data test code
├── app_lea_cap_acc_mcp.c MCP message handler
├── app_lea_cap_acc_content.c CCP/MCP content
├── app_lea_cap_acc_ccp.c CCP message handler
└── app_lea_cap_acc_ecfc.c ECFC message handler
└── io_hal
Initialization
The main()
function is invoked when the board is powered on or the chip boots up, and it performs the following initialization functions:
int main(void)
{
app_cfg_init();
app_msg_init();
board_init();
app_gap_init();
framework_init();
#if APP_LEA_INPUT_AUDIO_DATA_TEST
app_init_timer(app_evt_queue_handle, MAX_NUMBER_OF_APP_TIMER_MODULE);
#endif
pwr_mgr_init();
task_init();
os_sched_start();
return 0;
}
GAP Parameter Initialization
The app_gap_init()
function is used to initialize the GAP parameters.
Developers can easily customize the sample by modifying the following parameter values:
void app_gap_init(void)
{
le_gap_init(APP_MAX_BLE_LINK_NUM);
gap_lib_init();
/* Device name and device appearance */
uint8_t device_name[GAP_DEVICE_NAME_LEN] = "CAP Acceptor";
uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN;
le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name);
le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance);
/* Use LE Advertising Extensions */
uint8_t use_extended = true;
le_set_gap_param(GAP_PARAM_USE_EXTENDED_ADV, sizeof(use_extended), &use_extended);
/* GAP Bond Manager parameters */
uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE;
uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG | GAP_AUTHEN_BIT_SC_FLAG;
uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT;
uint8_t auth_oob = false;
uint8_t auth_use_fix_passkey = false;
uint32_t auth_fix_passkey = 0;
uint8_t auth_sec_req_enable = false;
uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG | GAP_AUTHEN_BIT_SC_FLAG;
uint8_t irk_auto = true;
gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode);
gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags);
gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap);
gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob);
le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey);
le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey),
&auth_use_fix_passkey);
le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable);
le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags),
&auth_sec_req_flags);
le_bond_set_param(GAP_PARAM_BOND_GEN_LOCAL_IRK_AUTO, sizeof(uint8_t), &irk_auto);
/* register gap message callback */
le_register_app_cb(app_gap_callback);
/* register gap common message callback */
gap_register_app_cb(app_gap_common_callback);
/* ble manager module initialize */
app_ble_mgr_lib_init();
#if APP_LEA_EATT_SUPPORT
app_lea_ecfc_init();
#endif
}
-
Initialize GAP and set the link number.
-
Initialize
gap_utils.lib
. -
Configure the device name with the parameter
GAP_PARAM_DEVICE_NAME
.Configure the appearance with the parameter
GAP_PARAM_APPEARANCE
.Configure the sample to use LE Advertising Extensions with the parameter
GAP_PARAM_USE_EXTENDED_ADV
.
gap_set_param()
andle_bond_set_param()
Initialize GAP pairing parameters.
le_register_app_cb()
andgap_register_app_cb()
Register the GAP message callback function
app_gap_callback()
and GAP common message callback functionapp_gap_common_callback()
, and all GAP callback messages will be handled in these callbacks.app_ble_mgr_lib_init()
Initialize the LE manager library. More information can be found in the chapter LE Manager Initialization of LE Manager.
void app_ble_mgr_lib_init(void) { BLE_MGR_PARAMS param = {0}; param.ble_ext_adv.enable = true; param.ble_ext_adv.adv_num = 1; #if (BAP_BROADCAST_SINK || BAP_SCAN_DELEGATOR) param.ble_scan.enable = true; gap_vendor_le_set_host_feature(0, 1); #endif param.ble_conn.enable = true; param.ble_conn.link_num = APP_MAX_BLE_LINK_NUM; ble_mgr_init(¶m); }
app_lea_ecfc_init()
Initialize ECFC if the sample enables
APP_LEA_EATT_SUPPORT
.void app_lea_ecfc_init(void) { gap_ecfc_init(1); gap_ecfc_reg_proto(PSM_EATT, app_lea_ecfc_callback, true, &app_ecfc_le_proto_id, GAP_ECFC_DATA_PATH_GATT); }
More information on LE GAP initialization and startup flow can be found in the GAP Parameters Initialization chapter of the LE Host.
LE Audio Profile Initialization
When the CAP acceptor application starts running, if the developer inputs the command reg 0
, the app_lea_profile_init()
will be called to initialize
the LE audio profile parameters.
More information can be found in the LE Audio Manager.
void app_lea_profile_init(void)
{
gatt_svc_init(GATT_SVC_USE_EXT_SERVER, MAX_BLE_SRV_NUM);
#if GATTC_TBL_STORAGE_SUPPORT
gattc_tbl_storage_init();
#endif
T_BLE_AUDIO_PARAMS ble_audio_param = {0};
ble_audio_param.evt_queue_handle = app_evt_queue_handle;
ble_audio_param.io_queue_handle = app_io_queue_handle;
#if APP_LEA_EATT_SUPPORT
ble_audio_param.bt_gatt_client_init = (GATT_CLIENT_DISCOV_MODE_REG_SVC_BIT |
GATT_CLIENT_DISCOV_MODE_CCCD_STORAGE_BIT |
GATT_CLIENT_DISCOV_MODE_USE_EXT_CLIENT |
GATT_CLIENT_DISCOV_MODE_GATT_SVC);
gatt_client_cfg_client_supported_feature(GATT_SVC_CLIENT_SUPPORTED_FEATURES_EATT_BEARER_BIT);
#else
ble_audio_param.bt_gatt_client_init = (GATT_CLIENT_DISCOV_MODE_REG_SVC_BIT |
GATT_CLIENT_DISCOV_MODE_CCCD_STORAGE_BIT |
GATT_CLIENT_DISCOV_MODE_USE_EXT_CLIENT);
#endif
ble_audio_param.acl_link_num = APP_MAX_BLE_LINK_NUM;
ble_audio_param.io_event_type = IO_MSG_TYPE_LE_AUDIO;
ble_audio_init(&ble_audio_param);
app_lea_acc_vc_mic_init();
app_lea_acc_bap_init();
app_lea_acc_cap_init();
app_lea_audio_data_init();
}
-
Initialize the GATT service module and service number in the LE manager library.
gattc_tbl_storage_init()
Initialize the GATT client service table storage function.
-
Initialize LE audio related parameters.
app_lea_acc_vc_mic_init()
Initialize the parameters for VCS and MICS, and register the callback function to handle related messages.
void app_lea_acc_vc_mic_init(void) { T_BLE_AUDIO_VC_MIC_PARAMS vc_mic_param = {0}; T_MICS_PARAM mics_param = {MICS_NOT_MUTE}; T_VCS_PARAM vcs_param = {0}; ...... ble_audio_vc_mic_init(&vc_mic_param); #if APP_LEA_VOCS_SUPPORT ...... vocs_set_param(0, ¶m_vocs); #endif #if (APP_LEA_AICS_FOR_VCS_SUPPORT || APP_LEA_AICS_FOR_MICS_SUPPORT) ...... #if APP_LEA_AICS_FOR_VCS_SUPPORT ...... aics_set_param(aics_vcs_srv_instance_id, AICS_PARAM_INPUT_STATE, sizeof(T_AICS_INPUT_STATE), (uint8_t *)&input_state, true); aics_set_param(aics_vcs_srv_instance_id, AICS_PARAM_GAIN_SETTING_PROP, sizeof(T_AICS_GAIN_SETTING_PROP), (uint8_t *)&gain_prop, false); aics_set_param(aics_vcs_srv_instance_id, AICS_PARAM_INPUT_TYPE, sizeof(uint8_t), &input_type, false); aics_set_param(aics_vcs_srv_instance_id, AICS_PARAM_INPUT_STATUS, sizeof(uint8_t), &input_status, false); aics_set_param(aics_vcs_srv_instance_id, AICS_PARAM_INPUT_DES, strlen(app_audio_input_des_vcs), (uint8_t *)app_audio_input_des_vcs, false); #endif #if APP_LEA_AICS_FOR_MICS_SUPPORT ...... aics_set_param(aics_mics_srv_instance_id, AICS_PARAM_INPUT_STATE, sizeof(T_AICS_INPUT_STATE), (uint8_t *)&input_state, true); aics_set_param(aics_mics_srv_instance_id, AICS_PARAM_GAIN_SETTING_PROP, sizeof(T_AICS_GAIN_SETTING_PROP), (uint8_t *)&gain_prop, false); aics_set_param(aics_mics_srv_instance_id, AICS_PARAM_INPUT_TYPE, sizeof(uint8_t), &input_type, false); aics_set_param(aics_mics_srv_instance_id, AICS_PARAM_INPUT_STATUS, sizeof(uint8_t), &input_status, false); aics_set_param(aics_mics_srv_instance_id, AICS_PARAM_INPUT_DES, strlen(app_audio_input_des_mics), (uint8_t *)app_audio_input_des_mics, false); #endif #endif #if MICP_MIC_DEVICE mics_param.mic_mute = MICS_NOT_MUTE; mics_set_param(&mics_param); #endif #if VCP_VOLUME_RENDERER vcs_param.volume_setting = app_cfg_nv.lea_vcs_vol_setting; vcs_param.mute = app_cfg_nv.lea_vcs_mute; vcs_param.change_counter = app_cfg_nv.lea_vcs_change_cnt; vcs_param.volume_flags = app_cfg_nv.lea_vcs_vol_flag; vcs_param.step_size = app_cfg_nv.lea_vcs_step_size; vcs_set_param(&vcs_param); #endif ble_audio_cback_register(app_lea_acc_vc_mic_handle_msg); }
app_lea_acc_bap_init()
Initialize LE audio BAP role.
void app_lea_acc_bap_init(void) { T_BAP_ROLE_INFO role_info = {0}; ble_audio_cback_register(app_lea_acc_bap_handle_msg); ...... bap_role_init(&role_info); T_PACS_PARAMS pacs_params = {0}; ...... pacs_params.sink_locations.is_exist = true; pacs_params.sink_locations.is_notify = true; pacs_params.sink_locations.is_write = false; pacs_params.sink_locations.sink_audio_location = app_db.lea_sink_audio_location; pacs_params.source_locations.is_exist = true; pacs_params.source_locations.is_notify = true; pacs_params.source_locations.is_write = false; pacs_params.source_locations.source_audio_location = app_db.lea_source_audio_location; pacs_params.supported_contexts.is_notify = true; pacs_params.supported_contexts.sink_supported_contexts = app_db.lea_sink_supported_contexts; pacs_params.supported_contexts.source_supported_contexts = app_db.lea_source_supported_contexts; pacs_pac_add(SERVER_AUDIO_SINK, app_lea_sink_codec, sizeof(app_lea_sink_codec), true); pacs_pac_add(SERVER_AUDIO_SOURCE, app_lea_source_codec, sizeof(app_lea_source_codec), true); pacs_init(&pacs_params); #if BAP_UNICAST_SERVER app_ext_adv_adv_cfg(LE_EXT_ADV_ASCS); #endif #if BAP_SCAN_DELEGATOR app_ext_adv_adv_cfg(LE_EXT_ADV_BASS); #endif }
app_lea_acc_cap_init()
Initialize LE audio CAP related parameters.
void app_lea_acc_cap_init(void) { T_CAP_INIT_PARAMS cap_init_param = {0}; cap_init_param.cap_role = CAP_ROLE; cap_init_param.cas.enable = true; #if CSIP_SET_MEMBER if (app_db.csis_cfg != APP_LEA_CSIS_CFG_NOT_EXIST) { app_lea_acc_csis_init(&cap_init_param); } #endif #if MCP_MEDIA_CONTROL_CLIENT app_lea_acc_mcp_init_cap(&cap_init_param); #endif #if CCP_CALL_CONTROL_CLIENT app_lea_acc_ccp_init_cap(&cap_init_param); #endif cap_init(&cap_init_param); }
app_lea_audio_data_init()
Initialize the LE audio data test code.
void app_lea_audio_data_init(void) { os_queue_init(&app_db.iso_input_queue); os_queue_init(&app_db.iso_output_queue); gap_register_direct_cb(app_lea_data_direct_cb); }
GAP Message Handler
The app_handle_gap_msg()
function is invoked whenever a GAP message is received from the GAP.
More information on GAP messages can be found in the Bluetooth LE GAP Message chapter
of the LE Host.
void app_handle_gap_msg(T_IO_MSG *p_gap_msg)
{
T_LE_GAP_MSG gap_msg;
memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param));
ble_mgr_handle_gap_msg(p_gap_msg->subtype, &gap_msg);
APP_PRINT_TRACE1("app_handle_gap_msg: subtype %d", p_gap_msg->subtype);
switch (p_gap_msg->subtype)
{
case GAP_MSG_LE_DEV_STATE_CHANGE:
{
app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state,
gap_msg.msg_data.gap_dev_state_change.cause);
}
break;
case GAP_MSG_LE_CONN_STATE_CHANGE:
{
app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id,
(T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state,
gap_msg.msg_data.gap_conn_state_change.disc_cause);
}
break;
......
case GAP_MSG_LE_AUTHEN_STATE_CHANGE:
{
app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id,
gap_msg.msg_data.gap_authen_state.new_state,
gap_msg.msg_data.gap_authen_state.status);
}
break;
......
}
ble_audio_handle_gap_msg(p_gap_msg->subtype, gap_msg);
}
The CAP acceptor sample will call
app_ext_adv_params_init()
andapp_ext_adv_start()
to start advertising when receivingGAP_INIT_STATE_STACK_READY
.void app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) { APP_PRINT_INFO3("app_handle_dev_state_evt: init state %d, scan state %d, cause 0x%x", new_state.gap_init_state, new_state.gap_scan_state, cause); if (gap_dev_state.gap_init_state != new_state.gap_init_state) { if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { uint8_t bt_addr[6]; APP_PRINT_INFO0("app_handle_dev_state_evt: GAP stack ready"); /*stack ready*/ gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); data_uart_print("local bd addr: 0x%2x:%2x:%2x:%2x:%2x:%2x\r\n", bt_addr[5], bt_addr[4], bt_addr[3], bt_addr[2], bt_addr[1], bt_addr[0]); app_ext_adv_params_init(); app_ext_adv_start(); } } gap_dev_state = new_state; }
The CAP acceptor sample will call
app_ext_adv_start()
to start advertising when receivingGAP_CONN_STATE_DISCONNECTED
.void app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) { T_APP_LE_LINK *p_link; APP_PRINT_INFO3("app_handle_conn_state_evt: conn_id %d, new_state %d, disc_cause 0x%x", conn_id, new_state, disc_cause); p_link = app_link_find_le_link_by_conn_id(conn_id); switch (new_state) { ...... case GAP_CONN_STATE_DISCONNECTED: if (p_link != NULL) { if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) { APP_PRINT_ERROR2("app_handle_conn_state_evt: connection lost, conn_id %d, cause 0x%x", conn_id, disc_cause); } data_uart_print("Disconnect conn_id %d\r\n", conn_id); app_link_free_le_link(p_link); app_ext_adv_start(); } break; ...... default: break; } }
If the MCP client or the CCP client is supported, the CAP acceptor sample will call
gatt_client_start_discovery_all()
to start the service discovery procedure when receivingGAP_AUTHEN_STATE_COMPLETE
with causeGAP_SUCCESS
.void app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) { APP_PRINT_INFO2("app_handle_authen_state_evt: conn_id %d, cause 0x%x", conn_id, cause); switch (new_state) { case GAP_AUTHEN_STATE_COMPLETE: { if (cause == GAP_SUCCESS) { data_uart_print("Pair success\r\n"); APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); #if (MCP_MEDIA_CONTROL_CLIENT || CCP_CALL_CONTROL_CLIENT) gatt_client_start_discovery_all(le_get_conn_handle(conn_id), app_bt_gatt_client_cb); #endif } else { data_uart_print("Pair failed: cause 0x%x\r\n", cause); APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); } } break; default: { APP_PRINT_ERROR1("app_handle_authen_state_evt: unknown new_state %d", new_state); } break; } }
Callback Message Handler
When the CAP acceptor sample handles the GAP callback, the ble_mgr_handle_gap_cb()
and ble_audio_handle_gap_cb()
will be
called to handle the callback message.
If the GATTC_TBL_STORAGE_SUPPORT
is enabled, the CAP acceptor sample will call gattc_tbl_storage_handle_bond_modify()
when
receiving GAP_MSG_LE_BOND_MODIFY_INFO
. If the bond information of the remote device is deleted, the GATT service table of
the same remote device will be removed together.
T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data)
{
T_APP_RESULT result = APP_RESULT_SUCCESS;
T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data;
ble_mgr_handle_gap_cb(cb_type, p_cb_data);
ble_audio_handle_gap_cb(cb_type, p_cb_data);
//APP_PRINT_TRACE1("app_gap_callback: cb_type 0x%x", cb_type);
switch (cb_type)
{
case GAP_MSG_LE_CONN_UPDATE_IND:
APP_PRINT_INFO5("GAP_MSG_LE_CONN_UPDATE_IND: conn_id %d, conn_interval_max 0x%x, conn_interval_min 0x%x, conn_latency 0x%x,supervision_timeout 0x%x",
p_data->p_le_conn_update_ind->conn_id,
p_data->p_le_conn_update_ind->conn_interval_max,
p_data->p_le_conn_update_ind->conn_interval_min,
p_data->p_le_conn_update_ind->conn_latency,
p_data->p_le_conn_update_ind->supervision_timeout);
/* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */
result = APP_RESULT_ACCEPT;
break;
case GAP_MSG_LE_BOND_MODIFY_INFO:
APP_PRINT_INFO1("GAP_MSG_LE_BOND_MODIFY_INFO: type 0x%x",
p_data->p_le_bond_modify_info->type);
#if GATTC_TBL_STORAGE_SUPPORT
gattc_tbl_storage_handle_bond_modify(p_data->p_le_bond_modify_info);
#endif
break;
default:
//APP_PRINT_ERROR1("app_gap_callback: unhandled cb_type 0x%x", cb_type);
break;
}
return result;
}
LE Audio Flow
This chapter describes the LE audio flows related to the Acceptor Role.
CSIS Configuration
Dev_ACC_NO_CSIS
: Do not register CSIS service.Developers enter user command:
reg 0
Dev_ACC_CSIS_RANK1
: Register CSIS service, RANK characteristic value is 1.Developers enter user command:
reg 1
Dev_ACC_CSIS_RANK2
: Register CSIS service, RANK characteristic value is 2.Developers enter user command:
reg 2
Unicast Audio Start and Stop Flow
An Initiator acting in the role of BAP Unicast Client uses this procedure to start and stop one unicast Audio Stream. Unicast audio start and stop procedure is shown below:
-
LE Audio Manager will send this message when ASCS ASE characteristic value changes.
LE_AUDIO_MSG_ASCS_SETUP_DATA_PATH
LE Audio Manager will send this message when the setup data path procedure is completed.
LE_AUDIO_MSG_ASCS_REMOVE_DATA_PATH
LE Audio Manager will send this message when the remove data path procedure is completed.
Broadcast Audio Reception Start and Stop Flow
Commander acting in the BAP Broadcast Assistant role uses this procedure to start and stop the reception of broadcast Audio Streams by one Acceptor. Broadcast audio reception start and stop are shown as below:
-
LE Audio Manager will send this message when the local BASS Broadcast Receive State characteristic value changes.
LE_AUDIO_MSG_BASS_BA_ADD_SOURCE
LE Audio Manager will send this message when the BAP Broadcast Assistant role performs the Add Source operation.
-
LE Audio Manager will send this message when the BIG sync state changes.
MSG_BLE_AUDIO_BIG_SETUP_DATA_PATH
LE Audio Manager will send this message when the setup data path procedure is completed.
MSG_BLE_AUDIO_BIG_REMOVE_DATA_PATH
LE Audio Manager will send this message when the remove data path procedure is completed.
Broadcast Sink Role Flow
An acceptor, acting in the role of BAP Broadcast Sink, uses this procedure to start the reception of broadcast audio streams. Broadcast sink role flow is shown as below:
LE_AUDIO_MSG_BASS_LOCAL_ADD_SOURCE
LE Audio Manager will send this message when the local device performs the Add Source operation.
-
LE Audio Manager will send this message when the BIG sync state changes.
MSG_BLE_AUDIO_BIG_SETUP_DATA_PATH
LE Audio Manager will send this message when the setup data path procedure is completed.