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