蓝牙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流程简述的主要内容,如果未能解决你的问题,请参考以下文章