【Bluedroid】AVRCP 连接源码分析(三)

接着上一篇【Bluedroid】AVRCP 连接源码分析(一)-CSDN博客,继续AVRCP连接的源码分析。

AVRC_OpenBrowse

/packages/modules/Bluetooth/system/stack/avrc/avrc_api.cc
/******************************************************************************** Function         AVRC_OpenBrowse** Description      This function is called to open a browsing connection to*                  AVCTP. The connection can be either an initiator or*                  acceptor, as determined by the p_conn_role.*                  The handle is returned by a previous call to AVRC_Open.** Returns          AVRC_SUCCESS if successful.*                  AVRC_NO_RESOURCES if there are not enough resources to open*                  the connection.******************************************************************************/
uint16_t AVRC_OpenBrowse(uint8_t handle, uint8_t conn_role) {return AVCT_CreateBrowse(handle, conn_role);
}

AVRC_OpenBrowse 函数主要功能是发起一个到 AVCTP的浏览连接。这个连接可以是发起方(initiator)连接,也可以是接收方(acceptor)连接,具体由传入的 conn_role 参数决定。

AVCT_CreateBrowse

packages/modules/Bluetooth/system/stack/avct/avct_api.cc
/********************************************************************************* Function         AVCT_CreateBrowse** Description      Create an AVCTP Browse channel.  There are two types of*                  connections, initiator and acceptor, as determined by*                  the role parameter.  When this function is called to*                  create an initiator connection, the Browse channel to*                  the peer device is initiated if one does not already exist.*                  If an acceptor connection is created, the connection waits*                  passively for an incoming AVCTP connection from a peer*                  device.*** Returns          AVCT_SUCCESS if successful, otherwise error.*******************************************************************************/
uint16_t AVCT_CreateBrowse(uint8_t handle, uint8_t role) {uint16_t result = AVCT_SUCCESS;tAVCT_CCB* p_ccb;tAVCT_BCB* p_bcb;int index;log::verbose("AVCT_CreateBrowse: {}", role);/* map handle to ccb */// 1. 映射句柄到连接控制块p_ccb = avct_ccb_by_idx(handle);if (p_ccb == NULL) {return AVCT_BAD_HANDLE;} else {/* mark this CCB as supporting browsing channel */if ((p_ccb->allocated & AVCT_ALOC_BCB) == 0) {p_ccb->allocated |= AVCT_ALOC_BCB;}}/* if initiator connection */// 2. 发起方连接处理if (role == AVCT_INT) {/* the link control block must exist before this function is called as INT.*/if ((p_ccb->p_lcb == NULL) || (p_ccb->p_lcb->allocated == 0)) {result = AVCT_NOT_OPEN;} else {/* find link; if none allocate a new one */index = p_ccb->p_lcb->allocated;if (index > AVCT_NUM_LINKS) {result = AVCT_BAD_HANDLE;} else {p_bcb = &avct_cb.bcb[index - 1];p_bcb->allocated = index;}}if (result == AVCT_SUCCESS) {/* bind bcb to ccb */p_ccb->p_bcb = p_bcb;p_bcb->peer_addr = p_ccb->p_lcb->peer_addr;log::verbose("ch_state: {}", p_bcb->ch_state);tAVCT_LCB_EVT avct_lcb_evt;avct_lcb_evt.p_ccb = p_ccb;avct_bcb_event(p_bcb, AVCT_LCB_UL_BIND_EVT, &avct_lcb_evt);}}return result;
}

创建一个 AVCTP的浏览通道。根据传入的 role 参数,连接可以是发起方(initiator)连接或者接收方(acceptor)连接。如果是发起方连接,会尝试发起与对端设备的浏览通道连接;如果是接收方连接,会被动等待来自对端设备的 AVCTP 连接。

avct_bcb_event(AVCT_LCB_UL_BIND_EVT)

packages/modules/Bluetooth/system/stack/avct/avct_lcb.cc
/********************************************************************************* Function         avct_bcb_event** Description      State machine event handling function for lcb*** Returns          Nothing.*******************************************************************************/
void avct_bcb_event(tAVCT_BCB* p_bcb, uint8_t event, tAVCT_LCB_EVT* p_data) {tAVCT_LCB_ST_TBL state_table; // 存储当前状态对应的状态转移表uint8_t action;int i;log::verbose("BCB lcb={} event={} state={}", p_bcb->allocated,avct_lcb_evt_str[event], avct_lcb_st_str[p_bcb->state]);/* look up the state table for the current state */// 1. 查找当前状态的状态转移表state_table = avct_lcb_st_tbl[p_bcb->state];/* set next state */// 2. 设置下一个状态p_bcb->state = state_table[event][AVCT_LCB_NEXT_STATE];/* execute action functions */// 3. 执行动作函数for (i = 0; i < AVCT_LCB_ACTIONS; i++) {action = state_table[event][i];if (action != AVCT_LCB_IGNORE) {(*avct_bcb_action[action])(p_bcb, p_data);} else {break;}}
}

处理 tAVCT_BCB( AVCTP 浏览通道控制块)状态机事件的函数。根据传入的事件和当前状态,查找对应的状态转移表,更新控制块的状态,并执行相应的动作函数。

avct_bcb_chnl_open

packages/modules/Bluetooth/system/stack/avct/avct_bcb_act.cc
/********************************************************************************* Function         avct_bcb_chnl_open** Description      Open L2CAP channel to peer*** Returns          Nothing.*******************************************************************************/
void avct_bcb_chnl_open(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {uint16_t result = AVCT_RESULT_FAIL;tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb);tL2CAP_ERTM_INFO ertm_info;/* Set the FCR options: Browsing channel mandates ERTM */ertm_info.preferred_mode = L2CAP_FCR_ERTM_MODE;/* call l2cap connect req */p_bcb->ch_state = AVCT_CH_CONN;p_bcb->ch_lcid =L2CA_ConnectReq2(AVCT_BR_PSM, p_lcb->peer_addr, BTA_SEC_AUTHENTICATE);if (p_bcb->ch_lcid == 0) {/* if connect req failed, send ourselves close event */tAVCT_LCB_EVT avct_lcb_evt;avct_lcb_evt.result = result;avct_bcb_event(p_bcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt);}
}

L2CA_ConnectReq2

L2CA_ConnectReq2源码这里不再分析。

对端设备收到 L2CAP 连接请求后,会根据自身的状态和能力进行处理,并发送 L2CAP 连接响应。响应消息用于告知发起方连接请求的结果(成功或失败),以及协商连接的一些参数。

发起方收到连接响应后,会根据结果码进行相应的处理。如果连接成功,会使用分配的 LCID 进行后续的数据传输;如果连接失败,可能会进行错误处理或重试。

bta_av_rc_ctrl_cback

bta_av_rc_ctrl_cback前文有分析,不再赘述。

bta_av_non_state_machine_event(BTA_AV_AVRC_BROWSE_OPEN_EVT)

bta_av_rc_browse_opened

packages/modules/Bluetooth/system/bta/av/bta_av_act.cc
/********************************************************************************* Function         bta_av_rc_browse_opened** Description      AVRC browsing channel is opened** Returns          void*******************************************************************************/
void bta_av_rc_browse_opened(tBTA_AV_DATA* p_data) {tBTA_AV_CB* p_cb = &bta_av_cb;tBTA_AV_RC_CONN_CHG* p_msg = (tBTA_AV_RC_CONN_CHG*)p_data;tBTA_AV_RC_BROWSE_OPEN rc_browse_open;log::info("peer_addr: {} rc_handle:{}",ADDRESS_TO_LOGGABLE_CSTR(p_msg->peer_addr), p_msg->handle);// 填充 rc_browse_open 结构体rc_browse_open.status = BTA_AV_SUCCESS;rc_browse_open.rc_handle = p_msg->handle;rc_browse_open.peer_addr = p_msg->peer_addr;// 准备回调数据并调用回调函数tBTA_AV bta_av_data;bta_av_data.rc_browse_open = rc_browse_open;(*p_cb->p_cback)(BTA_AV_RC_BROWSE_OPEN_EVT, &bta_av_data);
}

处理 AVRCP浏览通道已打开的事件。当 AVRCP 浏览通道成功打开时,会收集相关信息,如状态、句柄和对端设备地址等,然后调用回调函数通知上层模块浏览通道已成功打开。

bta_av_source_callback(BTA_AV_RC_BROWSE_OPEN_EVT)

btif_av_handle_bta_av_event

btif_av_handle_event

同前文分析。

BtifAvStateMachine::StateOpened::ProcessEvent

btif_rc_handler(BTA_AV_RC_BROWSE_OPEN_EVT)

handle_rc_browse_connect

packages/modules/Bluetooth/system/btif/src/btif_rc.cc
/****************************************************************************  Function       handle_rc_browse_connect**  - Argument:    tBTA_AV_RC_OPEN  browse RC open data structure**  - Description: browse RC connection event handler****************************************************************************/
void handle_rc_browse_connect(tBTA_AV_RC_BROWSE_OPEN* p_rc_br_open) {log::verbose("rc_handle {} status {}", p_rc_br_open->rc_handle,p_rc_br_open->status);// 1. 设备查找btif_rc_device_cb_t* p_dev =btif_rc_get_device_by_handle(p_rc_br_open->rc_handle);if (!p_dev) {log::error("p_dev is null");return;}/* check that we are already connected to this address since being connected* to a browse when not connected to the control channel over AVRCP is* probably not preferred anyways. */// 2. 连接成功处理if (p_rc_br_open->status == BTA_AV_SUCCESS) {p_dev->br_connected = true;if (btif_av_src_sink_coexist_enabled()) {if (btif_av_peer_is_connected_source(p_dev->rc_addr)) { // 支持共存且对端是已连接源设备if (bt_rc_ctrl_callbacks != NULL) {// 通知上层应用 AVRCP 浏览连接已建立do_in_jni_thread(FROM_HERE,base::BindOnce(bt_rc_ctrl_callbacks->connection_state_cb, true,true, p_dev->rc_addr));}} else { // 支持共存但对端不是已连接源设备p_dev->launch_cmd_pending |= RC_PENDING_ACT_REPORT_CONN; // 有浏览连接事件待处理log::verbose("pending rc browse connection event");}} else { // 不支持共存if (bt_rc_ctrl_callbacks != NULL) {// 通知上层应用连接已建立do_in_jni_thread(FROM_HERE,base::BindOnce(bt_rc_ctrl_callbacks->connection_state_cb, true,true, p_dev->rc_addr));} else {log::warn("bt_rc_ctrl_callbacks is null.");}}}
}

处理 AVRCP浏览连接事件。当接收到 AVRCP 浏览通道打开的事件时,会根据事件的状态和系统的配置情况,更新设备的连接状态,并通过回调函数通知上层应用。

关键字

AVCT_CreateBrowse|avct_bcb_event|bta_av_rc_ctrl_cback|bta_av_rc_browse_opened|handle_rc_browse_connect

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/70589.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于大语言模型的推荐系统(1)

推荐系统&#xff08;recommendation system&#xff09;非常重要。事实上&#xff0c;搜索引擎&#xff0c;电子商务&#xff0c;视频&#xff0c;音乐平台&#xff0c;社交网络等等&#xff0c;几乎所有互联网应用的核心就是向用户推荐内容&#xff0c;商品&#xff0c;电影&…

高性能GPU计算:释放计算潜力的加速利器

高性能GPU计算:释放计算潜力的加速利器 大家好,我是Echo_Wish,今天我们来聊一聊 高性能GPU计算。近年来,随着人工智能、深度学习、科学计算等领域的快速发展,GPU(图形处理单元)作为计算加速的核心技术,逐渐成为数据处理的“核心大脑”。尤其是在深度学习模型训练和大规…

QT闲记-状态栏,模态对话框,非模态对话框

1、创建状态栏 跟菜单栏一样,如果是继承于QMainWindow类,那么可以获取窗口的状态栏,否则就要创建一个状态栏。通过statusBar()获取窗口的状态栏。 2、添加组件 通常添加Label 来显示相关信息,当然也可以添加其他的组件。通过addWidget()添加组件 3、设置状态栏样式 …

SHELL32!SHLoadPopupMenu函数分析之添加属性菜单项

SHELL32!SHLoadPopupMenu函数分析之添加属性菜单项 第一部分&#xff1a; // // user does not support pop-up only menu. // STDAPI_(HMENU) SHLoadPopupMenu(HINSTANCE hinst, UINT id) { HMENU hmenuParent LoadMenu(hinst, MAKEINTRESOURCE(id)); if (hmenuPare…

将RocketMQ集成到了Spring Boot项目中,实现站内信功能

1. 添加依赖 首先,在pom.xml中添加RocketMQ的依赖: <dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot

C语言基础要素:安装 Visual Studio 2022

安装 Visual Studio 2022 Visual Studio 是由微软开发的一款集成开发环境&#xff08;IDE&#xff09;&#xff0c;支持多种编程语言和开发平台。它提供了丰富的工具和功能&#xff0c;帮助开发者高效地编写、调试和部署应用程序。无论是桌面应用、Web 应用还是移动应用&#…

[ TypeScript ] “undefined extends xxx“ 总是为 true 的 bug

版本号 "typescript": "^5.7.3", "unplugin": "^2.2.0",说明 在使用 unplugin 时 , 我定义插件的参数是 必填的, 使用时却是一个可空参数, 不传参也不会报错, (options?: UserOptions) > Return &#x1f632;&#x1f632;&…

[通俗易懂C++]:指针和const

之前的文章有说过,使用指针我们可以改变指针指向的内容(通过给指针赋一个新的地址)或者改变被保存地址的值(通过给解引用指针赋一个新值): int main() {int x { 5 }; // 创建一个整数变量 x&#xff0c;初始值为 5int* ptr { &x }; // 创建一个指针 ptr&#xff0c;指向 …

华为昇腾服务器(固件版本查询、驱动版本查询、CANN版本查询)

文章目录 1. **查看固件和驱动版本**2. **查看CANN版本**3. **其他辅助方法**注意事项 在华为昇腾服务器上查看固件、驱动和CANN版本的常用方法如下&#xff1a; 1. 查看固件和驱动版本 通过命令行工具 npu-smi 执行以下命令查看当前设备的固件&#xff08;Firmware&#xff0…

设计心得——解耦的实现技术

一、说明 在前面的“设计心得——解耦”中&#xff0c;对解耦进行了高层次的抽象说明。本篇则对在实践中常用的解耦技术进行逐一分析说明&#xff0c;以期为开发者能更从理论到实践搭建一个桥梁。至于大家能够如何更好的在自己的项目中进行解耦的实践&#xff0c;就需要不断的…

Blaze RangePartitioning 算子Native实现全解析

引言&#xff1a;本文将全面且深入地解析Blaze RangePartitioning算子的Native实现过程。相较于原生Spark&#xff0c;RangePartitioning的Native实现在执行时间上达到了30%的显著下降&#xff0c;同时在资源开销方面节省了高达76%。这一改进大幅降低了运行成本&#xff0c;展现…

卷积与动态特征选择:重塑YOLOv8的多尺度目标检测能力

文章目录 1. YOLOv8的网络结构概述2. 添加注意力机制2.1 为什么添加注意力机制&#xff1f;2.2 如何将注意力机制集成到YOLOv8中&#xff1f;2.3 效果分析 3. C2f模块的集成3.1 C2f模块简介3.2 如何在YOLOv8中集成C2f模块&#xff1f;3.3 效果分析 4. 卷积操作的优化4.1 卷积操…

Web入侵实战分析-常见web攻击类应急处置实验2

场景说明 某天运维人员&#xff0c;发现运维的公司站点被黑页&#xff0c;首页标题被篡改&#xff0c;你获得的信息如下&#xff1a; 操作系统&#xff1a;windows server 2008 R2业务&#xff1a;公司官网网站架构&#xff1a;通过phpstudy运行apache mysqlphp开放端口&…

WebXR教学 02 配置开发环境

默认操作系统为Windows 1.VS Code VS Code 是一款轻量级、功能强大的代码编辑器&#xff0c;适用于多种编程语言。 下载 步骤 1&#xff1a;访问 VS Code 官方网站 打开浏览器&#xff08;如 Chrome、Edge 等&#xff09;。 在地址栏输入以下网址&#xff1a; https://code.v…

Flask实现高效日志记录模块

目录 一. 简介&#xff1a; 1. 为什么需要请求日志 二. 日志模块组成 1. 对应日志表创建&#xff08;包含日志记录的关键字段&#xff09; 2. 编写日志记录静态方法 3. 在Flask中捕获请求日志 4. 捕获异常并记录错误日志 5. 编写日志接口数据展示 6. 写入数据展…

前端框架虚拟DOM的产生

直接说结论&#xff1a;为了找出与命令式(原生实现步骤)所执行代码的最小差异化&#xff0c;从而优化代码性能。 命令式&#xff1a; 可以理解为面向过程编程&#xff0c;需要写好每个实现步骤 <div id"app"></div> const div document.querySelector…

RoCBert:具有多模态对比预训练的健壮中文BERT

摘要 大规模预训练语言模型在自然语言处理&#xff08;NLP&#xff09;任务上取得了最新的最优结果&#xff08;SOTA&#xff09;。然而&#xff0c;这些模型容易受到对抗攻击的影响&#xff0c;尤其是对于表意文字语言&#xff08;如中文&#xff09;。 在本研究中&#xff0…

Jetpack Architecture系列教程之(三)——ViewModel控制器

目录 介绍 如何使用 添加依赖 构建ViewModel 分析ViewModel ViewModel生命周期 ViewModel加载原理 介绍 ViewModel 的出现是为了解决数据因Android UI控制器在生命周期活动中造成数据丢失的问题。 在一般情况下&#xff0c;页面数据丢失&#xff08;转屏、闪退等生命周期…

在低功耗MCU上实现人工智能和机器学习

作者&#xff1a;Silicon Labs 人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;技术不仅正在快速发展&#xff0c;还逐渐被创新性地应用于低功耗的微控制器&#xff08;MCU&#xff09;中&#xff0c;从而实现边缘AI/ML解决方案。这些MCU是许多嵌入式…

rpc到自己java实现rpc调用再到rpc框架设计

目录 rpc(Remote Procedure Call)rpc一般架构为什么要引入rpc自己实现rpc调用1. 新建一个maven项目&#xff0c;加入hessian依赖2. 服务端3. Stub代理4. 客户端测试输出5. rpc程序分析附 请求参数和序列化程序 6. 总结 回顾RPCRPC 序列化协议RPC 网络协议注册中心的引入dubbo框…