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