Bluetooth initialization - enable in Bluetooth process - Init Stack

1. Overview

初始化协议栈过程分两个函数执行:btu_init_core() 、BTE_InitStack()。
前者是核心的组成部分,后者是可选的组成部分。

1.1 btu_init_core Overview

btu_init_core()

1.2 BTE_InitStack Overview

BTE_InitStack()

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

system/bt/main/bte_init.cc

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;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容