1. Overview
初始化协议栈过程分两个函数执行:btu_init_core() 、BTE_InitStack()。
前者是核心的组成部分,后者是可选的组成部分。
1.1 btu_init_core Overview
1.2 BTE_InitStack Overview
2. Core Stack
system/bt/stack/btu/btu_init.cc
void btu_init_core() {
/* Initialize the mandatory core stack components */
btm_init();
l2c_init();
sdp_init();
gatt_init();
SMP_Init();
btm_ble_init();
}
2.1 btm_init
system/bt/stack/btm/btm_main.cc
void btm_init(void) {
/* All fields are cleared; nonzero fields are reinitialized in appropriate
* function */
memset(&btm_cb, 0, sizeof(tBTM_CB));
btm_cb.page_queue = fixed_queue_new(SIZE_MAX);
btm_cb.sec_pending_q = fixed_queue_new(SIZE_MAX);
btm_cb.sec_collision_timer = alarm_new("btm.sec_collision_timer");
btm_cb.pairing_timer = alarm_new("btm.pairing_timer");
#if defined(BTM_INITIAL_TRACE_LEVEL)
btm_cb.trace_level = BTM_INITIAL_TRACE_LEVEL;
#else
btm_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
#endif
/* Initialize BTM component structures */
btm_inq_db_init(); /* Inquiry Database and Structures */
btm_acl_init(); /* ACL Database and Structures */
/* Security Manager Database and Structures */
if (stack_config_get_interface()->get_pts_secure_only_mode())
btm_sec_init(BTM_SEC_MODE_SC);
else
btm_sec_init(BTM_SEC_MODE_SP);
btm_sco_init(); /* SCO Database and Structures (If included) */
btm_cb.sec_dev_rec = list_new(osi_free);
btm_dev_init(); /* Device Manager Structures & HCI_Reset */
}
2.1.1 btm_inq_db_init
system/bt/stack/btm/btm_inq.cc
void btm_inq_db_init(void) {
alarm_free(btm_cb.btm_inq_vars.remote_name_timer);
btm_cb.btm_inq_vars.remote_name_timer =
alarm_new("btm_inq.remote_name_timer");
btm_cb.btm_inq_vars.no_inc_ssp = BTM_NO_SSP_ON_INQUIRY;
}
2.1.2 btm_acl_init
system/bt/stack/btm/btm_acl.cc
void btm_acl_init(void) {
btm_cb.btm_def_link_super_tout = HCI_DEFAULT_INACT_TOUT;
btm_cb.acl_disc_reason = 0xff;
}
2.1.3 btm_sec_init
system/bt/stack/btm/btm_sec.cc
void btm_sec_init(uint8_t sec_mode) {
btm_cb.security_mode = sec_mode;
btm_cb.pairing_bda = RawAddress::kAny;
}
2.1.4 btm_sco_init
system/bt/stack/btm/btm_sco.cc
void btm_sco_init(void) {
btm_cb.sco_cb.sco_disc_reason = BTM_INVALID_SCO_DISC_REASON;
btm_cb.sco_cb.def_esco_parms = esco_parameters_for_codec(ESCO_CODEC_CVSD);
btm_cb.sco_cb.def_esco_parms.max_latency_ms = 12;
btm_cb.sco_cb.sco_route = ESCO_DATA_PATH_PCM;
}
2.1.5 btm_dev_init
system/bt/stack/btm/btm_devctl.cc
void btm_dev_init() {
memset(btm_cb.cfg.bd_name, 0, sizeof(tBTM_LOC_BD_NAME));
btm_cb.devcb.read_local_name_timer = alarm_new("btm.read_local_name_timer");
btm_cb.devcb.read_rssi_timer = alarm_new("btm.read_rssi_timer");
btm_cb.devcb.read_failed_contact_counter_timer =
alarm_new("btm.read_failed_contact_counter_timer");
btm_cb.devcb.read_automatic_flush_timeout_timer =
alarm_new("btm.read_automatic_flush_timeout_timer");
btm_cb.devcb.read_link_quality_timer =
alarm_new("btm.read_link_quality_timer");
btm_cb.devcb.read_inq_tx_power_timer =
alarm_new("btm.read_inq_tx_power_timer");
btm_cb.devcb.qos_setup_timer = alarm_new("btm.qos_setup_timer");
btm_cb.devcb.read_tx_power_timer = alarm_new("btm.read_tx_power_timer");
btm_cb.btm_acl_pkt_types_supported =
BTM_ACL_PKT_TYPES_MASK_DH1 + BTM_ACL_PKT_TYPES_MASK_DM1 +
BTM_ACL_PKT_TYPES_MASK_DH3 + BTM_ACL_PKT_TYPES_MASK_DM3 +
BTM_ACL_PKT_TYPES_MASK_DH5 + BTM_ACL_PKT_TYPES_MASK_DM5;
btm_cb.btm_sco_pkt_types_supported =
ESCO_PKT_TYPES_MASK_HV1 + ESCO_PKT_TYPES_MASK_HV2 +
ESCO_PKT_TYPES_MASK_HV3 + ESCO_PKT_TYPES_MASK_EV3 +
ESCO_PKT_TYPES_MASK_EV4 + ESCO_PKT_TYPES_MASK_EV5;
}
2.2 l2c_init
system/bt/stack/l2cap/l2c_main.cc
void l2c_init(void) {
int16_t xx;
memset(&l2cb, 0, sizeof(tL2C_CB));
/* the psm is increased by 2 before being used */
l2cb.dyn_psm = 0xFFF;
/* the LE PSM is increased by 1 before being used */
l2cb.le_dyn_psm = LE_DYNAMIC_PSM_START - 1;
/* Put all the channel control blocks on the free queue */
for (xx = 0; xx < MAX_L2CAP_CHANNELS - 1; xx++) {
l2cb.ccb_pool[xx].p_next_ccb = &l2cb.ccb_pool[xx + 1];
}
#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
/* it will be set to L2CAP_PKT_START_NON_FLUSHABLE if controller supports */
l2cb.non_flushable_pbf = L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT;
#endif
l2cb.p_free_ccb_first = &l2cb.ccb_pool[0];
l2cb.p_free_ccb_last = &l2cb.ccb_pool[MAX_L2CAP_CHANNELS - 1];
#ifdef L2CAP_DESIRED_LINK_ROLE
l2cb.desire_role = L2CAP_DESIRED_LINK_ROLE;
#else
l2cb.desire_role = HCI_ROLE_SLAVE;
#endif
/* Set the default idle timeout */
l2cb.idle_timeout = L2CAP_LINK_INACTIVITY_TOUT;
#if defined(L2CAP_INITIAL_TRACE_LEVEL)
l2cb.l2cap_trace_level = L2CAP_INITIAL_TRACE_LEVEL;
#else
l2cb.l2cap_trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
#endif
#if (L2CAP_CONFORMANCE_TESTING == TRUE)
/* Conformance testing needs a dynamic response */
l2cb.test_info_resp = L2CAP_EXTFEA_SUPPORTED_MASK;
#endif
/* Number of ACL buffers to use for high priority channel */
#if (L2CAP_HIGH_PRI_CHAN_QUOTA_IS_CONFIGURABLE == TRUE)
l2cb.high_pri_min_xmit_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA;
#endif
l2cb.l2c_ble_fixed_chnls_mask = L2CAP_FIXED_CHNL_ATT_BIT |
L2CAP_FIXED_CHNL_BLE_SIG_BIT |
L2CAP_FIXED_CHNL_SMP_BIT;
l2cb.rcv_pending_q = list_new(NULL);
CHECK(l2cb.rcv_pending_q != NULL);
l2cb.receive_hold_timer = alarm_new("l2c.receive_hold_timer");
}
2.3 sdp_init
system/bt/stack/sdp/sdp_main.cc
void sdp_init(void) {
/* Clears all structures and local SDP database (if Server is enabled) */
memset(&sdp_cb, 0, sizeof(tSDP_CB));
for (int i = 0; i < SDP_MAX_CONNECTIONS; i++) {
sdp_cb.ccb[i].sdp_conn_timer = alarm_new("sdp.sdp_conn_timer");
}
/* Initialize the L2CAP configuration. We only care about MTU and flush */
sdp_cb.l2cap_my_cfg.mtu_present = true;
sdp_cb.l2cap_my_cfg.mtu = SDP_MTU_SIZE;
sdp_cb.l2cap_my_cfg.flush_to_present = true;
sdp_cb.l2cap_my_cfg.flush_to = SDP_FLUSH_TO;
sdp_cb.max_attr_list_size = SDP_MTU_SIZE - 16;
sdp_cb.max_recs_per_search = SDP_MAX_DISC_SERVER_RECS;
#if (SDP_SERVER_ENABLED == TRUE)
/* Register with Security Manager for the specific security level */
if (!BTM_SetSecurityLevel(false, SDP_SERVICE_NAME, BTM_SEC_SERVICE_SDP_SERVER,
BTM_SEC_NONE, SDP_PSM, 0, 0)) {
SDP_TRACE_ERROR("Security Registration Server failed");
return;
}
#endif
/* Register with Security Manager for the specific security level */
if (!BTM_SetSecurityLevel(true, SDP_SERVICE_NAME, BTM_SEC_SERVICE_SDP_SERVER,
BTM_SEC_NONE, SDP_PSM, 0, 0)) {
SDP_TRACE_ERROR("Security Registration for Client failed");
return;
}
#if defined(SDP_INITIAL_TRACE_LEVEL)
sdp_cb.trace_level = SDP_INITIAL_TRACE_LEVEL;
#else
sdp_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
#endif
sdp_cb.reg_info.pL2CA_ConnectInd_Cb = sdp_connect_ind;
sdp_cb.reg_info.pL2CA_ConnectCfm_Cb = sdp_connect_cfm;
sdp_cb.reg_info.pL2CA_ConnectPnd_Cb = NULL;
sdp_cb.reg_info.pL2CA_ConfigInd_Cb = sdp_config_ind;
sdp_cb.reg_info.pL2CA_ConfigCfm_Cb = sdp_config_cfm;
sdp_cb.reg_info.pL2CA_DisconnectInd_Cb = sdp_disconnect_ind;
sdp_cb.reg_info.pL2CA_DisconnectCfm_Cb = sdp_disconnect_cfm;
sdp_cb.reg_info.pL2CA_QoSViolationInd_Cb = NULL;
sdp_cb.reg_info.pL2CA_DataInd_Cb = sdp_data_ind;
sdp_cb.reg_info.pL2CA_CongestionStatus_Cb = NULL;
sdp_cb.reg_info.pL2CA_TxComplete_Cb = NULL;
/* Now, register with L2CAP */
if (!L2CA_Register(SDP_PSM, &sdp_cb.reg_info, true /* enable_snoop */,
nullptr)) {
SDP_TRACE_ERROR("SDP Registration failed");
}
}
2.4 gatt_main
system/bt/stack/gatt/gatt_main.cc
void gatt_init(void) {
tL2CAP_FIXED_CHNL_REG fixed_reg;
gatt_cb = tGATT_CB();
connection_manager::reset(true);
memset(&fixed_reg, 0, sizeof(tL2CAP_FIXED_CHNL_REG));
gatt_cb.def_mtu_size = GATT_DEF_BLE_MTU_SIZE;
gatt_cb.sign_op_queue = fixed_queue_new(SIZE_MAX);
gatt_cb.srv_chg_clt_q = fixed_queue_new(SIZE_MAX);
/* First, register fixed L2CAP channel for ATT over BLE */
fixed_reg.fixed_chnl_opts.mode = L2CAP_FCR_BASIC_MODE;
fixed_reg.fixed_chnl_opts.max_transmit = 0xFF;
fixed_reg.fixed_chnl_opts.rtrans_tout = 2000;
fixed_reg.fixed_chnl_opts.mon_tout = 12000;
fixed_reg.fixed_chnl_opts.mps = 670;
fixed_reg.fixed_chnl_opts.tx_win_sz = 1;
fixed_reg.pL2CA_FixedConn_Cb = gatt_le_connect_cback;
fixed_reg.pL2CA_FixedData_Cb = gatt_le_data_ind;
fixed_reg.pL2CA_FixedCong_Cb = gatt_le_cong_cback; /* congestion callback */
fixed_reg.default_idle_tout = 0xffff; /* 0xffff default idle timeout */
L2CA_RegisterFixedChannel(L2CAP_ATT_CID, &fixed_reg);
/* Now, register with L2CAP for ATT PSM over BR/EDR */
if (!L2CA_Register(BT_PSM_ATT, (tL2CAP_APPL_INFO*)&dyn_info,
false /* enable_snoop */, nullptr)) {
LOG(ERROR) << "ATT Dynamic Registration failed";
}
BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_ATT, BTM_SEC_NONE, BT_PSM_ATT,
0, 0);
BTM_SetSecurityLevel(false, "", BTM_SEC_SERVICE_ATT, BTM_SEC_NONE, BT_PSM_ATT,
0, 0);
gatt_cb.hdl_cfg.gatt_start_hdl = GATT_GATT_START_HANDLE;
gatt_cb.hdl_cfg.gap_start_hdl = GATT_GAP_START_HANDLE;
gatt_cb.hdl_cfg.app_start_hdl = GATT_APP_START_HANDLE;
gatt_cb.hdl_list_info = new std::list<tGATT_HDL_LIST_ELEM>();
gatt_cb.srv_list_info = new std::list<tGATT_SRV_LIST_ELEM>();
gatt_profile_db_init();
}
2.4.1 gatt_profile_db_init
system/bt/stack/gatt/gatt_attr.cc
void gatt_profile_db_init(void) {
uint16_t service_handle = 0;
/* Fill our internal UUID with a fixed pattern 0x81 */
std::array<uint8_t, Uuid::kNumBytes128> tmp;
tmp.fill(0x81);
/* Create a GATT profile service */
gatt_cb.gatt_if = GATT_Register(Uuid::From128BitBE(tmp), &gatt_profile_cback);
GATT_StartIf(gatt_cb.gatt_if);
Uuid service_uuid = Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER);
Uuid char_uuid = Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD);
btgatt_db_element_t service[] = {
{
.uuid = service_uuid,
.type = BTGATT_DB_PRIMARY_SERVICE,
},
{
.uuid = char_uuid,
.type = BTGATT_DB_CHARACTERISTIC,
.properties = GATT_CHAR_PROP_BIT_INDICATE,
.permissions = 0,
}};
GATTS_AddService(gatt_cb.gatt_if, service,
sizeof(service) / sizeof(btgatt_db_element_t));
service_handle = service[0].attribute_handle;
gatt_cb.handle_of_h_r = service[1].attribute_handle;
}
2.5 SMP_Init
system/bt/stack/smp/smp_api.cc
void SMP_Init(void) {
memset(&smp_cb, 0, sizeof(tSMP_CB));
smp_cb.smp_rsp_timer_ent = alarm_new("smp.smp_rsp_timer_ent");
smp_cb.delayed_auth_timer_ent = alarm_new("smp.delayed_auth_timer_ent");
#if defined(SMP_INITIAL_TRACE_LEVEL)
smp_cb.trace_level = SMP_INITIAL_TRACE_LEVEL;
#else
smp_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
#endif
SMP_TRACE_EVENT("%s", __func__);
smp_l2cap_if_init();
/* initialization of P-256 parameters */
p_256_init_curve();
/* Initialize failure case for certification */
smp_cb.cert_failure =
stack_config_get_interface()->get_pts_smp_failure_case();
if (smp_cb.cert_failure)
SMP_TRACE_ERROR("%s PTS FAILURE MODE IN EFFECT (CASE %d)", __func__,
smp_cb.cert_failure);
}
2.5.1 smp_l2cap_if_init
system/bt/stack/smp/smp_l2c.cc
void smp_l2cap_if_init(void) {
tL2CAP_FIXED_CHNL_REG fixed_reg;
fixed_reg.fixed_chnl_opts.mode = L2CAP_FCR_BASIC_MODE;
fixed_reg.fixed_chnl_opts.max_transmit = 0;
fixed_reg.fixed_chnl_opts.rtrans_tout = 0;
fixed_reg.fixed_chnl_opts.mon_tout = 0;
fixed_reg.fixed_chnl_opts.mps = 0;
fixed_reg.fixed_chnl_opts.tx_win_sz = 0;
fixed_reg.pL2CA_FixedConn_Cb = smp_connect_callback;
fixed_reg.pL2CA_FixedData_Cb = smp_data_received;
fixed_reg.pL2CA_FixedTxComplete_Cb = smp_tx_complete_callback;
fixed_reg.pL2CA_FixedCong_Cb =
NULL; /* do not handle congestion on this channel */
fixed_reg.default_idle_tout =
60; /* set 60 seconds timeout, 0xffff default idle timeout */
L2CA_RegisterFixedChannel(L2CAP_SMP_CID, &fixed_reg);
fixed_reg.pL2CA_FixedConn_Cb = smp_br_connect_callback;
fixed_reg.pL2CA_FixedData_Cb = smp_br_data_received;
L2CA_RegisterFixedChannel(L2CAP_SMP_BR_CID, &fixed_reg);
}
2.6 btm_ble_init
system/bt/stack/btm/btm_ble_gap.cc
void btm_ble_init(void) {
tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb;
BTM_TRACE_DEBUG("%s", __func__);
alarm_free(p_cb->observer_timer);
alarm_free(p_cb->inq_var.fast_adv_timer);
memset(p_cb, 0, sizeof(tBTM_BLE_CB));
memset(&(btm_cb.cmn_ble_vsc_cb), 0, sizeof(tBTM_BLE_VSC_CB));
btm_cb.cmn_ble_vsc_cb.values_read = false;
p_cb->observer_timer = alarm_new("btm_ble.observer_timer");
p_cb->cur_states = 0;
p_cb->inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
p_cb->inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
p_cb->inq_var.adv_chnl_map = BTM_BLE_DEFAULT_ADV_CHNL_MAP;
p_cb->inq_var.afp = BTM_BLE_DEFAULT_AFP;
p_cb->inq_var.sfp = BTM_BLE_DEFAULT_SFP;
p_cb->inq_var.connectable_mode = BTM_BLE_NON_CONNECTABLE;
p_cb->inq_var.discoverable_mode = BTM_BLE_NON_DISCOVERABLE;
p_cb->inq_var.fast_adv_timer = alarm_new("btm_ble_inq.fast_adv_timer");
p_cb->inq_var.inquiry_timer = alarm_new("btm_ble_inq.inquiry_timer");
/* for background connection, reset connection params to be undefined */
p_cb->scan_int = p_cb->scan_win = BTM_BLE_SCAN_PARAM_UNDEF;
p_cb->inq_var.evt_type = BTM_BLE_NON_CONNECT_EVT;
p_cb->addr_mgnt_cb.refresh_raddr_timer =
alarm_new("btm_ble_addr.refresh_raddr_timer");
#if (BLE_VND_INCLUDED == FALSE)
btm_ble_adv_filter_init();
#endif
}
2.6.1 btm_ble_adv_filter_init
system/bt/stack/btm/btm_ble_adv_filter.cc
void btm_ble_adv_filter_init(void) {
memset(&btm_ble_adv_filt_cb, 0, sizeof(tBTM_BLE_ADV_FILTER_CB));
BTM_BleGetVendorCapabilities(&cmn_ble_vsc_cb);
if (!is_filtering_supported()) return;
if (cmn_ble_vsc_cb.max_filter > 0) {
btm_ble_adv_filt_cb.p_addr_filter_count = (tBTM_BLE_PF_COUNT*)osi_malloc(
sizeof(tBTM_BLE_PF_COUNT) * cmn_ble_vsc_cb.max_filter);
}
}
2.6.1.1 BTM_BleGetVendorCapabilities
system/bt/stack/btm/btm_ble_gap.cc
extern void BTM_BleGetVendorCapabilities(tBTM_BLE_VSC_CB* p_cmn_vsc_cb) {
BTM_TRACE_DEBUG("BTM_BleGetVendorCapabilities");
if (NULL != p_cmn_vsc_cb) {
*p_cmn_vsc_cb = btm_cb.cmn_ble_vsc_cb;
}
}
3. Optional Stack
void BTE_InitStack(void) {
/* Initialize the optional stack components */
RFCOMM_Init();
/**************************
* BNEP and its profiles **
**************************/
#if (BNEP_INCLUDED == TRUE)
BNEP_Init();
#if (PAN_INCLUDED == TRUE)
PAN_Init();
#endif /* PAN */
#endif /* BNEP Included */
/**************************
* AVDT and its profiles **
**************************/
A2DP_Init();
AVRC_Init();
/***********
* Others **
***********/
GAP_Init();
#if (HID_HOST_INCLUDED == TRUE)
HID_HostInit();
#endif
}
3.1 RFCOMM_Init
system/bt/stack/rfcomm/port_api.cc
void RFCOMM_Init(void) {
memset(&rfc_cb, 0, sizeof(tRFC_CB)); /* Init RFCOMM control block */
rfc_cb.rfc.last_mux = MAX_BD_CONNECTIONS;
#if defined(RFCOMM_INITIAL_TRACE_LEVEL)
rfc_cb.trace_level = RFCOMM_INITIAL_TRACE_LEVEL;
#else
rfc_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
#endif
rfcomm_l2cap_if_init();
}
system/bt/stack/rfcomm/rfc_l2cap_if.cc
void rfcomm_l2cap_if_init(void) {
tL2CAP_APPL_INFO* p_l2c = &rfc_cb.rfc.reg_info;
p_l2c->pL2CA_ConnectInd_Cb = RFCOMM_ConnectInd;
p_l2c->pL2CA_ConnectCfm_Cb = RFCOMM_ConnectCnf;
p_l2c->pL2CA_ConnectPnd_Cb = NULL;
p_l2c->pL2CA_ConfigInd_Cb = RFCOMM_ConfigInd;
p_l2c->pL2CA_ConfigCfm_Cb = RFCOMM_ConfigCnf;
p_l2c->pL2CA_DisconnectInd_Cb = RFCOMM_DisconnectInd;
p_l2c->pL2CA_DisconnectCfm_Cb = NULL;
p_l2c->pL2CA_QoSViolationInd_Cb = RFCOMM_QoSViolationInd;
p_l2c->pL2CA_DataInd_Cb = RFCOMM_BufDataInd;
p_l2c->pL2CA_CongestionStatus_Cb = RFCOMM_CongestionStatusInd;
p_l2c->pL2CA_TxComplete_Cb = NULL;
L2CA_Register(BT_PSM_RFCOMM, p_l2c, true /* enable_snoop */, nullptr);
}
3.2 BNEP_Init
system/bt/stack/bnep/bnep_api.cc
void BNEP_Init(void) {
memset(&bnep_cb, 0, sizeof(tBNEP_CB));
#if defined(BNEP_INITIAL_TRACE_LEVEL)
bnep_cb.trace_level = BNEP_INITIAL_TRACE_LEVEL;
#else
bnep_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
#endif
}
3.3 PAN_Init
system/bt/stack/pan/pan_api.cc
void PAN_Init(void) {
memset(&pan_cb, 0, sizeof(tPAN_CB));
#if defined(PAN_INITIAL_TRACE_LEVEL)
pan_cb.trace_level = PAN_INITIAL_TRACE_LEVEL;
#else
pan_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
#endif
}
3.4 A2DP_Init
system/bt/stack/a2dp/a2dp_api.cc
void A2DP_Init(void) {
memset(&a2dp_cb, 0, sizeof(tA2DP_CB));
a2dp_cb.avdt_sdp_ver = AVDT_VERSION;
#if defined(A2DP_INITIAL_TRACE_LEVEL)
a2dp_cb.trace_level = A2DP_INITIAL_TRACE_LEVEL;
#else
a2dp_cb.trace_level = BT_TRACE_LEVEL_NONE;
#endif
}
3.5 AVRC_Init
system/bt/stack/avrc/avrc_sdp.cc
void AVRC_Init(void) {
memset(&avrc_cb, 0, sizeof(tAVRC_CB));
#if defined(AVRC_INITIAL_TRACE_LEVEL)
avrc_cb.trace_level = AVRC_INITIAL_TRACE_LEVEL;
#else
avrc_cb.trace_level = BT_TRACE_LEVEL_NONE;
#endif
}
3.6 GAP_Init
system/bt/stack/gap/gap_conn.cc
void GAP_Init(void) {
gap_conn_init();
gap_attr_db_init();
}
void gap_conn_init(void) {
memset(&conn, 0, sizeof(tGAP_CONN));
conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
conn.reg_info.pL2CA_ConnectCfm_Cb = gap_connect_cfm;
conn.reg_info.pL2CA_ConnectPnd_Cb = NULL;
conn.reg_info.pL2CA_ConfigInd_Cb = gap_config_ind;
conn.reg_info.pL2CA_ConfigCfm_Cb = gap_config_cfm;
conn.reg_info.pL2CA_DisconnectInd_Cb = gap_disconnect_ind;
conn.reg_info.pL2CA_DisconnectCfm_Cb = NULL;
conn.reg_info.pL2CA_QoSViolationInd_Cb = NULL;
conn.reg_info.pL2CA_DataInd_Cb = gap_data_ind;
conn.reg_info.pL2CA_CongestionStatus_Cb = gap_congestion_ind;
conn.reg_info.pL2CA_TxComplete_Cb = gap_tx_complete_ind;
conn.reg_info.pL2CA_CreditsReceived_Cb = gap_credits_received_cb;
}
void gap_attr_db_init(void) {
uint16_t service_handle;
/* Fill our internal UUID with a fixed pattern 0x82 */
std::array<uint8_t, Uuid::kNumBytes128> tmp;
tmp.fill(0x82);
Uuid app_uuid = Uuid::From128BitBE(tmp);
gatt_attr.fill({});
gatt_if = GATT_Register(app_uuid, &gap_cback);
GATT_StartIf(gatt_if);
Uuid svc_uuid = Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER);
Uuid name_uuid = Uuid::From16Bit(GATT_UUID_GAP_DEVICE_NAME);
Uuid icon_uuid = Uuid::From16Bit(GATT_UUID_GAP_ICON);
Uuid addr_res_uuid = Uuid::From16Bit(GATT_UUID_GAP_CENTRAL_ADDR_RESOL);
btgatt_db_element_t service[] = {
{
.uuid = svc_uuid,
.type = BTGATT_DB_PRIMARY_SERVICE,
},
{.uuid = name_uuid,
.type = BTGATT_DB_CHARACTERISTIC,
.properties = GATT_CHAR_PROP_BIT_READ,
.permissions = GATT_PERM_READ},
{.uuid = icon_uuid,
.type = BTGATT_DB_CHARACTERISTIC,
.properties = GATT_CHAR_PROP_BIT_READ,
.permissions = GATT_PERM_READ},
{.uuid = addr_res_uuid,
.type = BTGATT_DB_CHARACTERISTIC,
.properties = GATT_CHAR_PROP_BIT_READ,
.permissions = GATT_PERM_READ}
#if (BTM_PERIPHERAL_ENABLED == TRUE) /* Only needed for peripheral testing */
,
{.uuid = Uuid::From16Bit(GATT_UUID_GAP_PREF_CONN_PARAM),
.type = BTGATT_DB_CHARACTERISTIC,
.properties = GATT_CHAR_PROP_BIT_READ,
.permissions = GATT_PERM_READ}
#endif
};
/* Add a GAP service */
GATTS_AddService(gatt_if, service,
sizeof(service) / sizeof(btgatt_db_element_t));
service_handle = service[0].attribute_handle;
gatt_attr[0].uuid = GATT_UUID_GAP_DEVICE_NAME;
gatt_attr[0].handle = service[1].attribute_handle;
gatt_attr[1].uuid = GATT_UUID_GAP_ICON;
gatt_attr[1].handle = service[2].attribute_handle;
gatt_attr[2].uuid = GATT_UUID_GAP_CENTRAL_ADDR_RESOL;
gatt_attr[2].handle = service[3].attribute_handle;
gatt_attr[2].attr_value.addr_resolution = 0;
#if (BTM_PERIPHERAL_ENABLED == TRUE) /* Only needed for peripheral testing */
gatt_attr[3].uuid = GATT_UUID_GAP_PREF_CONN_PARAM;
gatt_attr[3].attr_value.conn_param.int_max = GAP_PREFER_CONN_INT_MAX; /* 6 */
gatt_attr[3].attr_value.conn_param.int_min = GAP_PREFER_CONN_INT_MIN; /* 0 */
gatt_attr[3].attr_value.conn_param.latency = GAP_PREFER_CONN_LATENCY; /* 0 */
gatt_attr[3].attr_value.conn_param.sp_tout =
GAP_PREFER_CONN_SP_TOUT; /* 2000 */
gatt_attr[3].handle = service[4].attribute_handle;
#endif
}
3.7 HID_HostInit
system/bt/stack/hid/hidh_api.cc
void HID_HostInit(void) {
uint8_t log_level = hh_cb.trace_level;
memset(&hh_cb, 0, sizeof(tHID_HOST_CTB));
hh_cb.trace_level = log_level;
}