上一章讲了一下avdtp的连接过程,这一章我们看一下btstack的实例。

因为a2dp是一个音频传输的框架协议,具体的使用已经牵涉到应用层了,比如说我们的设备是个音箱设备还是个音源设备,我们目前是个音箱设备,所以可以看一下a2dp_sink_deom.c。

其中首先调用a2dp_and_avrcp_setup函数进行了一系列的初始化,从这个函数名就知道,初始化的内容包括了a2dp协议和avrcp协议,a2dp之前我们已经讲了其基础协议avdtp,avrcp的话呢是基于avctp协议的, AVCTP协议描述了蓝牙设备间Audio/Video的控制信号交换的格式和机制,它是一个总体的协议,具体的控制信息由其指定的协议(如AVRCP)实现,AVCTP本身只指定控制command和response的总体的格式,比如说我们在音箱端怎么暂停、播放、停止、上一首、下一首操作,就得依赖avrcp,再比如说音量同步功能,也是依赖avrcp。

1      l2cap_init();2       // Initialize AVDTP Sink3       a2dp_sink_init();4       a2dp_sink_register_packet_handler(&a2dp_sink_packet_handler);5       a2dp_sink_register_media_handler(&handle_l2cap_media_data_packet);67       avdtp_stream_endpoint_t * local_stream_endpoint = a2dp_sink_create_stream_endpoint(AVDTP_AUDIO,8           AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities),9           media_sbc_codec_configuration, sizeof(media_sbc_codec_configuration));10      if (!local_stream_endpoint){11          printf("A2DP Sink: not enough memory to create local stream endpoint\n");12          return 1;13      }14      a2dp_local_seid = avdtp_local_seid(local_stream_endpoint);1516      // Initialize AVRCP service.17      avrcp_init();18      avrcp_register_packet_handler(&avrcp_packet_handler);……

基本上都是一些初始化的操作,第一行初始化l2cap, 第二行初始化a2dp sink, 其中给l2cap的数据注册了回调函数

l2cap_register_service(&avdtp_packet_handler, BLUETOOTH_PSM_AVDTP, 0xffff, gap_get_security_level());

我们之前说过,l2cap建立逻辑信道,区分上层协议的依据就是PSM,所以这里的PSM一定要填BLUETOOTH_PSM_AVDTP。

之后凡是avdtp相关的l2cap数据都会进入这个avdtp_packet_handler去处理。

1   void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){2       bd_addr_t event_addr;3       uint16_t psm;4       uint16_t local_cid;5       uint8_t  status;6       uint16_t l2cap_mtu;78       bool accept_streaming_connection;9       bool outoing_signaling_active;10      bool decline_connection;1112      avdtp_stream_endpoint_t * stream_endpoint = NULL;13      avdtp_connection_t * connection = NULL;1415      switch (packet_type) {16          case L2CAP_DATA_PACKET:17              connection = avdtp_get_connection_for_l2cap_signaling_cid(channel);18              if (connection){19                  handle_l2cap_data_packet_for_signaling_connection(connection, packet, size);20                  break;21              }22             23              stream_endpoint = avdtp_get_stream_endpoint_for_l2cap_cid(channel);24              if (!stream_endpoint){25                  if (!connection) break;26                  handle_l2cap_data_packet_for_signaling_connection(connection, packet, size);27                  break;28              }29             30              if (stream_endpoint->connection){31                  if (channel == stream_endpoint->connection->l2cap_signaling_cid){32                      handle_l2cap_data_packet_for_signaling_connection(stream_endpoint->connection, packet, size);33                      break;34                  }35              }3637              if (channel == stream_endpoint->l2cap_media_cid){38                  btstack_assert(avdtp_sink_handle_media_data);39                  (*avdtp_sink_handle_media_data)(avdtp_local_seid(stream_endpoint), packet, size);40                  break;41              }4243              if (channel == stream_endpoint->l2cap_reporting_cid){44                  log_info("L2CAP_DATA_PACKET for reporting: NOT IMPLEMENTED");45              } else if (channel == stream_endpoint->l2cap_recovery_cid){46                  log_info("L2CAP_DATA_PACKET for recovery: NOT IMPLEMENTED");47              } else {48                  log_error("avdtp packet handler L2CAP_DATA_PACKET: local cid 0x%02x not found", channel);49              }50              break;51             52          case HCI_EVENT_PACKET:53              switch (hci_event_packet_get_type(packet)) {5455                  case L2CAP_EVENT_INCOMING_CONNECTION:56                      l2cap_event_incoming_connection_get_address(packet, event_addr);57                      local_cid = l2cap_event_incoming_connection_get_local_cid(packet);58                     59                      outoing_signaling_active = false;60                      accept_streaming_connection = false;61                     62                      connection = avdtp_get_connection_for_bd_addr(event_addr);……

有了上一章的讲述,这里面对各种数据包的分类就好理解了,handle_l2cap_data_packet_for_signaling_connection是处理signal channel的数据,第39行的(*avdtp_sink_handle_media_data)(avdtp_local_seid(stream_endpoint), packet, size)是处理stream channel的数据,第52行的HCI_EVENT_PACKET其实并不是真正的hci event,而是btstack虚拟出来的一类软件内部的hci event,看第55行就知道,这类hci event据事件type去执行不同操作,l2cap的signal channel去建立逻辑信道的连接的时候,也是有一套状态机的,其中有不同状态,这个L2CAP_EVENT_INCOMING_CONNECTION就是准备建立连接的状态。

我们再回到a2dp_and_avrcp_setup,

第4行a2dp_sink_register_packet_handler(&a2dp_sink_packet_handler);这里面除了有avdtp协议内部对于a2dp各子状态的处理之外,还注册了a2dp_sink_packet_handler这个应用层的回调函数,主要处理在a2dp连接各子状态的时候,对codec层需要做的一些处理,比如说sbc编码器的初始化,音频的具体处理,这些都依赖于上层的实现。

第5行a2dp_sink_register_media_handler(&handle_l2cap_media_data_packet);

这个handle_l2cap_media_data_packet是应用层对于stream包的处理函数,之前avdtp_packet_handler函数,在收到l2cap层的avdtp包的时候,会分析是signal channel的包还是stream channel的包,假如是stream channel的包的话,看一下39行,就是在执行这里所注册的回调函数了。一般来说,这里面应该做的工作是执行解码器解码的工作,解码完了打算干吗?送给播放器播放?具体的还是取决于应用层。

第7行

avdtp_stream_endpoint_t * local_stream_endpoint = a2dp_sink_create_stream_endpoint(AVDTP_AUDIO,AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities),media_sbc_codec_configuration, sizeof(media_sbc_codec_configuration));

创建一个sep,也可以看出a2dp中sep的确是一个虚拟的概念了,软件中想创建就可以创建的。

再深入看一下代码,看看给这个sep分配seid的时候:

static uint16_t avdtp_get_next_local_seid(void){if (stream_endpoints_id_counter == 0xffff) {stream_endpoints_id_counter = 1;} else {stream_endpoints_id_counter++;}return stream_endpoints_id_counter;}

可以看到seid无非是做了一个加1 的动态分配的动作。

第14行

a2dp_local_seid = avdtp_local_seid(local_stream_endpoint);

给a2dp_local_seid这个重要变量赋值,因为avdtp的连接是基于seid的,所以以后连接过程都是需要频繁用到的,用一个全局变量保存并不为过。

再接下来avrcp的一系列的初始化。

整个a2dp_and_avrcp_setup函数执行完成后,上层的服务就设置好了,a2dp_sink_demo.c支持从上位机输入指令执行相应程序,比如说,输入‘b’,就会调用a2dp_sink_establish_stream执行a2dp的连接操作,接下来,输入b试试看,让状态机跑起来吧。

蓝牙开发那些事(9)——结合代码看a2dp协议相关推荐

  1. 【Android】蓝牙开发——BLE(低功耗蓝牙)(附完整Demo)

    目录 目录 前言 一.相关概念介绍 二.实战开发 三.项目演示 四.Demo案例源码地址 五.更新记录 1.2020/12/29 :修改 setupService()中错误 2.2021/05/14 ...

  2. 泰凌微ble mesh蓝牙模组天猫精灵学习之旅④如何在Android开发低功耗蓝牙ble控制 TB-02 模块,代码工程全部开源!(附带Demo)

    本<泰凌微ble mesh蓝牙模组天猫精灵学习之旅>系列博客学习由半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1.小白也痴迷,如 ...

  3. java request 处理过程_小猿圈Java开发之从代码看spring mvc请求处理过程

    原标题:小猿圈Java开发之从代码看spring mvc请求处理过程 Java作为编程界的常青树,有自己生存的独到之处,小猿圈java讲师今天就分享一个关于从代码看spring mvc请求处理过程,通 ...

  4. 蓝牙配对模式 java_【Android】蓝牙开发—— 经典蓝牙配对介绍(Java代码实现演示)附Demo源码...

    目录 前言 一.连接&配对方法介绍 二.演示:第一次连接蓝牙设备  &  直接与蓝牙设备建立配对 三.总结 四.补充 五.Demo案例源码地址: 前言 前面两篇文章[Android]蓝 ...

  5. 【Android】蓝牙开发—— 经典蓝牙配对介绍(Java代码实现演示)附Demo源码

    目录 前言 一.连接&配对方法介绍 二.演示:第一次连接蓝牙设备  &  直接与蓝牙设备建立配对 三.总结 四.补充 五.Demo案例源码地址: 前言 前面两篇文章[Android]蓝 ...

  6. CSR蓝牙开发资源大全(软件代码资料)

    CSR蓝牙开发资源大全 BlueSuite 2.4.8  开发生产测试配置工具 http://pan.baidu.com/share/link?shareid=299289621&uk=339 ...

  7. android蓝牙开发代码,Android蓝牙开发(示例代码)

    Android蓝牙开发 近期做蓝牙小车,须要Android端来控制小车的运动.以此文记录开发过程. 使用HC-06无线蓝牙串口透传模块.对于其它的蓝牙设备本文相同适用. 蓝牙开发的流程: 获取本地蓝牙 ...

  8. android Ble4.0蓝牙开发之搜索慢、startLeScan()过时,6.0以上不需要定位权限也能快速搜索到蓝牙设备

    项目中需要用到android Ble蓝牙4.0开发技术,于是开启了蓝牙填坑之旅,说实话,蓝牙开发坑真多,跳出一个又进入下一个,每次遇到 问题,就觉得不可能解决了,还好在自己的摸索中,都一一的化解了,以 ...

  9. 安卓基于BLE的蓝牙开发入门

    BLE蓝牙开发简单入门 BLE背景介绍 引言 BLE简介 Gatt协议以及必备知识 蓝牙开发涉及的API介绍 BLE实战准备 真机调试 权限准备 写两个简单的页面 扫描设备主界面 扫描设备信息界面 实 ...

最新文章

  1. jsp页面定义的map
  2. android textview 白色,android – AutoCompleteTextview默认情况下,颜色设置为白色
  3. 面对SDN/NFV部署挑战 网络厂商能做什么?
  4. 浅谈社区电子商务的发展及其技术应用
  5. 云小课|云小课带你快速掌握云数据迁移CDM
  6. CSS基本选择器之类选择器多类名(CSS、HTML)
  7. gift to me by myself on 2012's new year
  8. 硬盘格式化数据恢复的软件推荐
  9. 编译原理复习总结及思维导图
  10. 15个经典面试问题及回答思路,挥泪整理面经
  11. java汤姆猫安装_汤姆猫跑酷安装
  12. php查找判断二维数组中是否含有某个值
  13. 用水流的概念来玩硬件(三)----LDO与DCDC电源电路
  14. 视频如何做成gif动图?
  15. 论文阅读——Automatic Testing and Improvement of Machine Translation
  16. 西澳大利亚大学计算机专业,西澳大利亚大学世界排名多少位(西澳大利亚大学热门专业介绍)...
  17. 修改远程桌面3389端口批处理
  18. OSI 七层模型详解
  19. 全球与中国地下用钢纤维市场深度研究分析报告
  20. 网络云存储技术Windows server 2012 (项目十三 NFS共享的配置与管理)

热门文章

  1. ubuntu16.04开机自动挂载nas盘
  2. 凤凰涅槃,浴火重生(2013年总结)
  3. 常见的纸张及相片尺寸
  4. 如何查看网站的收录与排名
  5. SWFUpload使用
  6. mac os 系统升级到 Catalina 版本后出现应用打不开 ,闪退,意外退出问题
  7. Maven跳过单元测试配置
  8. Type A卡和Type B卡的主要区别
  9. Groovy~Groovy的List(列表)操作
  10. git 安装windows错误处理