本文仅供个人记录一些日常笔记,仅供参考!
一、打开蓝牙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;
}