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