1 /******************************************************************************
2 *
3 * Copyright 2008-2016 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 * Name: avct_l2c_br.cc
22 *
23 * Description: This AVCTP module interfaces to L2CAP
24 *
25 *****************************************************************************/
26
27 #define LOG_TAG "avctp"
28
29 #include <bluetooth/log.h>
30
31 #include "avct_api.h"
32 #include "avct_int.h"
33 #include "internal_include/bt_target.h"
34 #include "l2c_api.h"
35 #include "l2cdefs.h"
36 #include "osi/include/allocator.h"
37 #include "osi/include/osi.h"
38 #include "stack/include/bt_hdr.h"
39 #include "types/raw_address.h"
40
41 using namespace bluetooth;
42
43 /* callback function declarations */
44 void avct_l2c_br_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
45 uint16_t psm, uint8_t id);
46 void avct_l2c_br_connect_cfm_cback(uint16_t lcid, uint16_t result);
47 void avct_l2c_br_config_cfm_cback(uint16_t lcid, uint16_t result,
48 tL2CAP_CFG_INFO* p_cfg);
49 void avct_l2c_br_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg);
50 void avct_l2c_br_disconnect_ind_cback(uint16_t lcid, bool ack_needed);
51 void avct_l2c_br_congestion_ind_cback(uint16_t lcid, bool is_congested);
52 void avct_l2c_br_data_ind_cback(uint16_t lcid, BT_HDR* p_buf);
53 void avct_br_on_l2cap_error(uint16_t lcid, uint16_t result);
54
55 /* L2CAP callback function structure */
56 const tL2CAP_APPL_INFO avct_l2c_br_appl = {avct_l2c_br_connect_ind_cback,
57 avct_l2c_br_connect_cfm_cback,
58 avct_l2c_br_config_ind_cback,
59 avct_l2c_br_config_cfm_cback,
60 avct_l2c_br_disconnect_ind_cback,
61 NULL,
62 avct_l2c_br_data_ind_cback,
63 avct_l2c_br_congestion_ind_cback,
64 NULL,
65 avct_br_on_l2cap_error,
66 NULL,
67 NULL,
68 NULL,
69 NULL};
70
71 /*******************************************************************************
72 *
73 * Function avct_l2c_br_is_passive
74 *
75 * Description check is the CCB associated with the given BCB was created
76 * as passive
77 *
78 * Returns true, if the given CCB is created as AVCT_PASSIVE
79 *
80 ******************************************************************************/
avct_l2c_br_is_passive(tAVCT_BCB * p_bcb)81 static bool avct_l2c_br_is_passive(tAVCT_BCB* p_bcb) {
82 bool is_passive = false;
83 tAVCT_LCB* p_lcb;
84 tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
85 p_lcb = avct_lcb_by_bcb(p_bcb);
86 int i;
87
88 for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
89 if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) {
90 log::verbose("Is bcb associated ccb control passive :0x{:x}",
91 p_ccb->cc.control);
92 if (p_ccb->cc.control & AVCT_PASSIVE) {
93 is_passive = true;
94 break;
95 }
96 }
97 }
98 return is_passive;
99 }
100
101 /*******************************************************************************
102 *
103 * Function avct_l2c_br_connect_ind_cback
104 *
105 * Description This is the L2CAP connect indication callback function.
106 *
107 *
108 * Returns void
109 *
110 ******************************************************************************/
avct_l2c_br_connect_ind_cback(const RawAddress & bd_addr,uint16_t lcid,uint16_t,uint8_t id)111 void avct_l2c_br_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
112 uint16_t /* psm */, uint8_t id) {
113 tAVCT_LCB* p_lcb;
114 uint16_t result = L2CAP_CONN_NO_RESOURCES;
115 tAVCT_BCB* p_bcb;
116 tL2CAP_ERTM_INFO ertm_info;
117
118 p_lcb = avct_lcb_by_bd(bd_addr);
119 if (p_lcb != NULL) {
120 /* control channel exists */
121 p_bcb = avct_bcb_by_lcb(p_lcb);
122 p_bcb->peer_addr = bd_addr;
123
124 if (p_bcb->allocated == 0) {
125 /* browsing channel does not exist yet and the browsing channel is
126 * registered
127 * - accept connection */
128 p_bcb->allocated = p_lcb->allocated; /* copy the index from lcb */
129
130 result = L2CAP_CONN_OK;
131 } else {
132 if (!avct_l2c_br_is_passive(p_bcb) || (p_bcb->ch_state == AVCT_CH_OPEN)) {
133 /* this BCB included CT role - reject */
134 result = L2CAP_CONN_NO_RESOURCES;
135 } else {
136 /* add channel ID to conflict ID */
137 p_bcb->conflict_lcid = p_bcb->ch_lcid;
138 result = L2CAP_CONN_OK;
139 log::verbose("Detected conflict_lcid:0x{:x}", p_bcb->conflict_lcid);
140 }
141 }
142 }
143 /* else no control channel yet, reject */
144
145 /* Set the FCR options: Browsing channel mandates ERTM */
146 ertm_info.preferred_mode = L2CAP_FCR_ERTM_MODE;
147
148 /* If we reject the connection, send DisconnectReq */
149 if (result != L2CAP_CONN_OK) {
150 log::verbose("Connection rejected to lcid:0x{:x}", lcid);
151 if (!L2CA_DisconnectReq(lcid)) {
152 log::warn("Unable to send L2CAP disconnect request cid:{}", lcid);
153 }
154 }
155
156 /* if result ok, proceed with connection */
157 if (result == L2CAP_CONN_OK) {
158 /* store LCID */
159 p_bcb->ch_lcid = lcid;
160
161 /* transition to configuration state */
162 p_bcb->ch_state = AVCT_CH_CFG;
163 }
164 }
165
avct_br_on_l2cap_error(uint16_t lcid,uint16_t result)166 void avct_br_on_l2cap_error(uint16_t lcid, uint16_t result) {
167 tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid);
168 if (p_bcb == nullptr) return;
169
170 if (p_bcb->ch_state == AVCT_CH_CONN && p_bcb->conflict_lcid == lcid) {
171 log::verbose("Reset conflict_lcid:0x{:x}", p_bcb->conflict_lcid);
172 p_bcb->conflict_lcid = 0;
173 return;
174 }
175 /* store result value */
176 p_bcb->ch_result = result;
177
178 /* Send L2CAP disconnect req */
179 avct_l2c_br_disconnect(lcid, 0);
180 }
181
182 /*******************************************************************************
183 *
184 * Function avct_l2c_br_connect_cfm_cback
185 *
186 * Description This is the L2CAP connect confirm callback function.
187 *
188 *
189 * Returns void
190 *
191 ******************************************************************************/
avct_l2c_br_connect_cfm_cback(uint16_t lcid,uint16_t result)192 void avct_l2c_br_connect_cfm_cback(uint16_t lcid, uint16_t result) {
193 tAVCT_BCB* p_bcb;
194
195 /* look up bcb for this channel */
196 p_bcb = avct_bcb_by_lcid(lcid);
197
198 if (p_bcb == NULL) {
199 return;
200 }
201 /* if in correct state */
202 if (p_bcb->ch_state == AVCT_CH_CONN) {
203 /* if result successful */
204 if (result == L2CAP_CONN_OK) {
205 /* set channel state */
206 p_bcb->ch_state = AVCT_CH_CFG;
207 }
208 /* else failure */
209 else {
210 log::error("Invoked with non OK status");
211 }
212 } else if (p_bcb->conflict_lcid == lcid) {
213 /* we must be in AVCT_CH_CFG state for the ch_lcid channel */
214 if (result == L2CAP_CONN_OK) {
215 /* just in case the peer also accepts our connection - Send L2CAP
216 * disconnect req */
217 log::verbose("Disconnect conflict_lcid:0x{:x}", p_bcb->conflict_lcid);
218 if (!L2CA_DisconnectReq(lcid)) {
219 log::warn("Unable to send L2CAP disconnect request peer:{} cid:{}",
220 p_bcb->peer_addr, lcid);
221 }
222 }
223 p_bcb->conflict_lcid = 0;
224 }
225 }
226
227 /*******************************************************************************
228 *
229 * Function avct_l2c_br_config_cfm_cback
230 *
231 * Description This is the L2CAP config confirm callback function.
232 *
233 *
234 * Returns void
235 *
236 ******************************************************************************/
avct_l2c_br_config_cfm_cback(uint16_t lcid,uint16_t initiator,tL2CAP_CFG_INFO * p_cfg)237 void avct_l2c_br_config_cfm_cback(uint16_t lcid, uint16_t initiator,
238 tL2CAP_CFG_INFO* p_cfg) {
239 avct_l2c_br_config_ind_cback(lcid, p_cfg);
240
241 tAVCT_BCB* p_lcb;
242
243 /* look up lcb for this channel */
244 p_lcb = avct_bcb_by_lcid(lcid);
245 if ((p_lcb == NULL) || (p_lcb->ch_state != AVCT_CH_CFG)) return;
246
247 p_lcb->ch_state = AVCT_CH_OPEN;
248 avct_bcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL);
249 }
250
251 /*******************************************************************************
252 *
253 * Function avct_l2c_br_config_ind_cback
254 *
255 * Description This is the L2CAP config indication callback function.
256 *
257 *
258 * Returns void
259 *
260 ******************************************************************************/
avct_l2c_br_config_ind_cback(uint16_t lcid,tL2CAP_CFG_INFO * p_cfg)261 void avct_l2c_br_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
262 tAVCT_BCB* p_lcb;
263 uint16_t max_mtu = BT_DEFAULT_BUFFER_SIZE - L2CAP_MIN_OFFSET - BT_HDR_SIZE;
264
265 /* look up lcb for this channel */
266 p_lcb = avct_bcb_by_lcid(lcid);
267 if (p_lcb == NULL) return;
268
269 /* store the mtu in tbl */
270 p_lcb->peer_mtu = L2CAP_DEFAULT_MTU;
271 if (p_cfg->mtu_present) {
272 p_lcb->peer_mtu = p_cfg->mtu;
273 }
274
275 if (p_lcb->peer_mtu > max_mtu) {
276 p_lcb->peer_mtu = max_mtu;
277 }
278
279 log::verbose("peer_mtu:{} use:{}", p_lcb->peer_mtu, max_mtu);
280 }
281
282 /*******************************************************************************
283 *
284 * Function avct_l2c_br_disconnect_ind_cback
285 *
286 * Description This is the L2CAP disconnect indication callback function.
287 *
288 *
289 * Returns void
290 *
291 ******************************************************************************/
avct_l2c_br_disconnect_ind_cback(uint16_t lcid,bool ack_needed)292 void avct_l2c_br_disconnect_ind_cback(uint16_t lcid, bool ack_needed) {
293 tAVCT_BCB* p_lcb;
294 uint16_t result = AVCT_RESULT_FAIL;
295
296 /* look up lcb for this channel */
297 p_lcb = avct_bcb_by_lcid(lcid);
298 if (p_lcb == NULL) return;
299
300 tAVCT_LCB_EVT avct_lcb_evt;
301 avct_lcb_evt.result = result;
302 avct_bcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt);
303 }
304
avct_l2c_br_disconnect(uint16_t lcid,uint16_t result)305 void avct_l2c_br_disconnect(uint16_t lcid, uint16_t result) {
306 if (!L2CA_DisconnectReq(lcid)) {
307 log::warn("Unable to send L2CAP disconnect request cid:{}", lcid);
308 }
309
310 tAVCT_BCB* p_lcb;
311 uint16_t res;
312
313 /* look up lcb for this channel */
314 p_lcb = avct_bcb_by_lcid(lcid);
315 if (p_lcb == NULL) return;
316
317 /* result value may be previously stored */
318 res = (p_lcb->ch_result != 0) ? p_lcb->ch_result : result;
319 p_lcb->ch_result = 0;
320
321 tAVCT_LCB_EVT avct_lcb_evt;
322 avct_lcb_evt.result = res;
323 avct_bcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt);
324 }
325
326 /*******************************************************************************
327 *
328 * Function avct_l2c_br_congestion_ind_cback
329 *
330 * Description This is the L2CAP congestion indication callback function.
331 *
332 *
333 * Returns void
334 *
335 ******************************************************************************/
avct_l2c_br_congestion_ind_cback(uint16_t lcid,bool is_congested)336 void avct_l2c_br_congestion_ind_cback(uint16_t lcid, bool is_congested) {
337 tAVCT_BCB* p_lcb;
338
339 /* look up lcb for this channel */
340 p_lcb = avct_bcb_by_lcid(lcid);
341 if (p_lcb == NULL) return;
342
343 tAVCT_LCB_EVT avct_lcb_evt;
344 avct_lcb_evt.cong = is_congested;
345 avct_bcb_event(p_lcb, AVCT_LCB_LL_CONG_EVT, &avct_lcb_evt);
346 }
347
348 /*******************************************************************************
349 *
350 * Function avct_l2c_br_data_ind_cback
351 *
352 * Description This is the L2CAP data indication callback function.
353 *
354 *
355 * Returns void
356 *
357 ******************************************************************************/
avct_l2c_br_data_ind_cback(uint16_t lcid,BT_HDR * p_buf)358 void avct_l2c_br_data_ind_cback(uint16_t lcid, BT_HDR* p_buf) {
359 tAVCT_BCB* p_lcb;
360 tAVCT_LCB_EVT evt_data;
361
362 /* look up lcb for this channel */
363 p_lcb = avct_bcb_by_lcid(lcid);
364 if (p_lcb == NULL) {
365 /* prevent buffer leak */
366 osi_free(p_buf);
367 return;
368 }
369
370 evt_data.p_buf = p_buf;
371 avct_bcb_event(p_lcb, AVCT_LCB_LL_MSG_EVT, &evt_data);
372 }
373