Android Bluetooth杂记

本文仅供个人记录一些日常笔记,仅供参考!

一、打开蓝牙LOG

将/etc/bluetooth/bt_stack.conf中的打印级别改成5,然后使用 logcat -v time 抓取相关 log,下面是bt_stack.conf的内容:

# Enable BtSnoop logging function
# valid value : true, false
BtSnoopLogOutput=false # btsnoop开关,如果要抓hci log改成true

# BtSnoop log output file
BtSnoopFileName=/sdcard/btsnoop_hci.log # btsnoop默认文件名及路径

# Preserve existing BtSnoop log before overwriting
BtSnoopSaveLog=false #保存上一次btsnoop log

# Enable trace level reconfiguration function
# Must be present before any TRC_ trace level settings
TraceConf=true # log级别重新配置开关

# Trace level configuration

# 各个模块log级别配置, 级别为5时打印所有debug消息,级别 0 不输出
#   BT_TRACE_LEVEL_NONE    0    ( No trace messages to be generated )
#   BT_TRACE_LEVEL_ERROR   1    ( Error condition trace messages )
#   BT_TRACE_LEVEL_WARNING 2    ( Warning condition trace messages )
#   BT_TRACE_LEVEL_API     3    ( API traces )
#   BT_TRACE_LEVEL_EVENT   4    ( Debug messages for events )
#   BT_TRACE_LEVEL_DEBUG   5    ( Full debug messages )
#   BT_TRACE_LEVEL_VERBOSE 6    ( Verbose messages ) - Currently supported for TRC_BTAPP only.
TRC_BTM=2
TRC_HCI=2
TRC_L2CAP=2
TRC_RFCOMM=2
TRC_OBEX=2
TRC_AVCT=2
TRC_AVDT=2
TRC_AVRC=2
TRC_AVDT_SCB=2
TRC_AVDT_CCB=2
TRC_A2D=2
TRC_SDP=2
TRC_GATT=2
TRC_SMP=2
TRC_BTAPP=2
TRC_BTIF=2

二、蓝牙调试技巧

调试过程中经常需要在蓝牙协议栈中添加打印,可以重新编译生成bluetooth.default.so, 然后push到机器里面。

1) 修改协议栈源码

2) 编译bluetooth.default.so

  • 进入android根目录
  • source build/envsetup.sh
  • lunch 56 选择对应的板子(userdebug模式) , 或 lunch 11 选择对应的板子(userdebug模式) 
  • 进入对应的目录执行mm: ~/work/CubieBoard7/android/external/bluetooth/bluedroid$ mm

    so生成路径: Install: out/target/product/s700_cb7/system/lib/hw/bluetooth.default.so

3) push bluetooth.default.so

  • $ adb root
  • $ adb remount
  • $ adb push bluetooth.default.so /system/lib/hw/

三、重要的函数和接口

1. 广播包上报

// system\bt\stack\btm\btm_ble_gap.cc 
void btm_ble_process_adv_pkt(uint8_t data_len, uint8_t* data)

1) 如果是active scan是否有收到scan response: 

  bool is_active_scan =
      btm_cb.ble_ctr_cb.inq_var.scan_type == BTM_BLE_SCAN_MODE_ACTI;
  if (is_active_scan && is_scannable && !is_scan_resp) {
    // If we didn't receive scan response yet, don't report the device.
    DVLOG(1) << " Waiting for scan response " << bda;
    return;
  }

2) 发现模式是否匹配: 

/**
 * Check ADV flag to make sure device is discoverable and match the search
 * condition
 */
static uint8_t btm_ble_is_discoverable(const RawAddress& bda,
                                       std::vector<uint8_t> const& adv_data) {
  uint8_t scan_state = BTM_BLE_NOT_SCANNING;

  /* for observer, always "discoverable */
  if (btm_cb.ble_ctr_cb.is_ble_observe_active())
    scan_state |= BTM_BLE_OBS_RESULT;

  if (!adv_data.empty()) {
    uint8_t flag = 0;
    uint8_t data_len;
    const uint8_t* p_flag = AdvertiseDataParser::GetFieldByType(
        adv_data, BTM_BLE_AD_TYPE_FLAG, &data_len);
    if (p_flag != NULL && data_len != 0) {
      flag = *p_flag;

      if ((btm_cb.btm_inq_vars.inq_active & BTM_BLE_GENERAL_INQUIRY) &&
          (flag & (BTM_BLE_LIMIT_DISC_FLAG | BTM_BLE_GEN_DISC_FLAG)) != 0) {
        scan_state |= BTM_BLE_INQ_RESULT;
      }
    }
  }
  return scan_state;
}

3) btm_ble_process_adv_pkt最后是adv上报,扫描回调分settings扫描和apk扫描,分别对应p_inq_results_cb和p_obs_results_cb回调:

  tBTM_INQ_RESULTS_CB* p_inq_results_cb = p_inq->p_inq_results_cb;
  if (p_inq_results_cb && (result & BTM_BLE_INQ_RESULT)) {
    (p_inq_results_cb)((tBTM_INQ_RESULTS*)&p_i->inq_info.results,
                       const_cast<uint8_t*>(adv_data.data()), adv_data.size());
  }

  tBTM_INQ_RESULTS_CB* p_obs_results_cb = btm_cb.ble_ctr_cb.p_obs_results_cb;
  if (p_obs_results_cb && (result & BTM_BLE_OBS_RESULT)) {
    (p_obs_results_cb)((tBTM_INQ_RESULTS*)&p_i->inq_info.results,
                       const_cast<uint8_t*>(adv_data.data()), adv_data.size());
  }

1)settings 扫描回调:p_inq_results_cb扫描回调指向bta_dm_inq_results_cb,在BTM_StartInquiry时被设置。
2)apk扫描回调:p_obs_results_cb扫描回调指向bta_dm_observe_results_cb,在BTM_BleObserve时被设置。
btm_ble_process_adv_pkt_cont详细的调用流程参考Android Bluetooth蓝牙scan过程: 三、Adv和Scan Resp接收

2. notify接收

//system\bt\stack\gatt\gatt_main.cc

void gatt_init(void) 
  /* First, register fixed L2CAP channel for ATT over BLE */
  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 */
  L2CA_RegisterFixedChannel(L2CAP_ATT_CID, &fixed_reg);

// gatt_le_data_ind

static void gatt_le_data_ind(uint16_t chan, const RawAddress& bd_addr,
                             BT_HDR* p_buf) {
      gatt_data_process(*p_tcb, L2CAP_ATT_CID, p_buf);
          gatt_client_handle_server_rsp(tcb, cid, op_code, msg_len, p);

// system\bt\stack\gatt\gatt_cl.cc

/** This function is called to handle the server response to client */
void gatt_client_handle_server_rsp(tGATT_TCB& tcb, uint16_t cid,
                                   uint8_t op_code, uint16_t len,
                                   uint8_t* p_data) {
  VLOG(1) << __func__ << " opcode: " << loghex(op_code);

  uint16_t payload_size = gatt_tcb_get_payload_size_rx(tcb, cid);

  if (op_code == GATT_HANDLE_VALUE_IND || op_code == GATT_HANDLE_VALUE_NOTIF ||
      op_code == GATT_HANDLE_MULTI_VALUE_NOTIF) {
    if (len >= payload_size) {
      LOG(ERROR) << StringPrintf(
          "%s: invalid indicate pkt size: %d, PDU size: %d", __func__, len + 1,
          payload_size);
      return;
    }

    gatt_process_notification(tcb, cid, op_code, len, p_data);
    return;
  }
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值