• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 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 "btm_api.h"
33 #include "btm_int.h"
34 #include "device/include/interop.h"
35 #include "l2c_api.h"
36 #include "l2cdefs.h"
37 #include "osi/include/osi.h"
38 
39 /* callback function declarations */
40 void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, uint16_t lcid, uint16_t psm,
41                                 uint8_t id);
42 void avdt_l2c_connect_cfm_cback(uint16_t lcid, uint16_t result);
43 void avdt_l2c_config_cfm_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg);
44 void avdt_l2c_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg);
45 void avdt_l2c_disconnect_ind_cback(uint16_t lcid, bool ack_needed);
46 void avdt_l2c_disconnect_cfm_cback(uint16_t lcid, uint16_t result);
47 void avdt_l2c_congestion_ind_cback(uint16_t lcid, bool is_congested);
48 void avdt_l2c_data_ind_cback(uint16_t lcid, BT_HDR* p_buf);
49 
50 /* L2CAP callback function structure */
51 const tL2CAP_APPL_INFO avdt_l2c_appl = {
52     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 };
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(BD_ADDR bd_addr,tBT_TRANSPORT transport,UNUSED_ATTR void * p_ref_data,uint8_t res)75 static void avdt_sec_check_complete_term(BD_ADDR bd_addr,
76                                          tBT_TRANSPORT transport,
77                                          UNUSED_ATTR void* p_ref_data,
78                                          uint8_t res) {
79   tAVDT_CCB* p_ccb = NULL;
80   tL2CAP_CFG_INFO cfg;
81   tAVDT_TC_TBL* p_tbl;
82 
83   AVDT_TRACE_DEBUG("avdt_sec_check_complete_term res: %d", res);
84   if (!bd_addr) {
85     AVDT_TRACE_WARNING("avdt_sec_check_complete_term: NULL BD_ADDR");
86     return;
87   }
88   p_ccb = avdt_ccb_by_bd(bd_addr);
89 
90   p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_ACP);
91   if (p_tbl == NULL) return;
92 
93   if (res == BTM_SUCCESS) {
94     /* Send response to the L2CAP layer. */
95     L2CA_ConnectRsp(bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_OK,
96                     L2CAP_CONN_OK);
97 
98     /* store idx in LCID table, store LCID in routing table */
99     avdt_cb.ad.lcid_tbl[p_tbl->lcid - L2CAP_BASE_APPL_CID] =
100         avdt_ad_tc_tbl_to_idx(p_tbl);
101     avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = p_tbl->lcid;
102 
103     /* transition to configuration state */
104     p_tbl->state = AVDT_AD_ST_CFG;
105 
106     /* Send L2CAP config req */
107     memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
108     cfg.mtu_present = true;
109     cfg.mtu = p_tbl->my_mtu;
110     cfg.flush_to_present = true;
111     cfg.flush_to = p_tbl->my_flush_to;
112     L2CA_ConfigReq(p_tbl->lcid, &cfg);
113   } else {
114     L2CA_ConnectRsp(bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_SECURITY_BLOCK,
115                     L2CAP_CONN_OK);
116     avdt_ad_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
117   }
118 }
119 
120 /*******************************************************************************
121  *
122  * Function         avdt_sec_check_complete_orig
123  *
124  * Description      The function called when Security Manager finishes
125  *                  verification of the service side connection
126  *
127  * Returns          void
128  *
129  ******************************************************************************/
avdt_sec_check_complete_orig(BD_ADDR bd_addr,tBT_TRANSPORT trasnport,UNUSED_ATTR void * p_ref_data,uint8_t res)130 static void avdt_sec_check_complete_orig(BD_ADDR bd_addr,
131                                          tBT_TRANSPORT trasnport,
132                                          UNUSED_ATTR void* p_ref_data,
133                                          uint8_t res) {
134   tAVDT_CCB* p_ccb = NULL;
135   tL2CAP_CFG_INFO cfg;
136   tAVDT_TC_TBL* p_tbl;
137 
138   AVDT_TRACE_DEBUG("avdt_sec_check_complete_orig res: %d", res);
139   if (bd_addr) p_ccb = avdt_ccb_by_bd(bd_addr);
140   p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_INT);
141   if (p_tbl == NULL) return;
142 
143   if (res == BTM_SUCCESS) {
144     /* set channel state */
145     p_tbl->state = AVDT_AD_ST_CFG;
146 
147     /* Send L2CAP config req */
148     memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
149     cfg.mtu_present = true;
150     cfg.mtu = p_tbl->my_mtu;
151     cfg.flush_to_present = true;
152     cfg.flush_to = p_tbl->my_flush_to;
153     L2CA_ConfigReq(p_tbl->lcid, &cfg);
154   } else {
155     L2CA_DisconnectReq(p_tbl->lcid);
156     avdt_ad_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
157   }
158 }
159 /*******************************************************************************
160  *
161  * Function         avdt_l2c_connect_ind_cback
162  *
163  * Description      This is the L2CAP connect indication callback function.
164  *
165  *
166  * Returns          void
167  *
168  ******************************************************************************/
avdt_l2c_connect_ind_cback(BD_ADDR bd_addr,uint16_t lcid,UNUSED_ATTR uint16_t psm,uint8_t id)169 void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, uint16_t lcid,
170                                 UNUSED_ATTR uint16_t psm, uint8_t id) {
171   tAVDT_CCB* p_ccb;
172   tAVDT_TC_TBL* p_tbl = NULL;
173   uint16_t result;
174   tL2CAP_CFG_INFO cfg;
175   tBTM_STATUS rc;
176 
177   /* do we already have a control channel for this peer? */
178   p_ccb = avdt_ccb_by_bd(bd_addr);
179   if (p_ccb == NULL) {
180     /* no, allocate ccb */
181     p_ccb = avdt_ccb_alloc(bd_addr);
182     if (p_ccb == NULL) {
183       /* no ccb available, reject L2CAP connection */
184       result = L2CAP_CONN_NO_RESOURCES;
185     } else {
186       /* allocate and set up entry; first channel is always signaling */
187       p_tbl = avdt_ad_tc_tbl_alloc(p_ccb);
188       p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu;
189       p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO;
190       p_tbl->tcid = AVDT_CHAN_SIG;
191       p_tbl->lcid = lcid;
192       p_tbl->id = id;
193       p_tbl->state = AVDT_AD_ST_SEC_ACP;
194       p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_ACP;
195 
196       if (interop_match_addr(INTEROP_2MBPS_LINK_ONLY,
197                              (const bt_bdaddr_t*)&bd_addr)) {
198         // Disable 3DH packets for AVDT ACL to improve sensitivity on HS
199         tACL_CONN* p_acl_cb = btm_bda_to_acl(bd_addr, BT_TRANSPORT_BR_EDR);
200         btm_set_packet_types(
201             p_acl_cb,
202             (btm_cb.btm_acl_pkt_types_supported | HCI_PKT_TYPES_MASK_NO_3_DH1 |
203              HCI_PKT_TYPES_MASK_NO_3_DH3 | HCI_PKT_TYPES_MASK_NO_3_DH5));
204       }
205 
206       /* Check the security */
207       rc = btm_sec_mx_access_request(bd_addr, AVDT_PSM, false,
208                                      BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG,
209                                      &avdt_sec_check_complete_term, NULL);
210       if (rc == BTM_CMD_STARTED) {
211         L2CA_ConnectRsp(p_ccb->peer_addr, p_tbl->id, lcid, L2CAP_CONN_PENDING,
212                         L2CAP_CONN_OK);
213       }
214       return;
215     }
216   }
217   /* deal with simultaneous control channel connect case */
218   else {
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     }
224     /* this must be a traffic channel; are we accepting a traffic channel
225     ** for this ccb?
226     */
227     else {
228       p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_MEDIA, p_ccb, AVDT_AD_ST_ACP);
229       if (p_tbl != NULL) {
230         /* yes; proceed with connection */
231         result = L2CAP_CONN_OK;
232       }
233 #if (AVDT_REPORTING == TRUE)
234       /* this must be a reporting channel; are we accepting a reporting channel
235       ** for this ccb?
236       */
237       else {
238         p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_REPORT, p_ccb, AVDT_AD_ST_ACP);
239         if (p_tbl != NULL) {
240           /* yes; proceed with connection */
241           result = L2CAP_CONN_OK;
242         }
243 #endif
244         /* else we're not listening for traffic channel; reject */
245         else {
246           result = L2CAP_CONN_NO_PSM;
247         }
248       }
249     }
250   }
251 
252   /* Send L2CAP connect rsp */
253   L2CA_ConnectRsp(bd_addr, id, lcid, result, 0);
254 
255   /* if result ok, proceed with connection */
256   if (result == L2CAP_CONN_OK) {
257     /* store idx in LCID table, store LCID in routing table */
258     avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] =
259         avdt_ad_tc_tbl_to_idx(p_tbl);
260     avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid;
261 
262     /* transition to configuration state */
263     p_tbl->state = AVDT_AD_ST_CFG;
264 
265     /* Send L2CAP config req */
266     memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
267     cfg.mtu_present = true;
268     cfg.mtu = p_tbl->my_mtu;
269     cfg.flush_to_present = true;
270     cfg.flush_to = p_tbl->my_flush_to;
271     L2CA_ConfigReq(lcid, &cfg);
272   }
273 }
274 
275 /*******************************************************************************
276  *
277  * Function         avdt_l2c_connect_cfm_cback
278  *
279  * Description      This is the L2CAP connect confirm callback function.
280  *
281  *
282  * Returns          void
283  *
284  ******************************************************************************/
avdt_l2c_connect_cfm_cback(uint16_t lcid,uint16_t result)285 void avdt_l2c_connect_cfm_cback(uint16_t lcid, uint16_t result) {
286   tAVDT_TC_TBL* p_tbl;
287   tL2CAP_CFG_INFO cfg;
288   tAVDT_CCB* p_ccb;
289 
290   AVDT_TRACE_DEBUG("avdt_l2c_connect_cfm_cback lcid: %d, result: %d", lcid,
291                    result);
292   /* look up info for this channel */
293   p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
294   if (p_tbl != NULL) {
295     /* if in correct state */
296     if (p_tbl->state == AVDT_AD_ST_CONN) {
297       /* if result successful */
298       if (result == L2CAP_CONN_OK) {
299         if (p_tbl->tcid != AVDT_CHAN_SIG) {
300           /* set channel state */
301           p_tbl->state = AVDT_AD_ST_CFG;
302 
303           /* Send L2CAP config req */
304           memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
305           cfg.mtu_present = true;
306           cfg.mtu = p_tbl->my_mtu;
307           cfg.flush_to_present = true;
308           cfg.flush_to = p_tbl->my_flush_to;
309           L2CA_ConfigReq(lcid, &cfg);
310         } else {
311           p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx);
312           if (p_ccb == NULL) {
313             result = L2CAP_CONN_NO_RESOURCES;
314           } else {
315             /* set channel state */
316             p_tbl->state = AVDT_AD_ST_SEC_INT;
317             p_tbl->lcid = lcid;
318             p_tbl->cfg_flags = AVDT_L2C_CFG_CONN_INT;
319 
320             if (interop_match_addr(INTEROP_2MBPS_LINK_ONLY,
321                                    (const bt_bdaddr_t*)&p_ccb->peer_addr)) {
322               // Disable 3DH packets for AVDT ACL to improve sensitivity on HS
323               tACL_CONN* p_acl_cb =
324                   btm_bda_to_acl(p_ccb->peer_addr, BT_TRANSPORT_BR_EDR);
325               btm_set_packet_types(
326                   p_acl_cb,
327                   (btm_cb.btm_acl_pkt_types_supported |
328                    HCI_PKT_TYPES_MASK_NO_3_DH1 | HCI_PKT_TYPES_MASK_NO_3_DH3 |
329                    HCI_PKT_TYPES_MASK_NO_3_DH5));
330             }
331 
332             /* Check the security */
333             btm_sec_mx_access_request(p_ccb->peer_addr, AVDT_PSM, true,
334                                       BTM_SEC_PROTO_AVDT, AVDT_CHAN_SIG,
335                                       &avdt_sec_check_complete_orig, NULL);
336           }
337         }
338       }
339 
340       /* failure; notify adaption that channel closed */
341       if (result != L2CAP_CONN_OK) {
342         avdt_ad_tc_close_ind(p_tbl, result);
343       }
344     }
345   }
346 }
347 
348 /*******************************************************************************
349  *
350  * Function         avdt_l2c_config_cfm_cback
351  *
352  * Description      This is the L2CAP config confirm callback function.
353  *
354  *
355  * Returns          void
356  *
357  ******************************************************************************/
avdt_l2c_config_cfm_cback(uint16_t lcid,tL2CAP_CFG_INFO * p_cfg)358 void avdt_l2c_config_cfm_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
359   tAVDT_TC_TBL* p_tbl;
360 
361   /* look up info for this channel */
362   p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
363   if (p_tbl != NULL) {
364     p_tbl->lcid = lcid;
365 
366     /* if in correct state */
367     if (p_tbl->state == AVDT_AD_ST_CFG) {
368       /* if result successful */
369       if (p_cfg->result == L2CAP_CONN_OK) {
370         /* update cfg_flags */
371         p_tbl->cfg_flags |= AVDT_L2C_CFG_CFM_DONE;
372 
373         /* if configuration complete */
374         if (p_tbl->cfg_flags & AVDT_L2C_CFG_IND_DONE) {
375           avdt_ad_tc_open_ind(p_tbl);
376         }
377       }
378       /* else failure */
379       else {
380         /* Send L2CAP disconnect req */
381         L2CA_DisconnectReq(lcid);
382       }
383     }
384   }
385 }
386 
387 /*******************************************************************************
388  *
389  * Function         avdt_l2c_config_ind_cback
390  *
391  * Description      This is the L2CAP config indication callback function.
392  *
393  *
394  * Returns          void
395  *
396  ******************************************************************************/
avdt_l2c_config_ind_cback(uint16_t lcid,tL2CAP_CFG_INFO * p_cfg)397 void avdt_l2c_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
398   tAVDT_TC_TBL* p_tbl;
399 
400   /* look up info for this channel */
401   p_tbl = avdt_ad_tc_tbl_by_lcid(lcid);
402   if (p_tbl != NULL) {
403     /* store the mtu in tbl */
404     if (p_cfg->mtu_present) {
405       p_tbl->peer_mtu = p_cfg->mtu;
406     } else {
407       p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
408     }
409     AVDT_TRACE_DEBUG("peer_mtu: %d, lcid: x%x", p_tbl->peer_mtu, 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   tAVDT_TC_TBL* 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   tAVDT_TC_TBL* 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   tAVDT_TC_TBL* 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   tAVDT_TC_TBL* 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