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