蓝牙学习记录

自适应调频技术是建立在自动信道质量分析基础上的一种频率自使用和功率自适应控制相结合的技术,他能使调频通信过程中自动避开被干扰的调频频点并以最小的发射功率、最低的被截获概率,达到在无干扰的调频信道上长时间保持优质通信的目的

蓝牙分层


image.png

蓝牙设备建立连接的过程


image.png

各种协议对比


image.png
image.png
image.png

蓝牙开发板的学习步骤


image.png

2和9引脚需要短接,这样才能烧写usb dongle


image.png
image.png

bluedroid
1、Android 4.2中BlueDroid的框架结构图:(Google官方提供)

init函数 文档里有讲解
init、enable函数主要实现的功能:
(1)、创建:btif_task/BTIF_TASK
(2)、初始化BTE
(3)、创建:btu_task/BTU_TASK
(4)、初始化HCI、串口相关,启动HCI工作主线程:bt_hc_callback,芯片上电、RF参数初始化、蓝牙地址名称相关设定;

interface->init函数 146行
stack_manager_get_interface()->init_stack();//会调用下面的_init_stack
const stack_manager_t* stack_manager_get_interface() {
ensure_manager_initialized();
management_thread = thread_new("stack_manager");

return &interface;
}

static const stack_manager_t interface = {init_stack, start_up_stack_async,
                                          shut_down_stack_async, clean_up_stack,

                                          get_stack_is_running};

thread_post(management_thread, event_init_stack, semaphore);

event_init_stack
btif_init_bluetooth();
void bte_main_boot_entry(void) {BTE MAIN API - Entry point for BTE chip/stack initialization
hci = hci_layer_get_interface();

image.png

packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp

int ret = sBluetoothInterface->init(&sBluetoothCallbacks);//调用到C的相应接口函

packages\apps\Bluetooth\jni\com_android_bluetooth_btservice_AdapterService.cpp
initNative函数的具体实现,通过bt_interface_t结构体,调用到C中的init函数实现。同时传入sBluetoothCallbacks回调函数结构体。这个函数结构体比较重要,底层的状态变化都是通过这个回调函数结构体中的函数实现。

3.1 协议栈初始化
协议栈初始化主要工作是初始化stackManager,创建stackManager工作线程,stackManager作为蓝牙协议栈的管理者,提供管理接口,主要工作即为初始化(init_stack)、打开(start_up_stack_async)、关闭(shut_down_stack_async)、清除协议栈(clean_up_stack)。每个操作会将消息发送到工作线程的工作队列中,在工作线程中执行。

init_stack进而会打开JNI工作线程(通过AttachCurrentThread将该线程连接到jvm中),该工作线程用于将底层消息回调(HAL_CBACK)到上层,sBluetoothCallbacks注册的回调。

image.png

hci_module_start_up
EXPORT_SYMBOL extern const module_t hci_module = {
.name = HCI_MODULE,
.init = NULL,
.start_up = hci_module_start_up,
.shut_down = hci_module_shut_down,
.clean_up = NULL,
.dependencies = {BTSNOOP_MODULE, NULL}};

// Interface functions

https://www.cnblogs.com/blogs-of-lxl/p/7010061.html

/*****************************************************************************

  • Function BTU_StartUp
  • Description Initializes the BTU control block.
  •              NOTE: Must be called before creating any tasks
    
  •                  (RPC, BTU, HCIT, APPL, etc.)
    
  • Returns void

*****************************************************************************/
void BTU_StartUp(void) {

//这个地方有关于11-01 15:52:52.869 11532 11532 D Avrcp : mVolumeStep = 4

packages/apps/Bluetooth/src/com/android/bluetooth/avrcp/Avrcp.java:493:

image.png

bt_btif : enable: start restricted = 0

BluetoothAdapterService: startDiscovery
//bt\hci\src\hci_layer_android.cc  
Return<void> hciEventReceived(const hidl_vec<uint8_t>& event) {
    LOG_DEBUG(LOG_TAG, "%s-->", __func__);
    BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_EVT, event);
    hci_event_received(FROM_HERE, packet);
    LOG_DEBUG(LOG_TAG, "%s<--", __func__);

谁来负责调用这个函数

//frameworks/base/core/java/android/bluetooth/BluetoothHeadset.java
int ret = sBluetoothInterface->start_discovery();

蓝牙搜索的流程
start_discovery函数

static int start_discovery(void) {
  /* sanity check */
  if (interface_ready() == false) return BT_STATUS_NOT_READY;

  return btif_dm_start_discovery();
}

主要是执行这个btif_dm_start_discovery()函数

/*****************************************************************************
 *
 *   btif api functions (no context switch)
 *
 ****************************************************************************/

/*******************************************************************************
 *
 * Function         btif_dm_start_discovery
 *
 * Description      Start device discovery/inquiry
 *
 * Returns          bt_status_t
 *
 ******************************************************************************/
bt_status_t btif_dm_start_discovery(void) {
  tBTA_DM_INQ inq_params;
  tBTA_SERVICE_MASK services = 0;

  BTIF_TRACE_EVENT("%s : pairing_cb.state: 0x%x", __FUNCTION__, pairing_cb.state);

  /* We should not go for inquiry in BONDING STATE. */
  if (pairing_cb.state == BT_BOND_STATE_BONDING)
      return BT_STATUS_BUSY;

  /* Cleanup anything remaining on index 0 */
  do_in_bta_thread(
      FROM_HERE,
      base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_DELETE, 0,
                 nullptr, base::Bind(&bte_scan_filt_param_cfg_evt, 0)));

  auto adv_filt_param = std::make_unique<btgatt_filt_param_setup_t>();
  /* Add an allow-all filter on index 0*/
  adv_filt_param->dely_mode = IMMEDIATE_DELY_MODE;
  adv_filt_param->feat_seln = ALLOW_ALL_FILTER;
  adv_filt_param->filt_logic_type = BTA_DM_BLE_PF_FILT_LOGIC_OR;
  adv_filt_param->list_logic_type = BTA_DM_BLE_PF_LIST_LOGIC_OR;
  adv_filt_param->rssi_low_thres = LOWEST_RSSI_VALUE;
  adv_filt_param->rssi_high_thres = LOWEST_RSSI_VALUE;
  do_in_bta_thread(
      FROM_HERE, base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_ADD,
                            0, base::Passed(&adv_filt_param),
                            base::Bind(&bte_scan_filt_param_cfg_evt, 0)));

  /* TODO: Do we need to handle multiple inquiries at the same time? */

  /* Set inquiry params and call API  设置扫描的模式*/
  inq_params.mode = BTA_DM_GENERAL_INQUIRY | BTA_BLE_GENERAL_INQUIRY;
#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
  inq_params.intl_duration[0] = BTIF_DM_INTERLEAVE_DURATION_BR_ONE;
  inq_params.intl_duration[1] = BTIF_DM_INTERLEAVE_DURATION_LE_ONE;
  inq_params.intl_duration[2] = BTIF_DM_INTERLEAVE_DURATION_BR_TWO;
  inq_params.intl_duration[3] = BTIF_DM_INTERLEAVE_DURATION_LE_TWO;
#endif
  inq_params.duration = BTIF_DM_DEFAULT_INQ_MAX_DURATION;

  inq_params.max_resps = BTIF_DM_DEFAULT_INQ_MAX_RESULTS;
  inq_params.report_dup = true;

  inq_params.filter_type = BTA_DM_INQ_CLR;
  /* TODO: Filter device by BDA needs to be implemented here */

  /* Will be enabled to true once inquiry busy level has been received */
  btif_dm_inquiry_in_progress = false;
  /* find nearby devices */
  BTA_DmSearch(&inq_params, services, bte_search_devices_evt);

  return BT_STATUS_SUCCESS;
}

主要是执行这个函数BTA_DmSearch(&inq_params, services, bte_search_devices_evt);

/*******************************************************************************
 *
 * Function         BTA_DmSearch
 *
 * Description      This function searches for peer Bluetooth devices. It
 *                  performs an inquiry and gets the remote name for devices.
 *                  Service discovery is done if services is non zero
 *
 *
 * Returns          void
 *
 ******************************************************************************/
void BTA_DmSearch(tBTA_DM_INQ* p_dm_inq, tBTA_SERVICE_MASK services,
                  tBTA_DM_SEARCH_CBACK* p_cback) {
  tBTA_DM_API_SEARCH* p_msg =
      (tBTA_DM_API_SEARCH*)osi_calloc(sizeof(tBTA_DM_API_SEARCH));

  p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
  memcpy(&p_msg->inq_params, p_dm_inq, sizeof(tBTA_DM_INQ));
  p_msg->services = services;
  p_msg->p_cback = p_cback;//bte_search_devices_evt 函数
  p_msg->rs_res = BTA_DM_RS_NONE;

  bta_sys_sendmsg(p_msg);
}

上面的函数,填充了一个结构体,然后调用bta_sys_sendmsg(p_msg);函数

/*******************************************************************************
 *
 * Function         bta_sys_sendmsg
 *
 * Description      Send a GKI message to BTA.  This function is designed to
 *                  optimize sending of messages to BTA.  It is called by BTA
 *                  API functions and call-in functions.
 *
 *                  TODO (apanicke): Add location object as parameter for easier
 *                  future debugging when doing alarm refactor
 *
 *
 * Returns          void
 *
 ******************************************************************************/
void bta_sys_sendmsg(void* p_msg) {
  base::MessageLoop* bta_message_loop = get_message_loop();

  if (!bta_message_loop || !bta_message_loop->task_runner().get()) {
    APPL_TRACE_ERROR("%s: MessageLooper not initialized", __func__);
    return;
  }

  bta_message_loop->task_runner()->PostTask(
      FROM_HERE, base::Bind(&bta_sys_event, static_cast<BT_HDR*>(p_msg)));
}

有关base:bind的介绍
Chromium源码—base基础库说明
https://blog.csdn.net/developer1024/article/details/79875200

应该是调用bta_sys_event函数

/*******************************************************************************
 *
 * Function         bta_sys_event
 *
 * Description      BTA event handler; called from task event handler.
 *
 *
 * Returns          void
 *
 ******************************************************************************/
void bta_sys_event(BT_HDR* p_msg) {
  uint8_t id;
  bool freebuf = true;

  APPL_TRACE_EVENT("%s: Event 0x%x", __func__, p_msg->event);

  /* get subsystem id from event */
  id = (uint8_t)(p_msg->event >> 8);

  /* verify id and call subsystem event handler */
  if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL)) {
    freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
  } else {
    APPL_TRACE_WARNING("%s: Received unregistered event id %d", __func__, id);
  }

  if (freebuf) {
    osi_free(p_msg);
  }
}

主要是这个代码
freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);

谁会对上面的东西赋值

/*******************************************************************************
 *
 * Function         bta_sys_register
 *
 * Description      Called by other BTA subsystems to register their event
 *                  handler.
 *
 *
 * Returns          void
 *
 ******************************************************************************/
void bta_sys_register(uint8_t id, const tBTA_SYS_REG* p_reg) {
  bta_sys_cb.reg[id] = (tBTA_SYS_REG*)p_reg;
  bta_sys_cb.is_reg[id] = true;
}

//使能蓝牙的时候注册的

define BTA_ID_DM_SEARCH 2 /* device manager search */

bta_sys_register(BTA_ID_DM_SEARCH, &bta_dm_search_reg);

主要是执行这个函数

/*******************************************************************************
 *
 * Function         bta_dm_search_sm_execute
 *
 * Description      State machine event handling function for DM
 *
 *
 * Returns          void
 *
 ******************************************************************************/
bool bta_dm_search_sm_execute(BT_HDR* p_msg) {
  tBTA_DM_ST_TBL state_table;
  uint8_t action;
  int i;

  APPL_TRACE_EVENT("bta_dm_search_sm_execute state:%d, event:0x%x",
                   bta_dm_search_cb.state, p_msg->event);

  /* look up the state table for the current state */
  state_table = bta_dm_search_st_tbl[bta_dm_search_cb.state];

  bta_dm_search_cb.state =
      state_table[p_msg->event & 0x00ff][BTA_DM_SEARCH_NEXT_STATE];

  /* execute action functions */
  for (i = 0; i < BTA_DM_SEARCH_ACTIONS; i++) {
    action = state_table[p_msg->event & 0x00ff][i];
    LOG_INFO(LOG_TAG, "%s: action:0x%x", __func__, action);
    if (action < BTA_DM_SEARCH_IGNORE) {
      (*bta_dm_search_action[action])((tBTA_DM_MSG*)p_msg);
    } else {
      break;
    }
  }
  return true;
}

bta_dm_search_action 这是一个全局的变量,里面是一堆函数

/* action function list */
const tBTA_DM_ACTION bta_dm_search_action[] = {

    bta_dm_search_start,               /* 0 BTA_DM_API_SEARCH */
    bta_dm_search_cancel,              /* 1 BTA_DM_API_SEARCH_CANCEL */
    bta_dm_discover,                   /* 2 BTA_DM_API_DISCOVER */
    bta_dm_inq_cmpl,                   /* 3 BTA_DM_INQUIRY_CMPL */
    bta_dm_rmt_name,                   /* 4 BTA_DM_REMT_NAME */
    bta_dm_sdp_result,                 /* 5 BTA_DM_SDP_RESULT */
    bta_dm_search_cmpl,                /* 6 BTA_DM_SEARCH_CMPL */
    bta_dm_free_sdp_db,                /* 7 BTA_DM_FREE_SDP_DB */
    bta_dm_disc_result,                /* 8 BTA_DM_DISC_RESULT */
    bta_dm_search_result,              /* 9 BTA_DM_SEARCH_RESULT */
    bta_dm_queue_search,               /* 10 BTA_DM_QUEUE_SEARCH */
    bta_dm_queue_disc,                 /* 11 BTA_DM_QUEUE_DISC */
    bta_dm_search_clear_queue,         /* 12 BTA_DM_SEARCH_CLEAR_QUEUE */
    bta_dm_search_cancel_cmpl,         /* 13 BTA_DM_SEARCH_CANCEL_CMPL */
    bta_dm_search_cancel_notify,       /* 14 BTA_DM_SEARCH_CANCEL_NOTIFY */
    bta_dm_search_cancel_transac_cmpl, /* 15 BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL
                                          */
    bta_dm_disc_rmt_name,              /* 16 BTA_DM_DISC_RMT_NAME */
    bta_dm_di_disc,                    /* 17 BTA_DM_API_DI_DISCOVER */
    bta_dm_close_gatt_conn};

应该执行的是下面这个函数

/*******************************************************************************
 *
 * Function         bta_dm_search_start
 *
 * Description      Starts an inquiry
 *
 *
 * Returns          void
 *
 ******************************************************************************/
void bta_dm_search_start(tBTA_DM_MSG* p_data) {
  tBTM_INQUIRY_CMPL result;

  size_t len = sizeof(tBT_UUID) * p_data->search.num_uuid;
  bta_dm_gattc_register();

  APPL_TRACE_DEBUG("%s avoid_scatter=%d", __func__,
                   p_bta_dm_cfg->avoid_scatter);

  if (p_bta_dm_cfg->avoid_scatter &&
      (p_data->search.rs_res == BTA_DM_RS_NONE) &&
      bta_dm_check_av(BTA_DM_API_SEARCH_EVT)) {
    memcpy(&bta_dm_cb.search_msg, &p_data->search, sizeof(tBTA_DM_API_SEARCH));
    return;
  }

  BTM_ClearInqDb(NULL);
  /* save search params */
  bta_dm_search_cb.p_search_cback = p_data->search.p_cback;
  bta_dm_search_cb.services = p_data->search.services;

  osi_free_and_reset((void**)&bta_dm_search_cb.p_srvc_uuid);

  if ((bta_dm_search_cb.num_uuid = p_data->search.num_uuid) != 0 &&
      p_data->search.p_uuid != NULL) {
    bta_dm_search_cb.p_srvc_uuid = (tBT_UUID*)osi_malloc(len);
    memcpy(bta_dm_search_cb.p_srvc_uuid, p_data->search.p_uuid, len);
  }
  result.status = BTM_StartInquiry((tBTM_INQ_PARMS*)&p_data->search.inq_params,
                                   bta_dm_inq_results_cb,
                                   (tBTM_CMPL_CB*)bta_dm_inq_cmpl_cb);

  APPL_TRACE_EVENT("%s status=%d", __func__, result.status);
  if (result.status != BTM_CMD_STARTED) {
    result.num_resp = 0;
    bta_dm_inq_cmpl_cb((void*)&result);
  }
}

重点关注下面这个函数

  result.status = BTM_StartInquiry((tBTM_INQ_PARMS*)&p_data->search.inq_params,
                                   bta_dm_inq_results_cb,
                                   (tBTM_CMPL_CB*)bta_dm_inq_cmpl_cb);

/*******************************************************************************
 *
 * Function         BTM_StartInquiry
 *
 * Description      This function is called to start an inquiry.
 *
 * Parameters:      p_inqparms - pointer to the inquiry information
 *                      mode - GENERAL or LIMITED inquiry, BR/LE bit mask
 *                             seperately
 *                      duration - length in 1.28 sec intervals (If '0', the
 *                                 inquiry is CANCELLED)
 *                      max_resps - maximum amount of devices to search for
 *                                  before ending the inquiry
 *                      filter_cond_type - BTM_CLR_INQUIRY_FILTER,
 *                                         BTM_FILTER_COND_DEVICE_CLASS, or
 *                                         BTM_FILTER_COND_BD_ADDR
 *                      filter_cond - value for the filter (based on
 *                                                          filter_cond_type)
 *
 *                  p_results_cb   - Pointer to the callback routine which gets
 *                                called upon receipt of an inquiry result. If
 *                                this field is NULL, the application is not
 *                                notified.
 *
 *                  p_cmpl_cb   - Pointer to the callback routine which gets
 *                                called upon completion.  If this field is
 *                                NULL, the application is not notified when
 *                                completed.
 * Returns          tBTM_STATUS
 *                  BTM_CMD_STARTED if successfully initiated
 *                  BTM_BUSY if already in progress
 *                  BTM_ILLEGAL_VALUE if parameter(s) are out of range
 *                  BTM_NO_RESOURCES if could not allocate resources to start
 *                                   the command
 *                  BTM_WRONG_MODE if the device is not up.
 *
 ******************************************************************************/
tBTM_STATUS BTM_StartInquiry(tBTM_INQ_PARMS* p_inqparms,
                             tBTM_INQ_RESULTS_CB* p_results_cb,
                             tBTM_CMPL_CB* p_cmpl_cb) {
  tBTM_STATUS status = BTM_CMD_STARTED;
  tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;

  BTM_TRACE_API("BTM_StartInquiry: mode: %d, dur: %d, rsps: %d, flt: %d",
                p_inqparms->mode, p_inqparms->duration, p_inqparms->max_resps,
                p_inqparms->filter_cond_type);

  /* Only one active inquiry is allowed in this implementation.
     Also do not allow an inquiry if the inquiry filter is being updated */
  if (p_inq->inq_active || p_inq->inqfilt_active) {
    /*check if LE observe is already running*/
    if (p_inq->scan_type == INQ_LE_OBSERVE &&
        p_inq->p_inq_ble_results_cb != NULL) {
      BTM_TRACE_API("BTM_StartInquiry: LE observe in progress");
      p_inq->scan_type = INQ_GENERAL;
      p_inq->inq_active = BTM_INQUIRY_INACTIVE;
      btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
      btm_send_hci_scan_enable(BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
    } else {
      BTM_TRACE_API("BTM_StartInquiry: return BUSY");
      return (BTM_BUSY);
    }
  } else
    p_inq->scan_type = INQ_GENERAL;

  /*** Make sure the device is ready ***/
  if (!BTM_IsDeviceUp()) return (BTM_WRONG_MODE);

  if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) != BTM_GENERAL_INQUIRY &&
      (p_inqparms->mode & BTM_BR_INQUIRY_MASK) != BTM_LIMITED_INQUIRY &&
      (p_inqparms->mode & BTM_BLE_INQUIRY_MASK) != BTM_BLE_GENERAL_INQUIRY &&
      (p_inqparms->mode & BTM_BLE_INQUIRY_MASK) != BTM_BLE_LIMITED_INQUIRY)
    return (BTM_ILLEGAL_VALUE);

#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
  if (p_inq->next_state == BTM_FINISH) return BTM_ILLEGAL_VALUE;
#endif

  /* Save the inquiry parameters to be used upon the completion of
   * setting/clearing the inquiry filter */
  p_inq->inqparms = *p_inqparms;

  /* Initialize the inquiry variables */
  p_inq->state = BTM_INQ_ACTIVE_STATE;
  p_inq->p_inq_cmpl_cb = p_cmpl_cb;
  p_inq->p_inq_results_cb = p_results_cb;
  p_inq->inq_cmpl_info.num_resp = 0; /* Clear the results counter */
  p_inq->inq_active = p_inqparms->mode;

  BTM_TRACE_DEBUG("BTM_StartInquiry: p_inq->inq_active = 0x%02x",
                  p_inq->inq_active);

/* interleave scan minimal conditions */
#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)

  /* check if both modes are present */
  if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK) &&
      (p_inqparms->mode & BTM_BR_INQUIRY_MASK)) {
    BTM_TRACE_API("BTM:Interleave Inquiry Mode Set");
    p_inqparms->duration = p_inqparms->intl_duration[p_inq->next_state];
    p_inq->inqparms.duration = p_inqparms->duration;
  } else {
    BTM_TRACE_API("BTM:Single Mode: No interleaving, Mode:0x%02x",
                  p_inqparms->mode);
    p_inq->next_state = BTM_NO_INTERLEAVING;
  }
#endif

  /* start LE inquiry here if requested */
  if ((p_inqparms->mode & BTM_BLE_INQUIRY_MASK)
#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
      &&
      (p_inq->next_state == BTM_BLE_ONE || p_inq->next_state == BTM_BLE_TWO ||
       p_inq->next_state == BTM_NO_INTERLEAVING)
#endif
          )

  {
#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
    p_inq->inq_active = (p_inqparms->mode & BTM_BLE_INQUIRY_MASK);
    BTM_TRACE_API("BTM:Starting LE Scan with duration %d and activeMode:0x%02x",
                  p_inqparms->duration,
                  (p_inqparms->mode & BTM_BLE_INQUIRY_MASK));
#endif
    if (!controller_get_interface()->supports_ble()) {
      p_inq->inqparms.mode &= ~BTM_BLE_INQUIRY_MASK;
      status = BTM_ILLEGAL_VALUE;
    }
    /* BLE for now does not support filter condition for inquiry */
    else {
      status = btm_ble_start_inquiry(
          (uint8_t)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
          p_inqparms->duration);
      if (status != BTM_CMD_STARTED) {
        BTM_TRACE_ERROR("Err Starting LE Inquiry.");
        p_inq->inqparms.mode &= ~BTM_BLE_INQUIRY_MASK;
      }
    }
#if (BTA_HOST_INTERLEAVE_SEARCH == FALSE)
    p_inqparms->mode &= ~BTM_BLE_INQUIRY_MASK;
#endif

#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
    if (p_inq->next_state == BTM_NO_INTERLEAVING) {
      p_inq->next_state = BTM_FINISH;
    } else {
      BTM_TRACE_API(
          "BTM:Interleaving: started LE scan, Advancing to next state: %d",
          p_inq->next_state + 1);
      p_inq->next_state += 1;
    }
    /* reset next_state if status <> BTM_Started */
    if (status != BTM_CMD_STARTED) p_inq->next_state = BTM_BR_ONE;

    /* if interleave scan..return here */
    return status;
#endif

    BTM_TRACE_DEBUG("BTM_StartInquiry: mode = %02x", p_inqparms->mode);
  }

  /* we're done with this routine if BR/EDR inquiry is not desired. */
  if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE)
    return status;

/* BR/EDR inquiry portion */
#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
  if ((p_inq->next_state == BTM_BR_ONE || p_inq->next_state == BTM_BR_TWO ||
       p_inq->next_state == BTM_NO_INTERLEAVING)) {
    p_inq->inq_active = (p_inqparms->mode & BTM_BR_INQUIRY_MASK);
#endif
    /* If a filter is specified, then save it for later and clear the current
       filter.
       The setting of the filter is done upon completion of clearing of the
       previous
       filter.
    */
    switch (p_inqparms->filter_cond_type) {
      case BTM_CLR_INQUIRY_FILTER:
        p_inq->state = BTM_INQ_SET_FILT_STATE;
        break;

      case BTM_FILTER_COND_DEVICE_CLASS:
      case BTM_FILTER_COND_BD_ADDR:
        /* The filter is not being used so simply clear it;
            the inquiry can start after this operation */
        p_inq->state = BTM_INQ_CLR_FILT_STATE;
        p_inqparms->filter_cond_type = BTM_CLR_INQUIRY_FILTER;
        /* =============>>>> adding LE filtering here ????? */
        break;

      default:
        return (BTM_ILLEGAL_VALUE);
    }

    /* Before beginning the inquiry the current filter must be cleared, so
     * initiate the command */
    status = btm_set_inq_event_filter(p_inqparms->filter_cond_type,
                                      &p_inqparms->filter_cond);
    if (status != BTM_CMD_STARTED) p_inq->state = BTM_INQ_INACTIVE_STATE;

#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
    if (p_inq->next_state == BTM_NO_INTERLEAVING)
      p_inq->next_state = BTM_FINISH;
    else {
      BTM_TRACE_API(
          "BTM:Interleaving: Started BTM inq, Advancing to next state: %d",
          p_inq->next_state + 1);
      p_inq->next_state += 1;
    }
  }
  if (status != BTM_CMD_STARTED) {
    /* Some error beginning the scan process.
       Reset the next_state parameter.. Do we need to reset the inq_active also?
    */
    BTM_TRACE_API("BTM:Interleaving: Error in Starting inquiry, status: 0x%02x",
                  status);
    p_inq->next_state = BTM_BR_ONE;
  }
#endif

  return (status);
}

可以看一下这个函数的实现

      status = btm_ble_start_inquiry(
 btm_send_hci_set_scan_params(
  btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
  hci_layer_get_interface()->transmit_command(
      p_buf, btu_hcif_command_complete_evt, btu_hcif_command_status_evt,
      vsc_callback);
static void transmit_command(BT_HDR* command,
                             command_complete_cb complete_callback,
                             command_status_cb status_callback, void* context) {
hci_layer_get_interface()->transmit_command

hci/src/hci_layer.c: Android BlueDroid分析: OSI中的reactor的实现与使用分析 transmit_command->fixed_queue_enqueue event_command_ready(fixed_queue_dequeue)->"packet_fragmenter->fragment_and_dispatch"->transmit_fragment--->hal->transmit_data

hci/src/hci_hal_mct.c: transmit_data--->vendor

stack/include/hcidefs.h: Definitions for Link Control Commands
static int start_discovery(void) {
btif_dm_start_discovery()
bt_status_t btif_dm_start_discovery(void) {
  /* Set inquiry params and call API   inq_params  是构造出来的查询条件参数.  */
  inq_params.mode = BTA_DM_GENERAL_INQUIRY | BTA_BLE_GENERAL_INQUIRY;
#if (BTA_HOST_INTERLEAVE_SEARCH == TRUE)
  inq_params.intl_duration[0] = BTIF_DM_INTERLEAVE_DURATION_BR_ONE;
  inq_params.intl_duration[1] = BTIF_DM_INTERLEAVE_DURATION_LE_ONE;
  inq_params.intl_duration[2] = BTIF_DM_INTERLEAVE_DURATION_BR_TWO;
  inq_params.intl_duration[3] = BTIF_DM_INTERLEAVE_DURATION_LE_TWO;
#endif
  inq_params.duration = BTIF_DM_DEFAULT_INQ_MAX_DURATION;

  inq_params.max_resps = BTIF_DM_DEFAULT_INQ_MAX_RESULTS;
  inq_params.report_dup = true;

  inq_params.filter_type = BTA_DM_INQ_CLR;

/*******************************************************************************
 *
 * Function         BTA_DmSearch
 *
 * Description      This function searches for peer Bluetooth devices. It
 *                  performs an inquiry and gets the remote name for devices.
 *                  Service discovery is done if services is non zero
 *
 *
 * Returns          void
 *
 ******************************************************************************/
//  BTA_DmSearch(&inq_params, services,bte_search_devices_evt);
void BTA_DmSearch(tBTA_DM_INQ* p_dm_inq, tBTA_SERVICE_MASK services,
                  tBTA_DM_SEARCH_CBACK* p_cback) {
  tBTA_DM_API_SEARCH* p_msg =
      (tBTA_DM_API_SEARCH*)osi_calloc(sizeof(tBTA_DM_API_SEARCH));

  p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
  memcpy(&p_msg->inq_params, p_dm_inq, sizeof(tBTA_DM_INQ));
  p_msg->services = services;
  p_msg->p_cback = p_cback;
  p_msg->rs_res = BTA_DM_RS_NONE;

  bta_sys_sendmsg(p_msg);
}

可以看到,该函数构造了一个消息p_msg,设置了事件类型以及回调函数。在这里,回调函数即前面的bte_search_devices_evt,它处理搜索的结果,并最终通过JNI提供的callback返回给上层。这个消息被发送到btu_task,由bta模块处理,代码如下

/*******************************************************************************
 *
 * Function         bte_search_devices_evt
 *
 * Description      Switches context from BTE to BTIF for DM search events
 *
 * Returns          void
 *
 ******************************************************************************/
//E:\code\phone_bsp\ocean\bt\btif\src\btif_dm.cc
static void bte_search_devices_evt(tBTA_DM_SEARCH_EVT event,
                                   tBTA_DM_SEARCH* p_data) {
  uint16_t param_len = 0;

  if (p_data) param_len += sizeof(tBTA_DM_SEARCH);
  /* Allocate buffer to hold the pointers (deep copy). The pointers will point
   * to the end of the tBTA_DM_SEARCH */
  switch (event) {
    case BTA_DM_INQ_RES_EVT: {
      if (p_data && p_data->inq_res.p_eir) param_len += p_data->inq_res.eir_len;
    } break;

    case BTA_DM_DISC_RES_EVT: {
      if (p_data && p_data->disc_res.raw_data_size && p_data->disc_res.p_raw_data)
        param_len += p_data->disc_res.raw_data_size;
    } break;
  }
  BTIF_TRACE_DEBUG("%s event=%s param_len=%d", __func__,
                   dump_dm_search_event(event), param_len);

  /* if remote name is available in EIR, set teh flag so that stack doesnt
   * trigger RNR */
  if (p_data && event == BTA_DM_INQ_RES_EVT) {
    p_data->inq_res.remt_name_not_required =
        check_eir_remote_name(p_data, NULL, NULL);
    BTIF_TRACE_DEBUG("%s, name_not_required=%d", __func__,p_data->inq_res.remt_name_not_required);
  }
//关键函数
  btif_transfer_context(
      btif_dm_search_devices_evt, (uint16_t)event, (char*)p_data, param_len,
      (param_len > sizeof(tBTA_DM_SEARCH)) ? search_devices_copy_cb : NULL);
}

E:\code\phone_bsp\ocean\bt\btif\src\btif_dm.cc

/******************************************************************************
 *
 * Function         btif_dm_search_devices_evt
 *
 * Description      Executes search devices callback events in btif context
 *
 * Returns          void
 *
 *****************************************************************************/
static void btif_dm_search_devices_evt(uint16_t event, char* p_param) {
  tBTA_DM_SEARCH* p_search_data;
  BTIF_TRACE_EVENT("%s event=%s", __func__, dump_dm_search_event(event));

  switch (event) {
    case BTA_DM_DISC_RES_EVT: {
      p_search_data = (tBTA_DM_SEARCH*)p_param;
      /* Remote name update */
      if (strlen((const char*)p_search_data->disc_res.bd_name)) {
        bt_property_t properties[1];
        bt_status_t status;

        properties[0].type = BT_PROPERTY_BDNAME;
        properties[0].val = p_search_data->disc_res.bd_name;
        properties[0].len = strlen((char*)p_search_data->disc_res.bd_name);
        RawAddress& bdaddr = p_search_data->disc_res.bd_addr;

        status =
            btif_storage_set_remote_device_property(&bdaddr, &properties[0]);
        ASSERTC(status == BT_STATUS_SUCCESS,
                "failed to save remote device property", status);
        HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, status, &bdaddr,
                  1, properties);
      }
      /* TODO: Services? */
    } break;

    case BTA_DM_INQ_RES_EVT: {
      /* inquiry result */
      bt_bdname_t bdname;
      uint8_t remote_name_len;
      tBTA_SERVICE_MASK services = 0;

      p_search_data = (tBTA_DM_SEARCH*)p_param;
      RawAddress& bdaddr = p_search_data->inq_res.bd_addr;

      BTIF_TRACE_DEBUG("%s() %s device_type = 0x%x\n", __func__,
                       bdaddr.ToString().c_str(),
                       p_search_data->inq_res.device_type);
      bdname.name[0] = 0;

      if (!check_eir_remote_name(p_search_data, bdname.name, &remote_name_len))
        check_cached_remote_name(p_search_data, bdname.name, &remote_name_len);

      /* Check EIR for remote name and services */
      if (p_search_data->inq_res.p_eir) {
        BTA_GetEirService(p_search_data->inq_res.p_eir,
                          p_search_data->inq_res.eir_len, &services);
        BTIF_TRACE_DEBUG("%s()EIR BTA services = %08X", __func__,
                         (uint32_t)services);
        /* TODO:  Get the service list and check to see which uuids we got and
         * send it back to the client. */
      }

      {
        bt_property_t properties[5];
        bt_device_type_t dev_type;
        uint32_t num_properties = 0;
        bt_status_t status;
        int addr_type = 0;
        bt_bdname_t alias;
        memset(&alias, 0, sizeof(alias));
        BTIF_DM_GET_REMOTE_PROP(&bdaddr, BT_PROPERTY_REMOTE_FRIENDLY_NAME,
                      &alias, sizeof(alias), properties[num_properties]);

        memset(properties, 0, sizeof(properties));
        /* RawAddress */
        BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
                                   BT_PROPERTY_BDADDR, sizeof(bdaddr), &bdaddr);
        num_properties++;
        /* BD_NAME */
        /* Don't send BDNAME if it is empty */
        /* send alias name as the name if alias name present */
        if (alias.name[0] != '\0') {
          BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
                                       BT_PROPERTY_BDNAME,
                                       strlen((char *)alias.name), &alias);
          num_properties++;
        } else if (bdname.name[0]) {
          if((check_eir_is_remote_name_short(p_search_data) == TRUE) &&
               (btif_storage_is_device_bonded(&bdaddr) == BT_STATUS_SUCCESS)) {
            BTIF_TRACE_DEBUG("%s Don't update about the device name ", __FUNCTION__);
          } else {
            BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
                                          BT_PROPERTY_BDNAME,
                                       strlen((char *)bdname.name), &bdname);
            num_properties++;
          }
        }

        /* DEV_CLASS */
        uint32_t cod = devclass2uint(p_search_data->inq_res.dev_class);
        BTIF_TRACE_DEBUG("%s cod is 0x%06x", __func__, cod);
        if (cod != 0) {
          BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
                                     BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod),
                                     &cod);
          num_properties++;
        }

        /* DEV_TYPE */
        /* FixMe: Assumption is that bluetooth.h and BTE enums match */

        /* Verify if the device is dual mode in NVRAM */
        int stored_device_type = 0;
        if (btif_get_device_type(bdaddr, &stored_device_type) &&
            ((stored_device_type != BT_DEVICE_TYPE_BREDR &&
              p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BREDR) ||
             (stored_device_type != BT_DEVICE_TYPE_BLE &&
              p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BLE))) {
          dev_type = (bt_device_type_t)BT_DEVICE_TYPE_DUMO;
        } else {
          dev_type = (bt_device_type_t)p_search_data->inq_res.device_type;
        }

        if (p_search_data->inq_res.device_type == BT_DEVICE_TYPE_BLE)
          addr_type = p_search_data->inq_res.ble_addr_type;
        BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
                                   BT_PROPERTY_TYPE_OF_DEVICE, sizeof(dev_type),
                                   &dev_type);
        num_properties++;
        /* RSSI */
        BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
                                   BT_PROPERTY_REMOTE_RSSI, sizeof(int8_t),
                                   &(p_search_data->inq_res.rssi));
        num_properties++;

        status =
            btif_storage_add_remote_device(&bdaddr, num_properties, properties);
        ASSERTC(status == BT_STATUS_SUCCESS,
                "failed to save remote device (inquiry)", status);
        status = btif_storage_set_remote_addr_type(&bdaddr, addr_type);
        ASSERTC(status == BT_STATUS_SUCCESS,
                "failed to save remote addr type (inquiry)", status);
        /* Callback to notify upper layer of device */
        HAL_CBACK(bt_hal_cbacks, device_found_cb, num_properties, properties);
      }
    } break;

    case BTA_DM_INQ_CMPL_EVT: {
      do_in_bta_thread(
          FROM_HERE,
          base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_DELETE, 0,
                     nullptr, base::Bind(&bte_scan_filt_param_cfg_evt, 0)));
    } break;
    case BTA_DM_DISC_CMPL_EVT: {
      HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb,
                BT_DISCOVERY_STOPPED);
    } break;
    case BTA_DM_SEARCH_CANCEL_CMPL_EVT: {
      /* if inquiry is not in progress and we get a cancel event, then
       * it means we are done with inquiry, but remote_name fetches are in
       * progress
       *
       * if inquiry  is in progress, then we don't want to act on this
       * cancel_cmpl_evt
       * but instead wait for the cancel_cmpl_evt via the Busy Level
       *
       */
      if (btif_dm_inquiry_in_progress == false) {
        btgatt_filt_param_setup_t adv_filt_param;
        memset(&adv_filt_param, 0, sizeof(btgatt_filt_param_setup_t));
        do_in_bta_thread(
            FROM_HERE,
            base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_DELETE, 0,
                       nullptr, base::Bind(&bte_scan_filt_param_cfg_evt, 0)));
        HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb,
                  BT_DISCOVERY_STOPPED);
      }
    } break;
  }
}

//
void bta_dm_search_start(tBTA_DM_MSG* p_data) {
//来自于这个结构体

/* action function list */
const tBTA_DM_ACTION bta_dm_search_action[] = {

    bta_dm_search_start,               /* 0 BTA_DM_API_SEARCH */
    bta_dm_search_cancel,              /* 1 BTA_DM_API_SEARCH_CANCEL */
    bta_dm_discover,                   /* 2 BTA_DM_API_DISCOVER */
    bta_dm_inq_cmpl,                   /* 3 BTA_DM_INQUIRY_CMPL */
    bta_dm_rmt_name,                   /* 4 BTA_DM_REMT_NAME */
    bta_dm_sdp_result,                 /* 5 BTA_DM_SDP_RESULT */
    bta_dm_search_cmpl,                /* 6 BTA_DM_SEARCH_CMPL */
    bta_dm_free_sdp_db,                /* 7 BTA_DM_FREE_SDP_DB */
    bta_dm_disc_result,                /* 8 BTA_DM_DISC_RESULT */
    bta_dm_search_result,              /* 9 BTA_DM_SEARCH_RESULT */
    bta_dm_queue_search,               /* 10 BTA_DM_QUEUE_SEARCH */
    bta_dm_queue_disc,                 /* 11 BTA_DM_QUEUE_DISC */
    bta_dm_search_clear_queue,         /* 12 BTA_DM_SEARCH_CLEAR_QUEUE */
    bta_dm_search_cancel_cmpl,         /* 13 BTA_DM_SEARCH_CANCEL_CMPL */
    bta_dm_search_cancel_notify,       /* 14 BTA_DM_SEARCH_CANCEL_NOTIFY */
    bta_dm_search_cancel_transac_cmpl, /* 15 BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL
                                          */
    bta_dm_disc_rmt_name,              /* 16 BTA_DM_DISC_RMT_NAME */
    bta_dm_di_disc,                    /* 17 BTA_DM_API_DI_DISCOVER */
    bta_dm_close_gatt_conn};

bool bta_dm_search_sm_execute(BT_HDR* p_msg) {
static const tBTA_SYS_REG bta_dm_search_reg = {bta_dm_search_sm_execute,
bta_dm_search_sm_disable};

tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK* p_cback) {
/* Bluetooth disabling is in progress */
if (bta_dm_cb.disabling) return BTA_FAILURE;

bta_sys_register(BTA_ID_DM, &bta_dm_reg);
bta_sys_register(BTA_ID_DM_SEARCH, &bta_dm_search_reg);

上面的结构体注册在这个地方
static const tBTA_SYS_REG bta_dm_search_reg = {bta_dm_search_sm_execute,
bta_dm_search_sm_disable};

蓝牙配对的流程
BlueDroid 蓝牙底层通信
https://www.meiwen.com.cn/subject/ptoiqxtx.html

create_bond函数, 主要参考下面这篇文章
A: How to do the createBond operation? B: Let me show you
https://www.jianshu.com/p/df2d959a8a77

static int create_bond(const RawAddress* bd_addr, int transport) {
  /* sanity check */
  if (interface_ready() == false) return BT_STATUS_NOT_READY;

  return btif_dm_create_bond(bd_addr, transport);
}

重点关注下面这个函数btif_dm_create_bond, 看注释表示的是与一个特定设备建立连接,他做了哪些操作?

此处的btif_dm_create_bond函数不会进行实际bond操作,只是将事件抛出去,由其他的线程进行处理;
此处的设计很巧妙,因为如果上层所有的蓝牙相关操作事件下发下来,在此就进行处理,在实际编码中必然要加上很多的互斥操作,这就增加了设计的复杂性。

03-16 17:16:52.604 8727 8751 I bt_btif : btif_dm_create_bond: bd_addr=20:74:cf:0b:ef:7d, transport=0

获取了设备的类型
bt_btif_config: btif_get_device_type: Device [20:74:cf:0b:ef:7d] type 1
返回值是1,表示是传统蓝牙

  system_bt_osi::device_type_t device_type;
  switch (type) {
    case BT_DEVICE_TYPE_BREDR:
      device_type = system_bt_osi::DEVICE_TYPE_BREDR;
      break;
    case BT_DEVICE_TYPE_BLE:
      device_type = system_bt_osi::DEVICE_TYPE_LE;
      break;
    case BT_DEVICE_TYPE_DUMO:
      device_type = system_bt_osi::DEVICE_TYPE_DUMO;

/*******************************************************************************
 *
 * Function         btif_dm_create_bond
 *
 * Description      Initiate bonding with the specified device
 *
 * Returns          bt_status_t
 *
 ******************************************************************************/
bt_status_t btif_dm_create_bond(const RawAddress* bd_addr, int transport) {
  btif_dm_create_bond_cb_t create_bond_cb;
  create_bond_cb.transport = transport;
  create_bond_cb.bdaddr = *bd_addr;

  BTIF_TRACE_EVENT("%s: bd_addr=%s, transport=%d", __func__,
                   bd_addr->ToString().c_str(), transport);
  if (pairing_cb.state != BT_BOND_STATE_NONE) return BT_STATUS_BUSY;

  btif_stats_add_bond_event(*bd_addr, BTIF_DM_FUNC_CREATE_BOND,
                            pairing_cb.state);

  btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_CREATE_BOND,
                        (char*)&create_bond_cb,
                        sizeof(btif_dm_create_bond_cb_t), NULL);

  return BT_STATUS_SUCCESS;
}

将这个消息发送出去,
03-16 17:16:52.604 8727 8751 D bt_btif : btif_transfer_context event 33026, len 7

那么谁来接受这个消息呢?
D bt_btif : btif task fetched event a001

/*******************************************************************************
 *
 * Function         btif_task
 *
 * Description      BTIF task handler managing all messages being passed
 *                  Bluetooth HAL and BTA.
 *
 * Returns          void
 *
 ******************************************************************************/
static void bt_jni_msg_ready(void* context) {
  BT_HDR* p_msg = (BT_HDR*)context;

  BTIF_TRACE_VERBOSE("btif task fetched event %x", p_msg->event);

  switch (p_msg->event) {
    case BT_EVT_CONTEXT_SWITCH_EVT:
      btif_context_switched(p_msg);
      break;
    default:
      BTIF_TRACE_ERROR("unhandled btif event (%d)", p_msg->event & BT_EVT_MASK);
      break;
  }
  osi_free(p_msg);
}

btif_dm_generic_evt函数会接收这个事件并进行后续处理;
bt_btif : btif_dm_generic_evt: event=33026

/*******************************************************************************
 *
 * Function         btif_dm_generic_evt
 *
 * Description      Executes non-BTA upstream events in BTIF context
 *
 * Returns          void
 *
 ******************************************************************************/
static void btif_dm_generic_evt(uint16_t event, char* p_param) {
  BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
  switch (event) {
    case BTIF_DM_CB_DISCOVERY_STARTED: {
      HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb,
                BT_DISCOVERY_STARTED);
    } break;

    case BTIF_DM_CB_CREATE_BOND: {
      pairing_cb.timeout_retries = NUM_TIMEOUT_RETRIES;
      btif_dm_create_bond_cb_t* create_bond_cb =
          (btif_dm_create_bond_cb_t*)p_param;
      btif_dm_cb_create_bond(create_bond_cb->bdaddr, create_bond_cb->transport);
    } break;

    case BTIF_DM_CB_REMOVE_BOND: {
      btif_dm_cb_remove_bond((RawAddress*)p_param);
    } break;

    case BTIF_DM_CB_HID_REMOTE_NAME: {
      btif_dm_cb_hid_remote_name((tBTM_REMOTE_DEV_NAME*)p_param);
    } break;

    case BTIF_DM_CB_BOND_STATE_BONDING: {
      bond_state_changed(BT_STATUS_SUCCESS, *((RawAddress*)p_param),
                         BT_BOND_STATE_BONDING);
    } break;
    case BTIF_DM_CB_LE_TX_TEST:
    case BTIF_DM_CB_LE_RX_TEST: {
      uint8_t status;
      STREAM_TO_UINT8(status, p_param);
      HAL_CBACK(bt_hal_cbacks, le_test_mode_cb,
                (status == 0) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL, 0);
    } break;
    case BTIF_DM_CB_LE_TEST_END: {
      uint8_t status;
      uint16_t count = 0;
      STREAM_TO_UINT8(status, p_param);
      if (status == 0) STREAM_TO_UINT16(count, p_param);
      HAL_CBACK(bt_hal_cbacks, le_test_mode_cb,
                (status == 0) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL, count);
    } break;
    default: {
      BTIF_TRACE_WARNING("%s : Unknown event 0x%x", __func__, event);
    } break;
  }
}

应该走的是下面这个case语句

 case BTIF_DM_CB_CREATE_BOND: {
      pairing_cb.timeout_retries = NUM_TIMEOUT_RETRIES;
      btif_dm_create_bond_cb_t* create_bond_cb =
          (btif_dm_create_bond_cb_t*)p_param;
      btif_dm_cb_create_bond(create_bond_cb->bdaddr, 

btif_dm_cb_create_bond函数会对绑定事件进行处理,此处对HID设备进行了特别的处理;

bt_btif : bond_state_changed: state=1, prev_state=0, sdp_attempts = 0

状态表
55    static final int BT_BOND_STATE_NONE = 0x00;
56    static final int BT_BOND_STATE_BONDING = 0x01;
57    static final int BT_BOND_STATE_BONDED = 0x02;
/*******************************************************************************
 *
 * Function         btif_dm_cb_create_bond
 *
 * Description      Create bond initiated from the BTIF thread context
 *                  Special handling for HID devices
 *
 * Returns          void
 *
 ******************************************************************************/
static void btif_dm_cb_create_bond(const RawAddress& bd_addr,
                                   tBTA_TRANSPORT transport) {
  bool is_hid = check_cod(&bd_addr, COD_HID_POINTING);

  if (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE ) {
    BTIF_TRACE_DEBUG("%s: btm_cb.pairing_state = %d, one pairing in progress ",
                      __func__, btm_cb.pairing_state);
    LOG_INFO(LOG_TAG, "%s: btm_cb.pairing_state = %d, one pairing in progress ",
                      __func__, btm_cb.pairing_state);
    return;
  }

  bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING);

  int device_type;
  int addr_type;
  std::string addrstr = bd_addr.ToString();
  const char* bdstr = addrstr.c_str();
  if (transport == BT_TRANSPORT_LE) {
    if (!btif_config_get_int(bdstr, "DevType", &device_type)) {
      btif_config_set_int(bdstr, "DevType", BT_DEVICE_TYPE_BLE);
    }
    if (btif_storage_get_remote_addr_type(&bd_addr, &addr_type) !=
        BT_STATUS_SUCCESS) {
      // Try to read address type. OOB pairing might have set it earlier, but
      // didn't store it, it defaults to BLE_ADDR_PUBLIC
      uint8_t tmp_dev_type;
      uint8_t tmp_addr_type;
      BTM_ReadDevInfo(bd_addr, &tmp_dev_type, &tmp_addr_type);
      addr_type = tmp_addr_type;

      btif_storage_set_remote_addr_type(&bd_addr, addr_type);
    }
  }
  if ((btif_config_get_int(bdstr, "DevType", &device_type) &&
       (btif_storage_get_remote_addr_type(&bd_addr, &addr_type) ==
        BT_STATUS_SUCCESS) &&
       (device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE) ||
      (transport == BT_TRANSPORT_LE)) {
    BTA_DmAddBleDevice(bd_addr, addr_type, device_type);
  }

  if (is_hid && (device_type & BT_DEVICE_TYPE_BLE) == 0) {
    bt_status_t status;
    status = (bt_status_t)btif_hh_connect(&bd_addr);
    if (status != BT_STATUS_SUCCESS)
      bond_state_changed(status, bd_addr, BT_BOND_STATE_NONE);
  } else {
    BTA_DmBondByTransport(bd_addr, transport);
  }
  /*  Track  originator of bond creation  */
  pairing_cb.is_local_initiated = true;
}

主要的函数就是这个 BTA_DmBondByTransports
这个函数的主要功能就是发送了一条消息出去

/*******************************************************************************
 *
 * Function         BTA_DmBondByTransports
 *
 * Description      This function initiates a bonding procedure with a peer
 *                  device
 *
 *
 * Returns          void
 *
 ******************************************************************************/
void BTA_DmBondByTransport(const RawAddress& bd_addr,
                           tBTA_TRANSPORT transport) {
  tBTA_DM_API_BOND* p_msg =
      (tBTA_DM_API_BOND*)osi_malloc(sizeof(tBTA_DM_API_BOND));

  p_msg->hdr.event = BTA_DM_API_BOND_EVT;
  p_msg->bd_addr = bd_addr;
  p_msg->transport = transport;

  bta_sys_sendmsg(p_msg);
}

谁来处理这个消息

/*******************************************************************************
 *
 * Function         bta_sys_event
 *
 * Description      BTA event handler; called from task event handler.
 *
 *
 * Returns          void
 *
 ******************************************************************************/
void bta_sys_event(BT_HDR* p_msg) {
  uint8_t id;
  bool freebuf = true;

  APPL_TRACE_EVENT("%s: Event 0x%x", __func__, p_msg->event);
  LOG_INFO(LOG_TAG, "%s: p_msg->event:0x%x", __func__, p_msg->event);
  /* get subsystem id from event */
  id = (uint8_t)(p_msg->event >> 8);

  /* verify id and call subsystem event handler */
  if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL)) {
    freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
  } else {
    APPL_TRACE_WARNING("%s: Received unregistered event id %d", __func__, id);
  }

  if (freebuf) {
    osi_free(p_msg);
  }
}

之后调用的是哪一个函数, id = (0x107 >> 8) = 1;

bt_btif : bta_sys_event: Event 0x107 
bt_btif : bta_dm_sm_execute event:0x7
static const tBTA_SYS_REG bta_dm_reg = {bta_dm_sm_execute, bta_dm_sm_disable};
  bta_sys_register(BTA_ID_DM, &bta_dm_reg);

根据event调用不同的处理函数。event = 7;

/*******************************************************************************
 *
 * Function         bta_dm_sm_execute
 *
 * Description      State machine event handling function for DM
 *
 *
 * Returns          void
 *
 ******************************************************************************/
bool bta_dm_sm_execute(BT_HDR* p_msg) {
  uint16_t event = p_msg->event & 0x00ff;

  APPL_TRACE_EVENT("bta_dm_sm_execute event:0x%x", event);

  /* execute action functions */
  if (event < BTA_DM_NUM_ACTIONS) {
    (*bta_dm_action[event])((tBTA_DM_MSG*)p_msg);
  }

  return true;
}

调用下面的这个函数

/*******************************************************************************
 *
 * Function         bta_dm_bond
 *
 * Description      Bonds with peer device
 *
 *
 * Returns          void
 *
 ******************************************************************************/
void bta_dm_bond(tBTA_DM_MSG* p_data) {

这个函数做了哪些工作, 发现设备的类型

/*******************************************************************************
 *
 * Function         BTM_ReadDevInfo
 *
 * Description      This function is called to read the device/address type
 *                  of BD address.
 *
 * Parameter        remote_bda: remote device address
 *                  p_dev_type: output parameter to read the device type.
 *                  p_addr_type: output parameter to read the address type.
 *
 ******************************************************************************/
void BTM_ReadDevInfo(const RawAddress& remote_bda, tBT_DEVICE_TYPE* p_dev_type,
                     tBLE_ADDR_TYPE* p_addr_type) {

      *p_dev_type = BT_DEVICE_TYPE_BREDR;
      *p_addr_type = BLE_ADDR_PUBLIC;

然后使用下面这个函数进行第二阶段传输

/*******************************************************************************
 *
 * Function         btm_sec_bond_by_transport
 *
 * Description      this is the bond function that will start either SSP or SMP.
 *
 * Parameters:      bd_addr      - Address of the device to bond
 *                  pin_len      - length in bytes of the PIN Code
 *                  p_pin        - pointer to array with the PIN Code
 *                  trusted_mask - bitwise OR of trusted services
 *                                 (array of uint32_t)
 *
 *  Note: After 2.1 parameters are not used and preserved here not to change API
 ******************************************************************************/
tBTM_STATUS btm_sec_bond_by_transport(const RawAddress& bd_addr,
                                      tBT_TRANSPORT transport, uint8_t pin_len,
                                      uint8_t* p_pin, uint32_t trusted_mask[]) {

这个函数做了哪些工作

/*******************************************************************************
 *
 * Function         btm_find_or_alloc_dev
 *
 * Description      Look for the record in the device database for the record
 *                  with specified BD address
 *
 * Returns          Pointer to the record or NULL
 *
 ******************************************************************************/
tBTM_SEC_DEV_REC* btm_find_or_alloc_dev(const RawAddress& bd_addr) {
  tBTM_SEC_DEV_REC* p_dev_rec;
  BTM_TRACE_EVENT("btm_find_or_alloc_dev");
  p_dev_rec = btm_find_dev(bd_addr);
  if (p_dev_rec == NULL) {
    /* Allocate a new device record or reuse the oldest one */
    p_dev_rec = btm_sec_alloc_dev(bd_addr);
  }
  return (p_dev_rec);
}
/*******************************************************************************
 *
 * Function         btm_sec_alloc_dev
 *
 * Description      Look for the record in the device database for the record
 *                  with specified address
 *
 * Returns          Pointer to the record or NULL
 *
 ******************************************************************************/
tBTM_SEC_DEV_REC* btm_sec_alloc_dev(const RawAddress& bd_addr) {
  tBTM_INQ_INFO* p_inq_info;
  BTM_TRACE_EVENT("btm_sec_alloc_dev");

  tBTM_SEC_DEV_REC* p_dev_rec = btm_sec_allocate_dev_rec();

  /* Check with the BT manager if details about remote device are known */
  /* outgoing connection */
  p_inq_info = BTM_InqDbRead(bd_addr);
  if (p_inq_info != NULL) {
    memcpy(p_dev_rec->dev_class, p_inq_info->results.dev_class, DEV_CLASS_LEN);

    p_dev_rec->device_type = p_inq_info->results.device_type;
    p_dev_rec->ble.ble_addr_type = p_inq_info->results.ble_addr_type;
  } else if (bd_addr == btm_cb.connecting_bda)
    memcpy(p_dev_rec->dev_class, btm_cb.connecting_dc, DEV_CLASS_LEN);

  /* update conn params, use default value for background connection params */
  memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));

  p_dev_rec->bd_addr = bd_addr;

  p_dev_rec->ble_hci_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_LE);
  p_dev_rec->hci_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_BR_EDR);

  return (p_dev_rec);
}

建立连接, 蓝牙链路分两种同步链路(SCO)和异步链路(ACL)。A2DP(Advanced Audio Distribution Profile 高级音频传输模型)是跑在ACL链路上去高品质音频协议。A2DP定义了ACL(Asynchronous Connectionless 异步无连接)信道上传送单声道或立体声等高质量音A2DP 功能频信息的协议和过程

  p_dev_rec->ble_hci_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_LE);
  p_dev_rec->hci_handle = BTM_GetHCIConnHandle(bd_addr, BT_TRANSPORT_BR_EDR);

这些都是在一个函数里面
tBTM_STATUS btm_sec_bond_by_transport(const RawAddress& bd_addr,
btm_sec_change_pairing_state(BTM_PAIR_STATE_GET_REM_NAME);
status = BTM_ReadRemoteDeviceName(bd_addr, NULL, BT_TRANSPORT_BR_EDR);
BTM_TRACE_DEBUG("State:%s sm4: 0x%x sec_state:%d",
btm_pair_state_descr(btm_cb.pairing_state), p_dev_rec->sm4,
p_dev_rec->sec_state);

最后的逻辑在这个地方接收

/*******************************************************************************
 *
 * Function         btm_sec_rmt_host_support_feat_evt
 *
 * Description      This function is called when the
 *                  HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT is received
 *
 * Returns          void
 *
 ******************************************************************************/
void btm_sec_rmt_host_support_feat_evt(uint8_t* p) {
  tBTM_SEC_DEV_REC* p_dev_rec;
  RawAddress bd_addr; /* peer address */
  BD_FEATURES features;

  STREAM_TO_BDADDR(bd_addr, p);
  p_dev_rec = btm_find_or_alloc_dev(bd_addr);

  BTM_TRACE_EVENT("btm_sec_rmt_host_support_feat_evt  sm4: 0x%x  p[0]: 0x%x",
                  p_dev_rec->sm4, p[0]);

  if (BTM_SEC_IS_SM4_UNKNOWN(p_dev_rec->sm4)) {
    p_dev_rec->sm4 = BTM_SM4_KNOWN;
    STREAM_TO_ARRAY(features, p, HCI_FEATURE_BYTES_PER_PAGE);
    if (HCI_SSP_HOST_SUPPORTED(features)) {
      p_dev_rec->sm4 = BTM_SM4_TRUE;
    }
    BTM_TRACE_EVENT(
        "btm_sec_rmt_host_support_feat_evt sm4: 0x%x features[0]: 0x%x",
        p_dev_rec->sm4, features[0]);
  }
}

上面这个函数被谁调用

btu_hcif_host_support_evt

上面这个函数谁调用

void btu_hcif_process_event(UNUSED_ATTR uint8_t controller_id, BT_HDR* p_msg) {

谁来调用这个函数

void btu_hci_msg_process(BT_HDR* p_msg) {

获取到了对端的设备的名称调用哪个函数

/*******************************************************************************
 *
 * Function         btm_sec_rmt_name_request_complete
 *
 * Description      This function is called when remote name was obtained from
 *                  the peer device
 *
 * Returns          void
 *
 ******************************************************************************/
void btm_sec_rmt_name_request_complete(const RawAddress* p_bd_addr,
                                       uint8_t* p_bd_name, uint8_t status) {

a2dp协议学习


image.png

L2CAP基于信道的概念,信道的每一个端点被称为信道标识符(CID) 不同设备间CID可复用,但本地设备CID不可复用
以下是CID ACL-U和AMP-U链路的name space(LE-U未列出)


image.png

2)A2DP的连接:

AVDTP连接的建立首先依赖于L2CAP连接的建立,它会在同一条ACL Link上建立两条L2CAP Channel,一条是用来Signaling,另一条用来进行Stream,report和recovery的传输。

image.png

(1)Signaling的主要过程为:1.DISCOVER 2.GET_CAPABILITIES 3.SET_CONFIGURATION 4.OPEN 5.START。

a2dp profile 播放音频的流程
init_src函数

/*******************************************************************************
 *
 * Function         init_src
 *
 * Description      Initializes the AV interface for source mode
 *
 * Returns          bt_status_t
 *
 ******************************************************************************/
static bt_status_t init_src(
    btav_source_callbacks_t* callbacks,
    std::vector<btav_a2dp_codec_config_t> codec_priorities,
    int max_a2dp_connections, int a2dp_multicast_state) {
  bt_status_t status = BT_STATUS_FAIL;
  BTIF_TRACE_EVENT("%s() with max conn = %d", __func__, max_a2dp_connections);
  char value[PROPERTY_VALUE_MAX] = {'\0'};

  osi_property_get("persist.vendor.bt.enable.splita2dp", value, "true");
  BTIF_TRACE_ERROR("split_a2dp_status = %s",value);
  bt_split_a2dp_enabled = (strcmp(value, "true") == 0);
  BTIF_TRACE_ERROR("split_a2dp_status = %d",bt_split_a2dp_enabled);

  if (bt_av_sink_callbacks != NULL)
        // already did btif_av_init()
        status = BT_STATUS_SUCCESS;
  else {
    if (a2dp_multicast_state && !bt_split_a2dp_enabled)
      is_multicast_supported = true;
    btif_max_av_clients = max_a2dp_connections;
    for (int i = 0; i < btif_max_av_clients; i++)
      btif_av_cb[i].codec_priorities = codec_priorities;
    if (codec_config_update_enabled != false) {
        BTIF_TRACE_IMP("%s: Codec cfg update enabled changed to false", __func__);
        codec_config_update_enabled = false;
    }
    status = btif_av_init(BTA_A2DP_SOURCE_SERVICE_ID);
    if (status == BT_STATUS_SUCCESS) bt_av_src_callbacks = callbacks;
  }
  return status;
}

bta_sys_event方法里面没有实际的处理消息的方法。根据消息id,查询是否存在注册该id的回调函数,存在则调用回调函数处理该消息。

//bt\bta\sys\bta_sys_main.cc  
if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL)) {
    freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);//检查是否有相应的处理函数
  } else {
    APPL_TRACE_WARNING("%s: Received unregistered event id %d", __func__, id);
  }

/* registration structure /
typedef struct {
tBTA_SYS_EVT_HDLR
evt_hdlr;
tBTA_SYS_DISABLE* disable;
} tBTA_SYS_REG;

tBTM_STATUS btm_ble_start_inquiry(uint8_t mode, uint8_t duration) {

//发送一个bta_sys信息
bta_sys_sendmsg(p_msg);//bta_sys_event处理

这个里面讲解了base::bind的介绍
https://www.jianshu.com/writer#/notebooks/32840582/notes/39138896/preview

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

推荐阅读更多精彩内容