2015年1月21日 星期三

bluedroid源碼分析之ACL包發送和接收(三) (轉)

原 http://stackvoid.com/ACL-Send-Recv-Data_3/

本文講的是 Bluedroid 中數據包在 L2CAP 層入隊列的一系列函數源碼分析。
l2c_enqueue_peer_data 函數的主要作用是將我們的音樂數據包入數據發送隊列以及處理 FCR segmentation 和當前 Channel 是否擁堵的檢測,我們來詳細讀一下他的源碼。其主要做了這麼幾件事: 1. 組裝好 p_buf 併入 當前 CCB 的 xmit_hold_q 隊列。 2. 檢查當前 Channel 擁堵情況。 3. 當前 Link 支持 RR,則檢查當前ACL數據包所在 Channel 的權限,如果當前 CCB 中的權限高於 RR,則把 RR 中的權限設置為跟 CCB 相同。 4. 若 Link 上沒有發送窗口,則將 l2cb.check_round_robin 置為TRUE,下一次需要 RR
  1 void l2c_enqueue_peer_data (tL2C_CCB *p_ccb, BT_HDR *p_buf)
  2 {
  3     UINT8       *p;
  4 
  5     if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE)
  6     {
  7         p_buf->event = 0;
  8     }
  9     else
 10     {
 11         /* Save the channel ID for faster counting */
 12         p_buf->event = p_ccb->local_cid;
 13 
 14         /* Step back to add the L2CAP header */
 15         p_buf->offset -= L2CAP_PKT_OVERHEAD;
 16         p_buf->len    += L2CAP_PKT_OVERHEAD;
 17 
 18         /* Set the pointer to the beginning of the data */
 19         p = (UINT8 *)(p_buf + 1) + p_buf->offset;
 20 
 21         /* Now the L2CAP header */
 22         UINT16_TO_STREAM (p, p_buf->len - L2CAP_PKT_OVERHEAD);
 23         UINT16_TO_STREAM (p, p_ccb->remote_cid);
 24     }
 25 
 26     GKI_enqueue (&p_ccb->xmit_hold_q, p_buf);//真正將組裝好的 p_buf 入隊
 27 
 28     l2cu_check_channel_congestion (p_ccb);  //檢測當前 Channel 擁堵情況,下面會繼續分析這個函數
 29 
 30 #if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
 31     /* if new packet is higher priority than serving ccb and it is not overrun */
 32     if (( p_ccb->p_lcb->rr_pri > p_ccb->ccb_priority ) //當前數據包所在Channel的權限
 33       &&( p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota > 0))
 34     {
 35         /* send out higher priority packet */
 36         p_ccb->p_lcb->rr_pri = p_ccb->ccb_priority;//當前要發送的數據的Channel,設置為ccb_priority,比原來權限要高。
 37     }
 38 #endif
 39 
 40     //如果當前 link 上的 link_xmit_quota ==0(link上的發送窗口為0),那麼有必要做一次 RR
 41     if (p_ccb->p_lcb->link_xmit_quota == 0)
 42         l2cb.check_round_robin = TRUE;
 43 }
 44 
 45 //check if any change in congestion status
 46 
 47 void l2cu_check_channel_congestion (tL2C_CCB *p_ccb)
 48 {
 49     UINT16 q_count = p_ccb->xmit_hold_q.count; //當前 CCB 中 發送數據隊列中數據包的總數
 50 
 51 #if (L2CAP_UCD_INCLUDED == TRUE)
 52     if ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID )
 53     {
 54         q_count += p_ccb->p_lcb->ucd_out_sec_pending_q.count;
 55     }
 56 #endif
 57 
 58     /* If the CCB queue limit is subject to a quota, check for congestion */
 59 
 60     /* if this channel has outgoing traffic */
 61     if ((p_ccb->p_rcb)&&(p_ccb->buff_quota != 0))
 62     {
 63         /* If this channel was congested */
 64         if ( p_ccb->cong_sent ) //當前 Channel 的這個欄位為TRUE,是否真正擁堵,我們要繼續判斷
 65         {
 66             /* If the channel is not congested now, tell the app */
 67             //p_ccb->buff_quota = quota_per_weighted_chnls[HCI_ACL_POOL_ID] * p_ccb->tx_data_rate
 68             //在函數 l2c_link_adjust_chnl_allocation 中配置此值
 69             if (q_count <= (p_ccb->buff_quota / 2))//q_count為 CCB 中的xmit_hold_q
 70             {
 71                 p_ccb->cong_sent = FALSE; //當前CCB中的 xmit_hold_q 小於 buffer_quota 值的一半,就認為已經不擁堵了
 72                 if (p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)
 73                 {
 74                     L2CAP_TRACE_DEBUG3 ("L2CAP - Calling CongestionStatus_Cb (FALSE), CID: 0x%04x  xmit_hold_q.count: %u  buff_quota: %u",
 75                                       p_ccb->local_cid, q_count, p_ccb->buff_quota);
 76 
 77                     /* Prevent recursive calling */
 78                     l2cb.is_cong_cback_context = TRUE;
 79                     (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, FALSE);
 80                     l2cb.is_cong_cback_context = FALSE;
 81                 }
 82 #if (L2CAP_UCD_INCLUDED == TRUE)
 83                 else if ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID )//無連接的 CID
 84                 {
 85                     if ( p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb )
 86                     {
 87                         L2CAP_TRACE_DEBUG3 ("L2CAP - Calling UCD CongestionStatus_Cb (FALSE), SecPendingQ:%u,XmitQ:%u,Quota:%u",
 88                                              p_ccb->p_lcb->ucd_out_sec_pending_q.count,
 89                                              p_ccb->xmit_hold_q.count, p_ccb->buff_quota);
 90                         p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb( p_ccb->p_lcb->remote_bd_addr, FALSE );
 91                     }
 92                 }
 93 #endif
 94             }
 95         }
 96         else
 97         {
 98             /* If this channel was not congested but it is congested now, tell the app */
 99             if (q_count > p_ccb->buff_quota) //此時仍然處於擁堵狀態
100             {
101                 p_ccb->cong_sent = TRUE;
102                 if (p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)
103                 {
104                     L2CAP_TRACE_DEBUG3 ("L2CAP - Calling CongestionStatus_Cb (TRUE),CID:0x%04x,XmitQ:%u,Quota:%u",
105                         p_ccb->local_cid, q_count, p_ccb->buff_quota);
106 
107                     (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid, TRUE);
108                 }
109 #if (L2CAP_UCD_INCLUDED == TRUE)
110                 else if ( p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID )
111                 {
112                     if ( p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb )
113                     {
114                         L2CAP_TRACE_DEBUG3 ("L2CAP - Calling UCD CongestionStatus_Cb (TRUE), SecPendingQ:%u,XmitQ:%u,Quota:%u",
115                                              p_ccb->p_lcb->ucd_out_sec_pending_q.count,
116                                              p_ccb->xmit_hold_q.count, p_ccb->buff_quota);
117                         p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb( p_ccb->p_lcb->remote_bd_addr, TRUE );
118                     }
119                 }
120 #endif
121             }
122         }
123     }
124 }

沒有留言:

張貼留言