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