蓝牙BLE设备断线回连分析

在 文章中分析了Hogp的连接的流程 ,这里分析一下回连的流程.

在使用ble设备的过程中,我们发现当设备和主机配对之后,如果没有解除配对,那么即便设备和主机断开,那么也是可以重新连接而不需要重新走配对的流程,这里的分析的源代码是Android7.0 .

回连的大概的流程是:hogp 连接完成之后,会把当前的device 加入到whitelist里面.,标记为可以回连的设备.当设备和主机断开的时候,主机会根据whitelist里面的设备来进行回连.

这里我们从hogp连接流程中将device加入到 whitelist的流程来开始分析.

/*******************************************************************************
**
** Function         bta_hh_le_open_cmpl
**
** Description      HID over GATT connection sucessfully opened
**
*******************************************************************************/
void bta_hh_le_open_cmpl(tBTA_HH_DEV_CB *p_cb)
{
    if ( p_cb->disc_active == BTA_HH_LE_DISC_NONE)
    {
        bta_hh_le_register_input_notif(p_cb, p_cb->mode, TRUE);
        bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);

#if (BTA_HH_LE_RECONN == TRUE)
        if (p_cb->status == BTA_HH_OK)
        {
            bta_hh_le_add_dev_bg_conn(p_cb, TRUE);//加入到bg connection 中
        }
#endif
    }
}

 

继续看bta_hh_le_add_dev_bg_conn 的实现:

static void bta_hh_le_add_dev_bg_conn(tBTA_HH_DEV_CB *p_cb, BOOLEAN check_bond) 
{ 
    UINT8 sec_flag=0; BOOLEAN to_add = TRUE; 
    if (check_bond) 
    { /* start reconnection if remote is a bonded device */ /* verify bond */ 
        BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE);
        if ((sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) == 0) 
            to_add = FALSE;//如果没有完成安全认证,那么不会加入到whitelist里面  }
        if (!p_cb->in_bg_conn && to_add) { /* add device into BG connection to accept remote initiated connection */ 
            BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, FALSE, BTA_GATT_TRANSPORT_LE); 
            p_cb->in_bg_conn = TRUE;//标记为in_bg_conn 为true 
            BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL); 
     } 
        return; 
    }
}

 

这里 分为两个步骤:

  1.  BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, FALSE, BTA_GATT_TRANSPORT_LE);
  2. BTA_DmBleSetBgConnType(BTA_DM_BLE_CONN_AUTO, NULL); 

 这里的重点是第一个步骤,我们依次分析:

bta_gattc_api.c

void BTA_GATTC_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda,
                    BOOLEAN is_direct, tBTA_GATT_TRANSPORT transport)
{
    tBTA_GATTC_API_OPEN *p_buf =
       (tBTA_GATTC_API_OPEN *) osi_malloc(sizeof(tBTA_GATTC_API_OPEN));

    p_buf->hdr.event = BTA_GATTC_API_OPEN_EVT;
    p_buf->client_if = client_if;
    p_buf->is_direct = is_direct;
    p_buf->transport = transport;
    memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);

    bta_sys_sendmsg(p_buf);
}

 

这里不多说,  bta_gattc_hdl_event  -->BTA_GATTC_API_OPEN_EVT ->bta_gattc_process_api_open 我们直接看实际处理的函数 

bta_gattc_act.c

void bta_gattc_process_api_open (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg)
{
    UINT16 event = ((BT_HDR *)p_msg)->event;
    tBTA_GATTC_CLCB *p_clcb = NULL;
    tBTA_GATTC_RCB *p_clreg = bta_gattc_cl_get_regcb(p_msg->api_conn.client_if);
    UNUSED(p_cb);

    if (p_clreg != NULL)
    {
        if (p_msg->api_conn.is_direct)//is_direct是false
        {
            if ((p_clcb = bta_gattc_find_alloc_clcb(p_msg->api_conn.client_if,
                                                    p_msg->api_conn.remote_bda,
                                                    p_msg->api_conn.transport)) != NULL)
            {
                bta_gattc_sm_execute(p_clcb, event, p_msg);
            }
            else
            {
                APPL_TRACE_ERROR("No resources to open a new connection.");

                bta_gattc_send_open_cback(p_clreg,
                                          BTA_GATT_NO_RESOURCES,
                                          p_msg->api_conn.remote_bda,
                                          BTA_GATT_INVALID_CONN_ID,
                                          p_msg->api_conn.transport, 0);
            }
        }
        else
        {
            bta_gattc_init_bk_conn(&p_msg->api_conn, p_clreg);//init bg conn
        }
    }

}

 

继续看bta_gattc_init_bk_conn 

/*******************************************************************************
**
** Function         bta_gattc_init_bk_conn
**
** Description      Process API Open for a background connection
**
** Returns          void
**
*******************************************************************************/
void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg)
{
    tBTA_GATT_STATUS         status = BTA_GATT_NO_RESOURCES;
    UINT16                   conn_id;
    tBTA_GATTC_CLCB         *p_clcb;
    tBTA_GATTC_DATA         gattc_data;

    if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, TRUE, FALSE))//标记p_bg_tck->cif_mask ,暂时没看出来用处
    {
        /* always call open to hold a connection */
        if (!GATT_Connect(p_data->client_if, p_data->remote_bda, false, p_data->transport, false))//执行gatt_connect,注意这里的参数是no_direct
        {
        /*出错处理*/
        }
        else
        {
            status = BTA_GATT_OK;

            /* if is a connected remote device */
            if (GATT_GetConnIdIfConnected(p_data->client_if,
                                          p_data->remote_bda,
                                          &conn_id,
                                          p_data->transport))
            {
                if ((p_clcb = bta_gattc_find_alloc_clcb(p_data->client_if, p_data->remote_bda,
                    BTA_GATT_TRANSPORT_LE)) != NULL)
                {
                    gattc_data.hdr.layer_specific = p_clcb->bta
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是 Android 手机蓝牙BLE 设备建立连接的代码示例: 1. 在 AndroidManifest.xml 文件中添加蓝牙权限: ```xml <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> ``` 2. 在 Activity 中初始化 BluetoothAdapter 对象: ```java private BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); ``` 3. 扫描 BLE 设备并建立连接: ```java // 扫描时间 10 秒 private static final long SCAN_PERIOD = 10000; // 扫描回调 private final BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) { // 根据设备名称或 MAC 地址过滤 if (device.getName() != null && device.getName().startsWith("BLE")) { // 停止扫描 bluetoothAdapter.stopLeScan(leScanCallback); // 建立连接 device.connectGatt(MainActivity.this, false, gattCallback); } } }; // GATT 回调 private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { // 连接成功,开始发现服务 gatt.discoverServices(); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // 连接断开 Log.i(TAG, "Disconnected from GATT server."); } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // 服务发现成功,可以进行数据交互 Log.i(TAG, "Services discovered."); } else { Log.w(TAG, "onServicesDiscovered received: " + status); } } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // 读取特征值成功 Log.i(TAG, "Characteristic read successfully."); } else { Log.w(TAG, "Characteristic read failed: " + status); } } }; // 开始扫描 BLE 设备 private void scanBLEDevice() { if (bluetoothAdapter == null) { Log.w(TAG, "Bluetooth not supported."); return; } // 如果正在扫描,则先停止扫描 bluetoothAdapter.stopLeScan(leScanCallback); // 开始扫描 bluetoothAdapter.startLeScan(leScanCallback); // 扫描 SCAN_PERIOD 后停止扫描 new Handler().postDelayed(new Runnable() { @Override public void run() { bluetoothAdapter.stopLeScan(leScanCallback); } }, SCAN_PERIOD); } ``` 注意:在建立连接之前需要先扫描 BLE 设备,扫描到符合条件的设备后才能进行连接。在连接建立成功后,需要调用 `discoverServices()` 方法发现设备的服务,然后才能进行数据交互。以上代码仅供参考,实际开发中需要根据具体需求进行调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值