我是靠谱客的博主 结实毛豆,最近开发中收集的这篇文章主要介绍蓝牙协议栈接收数据包流程1,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

void l2c_rcv_acl_data(BT_HDR* p_msg) 
{
  L2CAP_TRACE_WARNING("L2CAP - l2c_rcv_acl_data");
  uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
  //指向消息的数据域
  macdbg_dmphex_kernel((const char*)p_msg->data, p_msg->len );
  L2CAP_TRACE_WARNING("p_msg->offset = %x", p_msg->offset);

  if ((p_ccb->chnl_state == CST_OPEN) || (p_ccb->chnl_state == CST_CONFIG)){
        l2c_fcr_proc_pdu(p_ccb, p_msg);
        L2CAP_TRACE_WARNING("p_lcb = 1q5" );
      }else{
        L2CAP_TRACE_WARNING("p_lcb = 1q6" );
        osi_free(p_msg);
      }
  
  
  
  l2c_fcr_proc_pdu()
  
  
  L2c_fcr.cc
  void l2c_fcr_proc_pdu(tL2C_CCB* p_ccb, BT_HDR* p_buf) 
{                         
  CHECK(p_ccb != NULL);      
  CHECK(p_buf != NULL);
  uint8_t* p;
  uint16_t fcs;
  

static void process_i_frame(tL2C_CCB* p_ccb, BT_HDR* p_buf, uint16_t ctrl_word,
                            bool delay_ack) {
                            

static bool do_sar_reassembly(tL2C_CCB* p_ccb, BT_HDR* p_buf,
                              uint16_t ctrl_word) {
                              
L2c_csm.cc                              
void l2c_csm_execute(tL2C_CCB* p_ccb, uint16_t event, void* p_data) {
  if (!l2cu_is_ccb_active(p_ccb)) {
    L2CAP_TRACE_WARNING("%s CCB not in use, event (%d) cannot be processed",
                        __func__, event);
    return;
  }


  L2CAP_TRACE_ERROR("p_ccb->chnl_state = %x", p_ccb->chnl_state );
  

  switch (p_ccb->chnl_state) {
    case CST_CLOSED:
      l2c_csm_closed(p_ccb, event, p_data);
      break;

    case CST_ORIG_W4_SEC_COMP:
      l2c_csm_orig_w4_sec_comp(p_ccb, event, p_data);
      break;

    case CST_TERM_W4_SEC_COMP:
      l2c_csm_term_w4_sec_comp(p_ccb, event, p_data);
      break;

    case CST_W4_L2CAP_CONNECT_RSP:
      l2c_csm_w4_l2cap_connect_rsp(p_ccb, event, p_data);
      break;

    case CST_W4_L2CA_CONNECT_RSP:
      l2c_csm_w4_l2ca_connect_rsp(p_ccb, event, p_data);
      break;

    case CST_CONFIG:
      l2c_csm_config(p_ccb, event, p_data);
      break;

    case CST_OPEN:
      l2c_csm_open(p_ccb, event, p_data);
      break;

    case CST_W4_L2CAP_DISCONNECT_RSP:
      l2c_csm_w4_l2cap_disconnect_rsp(p_ccb, event, p_data);
      break;

    case CST_W4_L2CA_DISCONNECT_RSP:
      l2c_csm_w4_l2ca_disconnect_rsp(p_ccb, event, p_data);
      break;

    default:
      L2CAP_TRACE_DEBUG("Unhandled event! event = %d", event);
      break;
  }
}
                            
  

static void l2c_csm_open(tL2C_CCB* p_ccb, uint16_t event, void* p_data) {
  uint16_t local_cid = p_ccb->local_cid;
  tL2CAP_CFG_INFO* p_cfg;
  tL2C_CHNL_STATE tempstate;
  uint8_t tempcfgdone;
  uint8_t cfg_result;
  uint16_t* credit;

  L2CAP_TRACE_ERROR("L2CAP - LCID: 0x%04x  st: OPEN  evt: %s", p_ccb->local_cid,
                    l2c_csm_get_event_name(event));

  switch (event) {
    case L2CEVT_LP_DISCONNECT_IND: /* Link was disconnected */
      L2CAP_TRACE_API(
          "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  No Conf Needed",
          p_ccb->local_cid);
      l2cu_release_ccb(p_ccb);
      if (p_ccb->p_rcb)
        (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(local_cid, false);
      break;

    case L2CEVT_LP_QOS_VIOLATION_IND: /* QOS violation         */
      /* Tell upper layer. If service guaranteed, then clear the channel   */
      if (p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)
        (*p_ccb->p_rcb->api.pL2CA_QoSViolationInd_Cb)(
            p_ccb->p_lcb->remote_bd_addr);
      break;

    case L2CEVT_L2CAP_CONFIG_REQ: /* Peer config request   */
      p_cfg = (tL2CAP_CFG_INFO*)p_data;

      tempstate = p_ccb->chnl_state;
      tempcfgdone = p_ccb->config_done;
      p_ccb->chnl_state = CST_CONFIG;
      p_ccb->config_done &= ~IB_CFG_DONE;

      alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
                         l2c_ccb_timer_timeout, p_ccb);

      cfg_result = l2cu_process_peer_cfg_req(p_ccb, p_cfg);
      if (cfg_result == L2CAP_PEER_CFG_OK) {
        (*p_ccb->p_rcb->api.pL2CA_ConfigInd_Cb)(p_ccb->local_cid, p_cfg);
      }

      /* Error in config parameters: reset state and config flag */
      else if (cfg_result == L2CAP_PEER_CFG_UNACCEPTABLE) {
        alarm_cancel(p_ccb->l2c_ccb_timer);
        p_ccb->chnl_state = tempstate;
        p_ccb->config_done = tempcfgdone;
        l2cu_send_peer_config_rsp(p_ccb, p_cfg);
      } else /* L2CAP_PEER_CFG_DISCONNECT */
      {
        /* Disconnect if channels are incompatible
         * Note this should not occur if reconfigure
         * since this should have never passed original config.
         */
        l2cu_disconnect_chnl(p_ccb);
      }
      break;

    case L2CEVT_L2CAP_DISCONNECT_REQ: /* Peer disconnected request */
      if (p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
        /* Make sure we are not in sniff mode */
        {
          tBTM_PM_PWR_MD settings;
          memset((void*)&settings, 0, sizeof(settings));
          settings.mode = BTM_PM_MD_ACTIVE;
          BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr,
                           &settings);
        }
      }

      p_ccb->chnl_state = CST_W4_L2CA_DISCONNECT_RSP;
      alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
                         l2c_ccb_timer_timeout, p_ccb);
      L2CAP_TRACE_API(
          "L2CAP - Calling Disconnect_Ind_Cb(), CID: 0x%04x  Conf Needed",
          p_ccb->local_cid);
      (*p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb)(p_ccb->local_cid, true);
      break;

    case L2CEVT_L2CAP_DATA: /* Peer data packet rcvd    */

        L2CAP_TRACE_ERROR("L2gh.0" );
        
      if ((p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_DataInd_Cb)){

        L2CAP_TRACE_ERROR("L2gh.1" );
         (*p_ccb->p_rcb->api.pL2CA_DataInd_Cb)(p_ccb->local_cid, (BT_HDR*)p_data);
         //gap_data_ind
      }
      break;

    case L2CEVT_L2CA_DISCONNECT_REQ: /* Upper wants to disconnect */
      if (p_ccb->p_lcb->transport != BT_TRANSPORT_LE) {
        /* Make sure we are not in sniff mode */
        {
          tBTM_PM_PWR_MD settings;
          memset((void*)&settings, 0, sizeof(settings));
          settings.mode = BTM_PM_MD_ACTIVE;
          BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_ccb->p_lcb->remote_bd_addr,
                           &settings);
        }
      }

      if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
        l2cble_send_peer_disc_req(p_ccb);
      else
        l2cu_send_peer_disc_req(p_ccb);

      p_ccb->chnl_state = CST_W4_L2CAP_DISCONNECT_RSP;
      alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_DISCONNECT_TIMEOUT_MS,
                         l2c_ccb_timer_timeout, p_ccb);
      break;

    case L2CEVT_L2CA_DATA_WRITE: /* Upper layer data to send */
      l2c_enqueue_peer_data(p_ccb, (BT_HDR*)p_data);
      l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL);
      break;

    case L2CEVT_L2CA_CONFIG_REQ: /* Upper layer config req   */
      p_ccb->chnl_state = CST_CONFIG;
      p_ccb->config_done &= ~CFG_DONE_MASK;
      l2cu_process_our_cfg_req(p_ccb, (tL2CAP_CFG_INFO*)p_data);
      l2cu_send_peer_config_req(p_ccb, (tL2CAP_CFG_INFO*)p_data);
      alarm_set_on_mloop(p_ccb->l2c_ccb_timer, L2CAP_CHNL_CFG_TIMEOUT_MS,
                         l2c_ccb_timer_timeout, p_ccb);
      break;

    case L2CEVT_TIMEOUT:
      /* Process the monitor/retransmission time-outs in flow control/retrans
       * mode */
      if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
        l2c_fcr_proc_tout(p_ccb);
      break;

    case L2CEVT_ACK_TIMEOUT:
      l2c_fcr_proc_ack_tout(p_ccb);
      break;

    case L2CEVT_L2CA_SEND_FLOW_CONTROL_CREDIT:
      L2CAP_TRACE_DEBUG("%s Sending credit", __func__);
      credit = (uint16_t*)p_data;
      l2cble_send_flow_control_credit(p_ccb, *credit);
      break;

    case L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT:
      credit = (uint16_t*)p_data;
      L2CAP_TRACE_DEBUG("%s Credits received %d", __func__, *credit);
      if ((p_ccb->peer_conn_cfg.credits + *credit) > L2CAP_LE_CREDIT_MAX) {
        /* we have received credits more than max coc credits,
         * so disconnecting the Le Coc Channel
         */
        l2cble_send_peer_disc_req(p_ccb);
      } else {
        p_ccb->peer_conn_cfg.credits += *credit;

        tL2CA_CREDITS_RECEIVED_CB* cr_cb =
            p_ccb->p_rcb->api.pL2CA_CreditsReceived_Cb;
        if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE && (cr_cb)) {
          (*cr_cb)(p_ccb->local_cid, *credit, p_ccb->peer_conn_cfg.credits);
        }
        l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, NULL);
      }
      break;
  }
}


Gap_conn.cc
/*******************************************************************************
 *
 * Function         gap_data_ind
 *
 * Description      This function is called when data is received from L2CAP.
 *
 * Returns          void
 *
 ******************************************************************************/
static void gap_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg) {
  tGAP_CCB* p_ccb;


  
  DVLOG(1) << StringPrintf("GAP_CONN - gap_data_ind Rcvd L2CAP disc, CID: ");


   LOG(WARNING) << "******* gap_data_ind";

  /* Find CCB based on CID */
  p_ccb = gap_find_ccb_by_cid(l2cap_cid);
  if (p_ccb == NULL) {
    osi_free(p_msg);
    return;
  }

  if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) {
    fixed_queue_enqueue(p_ccb->rx_queue, p_msg);

    p_ccb->rx_queue_size += p_msg->len;
    /*
    DVLOG(1) << StringPrintf ("gap_data_ind - rx_queue_size=%d, msg len=%d",
                                   p_ccb->rx_queue_size, p_msg->len);
     */
        //bta_jv_l2cap_server_cback

    p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL, nullptr);
  } else {
    osi_free(p_msg);
  }
}


/*******************************************************************************
 *
 * Function         bta_jv_l2cap_server_cback
 *
 * Description      handles the l2cap server callback
 *
 * Returns          void
 *
 ******************************************************************************/
static void bta_jv_l2cap_server_cback(uint16_t gap_handle, uint16_t event,
                                      tGAP_CB_DATA* data) {
  tBTA_JV_L2C_CB* p_cb = &bta_jv_cb.l2c_cb[gap_handle];
  tBTA_JV evt_data;
  tBTA_JV_L2CAP_CBACK* p_cback;
  uint32_t socket_id;


   
   

  if (gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback) return;

  VLOG(2) << __func__ << ": gap_handle2=" << gap_handle
          << ", evt=" << loghex(event);


  VLOG(1) << __func__ << ": gap_handle1=" << gap_handle
          << ", evt=" << loghex(event);


  VLOG(0) << __func__ << ": gap_handle0=" << gap_handle
          << ", evt=" << loghex(event);


  
  evt_data.l2c_open.status = BTA_JV_SUCCESS;
  evt_data.l2c_open.handle = gap_handle;


  LOG(INFO) << "GapCallback event " << event;
  

  switch (event) {
    case GAP_EVT_CONN_OPENED:
      evt_data.l2c_open.rem_bda = *GAP_ConnGetRemoteAddr(gap_handle);
      evt_data.l2c_open.tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);
      p_cb->state = BTA_JV_ST_SR_OPEN;
      p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data, p_cb->l2cap_socket_id);
      break;

    case GAP_EVT_CONN_CLOSED:
      evt_data.l2c_close.async = true;
      evt_data.l2c_close.handle = p_cb->handle;
      p_cback = p_cb->p_cback;
      socket_id = p_cb->l2cap_socket_id;
      evt_data.l2c_close.status = bta_jv_free_l2c_cb(p_cb);
      p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt_data, socket_id);
      break;

    case GAP_EVT_CONN_DATA_AVAIL:
      evt_data.data_ind.handle = gap_handle;
      /* Reset idle timer to avoid requesting sniff mode while receiving data */
      bta_jv_pm_conn_busy(p_cb->p_pm_cb);
      p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data,
                    p_cb->l2cap_socket_id);

      //btsock_l2cap_cbk
      bta_jv_pm_conn_idle(p_cb->p_pm_cb);
      break;

    case GAP_EVT_TX_EMPTY:
      bta_jv_pm_conn_idle(p_cb->p_pm_cb);
      break;

    case GAP_EVT_CONN_CONGESTED:
    case GAP_EVT_CONN_UNCONGESTED:
      p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? true : false;
      evt_data.l2c_cong.cong = p_cb->cong;
      p_cb->p_cback(BTA_JV_L2CAP_CONG_EVT, &evt_data, p_cb->l2cap_socket_id);
      break;

    default:
      break;
  }
}


static void btsock_l2cap_cbk(tBTA_JV_EVT event, tBTA_JV* p_data,
                             uint32_t l2cap_socket_id) {
  APPL_TRACE_WARNING("btsock_l2cap_cbk: event: %d", event);
  switch (event) {
    case BTA_JV_L2CAP_START_EVT:
      on_srv_l2cap_listen_started(&p_data->l2c_start, l2cap_socket_id);
      break;


static void on_l2cap_data_ind(tBTA_JV* evt, uint32_t id) {
  l2cap_socket* sock;

  int app_uid = -1;
  uint32_t bytes_read = 0;

if (packet_put_tail_l(sock, buffer.data(), count)) {
          bytes_read = count;
          btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP,
                               SOCK_THREAD_FD_WR, sock->id);

Btif_sock_l2cap.cc

接收的数据包放入单链表的尾部
/* makes a copy of the data, returns true on success */
static char packet_put_tail_l(l2cap_socket* sock, const void* data,
                              uint32_t len) {
  if (sock->bytes_buffered >= L2CAP_MAX_RX_BUFFER) {
    LOG(ERROR) << __func__ << ": buffer overflow";
    return false;
  }

  struct packet* p = packet_alloc((const uint8_t*)data, len);
  p->next = NULL;
  p->prev = sock->last_packet;
  sock->last_packet = p;
  if (p->prev)
    p->prev->next = p;
  else
    sock->first_packet = p;

  sock->bytes_buffered += len;

  return true;
}

下一步应该是从此链表中取出数据包

通过socket发送给java端的服务端进程
 

最后

以上就是结实毛豆为你收集整理的蓝牙协议栈接收数据包流程1的全部内容,希望文章能够帮你解决蓝牙协议栈接收数据包流程1所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(83)

评论列表共有 0 条评论

立即
投稿
返回
顶部