bluedroidソースコード分析のACLパケット送信と受信(一)
32972 ワード
詳細については、私の個人サイトを参照してください. http://stackvoid.com/
ACLリンクはBluetoothにおいて非常に重要であり、A 2 DP、RFCOMMベースのアプリケーション、BNEPなどの重要なアプリケーションはACLリンクを確立し、ACLパケットを送信/受信しなければならない.今日はACLパッケージの送信/受信プロセス、および関連する重要なcommand/eventを分析します.
ACLパッケージ送信
以下の図(大図クリック)は、各種アプリケーション層がL 2 CAPを用いたAPI:L 2 CA_DataWriteがデータストリームを送信する過程で、このAPIは引き続き下に進み、私は正常なデータストリームの行方だけを分析した(しばらく他の状況を考慮していない).
アプリケーション層データからL 2 CAPへのエントリ
私たちは音楽を聴くシーンを仮定して、Mikeはみんなと一緒に音楽データストリームAVDTP以下の層の伝送を分析します.
AVDTPでは、すべての機能がDataを送信するには、avdt_を呼び出す必要があります.ad_write_reqという関数、Mikeはこの関数から分析します.
私たちの音楽データストリームがl 2 cに達するとdata_writeという関数の場合,フラグデータストリームは正式にL 2 CAP層に入る.以下のソースコードでl 2 c_を深く分析します.data_writeという関数.
l2c_data_write この関数は主に次のことをします.
パラメータcid(Channel ID)により対応するccb(Channel Control Block)が見つかり、戻りが見つからない L2CAP_DW_FAILED
テスト者がTESTERというマクロを開き、任意のデータを送信すると、データサイズがMTUの最大値より大きい場合、 L2CAP_DW_FAILED
チェックp_ccb->cong_sentフィールド、TRUEは、現在のChannelが混雑していることを示し、このときL 2 CAPのこのChannelはデータを受信せず、戻る L2CAP_DW_FAILED
以上の3つの条件はすべて通過して、データが送信することができることを説明して、データをl 2 c_を通過しますcsm_executeは処理を続行します.l 2 c_へcsm_execute関数は、このデータがl 2 CAPに渡されて処理されたことを示しており、上層部とは関係ありません.
l2c_csm_execute関数の実行が終了したら、p_を再度チェックccb->cong_sentフィールドは、現在のチャンネルが混雑しているかどうかを見て、混雑している場合は上位L 2 CAP_に伝えます.DW_CONGESTED、そうでなければL 2 CAP_に戻るDW_SUCCESSは、データが正常に送信されたことを示しています.
次のブログではL 2 CAP層の処理を見てみましょう.
詳細については、私の個人サイトを参照してください. http://stackvoid.com/
ACLリンクはBluetoothにおいて非常に重要であり、A 2 DP、RFCOMMベースのアプリケーション、BNEPなどの重要なアプリケーションはACLリンクを確立し、ACLパケットを送信/受信しなければならない.今日はACLパッケージの送信/受信プロセス、および関連する重要なcommand/eventを分析します.
ACLパッケージ送信
以下の図(大図クリック)は、各種アプリケーション層がL 2 CAPを用いたAPI:L 2 CA_DataWriteがデータストリームを送信する過程で、このAPIは引き続き下に進み、私は正常なデータストリームの行方だけを分析した(しばらく他の状況を考慮していない).
アプリケーション層データからL 2 CAPへのエントリ
私たちは音楽を聴くシーンを仮定して、Mikeはみんなと一緒に音楽データストリームAVDTP以下の層の伝送を分析します.
AVDTPでは、すべての機能がDataを送信するには、avdt_を呼び出す必要があります.ad_write_reqという関数、Mikeはこの関数から分析します.
1 // CCB SCB l2cap Channel , L2CAP API:L2CA_Data_Write
2 UINT8 avdt_ad_write_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, BT_HDR *p_buf)
3 {
4 UINT8 tcid;
5
6 /* get tcid from type, scb */
7 tcid = avdt_ad_type_to_tcid(type, p_scb);
8
9
10 return L2CA_DataWrite(avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][tcid].lcid, p_buf);
11 }
12 //L2CA_DataWrite , :
13 //1. L2CAP_DW_SUCCESS:
14 //2.L2CAP_DW_CONGESTED: ,
15 //3.L2CAP_DW_FAILED:
16 UINT8 L2CA_DataWrite (UINT16 cid, BT_HDR *p_data)
17 {
18 L2CAP_TRACE_API2 ("L2CA_DataWrite() CID: 0x%04x Len: %d", cid, p_data->len);
19 return l2c_data_write (cid, p_data, L2CAP_FLUSHABLE_CH_BASED);
20 }
私たちの音楽データストリームがl 2 cに達するとdata_writeという関数の場合,フラグデータストリームは正式にL 2 CAP層に入る.以下のソースコードでl 2 c_を深く分析します.data_writeという関数.
l2c_data_write この関数は主に次のことをします.
パラメータcid(Channel ID)により対応するccb(Channel Control Block)が見つかり、戻りが見つからない L2CAP_DW_FAILED
テスト者がTESTERというマクロを開き、任意のデータを送信すると、データサイズがMTUの最大値より大きい場合、 L2CAP_DW_FAILED
チェックp_ccb->cong_sentフィールド、TRUEは、現在のChannelが混雑していることを示し、このときL 2 CAPのこのChannelはデータを受信せず、戻る L2CAP_DW_FAILED
以上の3つの条件はすべて通過して、データが送信することができることを説明して、データをl 2 c_を通過しますcsm_executeは処理を続行します.l 2 c_へcsm_execute関数は、このデータがl 2 CAPに渡されて処理されたことを示しており、上層部とは関係ありません.
l2c_csm_execute関数の実行が終了したら、p_を再度チェックccb->cong_sentフィールドは、現在のチャンネルが混雑しているかどうかを見て、混雑している場合は上位L 2 CAP_に伝えます.DW_CONGESTED、そうでなければL 2 CAP_に戻るDW_SUCCESSは、データが正常に送信されたことを示しています.
1 // L2CA_DataWrite
2 UINT8 l2c_data_write (UINT16 cid, BT_HDR *p_data, UINT16 flags)
3 {
4 tL2C_CCB *p_ccb;
5
6 // l2cb.ccb_pool, Channel ID Channel Control Block
7 //l2cu_find_ccb_by_cid
8 if ((p_ccb = l2cu_find_ccb_by_cid (NULL, cid)) == NULL)
9 {
10 L2CAP_TRACE_WARNING1 ("L2CAP - no CCB for L2CA_DataWrite, CID: %d", cid);
11 GKI_freebuf (p_data);
12 return (L2CAP_DW_FAILED);
13 }
14
15 #ifndef TESTER /* Tester may send any amount of data. otherwise sending message
16 bigger than mtu size of peer is a violation of protocol */
17 if (p_data->len > p_ccb->peer_cfg.mtu)
18 {
19 L2CAP_TRACE_WARNING1 ("L2CAP - CID: 0x%04x cannot send message bigger than peer's mtu size", cid);
20 GKI_freebuf (p_data);
21 return (L2CAP_DW_FAILED);
22 }
23 #endif
24
25 /* channel based, packet based flushable or non-flushable */
26 //Bluedroid L2CAP_FLUSHABLE_CH_BASED
27 // layer_specific l2c_link_send_to_lower ACL
28 p_data->layer_specific = flags;
29
30 // Channel , L2CAP_DW_FAILED
31 // Channel
32 if (p_ccb->cong_sent)
33 {
34 L2CAP_TRACE_ERROR3 ("L2CAP - CID: 0x%04x cannot send, already congested xmit_hold_q.count: %u buff_quota: %u",
35 p_ccb->local_cid, p_ccb->xmit_hold_q.count, p_ccb->buff_quota);
36
37 GKI_freebuf (p_data);
38 return (L2CAP_DW_FAILED);
39 }
40 // ,
41 l2c_csm_execute (p_ccb, L2CEVT_L2CA_DATA_WRITE, p_data);
42
43 // , Channel ( )
44 // L2CAP_DW_CONGESTED , L2CAP ,
45 if (p_ccb->cong_sent)
46 return (L2CAP_DW_CONGESTED);
47
48 // , Channel
49 return (L2CAP_DW_SUCCESS);
50 }
51
52 // Channel ID Channel Control Block
53 tL2C_CCB *l2cu_find_ccb_by_cid (tL2C_LCB *p_lcb, UINT16 local_cid)
54 {
55 tL2C_CCB *p_ccb = NULL;
56 #if (L2CAP_UCD_INCLUDED == TRUE)
57 UINT8 xx;
58 #endif
59
60 if (local_cid >= L2CAP_BASE_APPL_CID) // 0x0040 Fixed Channel
61 {
62 /* find the associated CCB by "index" */
63 local_cid -= L2CAP_BASE_APPL_CID;
64
65 if (local_cid >= MAX_L2CAP_CHANNELS)
66 return NULL;
67
68 p_ccb = l2cb.ccb_pool + local_cid; //
69
70 /* make sure the CCB is in use */
71 if (!p_ccb->in_use)
72 {
73 p_ccb = NULL;
74 }
75 /* make sure it's for the same LCB */
76 else if (p_lcb && p_lcb != p_ccb->p_lcb)
77 {
78 p_ccb = NULL;
79 }
80 }
81 #if (L2CAP_UCD_INCLUDED == TRUE) // , , Fixed Channel
82 else
83 {
84 /* searching fixed channel */
85 p_ccb = l2cb.ccb_pool;
86 for ( xx = 0; xx < MAX_L2CAP_CHANNELS; xx++ )
87 {
88 if ((p_ccb->local_cid == local_cid)
89 &&(p_ccb->in_use)
90 &&(p_lcb == p_ccb->p_lcb))
91 break;
92 else
93 p_ccb++;
94 }
95 if ( xx >= MAX_L2CAP_CHANNELS )
96 return NULL;
97 }
98 #endif
99
100 return (p_ccb);
101 }
次のブログではL 2 CAP層の処理を見てみましょう.
詳細については、私の個人サイトを参照してください. http://stackvoid.com/