本文講的是 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 }
沒有留言:
張貼留言