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