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