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