1.1     首先初始化连接库

sinkConnectionInit();à

ConnectionInitEx2();  theCm.task.handler = connectionBluestackHandler;

连接库初始化完毕后,发送CL_INIT_CFM给ClientTask(/APPtask/MainTask),ClientTask在接收到该消息后,开始初始化Codec和GAIA。sinkInitCodecTask(); | GaiaInit(task, 1);

1.2     初始化Codec

sinkInitCodecTask();

Codec初始化完毕之后,sendInitCfmToApp()调用向ClientTask发送CODEC_INIT_CFM消息,ClientTask在接收到该消息后,开始初始化HFP。

1.3     HFP初始化

sinkHfpInit();à

HfpInit(); à

lHfp->task.handler = hfpProfileHandler;

hfpServicesInit();

hfpServiceChannelRegister(theHfp->services);à CL_RFCOMM_REGISTER_CFM

hfpProfileHandler()àcase CL_RFCOMM_REGISTER_CFM:à

hfpInitRfcommRegisterCfm();à

hfpRegisterServiceRecord(service); à/* registering an SDP record */

hfpServiceChannelRegister(service); /* Register RFCOMM channel for next service */

hfpProfileHandler()àcase CL_SDP_REGISTER_CFM:à

hfpInitSdpRegisterCfm()à

hfpInitSdpRegisterComplete()à

hfpInitCfmToApp(); à

MessageSend(theHfp->clientTask, HFP_INIT_CFM, message);

1.4     杂散外设初始化

HFP初始化完毕之后,HFP任务发送HFP_INIT_CFM信号给ClientTask,ClientTask在接收到该信号后,进行后续的一些杂散外设(如LCD,LED,USB)的初始化,以及一些必要的扫尾工作,这些初始化工作主要有下面两个调用完成。

InitEarlyUserFeatures();  |  sinkInitComplete();

InitEarlyUserFeatures();à

buttonManagerInit();

configManagerInit(TRUE); à/* Once system Managers initialized, load up configuration */

InitA2dp();

usbInit();

displayInit();

dutInit();

stateManagerEnterLimboState();

sinkInitComplete()à

RegisterDeviceIdServiceRecord();

sinkAvrcpInit();           /* initialize the AVRCP library */

InitUserFeatures(); àLedManagerEnableLEDS ();|MessageSystemTask(&theSink.task);|

MessageSend( &theSink.task , EventUsrPowerOn , NULL ) ;  /*Power on*/

sinkBleInitialiseDevice();   /* Perform BLE Initialization */

sinkAncInit();                /* Initialize ANC */

1.5     开机操作

case (EventUsrPowerOn):

stateManagerPowerOn();à

PioSetPowerPin ( TRUE ) ;

stateManagerEnterConnectableState( TRUE );

if(theSink.features.PairIfPDLLessThan

|| theSink.features.AutoReconnectPowerOn

|| theSink.panic_reconnect)à

MessageSend(&theSink.task, EventSysEnterPairingEmptyPDL, 0);

MessageSend(&theSink.task, EventUsrRssiPair, 0);

sinkBlePowerOnEvent();   /* Power on BLE */

stateManagerEnterConnectableState();à

sinkEnableConnectable();

stateManagerSetState ( deviceConnectable ) ;

if ( theSink.features.pair_mode_en )  /*if we want to auto enter pairing mode*/

stateManagerEnterConnDiscoverableState( req_disc );à

sinkEnableConnectable();  /* Make the device connectable */

sinkEnableDiscoverable();  /* Make the device discoverable */

stateManagerSetState(deviceConnDiscoverable);

当系统检测到A2DP或者SLC(HFP)链路断开时,或者设备开启了手动进入连接配对功能时,设备自动进入重连状态,其会从PDL中按顺序寻找可能的设备进行连接。具体调用关系是:首先调用sinkEnableMultipointConnectable()让设备进入可连接状态,然后向主任务先后发送两个用户信号: EventUsrEnterPairing, EventUsrEstablishSLC,前者的回调函数会设备进入可连接,可发现状态;后者会试图建立SLC连接。

sinkHandleSlcDisconnectInd()à

handleA2DPSignallingDisconnected()à

ButtonsLevelDetect()àif(theSink.features.GoConnectableButtonPress)à

sinkEnableMultipointConnectable();à

if((theSink.MultipointEnable)&&(stateManagerGetState() != deviceLimbo))

sinkEnableConnectable();  /* make device connectable */

/*Who sends EventUsrEnterPairing and EventUsrEstablishSLC msgs to the apptask???*/

MessageSend(&theSink.task, EventUsrEnterPairing, 0);

MessageSend(&theSink.task, EventUsrEstablishSLC, 0);

case (EventUsrEnterPairing):à

stateManagerEnterConnDiscoverableState( TRUE );

case ( EventUsrEstablishSLC ) :à

slcEstablishSLCRequest() ;

slcEstablishSLCRequest()首先获取PDL大小,然后取出首个已配对设备,判断其支持的profile是否被当前设备支持,是则尝试进行连接,否则发送信号通知apptask开始继续SLC连接(EventSysContinueSlcConnectRequest),无论连接成功与否,BlueStack都会通过信号返回此次连接的结果(HFP_SLC_CONNECT_CFM)。

slcEstablishSLCRequest() ;à

gSlcData.gListID = 0;

gSlcData.gPdlSize = ConnectionTrustedDeviceListSize();

slcIsListIdAvailable(gSlcData.gListID); gSlcData.gListID++;

slcAttemptConnection();à

if(attributes.profiles & (sink_hfp | sink_a2dp | sink_avrcp))

slcConnectDevice(&ag_addr.addr, attributes.profiles);

else

MessageSend(&theSink.task, EventSysContinueSlcConnectRequest, 0);

case EventSysContinueSlcConnectRequest:

slcContinueEstablishSLCRequest();à   /* attempt next connection */

slcGetNextListID();

slcAttemptConnection();

slcConnectDevice(&ag_addr.addr, attributes.profiles);à

HfpSlcConnectRequest(bd_addr, hfp_handsfree_and_headset, hfp_handsfree_all);

A2dpSignallingConnectRequest(bd_addr);

1.6     客户主动发起连接

当设备powerOn过程中会自动进入connectable模式,并试图连接PDL中设备,同样,在用户干预(对应按键按下,GAIA操作等)控制设备进入connectable&discoverable模式时,也会试图连接PDL中设备,当前两者操作都没有可以连接配对设备时,设备在connectable &discoverable状态会驻留一段时间,等待客户设备主动发起连接。对于到来的的客户连接请求,服务器首先会进行能力的交互,然后进行认证和鉴权流程,如果认证通过,双方建立其一条ACL链路,并通知上层应用。

手册CS-207482-UGP5_WritingBlueCoreApplication.pdf中例举了如何在两个蓝牙设备之间建立ACL链路,在该例子中,应用层使用L2CAP协议,使用简单的Just works的认证机制,其涉及到的消息以及API如下图所示:

ACL connection,Request IO Capability,Link Authenticated,L2CAP Connection等都是由BlueStack主动发起的,无需应用层干预。

在ADK的sink例程中,认证结束后,将当前已连接设备加入PDL,并通知应用层配对成功。

case CL_SM_AUTHENTICATE_CFM:

sinkHandleAuthenticateCfm();à

deviceManagerMarkTrusted(&cfm->bd_addr);

MessageSend (&theSink.task , EventSysPairingSuccessful , 0 );

case ( EventSysPairingSuccessful):

stateManagerEnterConnectableState(FALSE);  /*SM:[ConnDisc]->[Connectable]*/

之后BlueStack通知设备,A2DP连接建立成功。其对应的角色以及消息发送流程如图所示:

case A2DP_SIGNALLING_CONNECT_CFM:

handleA2DPSignallingConnected();à

MessageSend(&theSink.task,  EventSysA2dpConnected, 0);

connectA2dpStream( priority, D_SEC(5) );à

connectA2dpStream();à

openStream(priority, 0);

同时开启HFP连接,BlueStack首先发送CL_RFCOMM_CONNECT_IND信号给HFP库,HFP库随后通过HFP_SLC_CONNECT_IND信号通知应用层是否接受当前RFCOMM连接,随后依次进行一些HFP参数相关的交互,在应用层接收到HFP_SLC_CONNECT_CFM后,正式确认HFP连接成功。

case HFP_SLC_CONNECT_CFM:

sinkHandleSlcConnectCfm((HFP_SLC_CONNECT_CFM_T *) message);à

slcConnectionComplete();   /*Handle new connection setup */

slcConnectionSetup();   /* Handle common setup for new SLC/link loss */

MessageSendLater ( &theSink.task , EventSysCheckForAudioTransfer , 0 , 5000 ) ;

MessageSend (&theSink.task , EventSysSLCConnected , NULL );

至此,连接过程完成,设备处于已连接状态,随时接收到来的A2DP和HFP数据流请求。

十一、设备初始化(ADK4.0)的更多相关文章

  1. linux PCI设备初始化过程

    linux PCI设备初始化过程 start_kernel->rest_init 这个函数会启动一个核心线程0, 核心线程然后调用init -> do_basic_setup. 然后我们开 ...

  2. rt-thread 之组件与设备初始化配置

    @2019-03-08 [小记] rt-thread 初始化配置有两个分支: 第一,板级设备初始化 rt_components_board_init() 第二,内核组件初始化 rt_component ...

  3. linux内核中经常用到的设备初始化宏

    内核使用了大量不同的宏来标记具有不同作用的函数和数据结构.如宏__init.__devinit等.这些宏在include/linux/init.h头文件中定义.编译器通过这些宏可以把代码优化放到合适的 ...

  4. Nouveau源代码分析(三):NVIDIA设备初始化之nouveau_drm_probe

    Nouveau源代码分析(三) 向DRM注冊了Nouveau驱动之后,内核中的PCI模块就会扫描全部没有相应驱动的设备,然后和nouveau_drm_pci_table对比. 对于匹配的设备,PCI模 ...

  5. java Class的Long id初始化 为0的问题android数据库操做出现的 android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed

    java的class中的Long类型变量调用默认的 构造函数new后会被初始化为0. 这句话大家可能感觉这么低级的事情还用你说? 我想说的是这个会产生的一个应用场景 和 避免方法 场景:db插入时候p ...

  6. Towelroot v3.0版发布 将支持更多设备 Towelroot v3.0下载

    Towelroot虽然已经发布一段时间了,虽然所Towelroot可以一键ROOT很多设备,虽然它只有100多K.不过还是有一小部分的机型没办法ROOT成功的,也不知道什么原因.不过不用担心,Geoh ...

  7. Swift从入门到精通第十一篇 - 初始化 初识

    初始化(学习笔记) 环境Xcode 11.0 beta4 swift 5.1 初始化 初始化是类.结构体.枚举生成实例的过程,为该类的每个存储属性设置初始值,有些在实例使用前的设置或初始化也可在此实现 ...

  8. linux设备驱动程序-i2c(0)-i2c设备驱动源码实现

    (基于4.14内核版本) 为了梳理清楚linux内核中的i2c实现框架,从本文开始,博主将分几个章节分别解析i2c总线在linux内核中的形成过程.匹配过程.以及设备驱动程序源码实现. 在介绍linu ...

  9. 第十一章 Net 5.0 快速开发框架 YC.Boilerplate --图数据库模块Neo4j

    在线文档:http://doc.yc-l.com/#/README 在线演示地址:http://yc.yc-l.com/#/login 源码github:https://github.com/linb ...

随机推荐

  1. 8.Linux用户管理(上)

    1.什么是用户? 能正常登陆系统的都算用户 windows系统和linux系统的用户有什么区别? 本质上没有区别, linux支持多个用户同一时刻登陆系统, 互相之间不影响 而windows只允许同一 ...

  2. Mybaits 源码解析 (一)----- 搭建一个mybatis框架(MyBatis HelloWorld)

    源码分析之前先搭一个mybatis的demo,这个在看源码的时候能起到了很大的作用,因为在看源码的时候,会恍然大悟,为什么要这么配置,为什么要这么写.(老鸟可以跳过这篇) 开发环境的准备 创建mave ...

  3. Kubernetes入门学习--在Ubuntu16.0.4安装配置Minikube

    目 录 一. 安装minikube环境 1.1. 安装前准备 1.2. 安装Lantern 1.2.1. Lantern下载网站 1.2.2. Lantern下载地址 1.2.3. Lantern安装 ...

  4. navicat cannot load oci dll||oracle 改字符集为GBK后 navicat 连不上||Ora-28547 ora net错误

    此段适用于 解决 navicat cannot load oci dll 环境 Navicat Premium  和 oracle 原因,navicat 32 和64 都只支持 32位的oci.dll ...

  5. 数据结构(三十三)最小生成树(Prim、Kruskal)

    一.最小生成树的定义 一个连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树的n-1条边. 在一个网的所有生成树中,权值总和最小的生成树称为最小代价生成树(Minimum ...

  6. SpringBoot整合MybatisPlus3.X之分页插件(四)

    注:详细请看2.X博客中,3.X直接上代码. 建议装一个MybatisX插件,可以在Mapper和Xml来回切换 pom.xml <dependencies> <dependency ...

  7. SOLID原则、设计模式适用于Python语言吗

    在阅读 clean architecture的过程中,会发现作者经常提到recompile redeploy,这些术语看起来都跟静态类型语言有关,比如Java.C++.C#.而在我经常使用的pytho ...

  8. SSM简历模板1.0

    张三 xxx-xxxx-xxxx| xxxxxxx@qq.com| 南京 x岁 | 籍贯:江苏 已离职 | 求职意向:java开发工程师 | 期望薪资:面议 专业技能 1.熟悉MVC体系结构模式.B/ ...

  9. Vue运用

    目录结构: ├── README.md 项目介绍 ├── index.html 入口页面 ├── build 构建脚本目录 │   ├── build-server.js 运行本地构建服务器,可以访问 ...

  10. 从函数计算架构看 Serverless 的演进与思考

    作者 | 杨皓然  阿里巴巴高级技术专家 导读:云计算之所以能够成为 DT 时代颠覆性力量,是因为其本质是打破传统架构模式.降低成本并简化体系结构,用全新的思维更好的满足了用户需求.而无服务器计算(S ...