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 #include <bluetooth/log.h>
28 
29 #include <cstddef>
30 #include <cstdint>
31 
32 #include "internal_include/bt_target.h"
33 #include "l2cap_types.h"
34 #include "osi/include/allocator.h"
35 #include "stack/avct/avct_int.h"
36 #include "stack/include/avct_api.h"
37 #include "stack/include/bt_hdr.h"
38 #include "stack/include/l2cap_interface.h"
39 #include "stack/include/l2cdefs.h"
40 #include "types/raw_address.h"
41 
42 using namespace bluetooth;
43 
44 /* callback function declarations */
45 static void avct_l2c_br_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid, uint16_t psm,
46                                           uint8_t id);
47 static void avct_l2c_br_connect_cfm_cback(uint16_t lcid, tL2CAP_CONN result);
48 static void avct_l2c_br_config_cfm_cback(uint16_t lcid, uint16_t result, tL2CAP_CFG_INFO* p_cfg);
49 static void avct_l2c_br_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg);
50 static void avct_l2c_br_disconnect_ind_cback(uint16_t lcid, bool ack_needed);
51 static void avct_l2c_br_congestion_ind_cback(uint16_t lcid, bool is_congested);
52 static void avct_l2c_br_data_ind_cback(uint16_t lcid, BT_HDR* p_buf);
53 static 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_CCB* p_ccb = &avct_cb.ccb[0];
84   tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb);
85   int i;
86 
87   for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
88     if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) {
89       log::verbose("Is bcb associated ccb control passive :0x{:x}", p_ccb->cc.control);
90       if (p_ccb->cc.control & AVCT_PASSIVE) {
91         is_passive = true;
92         break;
93       }
94     }
95   }
96   return is_passive;
97 }
98 
99 /*******************************************************************************
100  *
101  * Function         avct_l2c_br_connect_ind_cback
102  *
103  * Description      This is the L2CAP connect indication callback function.
104  *
105  *
106  * Returns          void
107  *
108  ******************************************************************************/
avct_l2c_br_connect_ind_cback(const RawAddress & bd_addr,uint16_t lcid,uint16_t,uint8_t)109 void avct_l2c_br_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid, uint16_t /* psm */,
110                                    uint8_t /* id */) {
111   tL2CAP_CONN result = tL2CAP_CONN::L2CAP_CONN_NO_RESOURCES;
112   tAVCT_BCB* p_bcb{nullptr};
113 
114   tAVCT_LCB* p_lcb = avct_lcb_by_bd(bd_addr);
115   if (p_lcb != NULL) {
116     /* control channel exists */
117     p_bcb = avct_bcb_by_lcb(p_lcb);
118     p_bcb->peer_addr = bd_addr;
119 
120     if (p_bcb->allocated == 0) {
121       /* browsing channel does not exist yet and the browsing channel is
122        * registered
123        * - accept connection */
124       p_bcb->allocated = p_lcb->allocated; /* copy the index from lcb */
125 
126       result = tL2CAP_CONN::L2CAP_CONN_OK;
127     } else {
128       if (!avct_l2c_br_is_passive(p_bcb) || (p_bcb->ch_state == AVCT_CH_OPEN)) {
129         /* this BCB included CT role - reject */
130         result = tL2CAP_CONN::L2CAP_CONN_NO_RESOURCES;
131       } else {
132         /* add channel ID to conflict ID */
133         p_bcb->conflict_lcid = p_bcb->ch_lcid;
134         result = tL2CAP_CONN::L2CAP_CONN_OK;
135         log::verbose("Detected conflict_lcid:0x{:x}", p_bcb->conflict_lcid);
136       }
137     }
138   }
139 
140   /* if result ok, proceed with connection */
141   if (result == tL2CAP_CONN::L2CAP_CONN_OK) {
142     /* store LCID */
143     p_bcb->ch_lcid = lcid;
144     /* transition to configuration state */
145     p_bcb->ch_state = AVCT_CH_CFG;
146   } else {
147     /* else no control channel yet, reject */
148     /* If we reject the connection, send DisconnectReq */
149     log::verbose("Connection rejected to lcid:0x{:x}", lcid);
150     if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) {
151       log::warn("Unable to send L2CAP disconnect request cid:0x{:04x}", lcid);
152     }
153   }
154 }
155 
avct_br_on_l2cap_error(uint16_t lcid,uint16_t result)156 void avct_br_on_l2cap_error(uint16_t lcid, uint16_t result) {
157   tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid);
158   if (p_bcb == nullptr) {
159     return;
160   }
161 
162   if (p_bcb->ch_state == AVCT_CH_CONN && p_bcb->conflict_lcid == lcid) {
163     log::verbose("Reset conflict_lcid:0x{:x}", p_bcb->conflict_lcid);
164     p_bcb->conflict_lcid = 0;
165     return;
166   }
167   /* store result value */
168   p_bcb->ch_result = result;
169 
170   /* Send L2CAP disconnect req */
171   avct_l2c_br_disconnect(lcid, 0 /* is_ack_needed */);
172 }
173 
174 /*******************************************************************************
175  *
176  * Function         avct_l2c_br_connect_cfm_cback
177  *
178  * Description      This is the L2CAP connect confirm callback function.
179  *
180  *
181  * Returns          void
182  *
183  ******************************************************************************/
avct_l2c_br_connect_cfm_cback(uint16_t lcid,tL2CAP_CONN result)184 void avct_l2c_br_connect_cfm_cback(uint16_t lcid, tL2CAP_CONN result) {
185   /* look up bcb for this channel */
186   tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid);
187   if (p_bcb == nullptr) {
188     log::warn(
189             "Received browse connect confirm callback without a browse control channel "
190             "lcid:0x{:02x} status:{}",
191             lcid, l2cap_result_code_text(result));
192     return;
193   }
194   if (p_bcb->ch_state == AVCT_CH_CONN) {
195     /* if result successful */
196     if (result == tL2CAP_CONN::L2CAP_CONN_OK) {
197       /* set channel state */
198       p_bcb->ch_state = AVCT_CH_CFG;
199     } else {
200       log::error("Invoked with non OK lcid:0x{:04x} state:{} status:{}", lcid,
201                  avct_ch_state_text(p_bcb->ch_state), l2cap_result_code_text(result));
202     }
203   } else if (p_bcb->conflict_lcid == lcid) {
204     /* we must be in AVCT_CH_CFG state for the ch_lcid channel */
205     if (result == tL2CAP_CONN::L2CAP_CONN_OK) {
206       /* just in case the peer also accepts our connection - Send L2CAP
207        * disconnect req */
208       log::verbose("Disconnect conflict_lcid:0x{:x}", p_bcb->conflict_lcid);
209       if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) {
210         log::warn("Unable to send L2CAP disconnect request peer:{} lcid:0x{:04x}", p_bcb->peer_addr,
211                   lcid);
212       }
213     } else {
214       log::error("Invoked with failure peer:{} lcid:0x{:04x} conflict_lcid:0x{:04x} status:{}",
215                  p_bcb->peer_addr, lcid, p_bcb->conflict_lcid, l2cap_result_code_text(result));
216     }
217     p_bcb->conflict_lcid = 0;
218   }
219 }
220 
221 /*******************************************************************************
222  *
223  * Function         avct_l2c_br_config_cfm_cback
224  *
225  * Description      This is the L2CAP config confirm callback function.
226  *
227  *
228  * Returns          void
229  *
230  ******************************************************************************/
avct_l2c_br_config_cfm_cback(uint16_t lcid,uint16_t initiator,tL2CAP_CFG_INFO * p_cfg)231 void avct_l2c_br_config_cfm_cback(uint16_t lcid, uint16_t initiator, tL2CAP_CFG_INFO* p_cfg) {
232   log::verbose("lcid:0x{:04x} initiator:{}", lcid, initiator);
233   avct_l2c_br_config_ind_cback(lcid, p_cfg);
234 
235   /* look up bcb for this channel */
236   tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid);
237   if ((p_bcb == NULL) || (p_bcb->ch_state != AVCT_CH_CFG)) {
238     log::warn(
239             "Got config confirm callback with no browse channel or browse channel not in "
240             "configuration state");
241     return;
242   }
243 
244   p_bcb->ch_state = AVCT_CH_OPEN;
245   avct_bcb_event(p_bcb, AVCT_LCB_LL_OPEN_EVT, NULL);
246 }
247 
248 /*******************************************************************************
249  *
250  * Function         avct_l2c_br_config_ind_cback
251  *
252  * Description      This is the L2CAP config indication callback function.
253  *
254  *
255  * Returns          void
256  *
257  ******************************************************************************/
avct_l2c_br_config_ind_cback(uint16_t lcid,tL2CAP_CFG_INFO * p_cfg)258 void avct_l2c_br_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
259   log::verbose("lcid:0x{:04x}", lcid);
260   const uint16_t max_mtu = BT_DEFAULT_BUFFER_SIZE - L2CAP_MIN_OFFSET - BT_HDR_SIZE;
261 
262   /* look up bcb for this channel */
263   tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid);
264   if (p_bcb == NULL) {
265     log::warn("Unable to find browse control block lcid:0x{:02x}", lcid);
266     return;
267   }
268 
269   /* store the mtu in tbl */
270   p_bcb->peer_mtu = L2CAP_DEFAULT_MTU;
271   if (p_cfg->mtu_present) {
272     p_bcb->peer_mtu = p_cfg->mtu;
273   }
274 
275   if (p_bcb->peer_mtu > max_mtu) {
276     p_bcb->peer_mtu = max_mtu;
277   }
278 
279   log::verbose("peer_mtu:{} max_mtu:{}", p_bcb->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)292 void avct_l2c_br_disconnect_ind_cback(uint16_t lcid, bool /* ack_needed */) {
293   uint16_t result = AVCT_RESULT_FAIL;
294 
295   /* look up bcb for this channel */
296   tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid);
297   if (p_bcb == NULL) {
298     return;
299   }
300 
301   tAVCT_LCB_EVT avct_lcb_evt;
302   avct_lcb_evt.result = result;
303   avct_bcb_event(p_bcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt);
304 }
305 
avct_l2c_br_disconnect(uint16_t lcid,uint16_t result)306 void avct_l2c_br_disconnect(uint16_t lcid, uint16_t result) {
307   if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) {
308     log::warn("Unable to send L2CAP disconnect request cid:0x{:04x}", lcid);
309   }
310 
311   /* look up bcb for this channel */
312   tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid);
313   if (p_bcb == NULL) {
314     return;
315   }
316 
317   /* result value may be previously stored */
318   uint16_t res = (p_bcb->ch_result != 0) ? p_bcb->ch_result : result;
319   p_bcb->ch_result = 0;
320 
321   tAVCT_LCB_EVT avct_lcb_evt;
322   avct_lcb_evt.result = res;
323   avct_bcb_event(p_bcb, 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   /* look up bcb for this channel */
338   tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid);
339   if (p_bcb == NULL) {
340     return;
341   }
342 
343   tAVCT_LCB_EVT avct_lcb_evt;
344   avct_lcb_evt.cong = is_congested;
345   avct_bcb_event(p_bcb, 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   /* look up bcb for this channel */
360   tAVCT_BCB* p_bcb = avct_bcb_by_lcid(lcid);
361   if (p_bcb == NULL) {
362     /* prevent buffer leak */
363     osi_free(p_buf);
364     return;
365   }
366 
367   tAVCT_LCB_EVT evt_data{};
368   evt_data.p_buf = p_buf;
369   avct_bcb_event(p_bcb, AVCT_LCB_LL_MSG_EVT, &evt_data);
370 }
371