• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright 2002-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  This AVDTP adaption layer module interfaces to L2CAP
22  *
23  ******************************************************************************/
24 
25 #include <string.h>
26 #include "avdt_api.h"
27 #include "avdt_int.h"
28 #include "avdtc_api.h"
29 #include "bt_target.h"
30 #include "bt_types.h"
31 #include "bt_utils.h"
32 #include "bta/include/bta_av_api.h"
33 #include "btm_api.h"
34 #include "btm_int.h"
35 #include "device/include/interop.h"
36 #include "l2c_api.h"
37 #include "l2cdefs.h"
38 #include "osi/include/osi.h"
39 
40 /* callback function declarations */
41 void avdt_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
42                                 uint16_t psm, uint8_t id);
43 void avdt_l2c_connect_cfm_cback(uint16_t lcid, uint16_t result);
44 void avdt_l2c_config_cfm_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg);
45 void avdt_l2c_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg);
46 void avdt_l2c_disconnect_ind_cback(uint16_t lcid, bool ack_needed);
47 void avdt_l2c_disconnect_cfm_cback(uint16_t lcid, uint16_t result);
48 void avdt_l2c_congestion_ind_cback(uint16_t lcid, bool is_congested);
49 void avdt_l2c_data_ind_cback(uint16_t lcid, BT_HDR* p_buf);
50 
51 /* L2CAP callback function structure */
52 const tL2CAP_APPL_INFO avdt_l2c_appl = {avdt_l2c_connect_ind_cback,
53                                         avdt_l2c_connect_cfm_cback,
54                                         NULL,
55                                         avdt_l2c_config_ind_cback,
56                                         avdt_l2c_config_cfm_cback,
57                                         avdt_l2c_disconnect_ind_cback,
58                                         avdt_l2c_disconnect_cfm_cback,
59                                         NULL,
60                                         avdt_l2c_data_ind_cback,
61                                         avdt_l2c_congestion_ind_cback,
62                                         NULL, /* tL2CA_TX_COMPLETE_CB */
63                                         NULL /* tL2CA_CREDITS_RECEIVED_CB */};
64 
65 /*******************************************************************************
66  *
67  * Function         avdt_sec_check_complete_term
68  *
69  * Description      The function called when Security Manager finishes
70  *                  verification of the service side connection
71  *
72  * Returns          void
73  *
74  ******************************************************************************/
avdt_sec_check_complete_term(const RawAddress * bd_addr,tBT_TRANSPORT transport,UNUSED_ATTR void * p_ref_data,uint8_t res)75 static void avdt_sec_check_complete_term(const RawAddress* bd_addr,
76                                          tBT_TRANSPORT transport,
77                                          UNUSED_ATTR void* p_ref_data,
78                                          uint8_t res) {
79   AvdtpCcb* p_ccb = NULL;
80   tL2CAP_CFG_INFO cfg;
81   AvdtpTransportChannel* p_tbl;
82 
83   AVDT_TRACE_DEBUG("avdt_sec_check_complete_term res: %d", res);
84   p_ccb = avdt_ccb_by_bd(*bd_addr);
85 
86   p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_ACP);
87   if (p_tbl == NULL) return;
88 
89   if (res == BTM_SUCCESS) {
90     /* Send response to the L2CAP layer. */
91     L2CA_ConnectRsp(*bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_OK,
92                     L2CAP_CONN_OK);
93 
94     /* store idx in LCID table, store LCID in routing table */
95     avdtp_cb.ad.lcid_tbl[p_tbl->lcid - L2CAP_BASE_APPL_CID] =
96         avdt_ad_tc_tbl_to_idx(p_tbl);
97     avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = p_tbl->lcid;
98 
99     /* transition to configuration state */
100     p_tbl->state = AVDT_AD_ST_CFG;
101 
102     /* Send L2CAP config req */
103     memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
104     cfg.mtu_present = true;
105     cfg.mtu = p_tbl->my_mtu;
106     cfg.flush_to_present = true;
107     cfg.flush_to = p_tbl->my_flush_to;
108     L2CA_ConfigReq(p_tbl->lcid, &cfg);
109   } else {
110     L2CA_ConnectRsp(*bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_SECURITY_BLOCK,
111                     L2CAP_CONN_OK);
112     avdt_ad_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
113   }
114 }
115 
116 /*******************************************************************************
117  *
118  * Function         avdt_sec_check_complete_orig
119  *
120  * Description      The function called when Security Manager finishes
121  *                  verification of the service side connection
122  *
123  * Returns          void
124  *
125  ******************************************************************************/
avdt_sec_check_complete_orig(const RawAddress * bd_addr,tBT_TRANSPORT trasnport,UNUSED_ATTR void * p_ref_data,uint8_t res)126 static void avdt_sec_check_complete_orig(const RawAddress* bd_addr,
127                                          tBT_TRANSPORT trasnport,
128                                          UNUSED_ATTR void* p_ref_data,
129                                          uint8_t res) {
130   AvdtpCcb* p_ccb = NULL;
131   tL2CAP_CFG_INFO cfg;
132   AvdtpTransportChannel* p_tbl;
133 
134   AVDT_TRACE_DEBUG("avdt_sec_check_complete_orig res: %d", res);
135   if (bd_addr) p_ccb = avdt_ccb_by_bd(*bd_addr);
136   p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_INT);
137   if (p_tbl == NULL) return;
138 
139   if (res == BTM_SUCCESS) {
140     /* set channel state */
141     p_tbl->state = AVDT_AD_ST_CFG;
142 
143     /* Send L2CAP config req */
144     memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
145     cfg.mtu_present = true;
146     cfg.mtu = p_tbl->my_mtu;
147     cfg.flush_to_present = true;
148     cfg.flush_to = p_tbl->my_flush_to;
149     L2CA_ConfigReq(p_tbl->lcid, &cfg);
150   } else {
151     L2CA_DisconnectReq(p_tbl->lcid);
152     avdt_ad_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
153   }
154 }
155 /*******************************************************************************
156  *
157  * Function         avdt_l2c_connect_ind_cback
158  *
159  * Description      This is the L2CAP connect indication callback function.
160  *
161  *
162  * Returns          void
163  *
164  ******************************************************************************/
avdt_l2c_connect_ind_cback(const RawAddress & bd_addr,uint16_t lcid,UNUSED_ATTR uint16_t psm,uint8_t id)165 void avdt_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
166                                 UNUSED_ATTR uint16_t psm, uint8_t id) {
167   AvdtpCcb* p_ccb;
168   AvdtpTransportChannel* p_tbl = NULL;
169   uint16_t result;
170   tL2CAP_CFG_INFO cfg;
171   tBTM_STATUS rc;
172 
173   /* do we already have a control channel for this peer? */
174   p_ccb = avdt_ccb_by_bd(bd_addr);
175   if (p_ccb == NULL) {
176     /* no, allocate ccb */
177     int channel_index = BTA_AvObtainPeerChannelIndex(bd_addr);
178     if (channel_index >= 0) {
179       p_ccb = avdt_ccb_alloc_by_channel_index(bd_addr, channel_index);
180     }
181     if (p_ccb == nullptr) {
182       p_ccb = avdt_ccb_alloc(bd_addr);
183     }
184     if (p_ccb == NULL) {
185       /* no ccb available, reject L2CAP connection */
186       result = L2CAP_CONN_NO_RESOURCES;
187     } else {
188       /* allocate and set up entry; first channel is always signaling */
189       p_tbl = avdt_ad_tc_tbl_alloc(p_ccb);
190       p_tbl->my_mtu = avdtp_cb.rcb.ctrl_mtu;
191       p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO;
192       p_tbl->tcid = AVDT_CHAN_SIG;
193       p_tbl->lcid = lcid;
194       p_tbl->id = id;
195       p_tbl->state = AVDT_AD_ST_SEC_ACP;
196       p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_ACP;
197 
198       if (interop_match_addr(INTEROP_2MBPS_LINK_ONLY, &bd_addr)) {
199         // Disable 3DH packets for AVDT ACL to improve sensitivity on HS
200         tACL_CONN* p_acl_cb = btm_bda_to_acl(bd_addr, BT_TRANSPORT_BR_EDR);
201         btm_set_packet_types(
202             p_acl_cb,
203             (btm_cb.btm_acl_pkt_types_supported | HCI_PKT_TYPES_MASK_NO_3_DH1 |
204              HCI_PKT_TYPES_MASK_NO_3_DH3 | HCI_PKT_TYPES_MASK_NO_3_DH5));
205       }
206 
207       /* Check the security */
208       rc = btm_sec_mx_access_request(bd_addr, AVDT_PSM, false,
209                                      BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG,
210                                      &avdt_sec_check_complete_term, NULL);
211       if (rc == BTM_CMD_STARTED) {
212         L2CA_ConnectRsp(p_ccb->peer_addr, p_tbl->id, lcid, L2CAP_CONN_PENDING,
213                         L2CAP_CONN_OK);
214       }
215       return;
216     }
217   } else {
218     /* deal with simultaneous control channel connect case */
219     p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_CONN);
220     if (p_tbl != NULL) {
221       /* reject their connection */
222       result = L2CAP_CONN_NO_RESOURCES;
223     } else {
224       /* This must be a traffic channel; are we accepting a traffic channel
225        * for this ccb?
226        */
227       p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_MEDIA, p_ccb, AVDT_AD_ST_ACP);
228       if (p_tbl != NULL) {
229         /* yes; proceed with connection */
230         result = L2CAP_CONN_OK;
231       } else {
232         /* this must be a reporting channel; are we accepting a reporting
233          * channel for this ccb?
234          */
235         p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_REPORT, p_ccb, AVDT_AD_ST_ACP);
236         if (p_tbl != NULL) {
237           /* yes; proceed with connection */
238           result = L2CAP_CONN_OK;
239         } else {
240           /* else we're not listening for traffic channel; reject */
241           result = L2CAP_CONN_NO_PSM;
242         }
243       }
244     }
245   }
246 
247   /* Send L2CAP connect rsp */
248   L2CA_ConnectRsp(bd_addr, id, lcid, result, 0);
249 
250   /* if result ok, proceed with connection */
251   if (result == L2CAP_CONN_OK) {
252     /* store idx in LCID table, store LCID in routing table */
253     avdtp_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] =
254         avdt_ad_tc_tbl_to_idx(p_tbl);
255     avdtp_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
256 
257     /* transition to configuration state */
258     p_tbl->state = AVDT_AD_ST_CFG;
259 
260     /* Send L2CAP config req */
261     memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
262     cfg.mtu_present = true;
263     cfg.mtu = p_tbl->my_mtu;
264     cfg.flush_to_present = true;
265     cfg.flush_to = p_tbl->my_flush_to;
266     L2CA_ConfigReq(lcid, &cfg);
267   }
268 }
269 
270 /*******************************************************************************
271  *
272  * Function         avdt_l2c_connect_cfm_cback
273  *
274  * Description      This is the L2CAP connect confirm callback function.
275  *
276  *
277  * Returns          void
278  *
279  ******************************************************************************/
avdt_l2c_connect_cfm_cback(uint16_t lcid,uint16_t result)280 void avdt_l2c_connect_cfm_cback(uint16_t lcid, uint16_t result) {
281   AvdtpTransportChannel* p_tbl;
282   tL2CAP_CFG_INFO cfg;
283   AvdtpCcb* p_ccb;
284 
285   AVDT_TRACE_DEBUG("avdt_l2c_connect_cfm_cback lcid: %d, result: %d", lcid,
286                    result);
287   /* look up info for this channel */
288   p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
289   if (p_tbl != NULL) {
290     /* if in correct state */
291     if (p_tbl->state == AVDT_AD_ST_CONN) {
292       /* if result successful */
293       if (result == L2CAP_CONN_OK) {
294         if (p_tbl->tcid != AVDT_CHAN_SIG) {
295           /* set channel state */
296           p_tbl->state = AVDT_AD_ST_CFG;
297 
298           /* Send L2CAP config req */
299           memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
300           cfg.mtu_present = true;
301           cfg.mtu = p_tbl->my_mtu;
302           cfg.flush_to_present = true;
303           cfg.flush_to = p_tbl->my_flush_to;
304           L2CA_ConfigReq(lcid, &cfg);
305         } else {
306           p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
307           if (p_ccb == NULL) {
308             result = L2CAP_CONN_NO_RESOURCES;
309           } else {
310             /* set channel state */
311             p_tbl->state = AVDT_AD_ST_SEC_INT;
312             p_tbl->lcid = lcid;
313             p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_INT;
314 
315             if (interop_match_addr(INTEROP_2MBPS_LINK_ONLY,
316                                    (const RawAddress*)&p_ccb->peer_addr)) {
317               // Disable 3DH packets for AVDT ACL to improve sensitivity on HS
318               tACL_CONN* p_acl_cb =
319                   btm_bda_to_acl(p_ccb->peer_addr, BT_TRANSPORT_BR_EDR);
320               btm_set_packet_types(
321                   p_acl_cb,
322                   (btm_cb.btm_acl_pkt_types_supported |
323                    HCI_PKT_TYPES_MASK_NO_3_DH1 | HCI_PKT_TYPES_MASK_NO_3_DH3 |
324                    HCI_PKT_TYPES_MASK_NO_3_DH5));
325             }
326 
327             /* Check the security */
328             btm_sec_mx_access_request(p_ccb->peer_addr, AVDT_PSM, true,
329                                       BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG,
330                                       &avdt_sec_check_complete_orig, NULL);
331           }
332         }
333       }
334 
335       /* failure; notify adaption that channel closed */
336       if (result != L2CAP_CONN_OK) {
337         avdt_ad_tc_close_ind(p_tbl, result);
338       }
339     }
340   }
341 }
342 
343 /*******************************************************************************
344  *
345  * Function         avdt_l2c_config_cfm_cback
346  *
347  * Description      This is the L2CAP config confirm callback function.
348  *
349  *
350  * Returns          void
351  *
352  ******************************************************************************/
avdt_l2c_config_cfm_cback(uint16_t lcid,tL2CAP_CFG_INFO * p_cfg)353 void avdt_l2c_config_cfm_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
354   AvdtpTransportChannel* p_tbl;
355 
356   AVDT_TRACE_DEBUG("%s: lcid: %d", __func__, lcid);
357 
358   /* look up info for this channel */
359   p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
360   if (p_tbl != NULL) {
361     p_tbl->lcid = lcid;
362 
363     /* if in correct state */
364     if (p_tbl->state == AVDT_AD_ST_CFG) {
365       /* if result successful */
366       if (p_cfg->result == L2CAP_CONN_OK) {
367         /* update cfg_flags */
368         p_tbl->cfg_flags |= AVDT_L2C_CFG_CFM_DONE;
369 
370         /* if configuration complete */
371         if (p_tbl->cfg_flags & AVDT_L2C_CFG_IND_DONE) {
372           avdt_ad_tc_open_ind(p_tbl);
373         }
374       }
375       /* else failure */
376       else {
377         /* Send L2CAP disconnect req */
378         L2CA_DisconnectReq(lcid);
379       }
380     }
381   }
382 }
383 
384 /*******************************************************************************
385  *
386  * Function         avdt_l2c_config_ind_cback
387  *
388  * Description      This is the L2CAP config indication callback function.
389  *
390  *
391  * Returns          void
392  *
393  ******************************************************************************/
avdt_l2c_config_ind_cback(uint16_t lcid,tL2CAP_CFG_INFO * p_cfg)394 void avdt_l2c_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
395   AvdtpTransportChannel* p_tbl;
396 
397   AVDT_TRACE_DEBUG("%s: lcid: %d", __func__, lcid);
398 
399   /* look up info for this channel */
400   p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
401   if (p_tbl != NULL) {
402     /* store the mtu in tbl */
403     if (p_cfg->mtu_present) {
404       p_tbl->peer_mtu = p_cfg->mtu;
405     } else {
406       p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
407     }
408     AVDT_TRACE_DEBUG("%s: peer_mtu: %d, lcid: %d", __func__, p_tbl->peer_mtu,
409                      lcid);
410 
411     /* send L2CAP configure response */
412     memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
413     p_cfg->result = L2CAP_CFG_OK;
414     L2CA_ConfigRsp(lcid, p_cfg);
415 
416     /* if first config ind */
417     if ((p_tbl->cfg_flags & AVDT_L2C_CFG_IND_DONE) == 0) {
418       /* update cfg_flags */
419       p_tbl->cfg_flags |= AVDT_L2C_CFG_IND_DONE;
420 
421       /* if configuration complete */
422       if (p_tbl->cfg_flags & AVDT_L2C_CFG_CFM_DONE) {
423         avdt_ad_tc_open_ind(p_tbl);
424       }
425     }
426   }
427 }
428 
429 /*******************************************************************************
430  *
431  * Function         avdt_l2c_disconnect_ind_cback
432  *
433  * Description      This is the L2CAP disconnect indication callback function.
434  *
435  *
436  * Returns          void
437  *
438  ******************************************************************************/
avdt_l2c_disconnect_ind_cback(uint16_t lcid,bool ack_needed)439 void avdt_l2c_disconnect_ind_cback(uint16_t lcid, bool ack_needed) {
440   AvdtpTransportChannel* p_tbl;
441 
442   AVDT_TRACE_DEBUG("avdt_l2c_disconnect_ind_cback lcid: %d, ack_needed: %d",
443                    lcid, ack_needed);
444   /* look up info for this channel */
445   p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
446   if (p_tbl != NULL) {
447     if (ack_needed) {
448       /* send L2CAP disconnect response */
449       L2CA_DisconnectRsp(lcid);
450     }
451 
452     avdt_ad_tc_close_ind(p_tbl, 0);
453   }
454 }
455 
456 /*******************************************************************************
457  *
458  * Function         avdt_l2c_disconnect_cfm_cback
459  *
460  * Description      This is the L2CAP disconnect confirm callback function.
461  *
462  *
463  * Returns          void
464  *
465  ******************************************************************************/
avdt_l2c_disconnect_cfm_cback(uint16_t lcid,uint16_t result)466 void avdt_l2c_disconnect_cfm_cback(uint16_t lcid, uint16_t result) {
467   AvdtpTransportChannel* p_tbl;
468 
469   AVDT_TRACE_DEBUG("avdt_l2c_disconnect_cfm_cback lcid: %d, result: %d", lcid,
470                    result);
471   /* look up info for this channel */
472   p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
473   if (p_tbl != NULL) {
474     avdt_ad_tc_close_ind(p_tbl, result);
475   }
476 }
477 
478 /*******************************************************************************
479  *
480  * Function         avdt_l2c_congestion_ind_cback
481  *
482  * Description      This is the L2CAP congestion indication callback function.
483  *
484  *
485  * Returns          void
486  *
487  ******************************************************************************/
avdt_l2c_congestion_ind_cback(uint16_t lcid,bool is_congested)488 void avdt_l2c_congestion_ind_cback(uint16_t lcid, bool is_congested) {
489   AvdtpTransportChannel* p_tbl;
490 
491   /* look up info for this channel */
492   p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
493   if (p_tbl != NULL) {
494     avdt_ad_tc_cong_ind(p_tbl, is_congested);
495   }
496 }
497 
498 /*******************************************************************************
499  *
500  * Function         avdt_l2c_data_ind_cback
501  *
502  * Description      This is the L2CAP data indication callback function.
503  *
504  *
505  * Returns          void
506  *
507  ******************************************************************************/
avdt_l2c_data_ind_cback(uint16_t lcid,BT_HDR * p_buf)508 void avdt_l2c_data_ind_cback(uint16_t lcid, BT_HDR* p_buf) {
509   AvdtpTransportChannel* p_tbl;
510 
511   /* look up info for this channel */
512   p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
513   if (p_tbl != NULL) {
514     avdt_ad_tc_data_ind(p_tbl, p_buf);
515   } else /* prevent buffer leak */
516     osi_free(p_buf);
517 }
518