八、RFCOMM
1. RFCOMM
先来看看RFCOMM在协议栈层次体系中的位置。从下图可以看出RFCOMM处于传输层。与AVCTP,TCS-BIN处于同一层次。处于其上层的会话层中的OBEX,SPP等大部分协议通常都采用RFCOMM作为传输协议。因此RFCOMM传输协议在蓝牙协议栈中占据重要一席。

RFCOMM提供了基于L2CAP协议的串行(9针RS-232)模拟,支持在两个蓝牙设备间高达60路的通信连接。
1.1 RFCOMM使用示例——SPP
SPP(Serial Port Profile)定义了一系列协议和过程,蓝牙设备通过该协议实现RS232串行线缆的仿真。很多老式设备都工作在串行模块下面,使用SPP协议可以帮组连接这些老式设备。先来卡纳看SPP在蓝牙协议体系里面的位置:

从上图可以看出,SPP协议是大部分应用层协议都采用的会话层协议,常用的GOBEX以及HSP都采用了SPP协议。再来看看SPP协议所处的层次以及服务模型:

SPP按角色分为DevA和DevB,其中DevA是连接的发起者(initiator),DevB是等待连接的到来。从应用层角度看,SPP涉及到三个主要的过程:建立链路并设置虚拟串口连接、接收链路和建立虚拟串口连接、本地SDP数据库注册服务记录,其中第一项对DevA来说是强制实现的,后两项对DevB是强制实现的。
1.1.1 核心过程
1、建立链路并设置虚拟串口连接
该过程包括以下步骤:
1. Submit a query using SDP to find out the RFCOMM Server channel number of the desired application in the remote device. This might include a browsing capability to let the user select among available ports (or services) in the peer device. Or , if it is known exactly which service to contact, it is sufficient look up the necessary parameters using the Service Class ID associated with the desired service.
2. Optionally, require authentication of the remote device to be performed. Also optionally, require encryption to be turned on.
3. Request a new L2CAP channel to the remote RFCOMM entity.
4. Initiate an RFCOMM session on the L2CAP channel.
5. Start a new data link connection on the RFCOMM session, using the aforementioned server channel number.
After step 5, the virtual serial cable connection is ready to be used for communication between applications on both sides.
Note: If there already exists an RFCOMM session between the devices when setting up a new data link connection, the new connection must be established
on the existing RFCOMM.
2、接收链路和建立虚拟串口连接
该过程主要包括以下步骤:
1. If requested by the remote device, take part in authentication procedure and, upon further request, turn on encryption.
2. Accept a new channel establishment indication from L2CAP.
3. Accept an RFCOMM session establishment on that channel.
4. Accept a new data link connection on the RFCOMM session. This may trigger a local request to authenticate the remote device and turn on encryption, if the user has required that for the emulated serial port being connected to (and authentication/encryption procedures have not already been carried out ).
Note: steps 1 and 4 may be experienced as isolated events when there already exists an RFCOMM session to the remote device.
3、本地SDP数据库注册服务记录
该过程涉及到向本地SDP数据库为虚拟串口注册一条服务记录。这也意味着服务数据库的存在,以及对SDP查询的支持。
1.1.2 连接消息序列
先来看看DevB的初始化流程图。上层应用通过调用SppStartService()开始注册和初始化SPP服务,其中涉及到RFCOMM通道注册,SDP服务搜索等交互过程,在上层应用收到SPP_START_SERVICE_CFM表示服务初始化完成,下一步是等待DevA的连接到来。

再来看看典型的连接过程涉及到的消息交互流程图。DevA通过调用SppConnectRequest ()开启连接过程,DevB在接收到SPP_CONNECT_IND消息时决定是否接受该连接,并作出响应SppConnectResponse()。在DevA收到SPP_CLIENT_CONNECT_CFM,DevB收到SPP_SERVER_CONNECT_CFM后,表示SPP通信会话正式建立。

在走读ADK代码时候,你会发现一个奇怪的现象——通信模块(如L2CAP,RFCOMM,SPP等)里找不到数据收发的接口,传统的通信模块,比如SOCKET通信例程中,当通信链路建立后,会提供read/write,read_from/write_to等之类的显示读写函数帮助收发数据。这是因为ADK提供了流的机制,引入sink/source/transform概念。这样,当一条L2CAP/RFCOMM数据链路建立的同时会创建对应的sink实体,用于收发数据。Sink实体在有数据达到或者数据可以接受状态时向已注册任务(task)发送MESSAGE_MORE_DATA/MESSAGE_MORE_SPACE消息。以SPP为例,在DevA收到SPP_CLIENT_CONNECT_CFM,DevB收到SPP_SERVER_CONNECT_CFM后,例程将会保存已创建的sink实体,并进行配置。
Sink sink = (Sink) StreamRfcommSink(cfm->conn_id); /*从RFCOMM会话ID获取sink引用*/
SourceConfigure(StreamSourceFromSink(sink), VM_SOURCE_MESSAGES, VM_MESSAGES_ALL);
其实真正的sink实体创建于L2CAP链路创建成功的时候??这一点还只是猜测。
void connectionHandleL2capConnectCfm(const L2CA_AUTO_CONNECT_CFM_T *cfm){
Sink sink = StreamL2capSink(cfm->cid);
MessageSinkTask(sink, appTask); /* Associate the task with its sink */
}
目前还不清楚sink实体是何时创建的,总之,在SPP建立连接后,就拥有了一个数据收发的sink实体,通过该实体,配合BlueCore发送过来的MESSAGE_MORE_DATA和MESSAGE_MORE_SPACE等消息进行数据传输。
1.1.3 消息处理
SPP库例程中,DevA(Client)定义了一个回调函数——sppcConnectionHandler,用来接收下层的消息,并进行处理和转发。DevB(Server)定义了两个回调函数,一个用来处理连接时候的消息,一个用于处理服务相关(如SDP查询等)的消息。
spp->c.task.handler = sppcConnectionHandler;
spp->c.client_task = theAppTask;
TaskData sppsServiceTask = { sppServiceHandler };
spp->c.client_task = theAppTask;
SppConnectResponse()->
spp->c.task.handler= sppsConnectionHandler;
1.1.4 多串口仿真
两个使用RFCOMM通信的蓝牙设备可以同时打开多个串口仿真 ,RFCOMM支持多大60路,但是一个设备实际能打开的数据依实现而定。
ADK例程中怎么没有发现多串口复用相关的内容呢???
八、RFCOMM的更多相关文章
- 【转】Android bluetooth介绍(二): android blueZ蓝牙代码架构及其uart 到rfcomm流程
原文网址:http://blog.sina.com.cn/s/blog_602c72c50102uzoj.html 关键词:蓝牙blueZ UART HCI_UART H4 HCI L2CAP ...
- Android bluetooth介绍(两): android 蓝牙源架构和uart 至rfcomm过程
关键词:蓝牙blueZ UART HCI_UART H4 HCI L2CAP RFCOMM 版本号:基于android4.2先前版本 bluez内核:linux/linux3.08系统:an ...
- 如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成
阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ...
- iOS可视化动态绘制八种排序过程
前面几篇博客都是关于排序的,在之前陆陆续续发布的博客中,我们先后介绍了冒泡排序.选择排序.插入排序.希尔排序.堆排序.归并排序以及快速排序.俗话说的好,做事儿要善始善终,本篇博客就算是对之前那几篇博客 ...
- 我的MYSQL学习心得(八) 插入 更新 删除
我的MYSQL学习心得(八) 插入 更新 删除 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得( ...
- Mina、Netty、Twisted一起学(八):HTTP服务器
HTTP协议应该是目前使用最多的应用层协议了,用浏览器打开一个网站就是使用HTTP协议进行数据传输. HTTP协议也是基于TCP协议,所以也有服务器和客户端.HTTP客户端一般是浏览器,当然还有可能是 ...
- CRL快速开发框架系列教程八(使用CRL.Package)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- 【Oracle 集群】Linux下Oracle RAC集群搭建之Oracle DataBase安装(八)
Oracle 11G RAC数据库安装(八) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇总 ...
- 八皇后算法的另一种实现(c#版本)
八皇后: 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于 ...
随机推荐
- .Net Core下如何管理配置文件
一.前言 根据该issues来看,System.Configuration在.net core中已经不存在了,那么取而代之的是由Microsoft.Extensions.Cnfiguration.XX ...
- Kylin查询性能低下原因分析
在处理指数行情数据时(IDXD),我遇到一个KYLIN性能查询低下的问题,非常奇怪.经过一番研究发现了其中的原因并顺利解决: 症状: select count(*) from sensitop.idx ...
- [后端人员耍前端系列]AngularJs篇:30分钟快速掌握AngularJs
一.前言 对于前端系列,自然少不了AngularJs的介绍了.在前面文章中,我们介绍了如何使用KnockoutJs来打造一个单页面程序,后面一篇文章将介绍如何使用AngularJs的开发一个单页面应用 ...
- 终于解决:升级至.NET 4.6.1后VS2015生成WCF客户端代理类的问题
在Visual Studio 2015中将一个包含WCF引用的项目的targetFramework从4.5改为4.6.1的时候,VS2015会重新生成WCF客户端代理类.如果WCF引用配置中选中了&q ...
- 作业七:团队项目——Alpha版本冲刺阶段-07
昨天进展:代码编写. 今天安排:代码编写.
- [.net 面向对象编程基础] (18) 泛型
[.net 面向对象编程基础] (18) 泛型 上一节我们说到了两种数据类型数组和集合,数组是指包含同一类型的多个元素,集合是指.net中提供数据存储和检索的专用类. 数组使用前需要先指定大小,并且检 ...
- [Beautifulzzzz的博客目录] 快速索引点这儿O(∩_∩)O~~,红色标记的是不错的(⊙o⊙)哦~
3D相关开发 [direct-X] 1.direct-X最小框架 [OpenGL] 1.环境搭建及最小系统 [OpenGL] 2.企业版VC6.0自带的Win32-OpenGL工程浅析 51单片机 [ ...
- Direct2D教程(外篇)环境配置
2014年世界杯首场淘汰赛马上开始了,闲着没事,整理以前的博客草稿打发时间,意外的发现这篇文章,本来是打算加入到Direct2D那个系列的,不知道为什么把它给遗漏了.环境配置,对于熟手来说,不是什么重 ...
- 可拖动的DIV
在做WEB UI设计的时候,拖动某个HTML元素已经成为一种不能忽视的用户界面模式,比较典型的应用例子就是Dialog,一个元素是怎么实现拖动的呢?其实原理非常简单,要想实现首先得了解几个基本知识. ...
- Senparc.Weixin.MP SDK 微信公众平台开发教程(十):多客服接口说明
微信官方的多客服接口原理是通过用户发送的信息,开发者服务器返回一条指定类型的响应信息,使用户的对话状态切换到官方的多客服状态(持续一段时间),这段时间内用户发送的所有信息都不会到达开发者的服务器,而是 ...