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 #define LOG_TAG "avctp"
25 
26 #include <bluetooth/log.h>
27 
28 #include "avct_api.h"
29 #include "avct_int.h"
30 #include "btif/include/btif_av.h"
31 #include "internal_include/bt_target.h"
32 #include "l2c_api.h"
33 #include "l2cdefs.h"
34 #include "osi/include/allocator.h"
35 #include "osi/include/osi.h"
36 #include "stack/include/bt_hdr.h"
37 #include "types/raw_address.h"
38 
39 using namespace bluetooth;
40 
41 /* callback function declarations */
42 void avct_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
43                                 uint16_t psm, uint8_t id);
44 void avct_l2c_connect_cfm_cback(uint16_t lcid, uint16_t result);
45 void avct_l2c_config_cfm_cback(uint16_t lcid, uint16_t result,
46                                tL2CAP_CFG_INFO* p_cfg);
47 void avct_l2c_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg);
48 void avct_l2c_disconnect_ind_cback(uint16_t lcid, bool ack_needed);
49 void avct_l2c_congestion_ind_cback(uint16_t lcid, bool is_congested);
50 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 id)108 void avct_l2c_connect_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
109                                 uint16_t /* psm */, uint8_t id) {
110   tAVCT_LCB* p_lcb;
111   uint16_t result = L2CAP_CONN_OK;
112 
113   /* do we already have a channel for this peer? */
114   p_lcb = avct_lcb_by_bd(bd_addr);
115   if (p_lcb == NULL) {
116     /* no, allocate lcb */
117     p_lcb = avct_lcb_alloc(bd_addr);
118     if (p_lcb == NULL) {
119       /* no ccb available, reject L2CAP connection */
120       result = L2CAP_CONN_NO_RESOURCES;
121     }
122   }
123   /* else we already have a channel for this peer */
124   else {
125     if (!avct_l2c_is_passive(p_lcb) || (p_lcb->ch_state == AVCT_CH_OPEN)) {
126       /* this LCB included CT role - reject */
127       result = L2CAP_CONN_NO_RESOURCES;
128     } else {
129       /* TG role only - accept the connection from CT. move the channel ID to
130        * the conflict list */
131       p_lcb->conflict_lcid = p_lcb->ch_lcid;
132       log::verbose("avct_l2c_connect_ind_cback conflict_lcid:0x{:x}",
133                    p_lcb->conflict_lcid);
134     }
135   }
136 
137   if (p_lcb) {
138     log::verbose("avct_l2c_connect_ind_cback: 0x{:x}, res: {}, ch_state: {}",
139                  lcid, result, p_lcb->ch_state);
140   }
141 
142   /* If we reject the connection, send DisconnectReq */
143   if (result != L2CAP_CONN_OK) {
144     if (!L2CA_DisconnectReq(lcid)) {
145       log::warn("Unable to send L2CAP disconnect request peer:{} cid:{}",
146                 bd_addr, lcid);
147     }
148   }
149 
150   /* if result ok, proceed with connection */
151   if (result == L2CAP_CONN_OK) {
152     if (btif_av_src_sink_coexist_enabled()) {
153       tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
154       for (int i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
155         if (p_ccb && p_ccb->allocated && (p_ccb->p_lcb == NULL) &&
156             (p_ccb->cc.role == AVCT_ACP)) {
157           p_ccb->p_lcb = p_lcb;
158           log::verbose(
159               "ACP bind {} ccb to lcb, alloc {}, lcb {}, role {}, pid 0x{:x}",
160               i, p_ccb->allocated, fmt::ptr(p_ccb->p_lcb), p_ccb->cc.role,
161               p_ccb->cc.pid);
162         }
163       }
164     }
165     /* store LCID */
166     p_lcb->ch_lcid = lcid;
167 
168     /* transition to configuration state */
169     p_lcb->ch_state = AVCT_CH_CFG;
170   }
171 
172   if (p_lcb) log::verbose("ch_state cni: {}", p_lcb->ch_state);
173 }
174 
avct_on_l2cap_error(uint16_t lcid,uint16_t result)175 static void avct_on_l2cap_error(uint16_t lcid, uint16_t result) {
176   tAVCT_LCB* p_lcb = avct_lcb_by_lcid(lcid);
177   if (p_lcb == nullptr) return;
178   if (p_lcb->ch_state == AVCT_CH_CONN) {
179     log::verbose("avct_l2c_connect_cfm_cback conflict_lcid:0x{:x}",
180                  p_lcb->conflict_lcid);
181     if (p_lcb->conflict_lcid == lcid) {
182       p_lcb->conflict_lcid = 0;
183     } else {
184       tAVCT_LCB_EVT avct_lcb_evt;
185       avct_lcb_evt.result = result;
186       avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt);
187     }
188   } else if (p_lcb->ch_state == AVCT_CH_CFG) {
189     log::verbose("ERROR avct_l2c_config_cfm_cback L2CA_DisconnectReq {}",
190                  p_lcb->ch_state);
191     /* store result value */
192     p_lcb->ch_result = result;
193 
194     /* Send L2CAP disconnect req */
195     if (!L2CA_DisconnectReq(lcid)) {
196       log::warn("Unable to send L2CAP disconnect request peer:{} cid:{}",
197                 p_lcb->peer_addr, lcid);
198     }
199   }
200 }
201 
202 /*******************************************************************************
203  *
204  * Function         avct_l2c_connect_cfm_cback
205  *
206  * Description      This is the L2CAP connect confirm callback function.
207  *
208  *
209  * Returns          void
210  *
211  ******************************************************************************/
avct_l2c_connect_cfm_cback(uint16_t lcid,uint16_t result)212 void avct_l2c_connect_cfm_cback(uint16_t lcid, uint16_t result) {
213   tAVCT_LCB* p_lcb;
214 
215   /* look up lcb for this channel */
216   p_lcb = avct_lcb_by_lcid(lcid);
217   if (p_lcb != NULL) {
218     log::verbose(
219         "avct_l2c_connect_cfm_cback lcid:0x{:x} result: {} ch_state: {}, "
220         "conflict_lcid:0x{:x}",
221         lcid, result, p_lcb->ch_state, p_lcb->conflict_lcid);
222     /* if in correct state */
223     if (p_lcb->ch_state == AVCT_CH_CONN) {
224       /* if result successful */
225       if (result == L2CAP_CONN_OK) {
226         /* set channel state */
227         p_lcb->ch_state = AVCT_CH_CFG;
228       }
229       /* else failure */
230       else {
231         log::error("invoked with non OK status");
232       }
233     } else if (p_lcb->conflict_lcid == lcid) {
234       /* we must be in AVCT_CH_CFG state for the ch_lcid channel */
235       log::verbose(
236           "avct_l2c_connect_cfm_cback ch_state: {}, conflict_lcid:0x{:x}",
237           p_lcb->ch_state, p_lcb->conflict_lcid);
238       if (result == L2CAP_CONN_OK) {
239         /* just in case the peer also accepts our connection - Send L2CAP
240          * disconnect req */
241         if (!L2CA_DisconnectReq(lcid)) {
242           log::warn("Unable to send L2CAP disconnect request peer:{} cid:{}",
243                     p_lcb->peer_addr, lcid);
244         }
245       }
246       p_lcb->conflict_lcid = 0;
247     }
248     log::verbose("ch_state cnc: {}", p_lcb->ch_state);
249   }
250 }
251 
252 /*******************************************************************************
253  *
254  * Function         avct_l2c_config_cfm_cback
255  *
256  * Description      This is the L2CAP config confirm callback function.
257  *
258  *
259  * Returns          void
260  *
261  ******************************************************************************/
avct_l2c_config_cfm_cback(uint16_t lcid,uint16_t initiator,tL2CAP_CFG_INFO * p_cfg)262 void avct_l2c_config_cfm_cback(uint16_t lcid, uint16_t initiator,
263                                tL2CAP_CFG_INFO* p_cfg) {
264   avct_l2c_config_ind_cback(lcid, p_cfg);
265 
266   tAVCT_LCB* p_lcb;
267 
268   /* look up lcb for this channel */
269   p_lcb = avct_lcb_by_lcid(lcid);
270   if (p_lcb != NULL) {
271     log::verbose("avct_l2c_config_cfm_cback: 0x{:x}, ch_state: {},", lcid,
272                  p_lcb->ch_state);
273     /* if in correct state */
274     if (p_lcb->ch_state == AVCT_CH_CFG) {
275       p_lcb->ch_state = AVCT_CH_OPEN;
276       avct_lcb_event(p_lcb, AVCT_LCB_LL_OPEN_EVT, NULL);
277     }
278     log::verbose("ch_state cfc: {}", p_lcb->ch_state);
279   }
280 }
281 
282 /*******************************************************************************
283  *
284  * Function         avct_l2c_config_ind_cback
285  *
286  * Description      This is the L2CAP config indication callback function.
287  *
288  *
289  * Returns          void
290  *
291  ******************************************************************************/
avct_l2c_config_ind_cback(uint16_t lcid,tL2CAP_CFG_INFO * p_cfg)292 void avct_l2c_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
293   tAVCT_LCB* p_lcb;
294 
295   /* look up lcb for this channel */
296   p_lcb = avct_lcb_by_lcid(lcid);
297   if (p_lcb != NULL) {
298     log::verbose("avct_l2c_config_ind_cback: 0x{:x}, ch_state: {}", lcid,
299                  p_lcb->ch_state);
300     /* store the mtu in tbl */
301     if (p_cfg->mtu_present) {
302       p_lcb->peer_mtu = p_cfg->mtu;
303     } else {
304       p_lcb->peer_mtu = L2CAP_DEFAULT_MTU;
305     }
306   }
307 }
308 
309 /*******************************************************************************
310  *
311  * Function         avct_l2c_disconnect_ind_cback
312  *
313  * Description      This is the L2CAP disconnect indication callback function.
314  *
315  *
316  * Returns          void
317  *
318  ******************************************************************************/
avct_l2c_disconnect_ind_cback(uint16_t lcid,bool ack_needed)319 void avct_l2c_disconnect_ind_cback(uint16_t lcid, bool ack_needed) {
320   tAVCT_LCB* p_lcb;
321   uint16_t result = AVCT_RESULT_FAIL;
322 
323   /* look up lcb for this channel */
324   p_lcb = avct_lcb_by_lcid(lcid);
325   if (p_lcb != NULL) {
326     log::verbose("avct_l2c_disconnect_ind_cback: 0x{:x}, ch_state: {}", lcid,
327                  p_lcb->ch_state);
328     tAVCT_LCB_EVT avct_lcb_evt;
329     avct_lcb_evt.result = result;
330     avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt);
331     log::verbose("ch_state di: {}", p_lcb->ch_state);
332   }
333 }
334 
avct_l2c_disconnect(uint16_t lcid,uint16_t result)335 void avct_l2c_disconnect(uint16_t lcid, uint16_t result) {
336   if (!L2CA_DisconnectReq(lcid)) {
337     log::warn("Unable to send L2CAP disconnect request cid:{}", lcid);
338   }
339 
340   tAVCT_LCB* p_lcb;
341   uint16_t res;
342 
343   /* look up lcb for this channel */
344   p_lcb = avct_lcb_by_lcid(lcid);
345   if (p_lcb != NULL) {
346     log::verbose("avct_l2c_disconnect_cfm_cback: 0x{:x}, ch_state: {}, res: {}",
347                  lcid, p_lcb->ch_state, result);
348     /* result value may be previously stored */
349     res = (p_lcb->ch_result != 0) ? p_lcb->ch_result : result;
350     p_lcb->ch_result = 0;
351 
352     tAVCT_LCB_EVT avct_lcb_evt;
353     avct_lcb_evt.result = res;
354     avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt);
355     log::verbose("ch_state dc: {}", p_lcb->ch_state);
356   }
357 }
358 
359 /*******************************************************************************
360  *
361  * Function         avct_l2c_congestion_ind_cback
362  *
363  * Description      This is the L2CAP congestion indication callback function.
364  *
365  *
366  * Returns          void
367  *
368  ******************************************************************************/
avct_l2c_congestion_ind_cback(uint16_t lcid,bool is_congested)369 void avct_l2c_congestion_ind_cback(uint16_t lcid, bool is_congested) {
370   tAVCT_LCB* p_lcb;
371 
372   log::verbose("avct_l2c_congestion_ind_cback: 0x{:x}", lcid);
373   /* look up lcb for this channel */
374   p_lcb = avct_lcb_by_lcid(lcid);
375   if (p_lcb != NULL) {
376     tAVCT_LCB_EVT avct_lcb_evt;
377     avct_lcb_evt.cong = is_congested;
378     avct_lcb_event(p_lcb, AVCT_LCB_LL_CONG_EVT, &avct_lcb_evt);
379   }
380 }
381 
382 /*******************************************************************************
383  *
384  * Function         avct_l2c_data_ind_cback
385  *
386  * Description      This is the L2CAP data indication callback function.
387  *
388  *
389  * Returns          void
390  *
391  ******************************************************************************/
avct_l2c_data_ind_cback(uint16_t lcid,BT_HDR * p_buf)392 void avct_l2c_data_ind_cback(uint16_t lcid, BT_HDR* p_buf) {
393   tAVCT_LCB* p_lcb;
394 
395   log::verbose("avct_l2c_data_ind_cback: 0x{:x}", lcid);
396   /* look up lcb for this channel */
397   p_lcb = avct_lcb_by_lcid(lcid);
398   if (p_lcb != NULL) {
399     avct_lcb_event(p_lcb, AVCT_LCB_LL_MSG_EVT, (tAVCT_LCB_EVT*)&p_buf);
400   } else /* prevent buffer leak */
401   {
402     log::warn("ERROR -> avct_l2c_data_ind_cback drop buffer");
403     osi_free(p_buf);
404   }
405 }
406