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