蓝牙disable流程简述

Posted libs-liu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝牙disable流程简述相关的知识,希望对你有一定的参考价值。

蓝牙关闭的流程比打开流程要简单,主要就是一些profile的断连以及协议栈相关结构的释放。

这里简单说一下其流程,就直接从协议栈的disable的接口说起了。

static int disable(void) {
  if (!interface_ready())//检查hal层的callback
    return BT_STATUS_NOT_READY;
  stack_manager_get_interface()->shut_down_stack_async();
  return BT_STATUS_SUCCESS;
}

简单看下stack_manager_get_interface :

static const stack_manager_t interface = {
  init_stack,
  start_up_stack_async,
  shut_down_stack_async,
  clean_up_stack_async,

  get_stack_is_running
};

const stack_manager_t *stack_manager_get_interface() {
  ensure_manager_initialized();
  return &interface;
}

看shut_down_stack_async的具体实现:

static void shut_down_stack_async(void) {
  thread_post(management_thread, event_shut_down_stack, NULL);
}

这里就是把关闭的函数 post 到management_thread 里面来执行。继续执行的函数还是event_shut_down_stack

// Synchronous function to shut down the stack
static void event_shut_down_stack(UNUSED_ATTR void *context) {
...
  hack_future = future_new();//为了同步用的
  stack_is_running = false;

  btif_disable_bluetooth();//真正的disable的接口
  module_shut_down(get_module(BTIF_CONFIG_MODULE));//释放btif模块

  future_await(hack_future);//获得了信号量之后才能执行到这里
  module_shut_down(get_module(CONTROLLER_MODULE)); // Doesn‘t do any work, just puts it in a restartable state

  LOG_DEBUG("%s finished.", __func__);
  btif_thread_post(event_signal_stack_down, NULL);//通知上层stack down
}

这里简单说一下这个hack_future,其在这里的用途类似二值信号量,如果这个信号量不可用,就会一直等在future_await 这里,和其对应的一个函数叫future_ready,

void future_ready(future_t *future, void *value) {
  assert(future != NULL);
  assert(future->ready_can_be_called);

  future->ready_can_be_called = false;
  future->result = value;
  semaphore_post(future->semaphore);
}

这个函数会让这个信号量变得可读,future_await 就可以顺利返回继续执行。其实就是为了disable 过程的同步性。看了一下,其会在btif_disable_bluetooth_evt 这个函数中释放信号量,看函数名字应该是disable 完成的一个事件,这也符合我们的预期。关于这个信号量,就分析到这里。

下面主要看btif_disable_bluetooth :

/*******************************************************************************
**
** Function         btif_disable_bluetooth
**
** Description      Inititates shutdown of Bluetooth system.
**                  Any active links will be dropped and device entering
**                  non connectable/discoverable mode
**
** Returns          void
**
*******************************************************************************/
bt_status_t btif_disable_bluetooth(void)
{
    BTIF_TRACE_DEBUG("BTIF DISABLE BLUETOOTH");
    btif_dm_on_disable();
    /* cleanup rfcomm & l2cap api */
    btif_sock_cleanup();
    btif_pan_cleanup();
    BTA_DisableBluetooth();
    return BT_STATUS_SUCCESS;
}

这里的注释非常重要,可以帮助我们很好的理解函数,其语义是:关闭蓝牙系统,所有的link 都要断开,设备进入不可发现和不可连接的状态。

我这里的分析的case 就是当前蓝牙还连接着一个hid 设备的时候的disable 流程。

这里的重点是BTA_DisableBluetooth();,我这里先简单分析下其他的几个函数:

void btif_dm_on_disable()
{
    /* cancel any pending pairing requests */
    if (pairing_cb.state == BT_BOND_STATE_BONDING)
    {
        bt_bdaddr_t bd_addr;
        bdcpy(bd_addr.address, pairing_cb.bd_addr);
        btif_dm_cancel_bond(&bd_addr);//如果设备处于配对状态,那么取消配对
    }
}

这个很简单,如果设备处于配对状态,这个时候关闭设备,它的确应该取消配对,符合预期。

另外两个函数 一个和sock有关,另一个和pan有关,暂时都没有用到这些模块,暂时不分析。那么重点还是看BTA_DisableBluetooth();

/*******************************************************************************
**
** Function         BTA_DisableBluetooth
**
** Description      Disables bluetooth service.  This function is called when
**                  the application no longer needs bluetooth service
**
** Returns          void
**
*******************************************************************************/
tBTA_STATUS BTA_DisableBluetooth(void)
{
    BT_HDR    *p_msg;
    if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
    {
        p_msg->event = BTA_DM_API_DISABLE_EVT;//向DM模块发送disable 
        bta_sys_sendmsg(p_msg);
    }
...
    return BTA_SUCCESS;
}

这个函数就是向设备管理模块发送BTA_DM_API_DISABLE_EVT ,然后由设备管理模块继续进一步的操作。这里使用bta_sys_sendmsg,涉及到进程间通信,其他的文章中已经讲过,这里不赘述。最终调用的函数是在bta_dm_act.c中的bta_dm_disable:

/*******************************************************************************
**
** Function         bta_dm_disable
**
** Description      Disables the BT device manager
**
**
** Returns          void
**
*******************************************************************************/
void bta_dm_disable (tBTA_DM_MSG *p_data)
{
    UNUSED(p_data);

    /* Set l2cap idle timeout to 0 (so BTE immediately disconnects ACL link after last channel is closed) */
    L2CA_SetIdleTimeoutByBdAddr((UINT8 *)BT_BD_ANY, 0, BT_TRANSPORT_BR_EDR);//设置idletimeout时间,设置为0
    L2CA_SetIdleTimeoutByBdAddr((UINT8 *)BT_BD_ANY, 0, BT_TRANSPORT_LE);

    /* disable all active subsystems */
    bta_sys_disable(BTA_SYS_HW_BLUETOOTH);//关闭蓝牙相关的各个子模块。这里涉及到短线等操作

    BTM_SetDiscoverability(BTM_NON_DISCOVERABLE, 0, 0);//不可发现
    BTM_SetConnectability(BTM_NON_CONNECTABLE, 0, 0);//不可连接

    bta_dm_disable_pm();//电源管理相关
    bta_dm_disable_search_and_disc();//disable 搜索和服务发现的工作
    bta_dm_cb.disabling = TRUE;//设置正在断开的标志位

#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
    BTM_BleClearBgConnDev();//清楚whitelist
#endif

    if(BTM_GetNumAclLinks()==0)//如果已经没有link存在了,那么调用回调函数报告上层
    {
#if (defined(BTA_DISABLE_DELAY) && BTA_DISABLE_DELAY > 0)

        bta_sys_stop_timer(&bta_dm_cb.disable_timer);
        bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_conn_down_timer_cback;
        bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, BTA_DISABLE_DELAY);
#else
        bta_dm_disable_conn_down_timer_cback(NULL);
#endif
    }
    else//如果还有link存在,启动一个定时器,如果5s之后还有link存在,那么执行定时器回调函数
    {
        bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_timer_cback;
        bta_dm_cb.disable_timer.param = 0;
        bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 5000);
    }

}

 

 

 

 


xi按  ,,,,,

 

以上是关于蓝牙disable流程简述的主要内容,如果未能解决你的问题,请参考以下文章

蓝牙APP层的开启与关闭

Android 低功耗蓝牙开发简述

Android 低功耗蓝牙开发简述

Android 低功耗蓝牙开发简述

ESpBlufi官网代码Esp32蓝牙配网流程浅析

VSCode自定义代码片段——git命令操作一个完整流程