当前位置:   article > 正文

蓝牙协议栈源码分析(1)_ACL数据上行处理流程_hci蓝牙源码

hci蓝牙源码

本文主要讲解Android端Bluetooth Stack(Fluoride),接收到蓝牙Controller上报的ACL链路数据后在蓝牙协议栈的处理流程,如下图。

 

ACL:  异步无连接(Asynchronous Connection-oriented Link[logical transport]),主要用于分组数据传送,比如车载场景连接手机蓝牙时。

L2CAP:  逻辑链路控制和适配协议(Logical Link Control and Adaptation Protocol),负责管理逻辑层提供的逻辑链路。基于该协议不同应用可共享同一个逻辑链路。

BTU :     Bluetooth Upper Layer,This is the main task of the Bluetooth Upper Layers unit. It sits in aloop waiting for messages, and dispatches them to the appropiate handlers.

BTA :     Bluetooth application layer

Phy:   蓝牙物理层

代码流程分析:

1、HCI_layer处理流程

对接蓝牙驱动接收数据,接收从controller传来的ACL Data

hci_layer_android.cc

  1. class BluetoothHciCallbacks : public IBluetoothHciCallbacks {
  2.    ......
  3.   Return<void> initializationComplete(Status status) {
  4.     CHECK(status == Status::SUCCESS);
  5.     initialization_complete();
  6.     return Void();
  7.   }
  8.   Return<void> hciEventReceived(const hidl_vec<uint8_t>& event) {
  9.     BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_EVT, event);
  10.     hci_event_received(FROM_HERE, packet);
  11.     return Void();
  12.   }
  13.   // 接收到controller传来的ACL Data
  14.   Return<void> aclDataReceived(const hidl_vec<uint8_t>& data) {
  15.     BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_ACL, data);
  16.     acl_event_received(packet);
  17.     return Void();
  18.   }
  19.   Return<void> scoDataReceived(const hidl_vec<uint8_t>& data) {
  20.     BT_HDR* packet = WrapPacketAndCopy(MSG_HC_TO_STACK_HCI_SCO, data);
  21.     sco_data_received(packet);
  22.     return Void();
  23.   }
  24.   ......
  25. };

将数据进行重组、分发

通过注册的callback分发至上层模块

hci_layer.cc

  1. void acl_event_received(BT_HDR* packet) {
  2.   btsnoop->capture(packet, true);
  3.   packet_fragmenter->reassemble_and_dispatch(packet);
  4. }
  5. // Callback for the fragmenter to dispatch up a completely reassembled packet
  6. static void dispatch_reassembled(BT_HDR* packet) {
  7.   // Events should already have been dispatched before this point
  8.   CHECK((packet->event & MSG_EVT_MASK) != MSG_HC_TO_STACK_HCI_EVT);
  9.   CHECK(!send_data_upwards.is_null());
  10.   send_data_upwards.Run(FROM_HERE, packet);
  11. }

该回调的注册地方是在bte初始化启动的时候,通过 hci->set_data_cb注册数据接收callback。

bte_main.cc

  1. void bte_main_boot_entry(void) {
  2.   module_init(get_module(INTEROP_MODULE));
  3.   module_init(get_module(PROFILE_CONFIG_MODULE));
  4.   hci = hci_layer_get_interface();
  5.   if (!hci) {
  6.     LOG_ERROR(LOG_TAG, "%s could not get hci layer interface.", __func__);
  7.     return;
  8.   }
  9.   hci->set_data_cb(base::Bind(&post_to_hci_message_loop));
  10.   module_init(get_module(STACK_CONFIG_MODULE));
  11. }

对应的callback回调处理函数

  1. void post_to_hci_message_loop(const tracked_objects::Location& from_here,
  2.                               BT_HDR* p_msg) {
  3.   ......
  4.   hci_message_loop->task_runner()->PostTask(
  5.       from_here, base::Bind(&btu_hci_msg_process, p_msg));
  6.   ......  
  7. }

2、BTU处理流程

将Acl数据传递至L2CAP层处理

btu_task.cc

  1. void btu_hci_msg_process(BT_HDR* p_msg) {
  2. /* Determine the input message type. */
  3.   switch (p_msg->event & BT_EVT_MASK) {
  4.     case BT_EVT_TO_BTU_HCI_ACL:
  5.       /* All Acl Data goes to L2CAP */
  6.       l2c_rcv_acl_data(p_msg);
  7.       break;
  8.    ......
  9.   }
  10. }

3、L2CAP层处理

先根据handle查找到对应的LCB(link control block,定义参考下面代码),之后再根据CID取出对应CCB(channel control block,定义参考下面代码),最后通过来L2CAP状态机处理数据。

l2c_main.cc

  1. void l2c_rcv_acl_data(BT_HDR* p_msg) {
  2.   tL2C_LCB* p_lcb;
  3.   tL2C_CCB* p_ccb = NULL;
  4.   ......
  5.   /* Find the LCB based on the handle */
  6.   p_lcb = l2cu_find_lcb_by_handle(handle);
  7.   /* Look through all active CCBs on a link for a match based
  8.    * on the local CID. If passed the link pointer is NULL, all
  9.    * active links are searched. the CCB for this CID */
  10.   p_ccb = l2cu_find_ccb_by_cid(p_lcb, rcv_cid);     
  11.   ......
  12.   
  13.   /* Basic mode packets go straight to the state machine */
  14.   if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE)
  15.       l2c_csm_execute(p_ccb, L2CEVT_L2CAP_DATA, p_msg);
  16.   else {
  17.        /* eRTM or streaming mode, so we need to validate states first */
  18.        if ((p_ccb->chnl_state == CST_OPEN) ||
  19.            (p_ccb->chnl_state == CST_CONFIG))
  20.            l2c_fcr_proc_pdu(p_ccb, p_msg);
  21.        else
  22.            osi_free(p_msg);
  23.    }
  24.    ......
  25. }

tL2C_LCB及tL2C_CCB的定义如下,两者的关系是一个LCB中可以有多个CCB通过不同的CID区分。

  1. /* Define a link control block. There is one link control block between
  2.  * this device and any other device (i.e. BD ADDR).
  3.  */
  4. typedef struct t_l2c_linkcb {
  5.   bool in_use/* true when in use, false when not */
  6.   tL2C_LINK_STATE link_state;
  7.   uint16_t handle;        /* The handle used with LM */
  8.   tL2C_CCB_Q ccb_queue; /* Queue of CCBs on this LCB */
  9.   tL2C_CCB* p_pending_ccb;  /* ccb of waiting channel during link disconnect */
  10.   alarm_t* info_resp_timer; /* Timer entry for info resp timeout evt */
  11.   RawAddress remote_bd_addr; /* The BD address of the remote */
  12.   uint8_t link_role; /* Master or slave */
  13.   ......
  14. } tL2C_LCB;
  15. /* Define a channel control block (CCB). There may be many channel control
  16.  * blocks between the same two Bluetooth devices (i.e. on the same link).
  17.  * Each CCB has unique local and remote CIDs. All channel control blocks on
  18.  * the same physical link and are chained together.
  19.  */
  20. typedef struct t_l2c_ccb {
  21.   ......
  22.   tL2C_CHNL_STATE chnl_state; /* Channel state */
  23.   uint16_t local_cid;  /* Local CID */
  24.   uint16_t remote_cid; /* Remote CID */
  25.   tL2C_RCB* p_rcb;      /* Registration CB for this Channel */
  26.   ......
  27. } tL2C_CCB;
  28. typedef struct {
  29.   bool in_use;
  30.   uint16_t psm;
  31.   uint16_t real_psm; /* This may be a dummy RCB for an o/b connection but */
  32.                      /* this is the real PSM that we need to connect to */
  33. #if (L2CAP_UCD_INCLUDED == TRUE)
  34.   tL2C_UCD_REG ucd;
  35. #endif
  36.   tL2CAP_APPL_INFO api;
  37. } tL2C_RCB;
  38. typedef struct {
  39.   tL2CA_CONNECT_IND_CB* pL2CA_ConnectInd_Cb;
  40.   tL2CA_CONNECT_CFM_CB* pL2CA_ConnectCfm_Cb;
  41.   tL2CA_CONNECT_PND_CB* pL2CA_ConnectPnd_Cb;
  42.   tL2CA_CONFIG_IND_CB* pL2CA_ConfigInd_Cb;
  43.   tL2CA_CONFIG_CFM_CB* pL2CA_ConfigCfm_Cb;
  44.   tL2CA_DISCONNECT_IND_CB* pL2CA_DisconnectInd_Cb;
  45.   tL2CA_DISCONNECT_CFM_CB* pL2CA_DisconnectCfm_Cb;
  46.   tL2CA_QOS_VIOLATION_IND_CB* pL2CA_QoSViolationInd_Cb;
  47.   tL2CA_DATA_IND_CB* pL2CA_DataInd_Cb;
  48.   tL2CA_CONGESTION_STATUS_CB* pL2CA_CongestionStatus_Cb;
  49.   tL2CA_TX_COMPLETE_CB* pL2CA_TxComplete_Cb;
  50. } tL2CAP_APPL_INFO;

L2CAP状态机处理函数

l2c_csm.cc

  1. // This function executes the state machine. 
  2. void l2c_csm_execute(tL2C_CCB* p_ccb, uint16_t event, void* p_data) {
  3.     ......
  4.     switch (p_ccb->chnl_state) {
  5.       case CST_OPEN:
  6.         l2c_csm_open(p_ccb, event, p_data);
  7.         break;
  8.     ......
  9. }

Android L2CAP 定义的state及event如下:(图源网络,侵权可联系作者删除)
img

通过pL2CA_DataInd_Cb将数据回调到RFCOMM

  1. // This function handles events when the channel is in OPEN state. 
  2. static void l2c_csm_open(tL2C_CCB* p_ccb, uint16_t event, void* p_data) {
  3.    ......
  4.    case L2CEVT_L2CAP_DATA/* Peer data packet rcvd */
  5.       if ((p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_DataInd_Cb))
  6.         (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid,
  7.                                               (BT_HDR*)p_data);
  8.       break;
  9.    ......
  10. }

在RFCOMM task开启时会向L2CAP注册该pL2CA_DataInd_Cb回调接口

rfc_l2cap_if.cc

  1. void rfcomm_l2cap_if_init(void) {
  2. tL2CAP_APPL_INFO* p_l2c = &rfc_cb.rfc.reg_info;
  3. p_l2c->pL2CA_ConnectInd_Cb = RFCOMM_ConnectInd;
  4. p_l2c->pL2CA_ConnectCfm_Cb = RFCOMM_ConnectCnf;
  5. p_l2c->pL2CA_ConnectPnd_Cb = NULL;
  6. p_l2c->pL2CA_ConfigInd_Cb = RFCOMM_ConfigInd;
  7. p_l2c->pL2CA_ConfigCfm_Cb = RFCOMM_ConfigCnf;
  8. p_l2c->pL2CA_DisconnectInd_Cb = RFCOMM_DisconnectInd;
  9. p_l2c->pL2CA_DisconnectCfm_Cb = NULL;
  10. p_l2c->pL2CA_QoSViolationInd_Cb = RFCOMM_QoSViolationInd;
  11. p_l2c->pL2CA_DataInd_Cb = RFCOMM_BufDataInd;
  12. p_l2c->pL2CA_CongestionStatus_Cb = RFCOMM_CongestionStatusInd;
  13. p_l2c->pL2CA_TxComplete_Cb = NULL;
  14. L2CA_Register(BT_PSM_RFCOMM, p_l2c);
  15. }

4、RFCOMM层处理

通过RFCOMM 状态机处理数据

  1. void RFCOMM_BufDataInd(uint16_t lcid, BT_HDR* p_buf) {
  2. ......
  3.   event = rfc_parse_data(p_mcb, &rfc_cb.rfc.rx_frame, p_buf);
  4.   p_port = port_find_dlci_port(rfc_cb.rfc.rx_frame.dlci);
  5.   rfc_port_sm_execute(p_port, event, p_buf);
  6. ...... 
  7. }

RFCOMM 状态机处理函数

rfc_port_fsm.cc

  1. void rfc_port_sm_execute(tPORT* p_port, uint16_t eventvoid* p_data) {
  2. ......
  3.     case RFC_STATE_OPENED:
  4.       rfc_port_sm_opened(p_port, event, p_data);
  5.       break;
  6. ......
  7. }

Android定义的RFCOMM Port State如下:

RFCOMM Port State描述
RFC_STATE_CLOSED
RFC_STATE_SABME_WAIT_UA
RFC_STATE_ORIG_WAIT_SEC_CHECK
RFC_STATE_TERM_WAIT_SEC_CHECK
RFC_STATE_OPENED
RFC_STATE_DISC_WAIT_UA

跟据不同的event类型执行逻辑

  1. void rfc_port_sm_opened(tPORT* p_port, uint16_t eventvoid* p_data) {
  2.   switch (event) {
  3.   ......
  4.     case RFC_EVENT_UIH:
  5.       rfc_port_uplink_data(p_port, (BT_HDR*)p_data);
  6.       return;
  7.   ......
  8.   }
  9. }

Android定义的RFCOMM支持的帧(Frame)类型如下

类型描述
RFC_EVENT_OPEN
RFC_EVENT_CLOSE
RFC_EVENT_CLEAR
RFC_EVENT_DATA
RFC_EVENT_TIMEOUT
RFC_EVENT_SABMSet Asynchronous Balanced Mode (startup command)
RFC_EVENT_UAUnnumbered Acknowledgement (response when connected)
RFC_EVENT_DISCDisconnect (disconect command)
RFC_EVENT_DMDisconnected Mode (response to a command when disconected)
RFC_EVENT_UIHUnnumbered Information with Header check
  1. void rfc_port_uplink_data(tPORT* p_port, BT_HDR* p_buf) {
  2.   PORT_DataInd(p_port->rfc.p_mcb, p_port->dlci, p_buf);
  3. }

当从对等方接收到数据缓冲区时,从RFCOMM层调用此函数。

通过数据链路连接标识符(DLCI,Data Link Connection Identifier)找到对应的port,安卓支持最多30个port。

然后通过callback回调给上层应用。

port_rfc.cc

  1. void PORT_DataInd(tRFC_MCB* p_mcb, uint8_t dlci, BT_HDR* p_buf) {
  2.    tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
  3.   
  4.   /* If client registered callout callback with flow control we can just deliver
  5.    * receive data */
  6.   if (p_port->p_data_co_callback) {
  7.     /* Another packet is delivered to user. Send credits to peer if required */
  8.     if (p_port->p_data_co_callback(p_port->inx, (uint8_t*)p_buf, -1,
  9.                                    DATA_CO_CALLBACK_TYPE_INCOMING)) {
  10.       port_flow_control_peer(p_port, true1);
  11.     } else {
  12.       port_flow_control_peer(p_port, false0);
  13.     }
  14.     // osi_free(p_buf);
  15.     return;
  16.   }
  17.     
  18.   /* If client registered callback we can just deliver receive data */
  19.   if (p_port->p_data_callback) {
  20.     /* Another packet is delivered to user. Send credits to peer if required */
  21.     port_flow_control_peer(p_port, true1);
  22.     p_port->p_data_callback(p_port->inx, (uint8_t*)(p_buf + 1) + p_buf->offset,
  23.                             p_buf->len);
  24.     osi_free(p_buf);
  25.     return;
  26.   }
  27.   
  28.   if (p_port->p_callback && events) p_port->p_callback(events, p_port->inx);
  29. }

5、应用层处理逻辑

以AG为例子上层应用注册PORT Callback的地方是在AG服务初始时。

bta_ag_rfc.cc

  1. // Setup RFCOMM port for use by AG.
  2. void bta_ag_setup_port(tBTA_AG_SCB* p_scb, uint16_t handle) {
  3.   uint16_t i = bta_ag_scb_to_idx(p_scb) - 1;
  4.   /* set up data callback if using pass through mode */
  5.   if (bta_ag_cb.parse_mode == BTA_AG_PASS_THROUGH) {
  6.     PORT_SetDataCallback(handle, bta_ag_data_cback_tbl[i]);
  7.   }
  8.   PORT_SetEventMask(handle, BTA_AG_PORT_EV_MASK);
  9.   PORT_SetEventCallback(handle, bta_ag_port_cback_tbl[i]);
  10. }
  1. int PORT_SetEventCallback(uint16_t port_handle, tPORT_CALLBACK* p_port_cb) {
  2. .....
  3. p_port = &rfc_cb.port.port[port_handle - 1];
  4. p_port->p_callback = p_port_cb;
  5. .....
  6. }

bta_ag_port_cback_tbl定义如下

  1. const tBTA_AG_PORT_CBACK bta_ag_port_cback_tbl[] = {
  2.     bta_ag_port_cback_1, bta_ag_port_cback_2, bta_ag_port_cback_3};

实现为如下函数:

该函数用来处理RFCOMM Port callback,会发送一个BTA_AG_RFC_DATA_EVT消息,参考bta_sys_sendmsg的传输流程请看《BTA消息分发流程》,最终会调用到bta_ag_sm_execute函数

bta_ag_rfc.cc

  1. static void bta_ag_port_cback(UNUSED_ATTR uint32_t code, uint16_t port_handle,
  2.                               uint16_t handle) {
  3.    .......
  4.    BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
  5.    p_buf->event = BTA_AG_RFC_DATA_EVT;
  6.    p_buf->layer_specific = handle;
  7.    bta_sys_sendmsg(p_buf);
  8.    .......
  9. }

bta ag 状态机执行函数,这一步的操作是:

1、取出当前状态的event-action关联表,

2、获取当前event对应的state,设置为下一个state;

3、执行当前event对应的action;

bta_ag_main.cc

  1. void bta_ag_sm_execute(tBTA_AG_SCB* p_scb, uint16_t event,
  2.                        tBTA_AG_DATA* p_data) {
  3.     
  4.   /* look up the state table for the current state */
  5.   state_table = bta_ag_st_tbl[p_scb->state];
  6.   /* set next state */
  7.   p_scb->state = state_table[event][BTA_AG_NEXT_STATE];
  8.   /* execute action functions */
  9.   for (i = 0; i < BTA_AG_ACTIONS; i++) {
  10.     action = state_table[event][i];
  11.     if (action != BTA_AG_IGNORE) {
  12.       (*bta_ag_action[action])(p_scb, p_data);
  13.     } else {
  14.       break;
  15.     }
  16.   }
  17.   ......
  18. }

BTA_AG中定义了4个状态,其中每个状态还定义了每个Event对应的Action1、Action 2及Next State

  1. /* state table */
  2. const tBTA_AG_ST_TBL bta_ag_st_tbl[] = {bta_ag_st_init, bta_ag_st_opening,
  3.                                         bta_ag_st_open, bta_ag_st_closing};

读取并处理来自RFCOMM的数据

bta_ag_act.cc

  1. void bta_ag_rfc_data(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
  2.   ...
  3.   /* do the following */
  4.   for (;;) {
  5.     /* read data from rfcomm; if bad status, we're done */
  6.     if (PORT_ReadData(p_scb->conn_handle, buf, BTA_AG_RFC_READ_MAX, &len) !=
  7.         PORT_SUCCESS) {
  8.       break;
  9.     }
  10.     ...
  11.     /* run AT command interpreter on data */
  12.     bta_ag_at_parse(&p_scb->at_cb, buf, len);
  13.     if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) &&
  14.         bta_ag_sco_is_open(p_scb)) {
  15.       APPL_TRACE_IMP("%s change link policy for SCO", __func__);
  16.       bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
  17.     } else {
  18.       if (strstr(buf, "AT+IPHONEACCEV") != NULL) {
  19.           APPL_TRACE_IMP("%s: AT+IPHONEACCEV received, not setting idle", __func__);
  20.       } else {
  21.           APPL_TRACE_IMP("%s: resetting idle timer", __func__);
  22.           bta_sys_idle(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
  23.       }
  24.     }
  25.     /* no more data to read, we're done */
  26.     if (len < BTA_AG_RFC_READ_MAX) {
  27.       break;
  28.     }
  29.   }
  30. }

 解析RFCOMM上报的AT指令,未完待续。

  1. /**
  2.  * Parse AT commands. This function will take the input character string and parse it * * for AT commands according to the AT command table passed in the control block.
  3.  **/
  4. void bta_ag_process_at(tBTA_AG_AT_CB* p_cb) {
  5.     ......
  6.     /* if arguments match command capabilities */
  7.     if ((arg_type & p_cb->p_at_tbl[idx].arg_type) != 0) {
  8.       /* if it's a set integer check max, min range */
  9.       if (arg_type == BTA_AG_AT_SET &&
  10.           p_cb->p_at_tbl[idx].fmt == BTA_AG_AT_INT) {
  11.         int_arg = utl_str2int(p_arg);
  12.         if (int_arg < (int16_t)p_cb->p_at_tbl[idx].min ||
  13.             int_arg > (int16_t)p_cb->p_at_tbl[idx].max) {
  14.           /* arg out of range; error */
  15.           (*p_cb->p_err_cback)(p_cb->p_user, false, NULL);
  16.         } else {
  17.           (*p_cb->p_cmd_cback)(p_cb->p_user, p_cb->p_at_tbl[idx].command_id,
  18.                                arg_type, p_arg, int_arg);
  19.         }
  20.       } else {
  21.         (*p_cb->p_cmd_cback)(p_cb->p_user, p_cb->p_at_tbl[idx].command_id,
  22.                              arg_type, p_arg, int_arg);
  23.       }
  24.     }
  25.    ......
  26. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/192274
推荐阅读
相关标签
  

闽ICP备14008679号