1 /******************************************************************************
2  *
3  *  Copyright 2003-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 AVCTP module interfaces to L2CAP
22  *
23  ******************************************************************************/
24 #include <bluetooth/log.h>
25 
26 #include <cstddef>
27 #include <cstdint>
28 
29 #include "avct_api.h"
30 #include "avct_int.h"
31 #include "btif/include/btif_av.h"
32 #include "internal_include/bt_target.h"
33 #include "l2cap_types.h"
34 #include "osi/include/allocator.h"
35 #include "stack/include/bt_hdr.h"
36 #include "stack/include/l2cap_interface.h"
37 #include "stack/include/l2cdefs.h"
38 #include "types/raw_address.h"
39 
40 using namespace bluetooth;
41 
42 /* callback function declarations */
43 static void avct_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid, uint16_t psm,
44                                        uint8_t id);
45 static void avct_l2c_connect_cfm_cback(uint16_t lcid, tL2CAP_CONN result);
46 static void avct_l2c_config_cfm_cback(uint16_t lcid, uint16_t result, tL2CAP_CFG_INFO* p_cfg);
47 static void avct_l2c_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg);
48 static void avct_l2c_disconnect_ind_cback(uint16_t lcid, bool ack_needed);
49 static void avct_l2c_congestion_ind_cback(uint16_t lcid, bool is_congested);
50 static void avct_l2c_data_ind_cback(uint16_t lcid, BT_HDR* p_buf);
51 static void avct_on_l2cap_error(uint16_t lcid, uint16_t result);
52 
53 /* L2CAP callback function structure */
54 const tL2CAP_APPL_INFO avct_l2c_appl = {
55         avct_l2c_connect_ind_cback,
56         avct_l2c_connect_cfm_cback,
57         avct_l2c_config_ind_cback,
58         avct_l2c_config_cfm_cback,
59         avct_l2c_disconnect_ind_cback,
60         NULL,
61         avct_l2c_data_ind_cback,
62         avct_l2c_congestion_ind_cback,
63         NULL,
64         avct_on_l2cap_error,
65         NULL,
66         NULL,
67         NULL,
68         NULL,
69 };
70 
71 /*******************************************************************************
72  *
73  * Function         avct_l2c_is_passive
74  *
75  * Description      check is the CCB associated with the given LCB was created
76  *                  as passive
77  *
78  * Returns          true, if the given LCB is created as AVCT_PASSIVE
79  *
80  ******************************************************************************/
avct_l2c_is_passive(tAVCT_LCB * p_lcb)81 static bool avct_l2c_is_passive(tAVCT_LCB* p_lcb) {
82   bool is_passive = false;
83   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
84   int i;
85 
86   for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
87     if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) {
88       log::verbose("avct_l2c_is_ct control:x{:x}", p_ccb->cc.control);
89       if (p_ccb->cc.control & AVCT_PASSIVE) {
90         is_passive = true;
91         break;
92       }
93     }
94   }
95   return is_passive;
96 }
97 
98 /*******************************************************************************
99  *
100  * Function         avct_l2c_connect_ind_cback
101  *
102  * Description      This is the L2CAP connect indication callback function.
103  *
104  *
105  * Returns          void
106  *
107  ******************************************************************************/
avct_l2c_connect_ind_cback(const RawAddress & bd_addr,uint16_t lcid,uint16_t,uint8_t)108 void avct_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid, uint16_t /* psm */,
109                                 uint8_t /* id */) {
110   tL2CAP_CONN result = tL2CAP_CONN::L2CAP_CONN_OK;
111 
112   /* do we already have a channel for this peer? */
113   tAVCT_LCB* p_lcb = avct_lcb_by_bd(bd_addr);
114   if (p_lcb == nullptr) {
115     /* no, allocate lcb */
116     p_lcb = avct_lcb_alloc(bd_addr);
117     if (p_lcb == nullptr) {
118       /* no ccb available, reject L2CAP connection */
119       result = tL2CAP_CONN::L2CAP_CONN_NO_RESOURCES;
120     }
121   } else {
122     /* else we already have a channel for this peer */
123     if (!avct_l2c_is_passive(p_lcb) || (p_lcb->ch_state == AVCT_CH_OPEN)) {
124       /* this LCB included CT role - reject */
125       result = tL2CAP_CONN::L2CAP_CONN_NO_RESOURCES;
126     } else {
127       /* TG role only - accept the connection from CT. move the channel ID to
128        * the conflict list */
129       p_lcb->conflict_lcid = p_lcb->ch_lcid;
130       log::verbose("Accept connection from controller lcid:0x{:04x} conflict_lcid:0x{:04x}", lcid,
131                    p_lcb->conflict_lcid);
132     }
133   }
134 
135   /* if result ok, proceed with connection */
136   if (result == tL2CAP_CONN::L2CAP_CONN_OK) {
137     if (btif_av_src_sink_coexist_enabled()) {
138       tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
139       for (int i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
140         if (p_ccb && p_ccb->allocated && (p_ccb->p_lcb == NULL) &&
141             (p_ccb->cc.role == AVCT_ROLE_ACCEPTOR)) {
142           p_ccb->p_lcb = p_lcb;
143           log::verbose(
144                   "Source and sink coexistance enabled acceptor bind ccb to lcb idx:{} "
145                   "allocated:{} role {} pid 0x{:x}",
146                   i, p_ccb->allocated, avct_role_text(p_ccb->cc.role), p_ccb->cc.pid);
147         }
148       }
149     }
150     /* store LCID */
151     p_lcb->ch_lcid = lcid;
152 
153     /* transition to configuration state */
154     p_lcb->ch_state = AVCT_CH_CFG;
155 
156     log::debug("Received remote connection request peer:{} lcid:0x{:04x} ch_state:{}", bd_addr,
157                lcid, avct_ch_state_text(p_lcb->ch_state));
158   } else {
159     /* If we reject the connection, send DisconnectReq */
160     if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) {
161       log::warn("Unable to send L2CAP disconnect request peer:{} lcid:0x{:04x}", bd_addr, lcid);
162     }
163     log::info(
164             "Ignoring remote connection request no link or no resources peer:{} lcid:0x{:04x} "
165             "lcb_exists:{}",
166             bd_addr, lcid, p_lcb != nullptr);
167   }
168 }
169 
avct_on_l2cap_error(uint16_t lcid,uint16_t result)170 static void avct_on_l2cap_error(uint16_t lcid, uint16_t result) {
171   tAVCT_LCB* p_lcb = avct_lcb_by_lcid(lcid);
172   if (p_lcb == nullptr) {
173     return;
174   }
175   if (p_lcb->ch_state == AVCT_CH_CONN) {
176     log::verbose("avct_l2c_connect_cfm_cback conflict_lcid:0x{:x}", p_lcb->conflict_lcid);
177     if (p_lcb->conflict_lcid == lcid) {
178       p_lcb->conflict_lcid = 0;
179     } else {
180       tAVCT_LCB_EVT avct_lcb_evt;
181       avct_lcb_evt.result = result;
182       avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt);
183     }
184   } else if (p_lcb->ch_state == AVCT_CH_CFG) {
185     log::verbose("ERROR avct_l2c_config_cfm_cback L2CA_DisconnectReq {}", p_lcb->ch_state);
186     /* store result value */
187     p_lcb->ch_result = result;
188 
189     /* Send L2CAP disconnect req */
190     if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) {
191       log::warn("Unable to send L2CAP disconnect request peer:{} lcid:0x{:04x}", p_lcb->peer_addr,
192                 lcid);
193     }
194   }
195 }
196 
197 /*******************************************************************************
198  *
199  * Function         avct_l2c_connect_cfm_cback
200  *
201  * Description      This is the L2CAP connect confirm callback function.
202  *
203  *
204  * Returns          void
205  *
206  ******************************************************************************/
avct_l2c_connect_cfm_cback(uint16_t lcid,tL2CAP_CONN result)207 void avct_l2c_connect_cfm_cback(uint16_t lcid, tL2CAP_CONN result) {
208   tAVCT_LCB* p_lcb;
209 
210   /* look up lcb for this channel */
211   p_lcb = avct_lcb_by_lcid(lcid);
212   if (p_lcb != NULL) {
213     log::verbose("lcid:0x{:04x} result:{} ch_state:{} conflict_lcid:0x{:04x}", lcid, result,
214                  avct_ch_state_text(p_lcb->ch_state), p_lcb->conflict_lcid);
215     /* if in correct state */
216     if (p_lcb->ch_state == AVCT_CH_CONN) {
217       /* if result successful */
218       if (result == tL2CAP_CONN::L2CAP_CONN_OK) {
219         /* set channel state */
220         p_lcb->ch_state = AVCT_CH_CFG;
221       } else {
222         /* else failure */
223         log::error("invoked with non OK status lcid:0x{:04x} result:{}", lcid,
224                    l2cap_result_code_text(result));
225       }
226     } else if (p_lcb->conflict_lcid == lcid) {
227       /* we must be in AVCT_CH_CFG state for the ch_lcid channel */
228       log::verbose("ch_state:{} conflict_lcid:0x{:04x}", avct_ch_state_text(p_lcb->ch_state),
229                    p_lcb->conflict_lcid);
230       if (result == tL2CAP_CONN::L2CAP_CONN_OK) {
231         /* just in case the peer also accepts our connection - Send L2CAP
232          * disconnect req */
233         if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) {
234           log::warn("Unable to send L2CAP disconnect request peer:{} cid:0x{:04x}",
235                     p_lcb->peer_addr, lcid);
236         }
237       }
238       p_lcb->conflict_lcid = 0;
239     }
240     log::verbose("ch_state:{}", avct_ch_state_text(p_lcb->ch_state));
241   }
242 }
243 
244 /*******************************************************************************
245  *
246  * Function         avct_l2c_config_cfm_cback
247  *
248  * Description      This is the L2CAP config confirm callback function.
249  *
250  *
251  * Returns          void
252  *
253  ******************************************************************************/
avct_l2c_config_cfm_cback(uint16_t lcid,uint16_t is_initiator_local,tL2CAP_CFG_INFO * p_cfg)254 void avct_l2c_config_cfm_cback(uint16_t lcid, uint16_t is_initiator_local, tL2CAP_CFG_INFO* p_cfg) {
255   avct_l2c_config_ind_cback(lcid, p_cfg);
256 
257   /* look up lcb for this channel */
258   tAVCT_LCB* p_lcb = avct_lcb_by_lcid(lcid);
259   if (p_lcb == nullptr) {
260     log::warn("Received config confirm for unknown peer lcid::0x{:04x} is_initiator_local:{}", lcid,
261               is_initiator_local);
262     return;
263   }
264 
265   /* if in correct state */
266   if (p_lcb->ch_state == AVCT_CH_CFG) {
267     p_lcb->ch_state = AVCT_CH_OPEN;
268     avct_lcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL);
269   } else {
270     log::warn(
271             "Received config confirm in wrong state lcid:0x{:04x} ch_state:{} "
272             "is_initiator_local:{}",
273             lcid, avct_ch_state_text(p_lcb->ch_state), is_initiator_local);
274   }
275   log::verbose("ch_state lcid:0x{:04x} ch_state:{} is_initiator_local:{}", lcid,
276                avct_ch_state_text(p_lcb->ch_state), is_initiator_local);
277 }
278 
279 /*******************************************************************************
280  *
281  * Function         avct_l2c_config_ind_cback
282  *
283  * Description      This is the L2CAP config indication callback function.
284  *
285  *
286  * Returns          void
287  *
288  ******************************************************************************/
avct_l2c_config_ind_cback(uint16_t lcid,tL2CAP_CFG_INFO * p_cfg)289 void avct_l2c_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
290   tAVCT_LCB* p_lcb;
291 
292   /* look up lcb for this channel */
293   p_lcb = avct_lcb_by_lcid(lcid);
294   if (p_lcb != NULL) {
295     log::verbose("avct_l2c_config_ind_cback: 0x{:04x}, ch_state:{}", lcid,
296                  avct_ch_state_text(p_lcb->ch_state));
297     /* store the mtu in tbl */
298     if (p_cfg->mtu_present) {
299       p_lcb->peer_mtu = p_cfg->mtu;
300     } else {
301       p_lcb->peer_mtu = L2CAP_DEFAULT_MTU;
302     }
303   }
304 }
305 
306 /*******************************************************************************
307  *
308  * Function         avct_l2c_disconnect_ind_cback
309  *
310  * Description      This is the L2CAP disconnect indication callback function.
311  *
312  *
313  * Returns          void
314  *
315  ******************************************************************************/
avct_l2c_disconnect_ind_cback(uint16_t lcid,bool)316 void avct_l2c_disconnect_ind_cback(uint16_t lcid, bool /* ack_needed */) {
317   tAVCT_LCB* p_lcb;
318   uint16_t result = AVCT_RESULT_FAIL;
319 
320   /* look up lcb for this channel */
321   p_lcb = avct_lcb_by_lcid(lcid);
322   if (p_lcb != NULL) {
323     log::verbose("avct_l2c_disconnect_ind_cback: 0x{:x}, ch_state: {}", lcid, p_lcb->ch_state);
324     tAVCT_LCB_EVT avct_lcb_evt;
325     avct_lcb_evt.result = result;
326     avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt);
327     log::verbose("ch_state di: {}", p_lcb->ch_state);
328   }
329 }
330 
avct_l2c_disconnect(uint16_t lcid,uint16_t result)331 void avct_l2c_disconnect(uint16_t lcid, uint16_t result) {
332   if (!stack::l2cap::get_interface().L2CA_DisconnectReq(lcid)) {
333     log::warn("Unable to send L2CAP disconnect request cid:{}", lcid);
334   }
335 
336   tAVCT_LCB* p_lcb;
337   uint16_t res;
338 
339   /* look up lcb for this channel */
340   p_lcb = avct_lcb_by_lcid(lcid);
341   if (p_lcb != NULL) {
342     log::verbose("avct_l2c_disconnect_cfm_cback: 0x{:x}, ch_state: {}, res: {}", lcid,
343                  p_lcb->ch_state, result);
344     /* result value may be previously stored */
345     res = (p_lcb->ch_result != 0) ? p_lcb->ch_result : result;
346     p_lcb->ch_result = 0;
347 
348     tAVCT_LCB_EVT avct_lcb_evt;
349     avct_lcb_evt.result = res;
350     avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt);
351     log::verbose("ch_state:{}", p_lcb->ch_state);
352   }
353 }
354 
355 /*******************************************************************************
356  *
357  * Function         avct_l2c_congestion_ind_cback
358  *
359  * Description      This is the L2CAP congestion indication callback function.
360  *
361  *
362  * Returns          void
363  *
364  ******************************************************************************/
avct_l2c_congestion_ind_cback(uint16_t lcid,bool is_congested)365 void avct_l2c_congestion_ind_cback(uint16_t lcid, bool is_congested) {
366   tAVCT_LCB* p_lcb;
367 
368   log::verbose("avct_l2c_congestion_ind_cback: 0x{:x}", lcid);
369   /* look up lcb for this channel */
370   p_lcb = avct_lcb_by_lcid(lcid);
371   if (p_lcb != NULL) {
372     tAVCT_LCB_EVT avct_lcb_evt;
373     avct_lcb_evt.cong = is_congested;
374     avct_lcb_event(p_lcb, AVCT_LCB_LL_CONG_EVT, &avct_lcb_evt);
375   }
376 }
377 
378 /*******************************************************************************
379  *
380  * Function         avct_l2c_data_ind_cback
381  *
382  * Description      This is the L2CAP data indication callback function.
383  *
384  *
385  * Returns          void
386  *
387  ******************************************************************************/
avct_l2c_data_ind_cback(uint16_t lcid,BT_HDR * p_buf)388 void avct_l2c_data_ind_cback(uint16_t lcid, BT_HDR* p_buf) {
389   log::verbose("lcid: 0x{:02x}", lcid);
390   /* look up lcb for this channel */
391   tAVCT_LCB* p_lcb = avct_lcb_by_lcid(lcid);
392   if (p_lcb != NULL) {
393     avct_lcb_event(p_lcb, AVCT_LCB_LL_MSG_EVT, (tAVCT_LCB_EVT*)&p_buf);
394   } else {
395     /* prevent buffer leak */
396     log::warn("ERROR -> avct_l2c_data_ind_cback drop buffer");
397     osi_free(p_buf);
398   }
399 }
400