进入到android设置界面并打开蓝牙,扫描会自动开始。扫描到的蓝牙设备会显示在蓝牙列表中,点击设备即会对设备发起连接。
BluetoothSettings.java (packages\apps\settings\src\com\android\settings\bluetooth)
public final class BluetoothSettings extends DeviceListPreferenceFragment implements Indexable {
@Override
void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
// 停止扫描
mLocalAdapter.stopScanning();
// 点击蓝牙列表下的蓝牙设备
super.onDevicePreferenceClick(btPreference);
}
}
参数btPreference在蓝牙扫描的时候被加进蓝牙列表时传递进来,详细内容可参考 Android Bluetooth蓝牙scan过程
//BluetoothEventManager.java (packages\apps\settings\src\com\android\settings\bluetooth)
private class DeviceFoundHandler implements Handler {
public void onReceive(Context context, Intent intent,
BluetoothDevice device) {
short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
BluetoothClass btClass = intent.getParcelableExtra(BluetoothDevice.EXTRA_CLASS);
String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
// TODO Pick up UUID. They should be available for 2.1 devices.
// Skip for now, there's a bluez problem and we are not getting uuids even for 2.1.
CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
if (cachedDevice == null) {
cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
// new一个CachedBluetoothDevice对象,并传入BluetoothDevice device
CachedBluetoothDevice newDevice = new CachedBluetoothDevice(mContext, adapter, profileManager, device);
synchronized (mCachedDevices) {
mCachedDevices.add(newDevice);
}
return newDevice;
Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: "
+ cachedDevice);
// callback to UI to create Preference for new device
dispatchDeviceAdded(cachedDevice);
}
cachedDevice.setRssi(rssi);
cachedDevice.setBtClass(btClass);
cachedDevice.setNewName(name);
cachedDevice.setVisible(true);
}
}
public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
createDevicePreference(cachedDevice);
BluetoothDevicePreference preference = new BluetoothDevicePreference(getActivity(), cachedDevice);
mCachedDevice = cachedDevice; //BluetoothDevicePreference 构造方法中初始化
initDevicePreference(preference);
mDeviceListGroup.addPreference(preference);
mDevicePreferenceMap.put(cachedDevice, preference);
}
DeviceListPreferenceFragment.java (packages\apps\settings\src\com\android\settings\bluetooth)
void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
btPreference.onClicked();
}
BluetoothDevicePreference.java (packages\apps\settings\src\com\android\settings\bluetooth)
void onClicked() {
int bondState = mCachedDevice.getBondState();
if (mCachedDevice.isConnected()) {
// 已连接则断开
askDisconnect();
} else if (bondState == BluetoothDevice.BOND_BONDED) {
// 已绑定,直接发起连接
mCachedDevice.connect(true);
} else if (bondState == BluetoothDevice.BOND_NONE) {
// 未连接未绑定,发起配对
pair();
mCachedDevice.startPairing()
}
}
CachedBluetoothDevice.java (packages\apps\settings\src\com\android\settings\bluetooth)
boolean startPairing() {
// 停止扫描
if (mLocalAdapter.isDiscovering()) {
mLocalAdapter.cancelDiscovery();
}
// 配对
if (!mDevice.createBond()) {
return false;
}
mConnectAfterPairing = true; // auto-connect after pairing
return true;
}
mDevice是BluetoothDevice对象,在扫描到设备时在DeviceFoundHandler 方法中被传入到CachedBluetoothDevice。
BluetoothDevice.java (frameworks\base\core\java\android\bluetooth)
public boolean createBond() {
if (sService == null) {
Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
return false;
}
try {
return sService.createBond(this, TRANSPORT_AUTO);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
查看sService的定义:
private sServicez sService;
sService通过binder调用createBond。
AdapterService.java(packages\apps\bluetooth\src\com\android\bluetooth\btservice)
public class AdapterService extends Service {
boolean createBond(BluetoothDevice device, int transport) {
// 权限检查
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
return false;
}
// 停止扫描
// Pairing is unreliable while scanning, so cancel discovery
// Note, remove this when native stack improves
cancelDiscoveryNative();
// 发送bond消息
Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
msg.obj = device;
msg.arg1 = transport;
//发消息给Bond状态机
mBondStateMachine.sendMessage(msg);
return true;
}
private static class AdapterServiceBinder extends IBluetooth.Stub {
public boolean createBond(BluetoothDevice device, int transport) {
AdapterService service = getService();
if (service == null) return false;
return service.createBond(device, transport);
}
}
}
BondStateMachine.java (packages\apps\bluetooth\src\com\android\bluetooth\btservice)
private PendingCommandState mPendingCommandState = new PendingCommandState();
private StableState mStableState = new StableState();
private BondStateMachine(AdapterService service,
AdapterProperties prop, RemoteDevices remoteDevices) {
super("BondStateMachine:");
// 添加状态至状态树
addState(mStableState);
// 添加状态至状态树
addState(mPendingCommandState);
mRemoteDevices = remoteDevices;
mAdapterService = service;
mAdapterProperties = prop;
mAdapter = BluetoothAdapter.getDefaultAdapter();
// 设置初始化状态mStableState
setInitialState(mStableState);
}
从BondStateMachine的构造方法中可以看到状态机初始状态为StableState。
private class StableState extends State {
@Override
public void enter() {
infoLog("StableState(): Entering Off State");
}
@Override
public boolean processMessage(Message msg) {
BluetoothDevice dev = (BluetoothDevice)msg.obj;
switch(msg.what) {
case CREATE_BOND:
createBond(dev, msg.arg1, true);
byte[] addr = Utils.getBytesFromAddress(dev.getAddress());
// 调用Native方法创建绑定
if (!mAdapterService.createBondNative(addr, transport)) {
sendIntent(dev, BluetoothDevice.BOND_NONE,
BluetoothDevice.UNBOND_REASON_REMOVED);
return false;
}
break;
case REMOVE_BOND:
removeBond(dev, true);
break;
case BONDING_STATE_CHANGE:
int newState = msg.arg1;
/* if incoming pairing, transition to pending state */
if (newState == BluetoothDevice.BOND_BONDING)
{
sendIntent(dev, newState, 0);
transitionTo(mPendingCommandState);
}
else
{
Log.e(TAG, "In stable state, received invalid newState: " + newState);
}
break;
case CANCEL_BOND:
default:
Log.e(TAG, "Received unhandled state: " + msg.what);
return false;
}
return true;
}
}
com_android_bluetooth_btservice_AdapterService.cpp (packages\apps\bluetooth\jni)
static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address, jint transport) {
jbyte *addr;
jboolean result = JNI_FALSE;
if (!sBluetoothInterface) return result;
addr = env->GetByteArrayElements(address, NULL);
if (addr == NULL) {
jniThrowIOException(env, EINVAL);
return result;
}
int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr, transport);
env->ReleaseByteArrayElements(address, addr, 0);
result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
return result;
}
查看定义
static const bt_interface_t *sBluetoothInterface = NULL;
查找sBluetoothInterface的赋值,发现它加载了一个bluetooth.defualt.so模块:
#define BT_HARDWARE_MODULE_ID "bluetooth"
#define BT_STACK_MODULE_ID "bluetooth"
#define BT_STACK_TEST_MODULE_ID "bluetooth_test"
static void classInitNative(JNIEnv* env, jclass clazz)
{
hw_module_t* module;
const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID :
BT_STACK_TEST_MODULE_ID);
// 加载btStack模块 bluetooth.defualt.so
err = hw_get_module(id, (hw_module_t const**)&module);
if (err == 0) {
hw_device_t* abstraction;
err = module->methods->open(module, id, &abstraction);
if (err == 0) {
//最终转换为btStack结构体
bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
// sBluetoothInterface 赋值
sBluetoothInterface = btStack->get_bluetooth_interface();
} else {
ALOGE("Error while opening Bluetooth library");
}
} else {
ALOGE("No Bluetooth Library found");
}
}
查看hw_get_module的定义:
Hardware.c (hardware\libhardware)
/** Base path of the hal modules */
#if defined(__LP64__)
#define HAL_LIBRARY_PATH1 "/system/lib64/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"
#else
#define HAL_LIBRARY_PATH1 "/system/lib/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
#endif
/*
* Check if a HAL with given name and subname exists, if so return 0, otherwise
* otherwise return negative. On success path will contain the path to the HAL.
*/
static int hw_module_exists(char *path, size_t path_len, const char *name,
const char *subname)
{
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH2, name, subname);
if (access(path, R_OK) == 0)
return 0;
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH1, name, subname);
if (access(path, R_OK) == 0)
return 0;
return -ENOENT;
}
int hw_get_module(const char *id, const struct hw_module_t **module)
hw_get_module_by_class(id, NULL, module);
int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)
{
char path[PATH_MAX];
char name[PATH_MAX];
strlcpy(name, class_id, PATH_MAX);
/* Nothing found, try the default */
// 查找模块 bluetooth.default.so
if (hw_module_exists(path, sizeof(path), name, "default") == 0) {
goto found;
}
found:
return load(class_id, path, module);
void *handle;
struct hw_module_t *hmi;
handle = dlopen(path, RTLD_NOW);
/* Get the address of the struct hal_module_info. */
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
hmi = (struct hw_module_t *)dlsym(handle, sym);
}
Bluetooth.c (external\bluetooth\bluedroid\btif\src)
我们知道BlueDroid协议栈代码编译会 生成bluetooth.defualt.so模块,代码在external\bluetooth\bluedroid目录。
static const bt_interface_t bluetoothInterface
create_bond,
btif_dm_create_bond(bd_addr, transport);
Btif_dm.c (external\bluetooth\bluedroid\btif\src)
bt_status_t btif_dm_create_bond(const bt_bdaddr_t *bd_addr, int transport)
{
btif_dm_create_bond_cb_t create_bond_cb;
create_bond_cb.transport = transport;
bdcpy(create_bond_cb.bdaddr.address, bd_addr->address);
bdstr_t bdstr;
BTIF_TRACE_EVENT("%s: bd_addr=%s, transport=%d", __FUNCTION__,
bd2str((bt_bdaddr_t *) bd_addr, &bdstr), transport);
if (pairing_cb.state != BT_BOND_STATE_NONE)
return BT_STATUS_BUSY;
// btif_dm_generic_evt被调用
btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_CREATE_BOND,
(char *)&create_bond_cb, sizeof(btif_dm_create_bond_cb_t), NULL);
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);
}
return BT_STATUS_SUCCESS;
}
/*******************************************************************************
** Description Create bond initiated from the BTIF thread context
** Special handling for HID devices
*******************************************************************************/
static void btif_dm_cb_create_bond(bt_bdaddr_t *bd_addr, tBTA_TRANSPORT transport)
{
BOOLEAN is_hid = check_cod(bd_addr, COD_HID_POINTING);
bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING);
#if BLE_INCLUDED == TRUE
if(is_hid && device_type != BT_DEVICE_TYPE_BLE)
#else
if(is_hid)
#endif
{
int status;
status = btif_hh_connect(bd_addr);
if(status != BT_STATUS_SUCCESS)
bond_state_changed(status, bd_addr, BT_BOND_STATE_NONE);
}
else
{
BTA_DmBondByTransport((UINT8 *)bd_addr->address, transport);
}
/* Track originator of bond creation */
pairing_cb.is_local_initiated = TRUE;
}
设备的COD在广播接收的时候设置,如果是HID设备并且是经典蓝牙的话则连接hid,否则继续创建绑定。
Bta_dm_api.c (external\bluetooth\bluedroid\bta\dm)
void BTA_DmBondByTransport(BD_ADDR bd_addr, tBTA_TRANSPORT transport)
{
tBTA_DM_API_BOND *p_msg;
if ((p_msg = (tBTA_DM_API_BOND *) GKI_getbuf(sizeof(tBTA_DM_API_BOND))) != NULL)
{
p_msg->hdr.event = BTA_DM_API_BOND_EVT;
bdcpy(p_msg->bd_addr, bd_addr);
p_msg->transport = transport;
bta_sys_sendmsg(p_msg); // 调用 bta_dm_action -> bta_dm_bond
}
}
Bta_dm_act.c (external\bluetooth\bluedroid\bta\dm)
void bta_dm_bond (tBTA_DM_MSG *p_data)
{
tBTM_STATUS status;
tBTA_DM_SEC sec_event;
char *p_name;
// transport 默认为AUTO_TRANSPORT, 等于BTA_TRANSPORT_UNKNOWN
if (p_data->bond.transport == BTA_TRANSPORT_UNKNOWN)
status = BTM_SecBond ( p_data->bond.bd_addr, 0, NULL, 0 );
else
status = BTM_SecBondByTransport ( p_data->bond.bd_addr, p_data->bond.transport, 0, NULL, 0 );
}
Btm_sec.c (external\bluetooth\bluedroid\stack\btm)
tBTM_STATUS BTM_SecBond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
{
tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
#if BLE_INCLUDED == TRUE
if (BTM_UseLeLink(bd_addr))
transport = BT_TRANSPORT_LE;
#endif
return btm_sec_bond_by_transport(bd_addr, transport, pin_len, p_pin, trusted_mask);
}
/*******************************************************************************
** this is the bond function that will start either SSP or SMP.
*******************************************************************************/
tBTM_STATUS btm_sec_bond_by_transport (BD_ADDR bd_addr, tBT_TRANSPORT transport,
UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
{
tBTM_SEC_DEV_REC *p_dev_rec;
tBTM_STATUS status;
UINT8 *p_features;
UINT8 ii;
tACL_CONN *p= btm_bda_to_acl(bd_addr, transport);
BTM_TRACE_API ("btm_sec_bond_by_transport BDA: %02x:%02x:%02x:%02x:%02x:%02x",
bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
BTM_TRACE_DEBUG("btm_sec_bond_by_transport: Transport used %d" , transport);
if ((p_dev_rec = btm_find_or_alloc_dev (bd_addr)) == NULL)
{
return(BTM_NO_RESOURCES);
}
BTM_TRACE_DEBUG ("before update sec_flags=0x%x", p_dev_rec->sec_flags);
/* Tell controller to get rid of the link key if it has one stored */
if ((BTM_DeleteStoredLinkKey (bd_addr, NULL)) != BTM_SUCCESS)
return(BTM_NO_RESOURCES);
/* Save the PIN code if we got a valid one */
if (p_pin && (pin_len <= PIN_CODE_LEN) && (pin_len != 0))
{
btm_cb.pin_code_len = pin_len;
memcpy (btm_cb.pin_code, p_pin, PIN_CODE_LEN);
}
memcpy (btm_cb.pairing_bda, bd_addr, BD_ADDR_LEN);
// 设置btm 配对flag等于BTM_PAIR_FLAGS_WE_STARTED_DD
btm_cb.pairing_flags = BTM_PAIR_FLAGS_WE_STARTED_DD;
// 设置security_required等于BTM_SEC_OUT_AUTHENTICATE
p_dev_rec->security_required = BTM_SEC_OUT_AUTHENTICATE;
p_dev_rec->is_originator = TRUE;
if (trusted_mask)
BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
if (transport == BT_TRANSPORT_LE)
{
p_dev_rec->sec_flags &= ~ BTM_SEC_LE_MASK;
// 启动配对
if (SMP_Pair(bd_addr) == SMP_STARTED)
{
btm_cb.pairing_flags |= BTM_PAIR_FLAGS_LE_ACTIVE;
p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
btm_sec_change_pairing_state (BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
return BTM_CMD_STARTED;
}
btm_cb.pairing_flags = 0;
return(BTM_NO_RESOURCES);
}
#endif
// 下面是经典蓝牙启动配对,已省略
return status;
}
Smp_api.c (external\bluetooth\bluedroid\stack\smp)
/***********************************************************************
** This function call to perform a SMP pairing with peer device.
** Device support one SMP pairing at one time.
*******************************************************************************/
tSMP_STATUS SMP_Pair (BD_ADDR bd_addr)
{
tSMP_CB *p_cb = &smp_cb;
UINT8 status = SMP_PAIR_INTERNAL_ERR;
BTM_TRACE_EVENT ("SMP_Pair state=%d flag=0x%x ", p_cb->state, p_cb->flags);
// 首次配对,smp state 等于SMP_ST_IDLE
if (p_cb->state != SMP_ST_IDLE || p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)
{
/* pending security on going, reject this one */
return SMP_BUSY;
}
else
{
// 设置smp配对flag等于SMP_PAIR_FLAGS_WE_STARTED_DD
// 对应btm的flag BTM_PAIR_FLAGS_WE_STARTED_DD
p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD;
memcpy (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN);
// 远程设备固定至l2cap smp 信道
if (!L2CA_ConnectFixedChnl (L2CAP_SMP_CID, bd_addr))
{
SMP_TRACE_ERROR("SMP_Pair: L2C connect fixed channel failed.");
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
return status;
}
return SMP_STARTED;
}
}
L2c_api.c (external\bluetooth\bluedroid\stack\l2cap)
BOOLEAN L2CA_ConnectFixedChnl (UINT16 fixed_cid, BD_ADDR rem_bda)
{
tL2C_LCB *p_lcb;
tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
UINT16 reason;
#if BLE_INCLUDED == TRUE
if (fixed_cid >= L2CAP_ATT_CID && fixed_cid <= L2CAP_SMP_CID)
transport = BT_TRANSPORT_LE;
#endif
/* No link. Get an LCB and start link establishment */
if ((p_lcb = l2cu_allocate_lcb (rem_bda, FALSE, transport)) == NULL)
{
L2CAP_TRACE_WARNING ("L2CA_ConnectFixedChnl(0x%04x) - no LCB", fixed_cid);
return (FALSE);
}
/* Get a CCB and link the lcb to it */
if (!l2cu_initialize_fixed_ccb (p_lcb, fixed_cid,
&l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
{
p_lcb->disc_reason = L2CAP_CONN_NO_RESOURCES;
L2CAP_TRACE_WARNING ("L2CA_ConnectFixedChnl(0x%04x) - no CCB", fixed_cid);
l2cu_release_lcb (p_lcb);
return (FALSE);
}
if (!l2cu_create_conn(p_lcb, transport))
{
L2CAP_TRACE_WARNING ("L2CA_ConnectFixedChnl create_conn failed");
l2cu_release_lcb (p_lcb);
return (FALSE);
}
return (TRUE);
}
L2c_utils.c (external\bluetooth\bluedroid\stack\l2cap)
/*******************************************************************************
** This function initiates an acl connection via HCI
*******************************************************************************/
BOOLEAN l2cu_create_conn (tL2C_LCB *p_lcb, tBT_TRANSPORT transport)
{
int xx;
tL2C_LCB *p_lcb_cur = &l2cb.lcb_pool[0];
#if (BLE_INCLUDED == TRUE)
tBT_DEVICE_TYPE dev_type;
tBLE_ADDR_TYPE addr_type;
BTM_ReadDevInfo(p_lcb->remote_bd_addr, &dev_type, &addr_type);
if (transport == BT_TRANSPORT_LE)
{
if (!HCI_LE_HOST_SUPPORTED(btm_cb.devcb.local_lmp_features[HCI_EXT_FEATURES_PAGE_1]))
return FALSE;
p_lcb->ble_addr_type = addr_type;
p_lcb->transport = BT_TRANSPORT_LE;
return (l2cble_create_conn(p_lcb));
}
#endif
}
L2c_ble.c (external\bluetooth\bluedroid\stack\l2cap)
/***********************************************************************
** This function initiates an acl connection via HCI
*******************************************************************************/
BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb)
{
tBTM_BLE_CONN_ST conn_st = btm_ble_get_conn_st();
BOOLEAN rt = FALSE;
/* There can be only one BLE connection request outstanding at a time */
if (conn_st == BLE_CONN_IDLE)
{
rt = l2cble_init_direct_conn(p_lcb);
}
else
{
L2CAP_TRACE_WARNING ("L2CAP - LE - cannot start new connection at conn st: %d", conn_st);
btm_ble_enqueue_direct_conn_req(p_lcb);
if (conn_st == BLE_BG_CONN)
btm_ble_suspend_bg_conn();
rt = TRUE;
}
return rt;
}
/***********************************************************************
** This function is to initate a direct connection
***********************************************************************/
BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
{
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
UINT16 scan_int, scan_win;
BD_ADDR init_addr;
UINT8 init_addr_type = BLE_ADDR_PUBLIC,
own_addr_type = BLE_ADDR_PUBLIC;
// 发起连接
if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int */
scan_win, /* UINT16 scan_win */
FALSE, /* UINT8 white_list */
init_addr_type, /* UINT8 addr_type_peer */
init_addr, /* BD_ADDR bda_peer */
own_addr_type, /* UINT8 addr_type_own */
(UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF), /* UINT16 conn_int_min */
(UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF), /* UINT16 conn_int_max */
(UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency */
(UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */
0, /* UINT16 min_len */
0)) /* UINT16 max_len */
{
l2cu_release_lcb (p_lcb);
L2CAP_TRACE_ERROR("initate direct connection fail, no resources");
return (FALSE);
}
else // 发起连接成功
{
//设置一些状态
p_lcb->link_state = LST_CONNECTING;
l2cb.is_ble_connecting = TRUE;
memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
// 启动连接超时定时器(30s)
btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT);
//设置连接状态
btm_ble_set_conn_st (BLE_DIR_CONN);
return (TRUE);
}
}
Hcicmds.c (external\bluetooth\bluedroid\stack\hcic)
BOOLEAN btsnd_hcic_ble_create_ll_conn (UINT16 scan_int, UINT16 scan_win,
UINT8 init_filter_policy,
UINT8 addr_type_peer, BD_ADDR bda_peer,
UINT8 addr_type_own,
UINT16 conn_int_min, UINT16 conn_int_max,
UINT16 conn_latency, UINT16 conn_timeout,
UINT16 min_ce_len, UINT16 max_ce_len)
{
BT_HDR *p;
UINT8 *pp;
HCI_TRACE_WARNING("btsnd_hcic_ble_create_ll_conn: bda_peer= %0x:%0x:%0x:%0x:%0x:%0x",
bda_peer[0],bda_peer[1],bda_peer[2],bda_peer[3],bda_peer[4],bda_peer[5]);
if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_CREATE_LL_CONN)) == NULL)
return (FALSE);
pp = (UINT8 *)(p + 1);
p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_CREATE_LL_CONN;
p->offset = 0;
UINT16_TO_STREAM (pp, HCI_BLE_CREATE_LL_CONN);
UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_CREATE_LL_CONN);
UINT16_TO_STREAM (pp, scan_int);
UINT16_TO_STREAM (pp, scan_win);
UINT8_TO_STREAM (pp, init_filter_policy);
UINT8_TO_STREAM (pp, addr_type_peer);
BDADDR_TO_STREAM (pp, bda_peer);
UINT8_TO_STREAM (pp, addr_type_own);
UINT16_TO_STREAM (pp, conn_int_min);
UINT16_TO_STREAM (pp, conn_int_max);
UINT16_TO_STREAM (pp, conn_latency);
UINT16_TO_STREAM (pp, conn_timeout);
UINT16_TO_STREAM (pp, min_ce_len);
UINT16_TO_STREAM (pp, max_ce_len);
btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
return (TRUE);
}
Btu_hcif.c (external\bluetooth\bluedroid\stack\btu)
/*******************************************************************************
**
** Function btu_hcif_send_cmd
**
** Description This function is called to check if it can send commands
** to the Host Controller. It may be passed the address of
** a packet to send.
**
** Returns void
**
*******************************************************************************/
void btu_hcif_send_cmd (UINT8 controller_id, BT_HDR *p_buf)
{
tHCI_CMD_CB * p_hci_cmd_cb = &(btu_cb.hci_cmd_cb[controller_id]);
/* If there are already commands in the queue, then enqueue this command */
if ((p_buf) && (p_hci_cmd_cb->cmd_xmit_q.count))
{
GKI_enqueue (&(p_hci_cmd_cb->cmd_xmit_q), p_buf);
p_buf = NULL;
}
/* Allow for startup case, where no acks may be received */
if ( ((controller_id == LOCAL_BR_EDR_CONTROLLER_ID)
&& (p_hci_cmd_cb->cmd_window == 0)
&& (btm_cb.devcb.state == BTM_DEV_STATE_WAIT_RESET_CMPLT)) )
{
p_hci_cmd_cb->cmd_window = p_hci_cmd_cb->cmd_xmit_q.count + 1;
}
/* See if we can send anything */
while (p_hci_cmd_cb->cmd_window != 0)
{
if (!p_buf)
p_buf = (BT_HDR *)GKI_dequeue (&(p_hci_cmd_cb->cmd_xmit_q));
if (p_buf)
{
btu_hcif_store_cmd(controller_id, p_buf);
p_hci_cmd_cb->cmd_window--;
if (controller_id == LOCAL_BR_EDR_CONTROLLER_ID)
{
// 发送HCI CMD
HCI_CMD_TO_LOWER(p_buf);
}
else
{
GKI_freebuf(p_buf);;
}
p_buf = NULL;
}
else
break;
}
if (p_buf)
GKI_enqueue (&(p_hci_cmd_cb->cmd_xmit_q), p_buf);
}
查看HCI_CMD_TO_LOWER定义:
/* Sends an HCI command received from the upper stack to the BD/EDR HCI transport. */
#ifndef HCI_CMD_TO_LOWER
#define HCI_CMD_TO_LOWER(p) bte_main_hci_send((BT_HDR *)(p), BT_EVT_TO_LM_HCI_CMD);
#endif
Bte_main.c (external\bluetooth\bluedroid\main)
void bte_main_hci_send (BT_HDR *p_msg, UINT16 event)
{
UINT16 sub_event = event & BT_SUB_EVT_MASK; /* local controller ID */
p_msg->event = event;
if((sub_event == LOCAL_BR_EDR_CONTROLLER_ID) || \
(sub_event == LOCAL_BLE_CONTROLLER_ID))
{
if (bt_hc_if)
bt_hc_if->transmit_buf((TRANSAC)p_msg, \
(char *) (p_msg + 1), \
p_msg->len);
else
GKI_freebuf(p_msg);
}
}
查看bt_hc_if的赋值:
static void bte_main_in_hw_init(void)
{
// bt_hci_bdroid.c中的 bluetoothHCLibInterface
if ( (bt_hc_if = (bt_hc_interface_t *) bt_hc_get_interface()) \
== NULL)
{
APPL_TRACE_ERROR("!!! Failed to get BtHostControllerInterface !!!");
}
memset(&preload_retry_cb, 0, sizeof(bt_preload_retry_cb_t));
}
Bt_hci_bdroid.c (external/bluetooth/bluedroid/hci/src)
void bthc_tx(HC_BT_HDR *buf) {
pthread_mutex_lock(&hc_cb.worker_thread_lock);
if (hc_cb.worker_thread) {
if (buf)
utils_enqueue(&tx_q, buf); // 将buf放入队列tx_q,给到event_tx处理
// 构造一个work_item_t并放入thread->work_queue,
// worker_thread的线程处理函数run_thread会从thread->work_queue中取出这个item,
// 并调用回调函数event_tx
thread_post(hc_cb.worker_thread, event_tx, NULL);
}
pthread_mutex_unlock(&hc_cb.worker_thread_lock);
}
/** Transmit frame */
static int transmit_buf(TRANSAC transac, UNUSED_ATTR char *p_buf, UNUSED_ATTR int len) {
bthc_tx((HC_BT_HDR *)transac);
return BT_HC_STATUS_SUCCESS;
}
static const bt_hc_interface_t bluetoothHCLibInterface = {
sizeof(bt_hc_interface_t),
init,
set_power,
lpm,
preload,
postload,
transmit_buf,
logging,
cleanup,
tx_hc_cmd,
};
const bt_hc_interface_t *bt_hc_get_interface(void)
{
return &bluetoothHCLibInterface;
}
下面主要看下实际的发送函数event_tx:
event_tx里面有个while循环,通过utils_getnext从tx_q获取所有消息并保存到sending_msg_que,消息的个数为sending_msg_count。消息取完后跳出while,使用一个for循环取出所有要发送的消息并调用 p_hci_if->send发送出去。
注意: 如果我们已用完控制器的未用HCI命令信用(通常为1),则跳过队列中的所有HCI命令数据包。
static void event_tx(UNUSED_ATTR void *context) {
/*
* We will go through every packets in the tx queue.
* Fine to clear tx_cmd_pkts_pending.
*/
tx_cmd_pkts_pending = false;
HC_BT_HDR *sending_msg_que[64];
size_t sending_msg_count = 0;
int sending_hci_cmd_pkts_count = 0;
utils_lock();
HC_BT_HDR *p_next_msg = tx_q.p_first;
while (p_next_msg && sending_msg_count < ARRAY_SIZE(sending_msg_que))
{
// 注意: 如果我们已用完控制器的未用HCI命令信用(通常为1),
// 则跳过队列中的所有HCI命令数据包。
if ((p_next_msg->event & MSG_EVT_MASK)==MSG_STACK_TO_HC_HCI_CMD)
{
if (tx_cmd_pkts_pending ||
(sending_hci_cmd_pkts_count >= num_hci_cmd_pkts))
{
tx_cmd_pkts_pending = true;
p_next_msg = utils_getnext(p_next_msg); // 取出消息
continue;
}
sending_hci_cmd_pkts_count++; //增加消息计数sending_msg_count
}
HC_BT_HDR *p_msg = p_next_msg;
p_next_msg = utils_getnext(p_msg); // 取出消息
utils_remove_from_queue_unlocked(&tx_q, p_msg);
//把消息放入sending_msg_que,并增加消息计数sending_msg_count
sending_msg_que[sending_msg_count++] = p_msg;
}
utils_unlock();
for(size_t i = 0; i < sending_msg_count; i++)
p_hci_if->send(sending_msg_que[i]);
if (tx_cmd_pkts_pending)
BTHCDBG("Used up Tx Cmd credits");
}
p_hci_if在init函数中被赋值:
static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)
extern tHCI_IF hci_mct_func_table;
p_hci_if = &hci_h4_func_table
Hci_h4.c (external\bluetooth\bluedroid\hci\src)
/******************************************************************************
** HCI H4 Services interface table
******************************************************************************/
const tHCI_IF hci_h4_func_table =
{
hci_h4_init,
hci_h4_cleanup,
hci_h4_send_msg,
hci_h4_send_int_cmd,
hci_h4_get_acl_data_length,
hci_h4_receive_msg
};
/*******************************************************************************
** Function hci_h4_send_msg
** Description Determine message type, set HCI H4 packet indicator, and
** send message through USERIAL driver
*******************************************************************************/
void hci_h4_send_msg(HC_BT_HDR *p_msg)
{
uint8_t type = 0;
uint16_t handle;
uint16_t bytes_to_send, lay_spec;
uint8_t *p = ((uint8_t *)(p_msg + 1)) + p_msg->offset;
uint16_t event = p_msg->event & MSG_EVT_MASK;//event类型
uint16_t sub_event = p_msg->event & MSG_SUB_EVT_MASK; // sub_event类型
uint16_t acl_pkt_size = 0, acl_data_size = 0;
uint16_t bytes_sent;
/* wake up BT device if its in sleep mode */
lpm_wake_assert();
if (event == MSG_STACK_TO_HC_HCI_ACL)
type = H4_TYPE_ACL_DATA;
else if (event == MSG_STACK_TO_HC_HCI_SCO)
type = H4_TYPE_SCO_DATA;
else if (event == MSG_STACK_TO_HC_HCI_CMD)
type = H4_TYPE_COMMAND;
if (sub_event == LOCAL_BR_EDR_CONTROLLER_ID)
{
acl_data_size = h4_cb.hc_acl_data_size;
acl_pkt_size = h4_cb.hc_acl_data_size + HCI_ACL_PREAMBLE_SIZE;
}
else
{
acl_data_size = h4_cb.hc_ble_acl_data_size;
acl_pkt_size = h4_cb.hc_ble_acl_data_size + HCI_ACL_PREAMBLE_SIZE;
}
/* Do all the first chunks */
while (p_msg->len > acl_pkt_size)
{
/* Check if sending ACL data that needs fragmenting */
if ((event == MSG_STACK_TO_HC_HCI_ACL) && (p_msg->len > acl_pkt_size))
{
bytes_to_send = acl_pkt_size + 1;
/* 通过uart发送命令/数据 */
bytes_sent = userial_write(event,(uint8_t *) p,bytes_to_send);
write(userial_cb.fd, p_data + total, len);
/* 生成btsnoop追踪消息 */
btsnoop_capture(p_msg, false);
}
}
p = ((uint8_t *)(p_msg + 1)) + p_msg->offset - 1;
*p = type;
bytes_to_send = p_msg->len + 1;
/* 通过uart发送命令/数据 */
bytes_sent = userial_write(event,(uint8_t *) p, bytes_to_send);
write(userial_cb.fd, p_data + total, len);
/* 生成btsnoop追踪消息 */
btsnoop_capture(p_msg, false);
if (bt_hc_cbacks)
{
// 回调bte_main.c中的hc_cbacks->tx_result
bt_hc_cbacks->tx_result((TRANSAC) p_msg, (char *) (p_msg + 1), \
BT_HC_TX_SUCCESS);
}
return;
}
hci_h4_send_msg主要以下工作:
1)根据消息的event得到event和sub_event
2)根据event得到hci类型,根据sub_event得到acl_data_size和acl_packet_size
3)通过uart发送消息
4)生成btsnoop追踪数据
5)回调uart写成功状态,实际命令发送状态由userial_read_thread来完成。
Userial.c (external\bluetooth\bluedroid\hci\src)
uint16_t userial_write(uint16_t msg_id, const uint8_t *p_data, uint16_t len) {
UNUSED(msg_id);
uint16_t total = 0;
while (len) {
ssize_t ret = write(userial_cb.fd, p_data + total, len);
switch (ret) {
case -1:
ALOGE("%s error writing to serial port: %s", __func__, strerror(errno));
return total;
case 0: // don't loop forever in case write returns 0.
return total;
default:
total += ret;
len -= ret;
break;
}
send_byte_total+=total;
}
return total;
}
查看userial_cb.fd的赋值:
bool userial_open(userial_port_t port) {
// Call in to the vendor-specific library to open the serial port.
int fd_array[CH_MAX];
int num_ports = vendor_send_command(BT_VND_OP_USERIAL_OPEN, &fd_array);
userial_cb.fd = fd_array[0];
userial_cb.port = port;
if (pthread_create(&userial_cb.read_thread, NULL, userial_read_thread, NULL)) {
ALOGE("%s unable to spawn read thread.", __func__);
goto error;
}
}
Vendor.c (external\bluetooth\bluedroid\hci\src)
int vendor_send_command(bt_vendor_opcode_t opcode, void *param) {
return vendor_interface->op(opcode, param);
}
VENDOR_LIBRARY_NAME = "libbt-vendor.so";
vendor_open(const uint8_t *local_bdaddr)
lib_handle = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW);
vendor_interface = (bt_vendor_interface_t *)dlsym(lib_handle, VENDOR_LIBRARY_SYMBOL_NAME);
dlsym根据动态链接库操作句柄与符号,返回符号对应的地址。
可以得到vendor_interface的实现代码在libbt-vendor.so这个动态链接库中。
Bt_vendor_brcm.c (hardware\broadcom\libbt\src)
全局抓取一下libbt-vendor.so,我们在hardware\broadcom\libbt下的Android.mk中找到了libbt-vendor.so的包含的源文件。
抓取一下bt_vendor_interface_t,发现在Bt_vendor_brcm.c找到了它的实现:
// Entry point of DLib
const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE = {
sizeof(bt_vendor_interface_t),
init,
op,
case BT_VND_OP_USERIAL_OPEN:
int (*fd_array)[] = (int (*)[]) param;
int fd, idx;
fd = userial_vendor_open((tUSERIAL_CFG *) &userial_init_cfg);
/* Device port name where Bluetooth controller attached */
#ifndef BLUETOOTH_UART_DEVICE_PORT // bt_vendor_brcm.h
#define BLUETOOTH_UART_DEVICE_PORT "/dev/ttyO1" // maguro
#endif
// void userial_vendor_init中赋值:
// snprintf(vnd_userial.port_name, VND_PORT_NAME_MAXLEN, "%s", BLUETOOTH_UART_DEVICE_PORT);
vnd_userial.fd = open(vnd_userial.port_name, O_RDWR);//userial_vendor.c
return vnd_userial.fd;
if (fd != -1)
{
for (idx=0; idx < CH_MAX; idx++)
(*fd_array)[idx] = fd;
retval = 1;
}
}
cleanup
};
再回到hci_h4_send_msg查看bt_hc_cbacks的赋值:
Bt_hci_bdroid.c (external\bluetooth\bluedroid\hci\src)
static int init(const bt_hc_callbacks_t* p_cb, unsigned char *local_bdaddr)
/* store reference to user callbacks */
bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb;
static const bt_hc_interface_t bluetoothHCLibInterface = {
sizeof(bt_hc_interface_t),
init,
set_power,
lpm,
preload,
postload,
transmit_buf,
logging,
cleanup,
tx_hc_cmd,
};
bluetoothHCLibInterface的init函数在蓝牙enable的时候被调用:
Bte_main.c (external\bluetooth\bluedroid\main)
bt_hc_callbacks_t *bt_hc_cbacks = NULL;
static const bt_hc_callbacks_t hc_callbacks = {
sizeof(bt_hc_callbacks_t),
preload_cb,
postload_cb,
lpm_cb,
hostwake_ind,
alloc,
dealloc,
data_ind,
tx_result
};
static void bte_main_in_hw_init(void)
{
bt_hc_if = (bt_hc_interface_t *) bt_hc_get_interface() // Bt_hci_bdroid.c
return &bluetoothHCLibInterface;
}
bte_main_enable
bte_hci_enable
//调用bluetoothHCLibInterface的init函数,将bt_hc_cbacks赋值为hc_callbacks
int result = bt_hc_if->init(&hc_callbacks, btif_local_bd_addr.address);
bt_hc_cbacks = (bt_hc_callbacks_t *) p_cb; // Bt_hci_bdroid.c
最终将bt_hc_cbacks赋值为hc_callbacks。
当控制器收到HCI_LE_Create_Connection 命令,并创建连接后,控制器会发送HCI_LE_Connection_Complete 或者 HCI_LE_Enhanced_Connection_Complete事件给host。