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はこの関数から分析します.
 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/