1 /******************************************************************************
2  *
3  *  Copyright 2001-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 file contains the main BNEP functions
22  *
23  ******************************************************************************/
24 
25 #include <bluetooth/log.h>
26 #include <string.h>
27 
28 #include <cstdint>
29 
30 #include "bnep_api.h"
31 #include "bnep_int.h"
32 #include "bta/include/bta_sec_api.h"
33 #include "hci/controller_interface.h"
34 #include "internal_include/bt_target.h"
35 #include "l2cap_types.h"
36 #include "l2cdefs.h"
37 #include "main/shim/entry.h"
38 #include "main/shim/helpers.h"
39 #include "osi/include/alarm.h"
40 #include "osi/include/allocator.h"
41 #include "osi/include/fixed_queue.h"
42 #include "stack/include/bt_hdr.h"
43 #include "stack/include/bt_psm_types.h"
44 #include "stack/include/bt_types.h"
45 #include "stack/include/l2cap_interface.h"
46 #include "types/bt_transport.h"
47 #include "types/raw_address.h"
48 
49 using namespace bluetooth;
50 
51 /******************************************************************************/
52 /*                     G L O B A L    B N E P       D A T A                   */
53 /******************************************************************************/
54 tBNEP_CB bnep_cb;
55 
56 const uint16_t bnep_frame_hdr_sizes[] = {14, 1, 2, 8, 8};
57 
58 /******************************************************************************/
59 /*            L O C A L    F U N C T I O N     P R O T O T Y P E S            */
60 /******************************************************************************/
61 static void bnep_connect_ind(const RawAddress& bd_addr, uint16_t l2cap_cid, uint16_t psm,
62                              uint8_t l2cap_id);
63 static void bnep_connect_cfm(uint16_t l2cap_cid, tL2CAP_CONN result);
64 static void bnep_config_cfm(uint16_t l2cap_cid, uint16_t result, tL2CAP_CFG_INFO* p_cfg);
65 static void bnep_disconnect_ind(uint16_t l2cap_cid, bool ack_needed);
66 static void bnep_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg);
67 static void bnep_congestion_ind(uint16_t lcid, bool is_congested);
68 static void bnep_on_l2cap_error(uint16_t l2cap_cid, uint16_t result);
69 /*******************************************************************************
70  *
71  * Function         bnep_register_with_l2cap
72  *
73  * Description      This function registers BNEP PSM with L2CAP
74  *
75  * Returns          void
76  *
77  ******************************************************************************/
bnep_register_with_l2cap(void)78 tBNEP_RESULT bnep_register_with_l2cap(void) {
79   /* Initialize the L2CAP configuration. We only care about MTU and flush */
80   memset(&bnep_cb.l2cap_my_cfg, 0, sizeof(tL2CAP_CFG_INFO));
81 
82   bnep_cb.l2cap_my_cfg.mtu_present = true;
83   bnep_cb.l2cap_my_cfg.mtu = BNEP_MTU_SIZE;
84 
85   bnep_cb.reg_info.pL2CA_ConnectInd_Cb = bnep_connect_ind;
86   bnep_cb.reg_info.pL2CA_ConnectCfm_Cb = bnep_connect_cfm;
87   bnep_cb.reg_info.pL2CA_ConfigInd_Cb = nullptr;
88   bnep_cb.reg_info.pL2CA_ConfigCfm_Cb = bnep_config_cfm;
89   bnep_cb.reg_info.pL2CA_DisconnectInd_Cb = bnep_disconnect_ind;
90   bnep_cb.reg_info.pL2CA_DataInd_Cb = bnep_data_ind;
91   bnep_cb.reg_info.pL2CA_CongestionStatus_Cb = bnep_congestion_ind;
92   bnep_cb.reg_info.pL2CA_Error_Cb = bnep_on_l2cap_error;
93 
94   /* Now, register with L2CAP */
95   if (!stack::l2cap::get_interface().L2CA_RegisterWithSecurity(
96               BT_PSM_BNEP, bnep_cb.reg_info, false /* enable_snoop */, nullptr, BNEP_MTU_SIZE,
97               BNEP_MTU_SIZE, BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)) {
98     log::error("BNEP - Registration failed");
99     return BNEP_SECURITY_FAIL;
100   }
101 
102   return BNEP_SUCCESS;
103 }
104 
105 /*******************************************************************************
106  *
107  * Function         bnep_connect_ind
108  *
109  * Description      This function handles an inbound connection indication
110  *                  from L2CAP. This is the case where we are acting as a
111  *                  server.
112  *
113  * Returns          void
114  *
115  ******************************************************************************/
bnep_connect_ind(const RawAddress & bd_addr,uint16_t l2cap_cid,uint16_t,uint8_t)116 static void bnep_connect_ind(const RawAddress& bd_addr, uint16_t l2cap_cid, uint16_t /* psm */,
117                              uint8_t /* l2cap_id */) {
118   tBNEP_CONN* p_bcb = bnepu_find_bcb_by_bd_addr(bd_addr);
119 
120   /* If we are not acting as server, or already have a connection, or have */
121   /* no more resources to handle the connection, reject the connection.    */
122   if (!(bnep_cb.profile_registered) || (p_bcb) || ((p_bcb = bnepu_allocate_bcb(bd_addr)) == NULL)) {
123     if (!stack::l2cap::get_interface().L2CA_DisconnectReq(l2cap_cid)) {
124       log::warn("Unable to request L2CAP disconnect peer:{} cid:{}", bd_addr, l2cap_cid);
125     }
126     return;
127   }
128 
129   /* Transition to the next appropriate state, waiting for config setup. */
130   p_bcb->con_state = BNEP_STATE_CFG_SETUP;
131 
132   /* Save the L2CAP Channel ID. */
133   p_bcb->l2cap_cid = l2cap_cid;
134 
135   /* Start timer waiting for config setup */
136   alarm_set_on_mloop(p_bcb->conn_timer, BNEP_CONN_TIMEOUT_MS, bnep_conn_timer_timeout, p_bcb);
137 
138   log::debug("BNEP - Rcvd L2CAP conn ind, CID: 0x{:x}", p_bcb->l2cap_cid);
139 }
140 
bnep_on_l2cap_error(uint16_t l2cap_cid,uint16_t)141 static void bnep_on_l2cap_error(uint16_t l2cap_cid, uint16_t /* result */) {
142   tBNEP_CONN* p_bcb = bnepu_find_bcb_by_cid(l2cap_cid);
143   if (p_bcb == nullptr) {
144     return;
145   }
146 
147   /* Tell the upper layer, if there is a callback */
148   if ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb)) {
149     (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, false);
150   }
151 
152   if (!stack::l2cap::get_interface().L2CA_DisconnectReq(p_bcb->l2cap_cid)) {
153     log::warn("Unable to request L2CAP disconnect peer:{} cid:{}", p_bcb->rem_bda, l2cap_cid);
154   }
155 
156   bnepu_release_bcb(p_bcb);
157 }
158 
159 /*******************************************************************************
160  *
161  * Function         bnep_connect_cfm
162  *
163  * Description      This function handles the connect confirm events
164  *                  from L2CAP. This is the case when we are acting as a
165  *                  client and have sent a connect request.
166  *
167  * Returns          void
168  *
169  ******************************************************************************/
bnep_connect_cfm(uint16_t l2cap_cid,tL2CAP_CONN result)170 static void bnep_connect_cfm(uint16_t l2cap_cid, tL2CAP_CONN result) {
171   tBNEP_CONN* p_bcb;
172 
173   /* Find CCB based on CID */
174   p_bcb = bnepu_find_bcb_by_cid(l2cap_cid);
175   if (p_bcb == NULL) {
176     log::warn("BNEP - Rcvd conn cnf for unknown CID 0x{:x}", l2cap_cid);
177     return;
178   }
179 
180   /* If the connection response contains success status, then */
181   /* Transition to the next state and startup the timer.      */
182   if ((result == tL2CAP_CONN::L2CAP_CONN_OK) && (p_bcb->con_state == BNEP_STATE_CONN_START)) {
183     p_bcb->con_state = BNEP_STATE_CFG_SETUP;
184 
185     /* Start timer waiting for config results */
186     alarm_set_on_mloop(p_bcb->conn_timer, BNEP_CONN_TIMEOUT_MS, bnep_conn_timer_timeout, p_bcb);
187 
188     log::debug("BNEP - got conn cnf, sent cfg req, CID: 0x{:x}", p_bcb->l2cap_cid);
189   } else {
190     log::error("invoked with non OK status");
191   }
192 }
193 
194 /*******************************************************************************
195  *
196  * Function         bnep_config_cfm
197  *
198  * Description      This function processes the L2CAP configuration confirmation
199  *                  event.
200  *
201  * Returns          void
202  *
203  ******************************************************************************/
bnep_config_cfm(uint16_t l2cap_cid,uint16_t,tL2CAP_CFG_INFO *)204 static void bnep_config_cfm(uint16_t l2cap_cid, uint16_t /* initiator */,
205                             tL2CAP_CFG_INFO* /* p_cfg */) {
206   tBNEP_CONN* p_bcb;
207 
208   log::debug("BNEP - Rcvd cfg cfm, CID: 0x{:x}", l2cap_cid);
209 
210   /* Find CCB based on CID */
211   p_bcb = bnepu_find_bcb_by_cid(l2cap_cid);
212   if (p_bcb == NULL) {
213     log::warn("BNEP - Rcvd L2CAP cfg ind, unknown CID: 0x{:x}", l2cap_cid);
214     return;
215   }
216 
217   /* For now, always accept configuration from the other side */
218   p_bcb->con_state = BNEP_STATE_SEC_CHECKING;
219 
220   /* Start timer waiting for setup or response */
221   alarm_set_on_mloop(p_bcb->conn_timer, BNEP_HOST_TIMEOUT_MS, bnep_conn_timer_timeout, p_bcb);
222 
223   if (p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) {
224     bnep_sec_check_complete(&p_bcb->rem_bda, BT_TRANSPORT_BR_EDR, p_bcb);
225   }
226 }
227 
228 /*******************************************************************************
229  *
230  * Function         bnep_disconnect_ind
231  *
232  * Description      This function handles a disconnect event from L2CAP. If
233  *                  requested to, we ack the disconnect before dropping the CCB
234  *
235  * Returns          void
236  *
237  ******************************************************************************/
bnep_disconnect_ind(uint16_t l2cap_cid,bool)238 static void bnep_disconnect_ind(uint16_t l2cap_cid, bool /* ack_needed */) {
239   tBNEP_CONN* p_bcb;
240 
241   /* Find CCB based on CID */
242   p_bcb = bnepu_find_bcb_by_cid(l2cap_cid);
243   if (p_bcb == NULL) {
244     log::warn("BNEP - Rcvd L2CAP disc, unknown CID: 0x{:x}", l2cap_cid);
245     return;
246   }
247 
248   log::debug("BNEP - Rcvd L2CAP disc, CID: 0x{:x}", l2cap_cid);
249 
250   /* Tell the user if there is a callback */
251   if (p_bcb->con_state == BNEP_STATE_CONNECTED) {
252     if (bnep_cb.p_conn_state_cb) {
253       (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_DISCONNECTED, false);
254     }
255   } else {
256     if ((bnep_cb.p_conn_state_cb) && ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) ||
257                                       (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED))) {
258       (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, false);
259     }
260   }
261 
262   bnepu_release_bcb(p_bcb);
263 }
264 
265 /*******************************************************************************
266  *
267  * Function         bnep_congestion_ind
268  *
269  * Description      This is a callback function called by L2CAP when
270  *                  congestion status changes
271  *
272  ******************************************************************************/
bnep_congestion_ind(uint16_t l2cap_cid,bool is_congested)273 static void bnep_congestion_ind(uint16_t l2cap_cid, bool is_congested) {
274   tBNEP_CONN* p_bcb;
275 
276   /* Find BCB based on CID */
277   p_bcb = bnepu_find_bcb_by_cid(l2cap_cid);
278   if (p_bcb == NULL) {
279     log::warn("BNEP - Rcvd L2CAP cong, unknown CID: 0x{:x}", l2cap_cid);
280     return;
281   }
282 
283   if (is_congested) {
284     p_bcb->con_flags |= BNEP_FLAGS_L2CAP_CONGESTED;
285     if (bnep_cb.p_tx_data_flow_cb) {
286       bnep_cb.p_tx_data_flow_cb(p_bcb->handle, BNEP_TX_FLOW_OFF);
287     }
288   } else {
289     p_bcb->con_flags &= ~BNEP_FLAGS_L2CAP_CONGESTED;
290 
291     if (bnep_cb.p_tx_data_flow_cb) {
292       bnep_cb.p_tx_data_flow_cb(p_bcb->handle, BNEP_TX_FLOW_ON);
293     }
294 
295     /* While not congested, send as many buffers as we can */
296     while (!(p_bcb->con_flags & BNEP_FLAGS_L2CAP_CONGESTED)) {
297       BT_HDR* p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_bcb->xmit_q);
298 
299       if (!p_buf) {
300         break;
301       }
302 
303       uint16_t len = p_buf->len;
304 
305       if (stack::l2cap::get_interface().L2CA_DataWrite(l2cap_cid, p_buf) !=
306           tL2CAP_DW_RESULT::SUCCESS) {
307         log::warn("Unable to write L2CAP data peer:{} cid:{} len:{}", p_bcb->rem_bda, l2cap_cid,
308                   len);
309       }
310     }
311   }
312 }
313 
314 /*******************************************************************************
315  *
316  * Function         bnep_data_ind
317  *
318  * Description      This function is called when data is received from L2CAP.
319  *                  if we are the originator of the connection, we are the SDP
320  *                  client, and the received message is queued for the client.
321  *
322  *                  If we are the destination of the connection, we are the SDP
323  *                  server, so the message is passed to the server processing
324  *                  function.
325  *
326  * Returns          void
327  *
328  ******************************************************************************/
bnep_data_ind(uint16_t l2cap_cid,BT_HDR * p_buf)329 static void bnep_data_ind(uint16_t l2cap_cid, BT_HDR* p_buf) {
330   tBNEP_CONN* p_bcb;
331   uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
332   uint16_t rem_len = p_buf->len;
333   if (rem_len == 0) {
334     osi_free(p_buf);
335     return;
336   }
337   uint8_t type, ctrl_type, ext_type = 0;
338   bool extension_present, fw_ext_present;
339   uint16_t protocol = 0;
340 
341   /* Find CCB based on CID */
342   p_bcb = bnepu_find_bcb_by_cid(l2cap_cid);
343   if (p_bcb == NULL) {
344     log::warn("BNEP - Rcvd L2CAP data, unknown CID: 0x{:x}", l2cap_cid);
345     osi_free(p_buf);
346     return;
347   }
348 
349   /* Get the type and extension bits */
350   type = *p++;
351   extension_present = type >> 7;
352   type &= 0x7f;
353   if (type >= sizeof(bnep_frame_hdr_sizes) / sizeof(bnep_frame_hdr_sizes[0])) {
354     log::info("BNEP - rcvd frame, bad type: 0x{:02x}", type);
355     osi_free(p_buf);
356     return;
357   }
358   if ((rem_len <= bnep_frame_hdr_sizes[type]) || (rem_len > BNEP_MTU_SIZE)) {
359     log::debug("BNEP - rcvd frame, bad len: {}  type: 0x{:02x}", p_buf->len, type);
360     osi_free(p_buf);
361     return;
362   }
363 
364   rem_len--;
365 
366   if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
367       (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)) && (type != BNEP_FRAME_CONTROL)) {
368     log::warn("BNEP - Ignored L2CAP data while in state: {}, CID: 0x{:x}", p_bcb->con_state,
369               l2cap_cid);
370 
371     if (extension_present) {
372       /*
373       ** When there is no connection if a data packet is received
374       ** with unknown control extension headers then those should be processed
375       ** according to complain/ignore law
376       */
377       uint8_t ext, length;
378       uint16_t org_len, new_len;
379       /* parse the extension headers and process unknown control headers */
380       org_len = rem_len;
381       do {
382         if (org_len < 2) {
383           break;
384         }
385         ext = *p++;
386         length = *p++;
387 
388         new_len = (length + 2);
389         if (new_len > org_len) {
390           break;
391         }
392 
393         if ((ext & 0x7F) == BNEP_EXTENSION_FILTER_CONTROL) {
394           if (length == 0) {
395             break;
396           }
397           if (*p > BNEP_FILTER_MULTI_ADDR_RESPONSE_MSG) {
398             bnep_send_command_not_understood(p_bcb, *p);
399           }
400         }
401 
402         p += length;
403 
404         org_len -= new_len;
405       } while (ext & 0x80);
406     }
407     osi_free(p_buf);
408     return;
409   }
410 
411   if (type > BNEP_FRAME_COMPRESSED_ETHERNET_DEST_ONLY) {
412     log::debug("BNEP - rcvd frame, unknown type: 0x{:02x}", type);
413     osi_free(p_buf);
414     return;
415   }
416 
417   log::debug("BNEP - rcv frame, type: {} len: {} Ext: {}", type, p_buf->len, extension_present);
418 
419   /* Initialize addresses to 'not supplied' */
420   RawAddress src_addr = RawAddress::kEmpty;
421   RawAddress dst_addr = RawAddress::kEmpty;
422 
423   switch (type) {
424     case BNEP_FRAME_GENERAL_ETHERNET:
425       dst_addr = *(RawAddress*)p;
426       p += BD_ADDR_LEN;
427       src_addr = *(RawAddress*)p;
428       p += BD_ADDR_LEN;
429       BE_STREAM_TO_UINT16(protocol, p);
430       rem_len -= 14;
431       break;
432 
433     case BNEP_FRAME_CONTROL:
434       ctrl_type = *p;
435       p = bnep_process_control_packet(p_bcb, p, &rem_len, false);
436 
437       if (ctrl_type == BNEP_SETUP_CONNECTION_REQUEST_MSG &&
438           p_bcb->con_state != BNEP_STATE_CONNECTED && extension_present && p && rem_len) {
439         osi_free(p_bcb->p_pending_data);
440         p_bcb->p_pending_data = (BT_HDR*)osi_malloc(rem_len + sizeof(BT_HDR));
441         memcpy((uint8_t*)(p_bcb->p_pending_data + 1), p, rem_len);
442         p_bcb->p_pending_data->len = rem_len;
443         p_bcb->p_pending_data->offset = 0;
444       } else {
445         while (extension_present && p && rem_len) {
446           ext_type = *p++;
447           rem_len--;
448           extension_present = ext_type >> 7;
449           ext_type &= 0x7F;
450 
451           /* if unknown extension present stop processing */
452           if (ext_type != BNEP_EXTENSION_FILTER_CONTROL) {
453             break;
454           }
455 
456           p = bnep_process_control_packet(p_bcb, p, &rem_len, true);
457         }
458       }
459       osi_free(p_buf);
460       return;
461 
462     case BNEP_FRAME_COMPRESSED_ETHERNET:
463       BE_STREAM_TO_UINT16(protocol, p);
464       rem_len -= 2;
465       break;
466 
467     case BNEP_FRAME_COMPRESSED_ETHERNET_SRC_ONLY:
468       src_addr = *(RawAddress*)p;
469       p += BD_ADDR_LEN;
470       BE_STREAM_TO_UINT16(protocol, p);
471       rem_len -= 8;
472       break;
473 
474     case BNEP_FRAME_COMPRESSED_ETHERNET_DEST_ONLY:
475       dst_addr = *(RawAddress*)p;
476       p += BD_ADDR_LEN;
477       BE_STREAM_TO_UINT16(protocol, p);
478       rem_len -= 8;
479       break;
480   }
481 
482   /* Process the header extension if there is one */
483   while (extension_present && p && rem_len) {
484     ext_type = *p;
485     extension_present = ext_type >> 7;
486     ext_type &= 0x7F;
487 
488     /* if unknown extension present stop processing */
489     if (ext_type) {
490       log::debug("Data extension type 0x{:x} found", ext_type);
491       break;
492     }
493 
494     p++;
495     rem_len--;
496     p = bnep_process_control_packet(p_bcb, p, &rem_len, true);
497   }
498 
499   p_buf->offset += p_buf->len - rem_len;
500   p_buf->len = rem_len;
501 
502   /* Always give the upper layer MAC addresses */
503   if (src_addr == RawAddress::kEmpty) {
504     src_addr = p_bcb->rem_bda;
505   }
506 
507   if (dst_addr == RawAddress::kEmpty) {
508     dst_addr = bluetooth::ToRawAddress(bluetooth::shim::GetController()->GetMacAddress());
509   }
510 
511   /* check whether there are any extensions to be forwarded */
512   if (ext_type) {
513     fw_ext_present = true;
514   } else {
515     fw_ext_present = false;
516   }
517 
518   if (bnep_cb.p_data_buf_cb) {
519     (*bnep_cb.p_data_buf_cb)(p_bcb->handle, src_addr, dst_addr, protocol, p_buf, fw_ext_present);
520   } else if (bnep_cb.p_data_ind_cb) {
521     (*bnep_cb.p_data_ind_cb)(p_bcb->handle, src_addr, dst_addr, protocol, p, rem_len,
522                              fw_ext_present);
523     osi_free(p_buf);
524   }
525 }
526 
527 /*******************************************************************************
528  *
529  * Function         bnep_conn_timer_timeout
530  *
531  * Description      This function processes a timeout. If it is a startup
532  *                  timeout, we check for reading our BD address. If it
533  *                  is an L2CAP timeout, we send a disconnect req to L2CAP.
534  *
535  * Returns          void
536  *
537  ******************************************************************************/
bnep_conn_timer_timeout(void * data)538 void bnep_conn_timer_timeout(void* data) {
539   tBNEP_CONN* p_bcb = (tBNEP_CONN*)data;
540 
541   log::debug("BNEP - CCB timeout in state: {}  CID: 0x{:x} flags {:x}, re_transmit {}",
542              p_bcb->con_state, p_bcb->l2cap_cid, p_bcb->con_flags, p_bcb->re_transmits);
543 
544   if (p_bcb->con_state == BNEP_STATE_CONN_SETUP) {
545     log::debug("BNEP - CCB timeout in state: {}  CID: 0x{:x}", p_bcb->con_state, p_bcb->l2cap_cid);
546 
547     if (!(p_bcb->con_flags & BNEP_FLAGS_IS_ORIG)) {
548       if (!stack::l2cap::get_interface().L2CA_DisconnectReq(p_bcb->l2cap_cid)) {
549         log::warn("Unable to request L2CAP disconnect peer:{} cid:{}", p_bcb->rem_bda,
550                   p_bcb->l2cap_cid);
551       }
552       bnepu_release_bcb(p_bcb);
553       return;
554     }
555 
556     if (p_bcb->re_transmits++ != BNEP_MAX_RETRANSMITS) {
557       bnep_send_conn_req(p_bcb);
558       alarm_set_on_mloop(p_bcb->conn_timer, BNEP_CONN_TIMEOUT_MS, bnep_conn_timer_timeout, p_bcb);
559     } else {
560       if (!stack::l2cap::get_interface().L2CA_DisconnectReq(p_bcb->l2cap_cid)) {
561         log::warn("Unable to request L2CAP disconnect peer:{} cid:{}", p_bcb->rem_bda,
562                   p_bcb->l2cap_cid);
563       }
564 
565       if ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb)) {
566         (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, false);
567       }
568 
569       bnepu_release_bcb(p_bcb);
570       return;
571     }
572   } else if (p_bcb->con_state != BNEP_STATE_CONNECTED) {
573     log::debug("BNEP - CCB timeout in state: {}  CID: 0x{:x}", p_bcb->con_state, p_bcb->l2cap_cid);
574 
575     if (!stack::l2cap::get_interface().L2CA_DisconnectReq(p_bcb->l2cap_cid)) {
576       log::warn("Unable to request L2CAP disconnect peer:{} cid:{}", p_bcb->rem_bda,
577                 p_bcb->l2cap_cid);
578     }
579 
580     /* Tell the user if there is a callback */
581     if ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb)) {
582       (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda, BNEP_CONN_FAILED, false);
583     }
584 
585     bnepu_release_bcb(p_bcb);
586   } else if (p_bcb->con_flags & BNEP_FLAGS_FILTER_RESP_PEND) {
587     if (p_bcb->re_transmits++ != BNEP_MAX_RETRANSMITS) {
588       bnepu_send_peer_our_filters(p_bcb);
589       alarm_set_on_mloop(p_bcb->conn_timer, BNEP_FILTER_SET_TIMEOUT_MS, bnep_conn_timer_timeout,
590                          p_bcb);
591     } else {
592       if (!stack::l2cap::get_interface().L2CA_DisconnectReq(p_bcb->l2cap_cid)) {
593         log::warn("Unable to request L2CAP disconnect peer:{} cid:{}", p_bcb->rem_bda,
594                   p_bcb->l2cap_cid);
595       }
596 
597       /* Tell the user if there is a callback */
598       if (bnep_cb.p_conn_state_cb) {
599         (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda, BNEP_SET_FILTER_FAIL, false);
600       }
601 
602       bnepu_release_bcb(p_bcb);
603       return;
604     }
605   } else if (p_bcb->con_flags & BNEP_FLAGS_MULTI_RESP_PEND) {
606     if (p_bcb->re_transmits++ != BNEP_MAX_RETRANSMITS) {
607       bnepu_send_peer_our_multi_filters(p_bcb);
608       alarm_set_on_mloop(p_bcb->conn_timer, BNEP_FILTER_SET_TIMEOUT_MS, bnep_conn_timer_timeout,
609                          p_bcb);
610     } else {
611       if (!stack::l2cap::get_interface().L2CA_DisconnectReq(p_bcb->l2cap_cid)) {
612         log::warn("Unable to request L2CAP disconnect peer:{} cid:{}", p_bcb->rem_bda,
613                   p_bcb->l2cap_cid);
614       }
615 
616       /* Tell the user if there is a callback */
617       if (bnep_cb.p_conn_state_cb) {
618         (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda, BNEP_SET_FILTER_FAIL, false);
619       }
620 
621       bnepu_release_bcb(p_bcb);
622       return;
623     }
624   }
625 }
626 
627 /*******************************************************************************
628  *
629  * Function         bnep_connected
630  *
631  * Description      This function is called when a connection is established
632  *                  (after config).
633  *
634  * Returns          void
635  *
636  ******************************************************************************/
bnep_connected(tBNEP_CONN * p_bcb)637 void bnep_connected(tBNEP_CONN* p_bcb) {
638   bool is_role_change;
639 
640   if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED) {
641     is_role_change = true;
642   } else {
643     is_role_change = false;
644   }
645 
646   p_bcb->con_state = BNEP_STATE_CONNECTED;
647   p_bcb->con_flags |= BNEP_FLAGS_CONN_COMPLETED;
648   p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
649 
650   /* Ensure timer is stopped */
651   alarm_cancel(p_bcb->conn_timer);
652   p_bcb->re_transmits = 0;
653 
654   /* Tell the upper layer, if there is a callback */
655   if (bnep_cb.p_conn_state_cb) {
656     (*bnep_cb.p_conn_state_cb)(p_bcb->handle, p_bcb->rem_bda, BNEP_SUCCESS, is_role_change);
657   }
658 }
659