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