Android Bluetooth蓝牙connect过程

Android Bluetooth框架

在这里插入图片描述

一、Settings界面下connect

进入到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。

二、APK connect

你可能感兴趣的:(Android,android,bluetooth,bluedroid)