还是从上层的连接开始说起,当点击蓝牙进行配对的时候,调用create_bond开始配对连接
这里来到了btif_dm_create_bond函数中,由于我们刚开始进行绑定,所以绑定状态为BT_BOND_STATE_NONE,如果是其他状态,说明设备正在进行绑定,或者已经绑定成功,直接返回,然后再里面调用btif_dm_generic_evt继续绑定操作,同时传入BTIF_DM_CB_CREATE_BOND这个事件
btif_dm_generic_evt函数中进行参数传递,然后调用btif_dm_cb_create_bond
在函数中判断要连接的设备是不是hid(human interface device)人体接口设备,如果是hid,则另外作特殊处理,这里我们暂时假定不是hid,正常的设备调用BTA_DmBondByTransport继续
在BTA_DmBondByTransport函数中,我们看到了熟悉的一幕,组装evt事件,事件类型为BTA_DM_API_BOND_EVT,然后发送
BTA_DM_API_BOND_EVT的主事件id为BTA_ID_DM,所以选择bta_dm_action函数列表,然后根据子事件id,选择的ACTION是bta_dm_bond函数执行
在bta_dm_bond函数中,因为我们还不能确定绑定连接的设备是classic设备还是ble设备,这里的transport还是unknown,调用BTM_SecBond函数执行,也就是安全绑定,在这个函数最下面,最后调用了bta_dm_cb.p_sec_cback这个回调函数,这个回调我们前面也已经说股,就是bte_dm_evt函数,并且传入了BTA_DM_AUTH_CMPL_EVT事件,也就是认证完成后,调用bte_dm_evt函数处理
来到BTM_SecBond中,继续调用btm_sec_bond_by_transport函数,如果我们没有进行安全连接,则尝试进行配对操作,因为配对过程会进行认证,保证安全,如果是已经配对过的设备,则不需要进行配对,直接返回BTM_SUCCESS,表示连接成功,这里我们继续调用btm_sec_bond_by_transport进行安全绑定连接
btm_sec_bond_by_transport函数首先做一些判断,如果蓝牙设备已经连接并且配对建立链路,则直接返回,然后保存要进行配对的配对码,这里就进入到配对的过程
因为涉及到了配对过程,所以这其中必然会有配对的状态,右图就是配对涉及到的状态,以及配对状态转换的流程,刚开始我们的配对状态为BTM_PAIR_STATE_IDLE
由于我们要进行安全连接,所以这里还有一个安全性连接标志,在我们最开始启动security的时候,初始化为BTM_SEC_IN_USE,表示启动安全性绑定连接
我们前面的连接流程介绍过,第二个步骤会进行feature exchange,这个步骤是可选的,所以这里如果我们没有获取到对方特性feature,就去获取对方蓝牙设备的名称,将配对状态改为获取远端蓝牙设备,也就是BTM_PAIR_STATE_GET_REM_NAME,同时调用BTM_ReadRemoteDeviceName函数获取远端蓝牙设备名称,同时,如果前面的步骤都完成了,则直接进行安全认证,将配对状态改为等待pin码输入,也就是BTM_PAIR_STATE_WAIT_PIN_REQ
这里我们来看下RNR,在里面调用btm_initiate_rem_name函数
在这里我们发送命令不仅仅只是获取了对端蓝牙设备的名称,也包含了获取对端蓝牙设备其他的特性,也就是我们的连接流程中的第二步,feature exchange,那么这个时候,controller会上报hci remote host supported features notification事件
controller上报的event都由btu_hcif_process_event处理,在这里事件类型为HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT,调用btu_hcif_host_support_evt函数来处理
继续调用btm_sec_rmt_host_support_feat_evt
在这个函数中,最重要的一件是就是看对方蓝牙设备是否支持ssp(安全简单配对),如果支持ssp,sm4=4,这个也是我们蓝牙连接流程第二步feature exchange中所要做的事件,正好相吻合
之前我们进行RNR的时候获取对端蓝牙设备名称,那么这里对端蓝牙设备还需要返回该请求的响应,也就是HCI_RMT_NAME_REQUEST_COMP_EVT,代表RNR的完成