qcc304x笔记之主从切换(handover)机制详解(十六)

it2024-07-01  40

主从切换执行条件

引起主从切换的原因有PhyState改变,电池的状态,rssi状态,通话音质等方面,这里我们主要是针对PhyState改变引起的切换来举例说明 当PhyState状态改变时,交由stateProxy模块进行处理

(注:由于SDK在持续更新,有些接口可能会有些变化,所以仅供参考)

appPhyStateEnterInCase appPhyStateEnterInEar appPhyStateEnterOutOfEarAtRest appPhyStateExitInCase appPhyStateExitInEar appPhyStateExitOutOfEarAtRest appPhyStateMsgSendStateChangedInd PHY_STATE_CHANGED_IND stateProxy_HandlePhyStateChangedInd stateProxy_SendRemotePhyStateChangedInd stateProxy_HandlePhyStateChangedIndImpl stateProxy_MsgStateProxyEventClients

stateProxy_MsgStateProxyEventClients接口中会发送STATE_PROXY_EVENT事件到hdma(Handover Decision Making Algorithm)模块  

hdma_HandleMessage STATE_PROXY_EVENT hdma_HandleStateProxyEvent state_proxy_event_type_phystate hdma_HandlePhyState Hdma_CoreHandleEvent Hdma_CoreHandleBatteryStatus Hdma_CoreHandleVoiceQuality Hdma_CoreHandleLinkQuality /*hdma_StateUpdate会有四个地方调用,即有文章开头所说的几种原因,下面分别做了说明(case 1~5)*/ hdma_StateUpdate /* Case (1) bud is in case */ #ifdef INCLUDE_HDMA_BATTERY_EVENT /* Case (2) battery is critical */ #endif /* Case (3) primary is out of ear, secondary is in ear */ #ifdef INCLUDE_HDMA_RSSI_EVENT /* Case (4) RSSIs: skip this if the secondary is unable to be handed over to*/ #endif #ifdef INCLUDE_HDMA_MIC_QUALITY_EVENT /* Case (5) Mic quality during a voice call */ #endif /*当上述的任一条件成立,就执行切换的动作*/ hdma_SetHandoverEvent HDMA_HANDOVER_NOTIFICATION twsTopology_HandleHDMARequest twsTopology_TriggerHandoverEvent /*rules机制我们之前已经详细说明过了,这里不再多说了*/ RULE(TWSTOP_RULE_EVENT_HANDOVER, ruleTwsTopTwmHandoverStart, TWSTOP_PRIMARY_GOAL_HANDOVER_START), TWSTOP_PRIMARY_GOAL_HANDOVER_START GoalsEngine_ActivateGoal(tws_topology_goal_dynamic_handover)

上面这部分的逻辑主要是决定什么时候触发handover,也即是主从切换,下面就进入了handover的执行阶段。

主从切换执行内容

上面逻辑的最后调用了tws_topology_goal_dynamic_handover这个goal,goal机制在上篇博客中已经说明了,这里不再多说,然后我们再来看看,这个goal是在哪里定义的  

/*tws_topology_goals.c*/ const goal_entry_t goals[] = { ... SCRIPT_GOAL_CANCEL_SUCCESS_FAILED(tws_topology_goal_dynamic_handover, tws_topology_procedure_dynamic_handover, &dynamic_handover_script, tws_topology_goal_none, TWSTOP_RULE_EVENT_ROLE_SWITCH, TWSTOP_RULE_EVENT_HANDOVER_FAILED), ... }

它是在tws_topology_goals模块中定义的,当这个goals成功运行之后,根据我们之前说的goals规则,又会去调用dynamic_handover_script这个脚本。 同时当这个goal运行完成之后,成功了发送TWSTOP_RULE_EVENT_ROLE_SWITCH消息,失败了则发送TWSTOP_RULE_EVENT_HANDOVER_FAILED消息

下面继续跟踪dynamic_handover_script的定义

DEFINE_TOPOLOGY_SCRIPT(dynamic_handover, DYNAMIC_HANDOVER_SCRIPT); #define DYNAMIC_HANDOVER_SCRIPT(ENTRY) \ ENTRY(proc_notify_role_change_clients_fns, PROC_NOTIFY_ROLE_CHANGE_CLIENTS_FORCE_NOTIFICATION), \ ENTRY(proc_enable_le_connectable_handset_fns, PROC_ENABLE_LE_CONNECTABLE_PARAMS_DISABLE), \ ENTRY(proc_disconnect_le_connections_fns, NO_DATA), \ ENTRY(proc_handover_fns, NO_DATA), \ ENTRY(proc_set_role_fns, PROC_SET_ROLE_TYPE_DATA_SECONDARY),\

上面通过两个宏操作DEFINE_TOPOLOGY_SCRIPT、DYNAMIC_HANDOVER_SCRIPT,将五个函数指针数组,组合成上文中的dynamic_handover_script

这里我们就只针对 proc_handover_fns 函数指针数组进行分析,其主要是进行一些数据移交的工作。其它的模块有兴趣可以自行深入分析

const procedure_fns_t proc_handover_fns = { TwsTopology_ProcedureHandoverStart, TwsTopology_ProcedureHandoverCancel, }; TwsTopology_ProcedureHandoverStart twsTopology_ProcHandoverStart HandoverProfile_Handover HandoverProfile_MarshalP1Clients for(;i<(p1_ho_interfaces数组元素的个数);i++) p1_ho_interfaces->pFnMarshal()

p1_ho_interfaces则是定义在earbud_handover.c中,又是一个函数指针数组指针,上面的代码逻辑就是将下面的五个函数指针数组中的****Marshal()函数都调用执行一遍,至此,流程走到这里就清楚了

const handover_interface * p1_ho_interfaces[] = { &application_handover_interface, &connection_handover_if,/*if--interface*/ &a2dp_handover_if, &avrcp_handover, &hfp_handover_if, &kymera_a2dp_mirror_handover_if };

到这里基本上整个逻辑就梳理清楚了。

 

相关的工具资料等,请到我的博客<qcc514x_qcc304x开发调试笔记>最下面的网盘链接中下载。

最新回复(0)