1 /******************************************************************************
3 * Copyright (C) 2001-2012 Broadcom Corporation
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ******************************************************************************/
19 /******************************************************************************
21 * This file contains BNEP utility functions
23 ******************************************************************************/
33 #include "device/include/controller.h"
36 /********************************************************************************/
37 /* L O C A L F U N C T I O N P R O T O T Y P E S */
38 /********************************************************************************/
39 static UINT8 *bnepu_init_hdr (BT_HDR *p_buf, UINT16 hdr_len, UINT8 pkt_type);
41 void bnepu_process_peer_multicast_filter_set (tBNEP_CONN *p_bcb, UINT8 *p_filters, UINT16 len);
42 void bnepu_send_peer_multicast_filter_rsp (tBNEP_CONN *p_bcb, UINT16 response_code);
45 /*******************************************************************************
47 ** Function bnepu_find_bcb_by_cid
49 ** Description This function searches the bcb table for an entry with the
52 ** Returns the BCB address, or NULL if not found.
54 *******************************************************************************/
55 tBNEP_CONN *bnepu_find_bcb_by_cid (UINT16 cid)
60 /* Look through each connection control block */
61 for (xx = 0, p_bcb = bnep_cb.bcb; xx < BNEP_MAX_CONNECTIONS; xx++, p_bcb++)
63 if ((p_bcb->con_state != BNEP_STATE_IDLE) && (p_bcb->l2cap_cid == cid))
67 /* If here, not found */
72 /*******************************************************************************
74 ** Function bnepu_find_bcb_by_bd_addr
76 ** Description This function searches the BCB table for an entry with the
77 ** passed Bluetooth Address.
79 ** Returns the BCB address, or NULL if not found.
81 *******************************************************************************/
82 tBNEP_CONN *bnepu_find_bcb_by_bd_addr (UINT8 *p_bda)
87 /* Look through each connection control block */
88 for (xx = 0, p_bcb = bnep_cb.bcb; xx < BNEP_MAX_CONNECTIONS; xx++, p_bcb++)
90 if (p_bcb->con_state != BNEP_STATE_IDLE)
92 if (!memcmp ((UINT8 *)(p_bcb->rem_bda), p_bda, BD_ADDR_LEN))
97 /* If here, not found */
102 /*******************************************************************************
104 ** Function bnepu_allocate_bcb
106 ** Description This function allocates a new BCB.
108 ** Returns BCB address, or NULL if none available.
110 *******************************************************************************/
111 tBNEP_CONN *bnepu_allocate_bcb (BD_ADDR p_rem_bda)
116 /* Look through each connection control block for a free one */
117 for (xx = 0, p_bcb = bnep_cb.bcb; xx < BNEP_MAX_CONNECTIONS; xx++, p_bcb++)
119 if (p_bcb->con_state == BNEP_STATE_IDLE)
121 memset ((UINT8 *)p_bcb, 0, sizeof (tBNEP_CONN));
123 p_bcb->conn_tle.param = (UINT32) p_bcb;
125 memcpy ((UINT8 *)(p_bcb->rem_bda), (UINT8 *)p_rem_bda, BD_ADDR_LEN);
126 p_bcb->handle = xx + 1;
132 /* If here, no free BCB found */
137 /*******************************************************************************
139 ** Function bnepu_release_bcb
141 ** Description This function releases a BCB.
145 *******************************************************************************/
146 void bnepu_release_bcb (tBNEP_CONN *p_bcb)
148 /* Ensure timer is stopped */
149 btu_stop_timer (&p_bcb->conn_tle);
151 /* Drop any response pointer we may be holding */
152 p_bcb->con_state = BNEP_STATE_IDLE;
153 p_bcb->p_pending_data = NULL;
155 /* Free transmit queue */
156 while (!GKI_queue_is_empty(&p_bcb->xmit_q))
158 GKI_freebuf (GKI_dequeue (&p_bcb->xmit_q));
163 /*******************************************************************************
165 ** Function bnep_send_conn_req
167 ** Description This function sends a BNEP connection request to peer
171 *******************************************************************************/
172 void bnep_send_conn_req (tBNEP_CONN *p_bcb)
177 BNEP_TRACE_DEBUG ("%s: sending setup req with dst uuid %x",
178 __func__, p_bcb->dst_uuid.uu.uuid16);
179 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (BNEP_POOL_ID)) == NULL)
181 BNEP_TRACE_ERROR ("%s: not able to send connection request", __func__);
185 p_buf->offset = L2CAP_MIN_OFFSET;
186 p = p_start = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
188 /* Put in BNEP frame type - filter control */
189 UINT8_TO_BE_STREAM (p, BNEP_FRAME_CONTROL);
191 /* Put in filter message type - set filters */
192 UINT8_TO_BE_STREAM (p, BNEP_SETUP_CONNECTION_REQUEST_MSG);
194 UINT8_TO_BE_STREAM (p, p_bcb->dst_uuid.len);
196 if (p_bcb->dst_uuid.len == 2)
198 UINT16_TO_BE_STREAM (p, p_bcb->dst_uuid.uu.uuid16);
199 UINT16_TO_BE_STREAM (p, p_bcb->src_uuid.uu.uuid16);
201 else if (p_bcb->dst_uuid.len == 4)
203 UINT32_TO_BE_STREAM (p, p_bcb->dst_uuid.uu.uuid32);
204 UINT32_TO_BE_STREAM (p, p_bcb->src_uuid.uu.uuid32);
206 else if (p_bcb->dst_uuid.len == 16)
208 memcpy (p, p_bcb->dst_uuid.uu.uuid128, p_bcb->dst_uuid.len);
209 p += p_bcb->dst_uuid.len;
210 memcpy (p, p_bcb->src_uuid.uu.uuid128, p_bcb->dst_uuid.len);
211 p += p_bcb->dst_uuid.len;
215 BNEP_TRACE_ERROR ("%s: uuid: %x, invalid length: %x",
216 __func__, p_bcb->dst_uuid.uu.uuid16, p_bcb->dst_uuid.len);
219 p_buf->len = (UINT16)(p - p_start);
221 bnepu_check_send_packet (p_bcb, p_buf);
225 /*******************************************************************************
227 ** Function bnep_send_conn_responce
229 ** Description This function sends a BNEP setup response to peer
233 *******************************************************************************/
234 void bnep_send_conn_responce (tBNEP_CONN *p_bcb, UINT16 resp_code)
239 BNEP_TRACE_EVENT ("BNEP - bnep_send_conn_responce for CID: 0x%x", p_bcb->l2cap_cid);
240 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (BNEP_POOL_ID)) == NULL)
242 BNEP_TRACE_ERROR ("BNEP - not able to send connection response");
246 p_buf->offset = L2CAP_MIN_OFFSET;
247 p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
249 /* Put in BNEP frame type - filter control */
250 UINT8_TO_BE_STREAM (p, BNEP_FRAME_CONTROL);
252 /* Put in filter message type - set filters */
253 UINT8_TO_BE_STREAM (p, BNEP_SETUP_CONNECTION_RESPONSE_MSG);
255 UINT16_TO_BE_STREAM (p, resp_code);
259 bnepu_check_send_packet (p_bcb, p_buf);
264 /*******************************************************************************
266 ** Function bnepu_send_peer_our_filters
268 ** Description This function sends our filters to a peer
272 *******************************************************************************/
273 void bnepu_send_peer_our_filters (tBNEP_CONN *p_bcb)
279 BNEP_TRACE_DEBUG ("BNEP sending peer our filters");
281 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (BNEP_POOL_ID)) == NULL)
283 BNEP_TRACE_ERROR ("BNEP - no buffer send filters");
287 p_buf->offset = L2CAP_MIN_OFFSET;
288 p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
290 /* Put in BNEP frame type - filter control */
291 UINT8_TO_BE_STREAM (p, BNEP_FRAME_CONTROL);
293 /* Put in filter message type - set filters */
294 UINT8_TO_BE_STREAM (p, BNEP_FILTER_NET_TYPE_SET_MSG);
296 UINT16_TO_BE_STREAM (p, (4 * p_bcb->sent_num_filters));
297 for (xx = 0; xx < p_bcb->sent_num_filters; xx++)
299 UINT16_TO_BE_STREAM (p, p_bcb->sent_prot_filter_start[xx]);
300 UINT16_TO_BE_STREAM (p, p_bcb->sent_prot_filter_end[xx]);
303 p_buf->len = 4 + (4 * p_bcb->sent_num_filters);
305 bnepu_check_send_packet (p_bcb, p_buf);
307 p_bcb->con_flags |= BNEP_FLAGS_FILTER_RESP_PEND;
309 /* Start timer waiting for setup response */
310 btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_FILTER_SET_TIMEOUT);
314 /*******************************************************************************
316 ** Function bnepu_send_peer_our_multi_filters
318 ** Description This function sends our multicast filters to a peer
322 *******************************************************************************/
323 void bnepu_send_peer_our_multi_filters (tBNEP_CONN *p_bcb)
329 BNEP_TRACE_DEBUG ("BNEP sending peer our multicast filters");
331 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (BNEP_POOL_ID)) == NULL)
333 BNEP_TRACE_ERROR ("BNEP - no buffer to send multicast filters");
337 p_buf->offset = L2CAP_MIN_OFFSET;
338 p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
340 /* Put in BNEP frame type - filter control */
341 UINT8_TO_BE_STREAM (p, BNEP_FRAME_CONTROL);
343 /* Put in filter message type - set filters */
344 UINT8_TO_BE_STREAM (p, BNEP_FILTER_MULTI_ADDR_SET_MSG);
346 UINT16_TO_BE_STREAM (p, (2 * BD_ADDR_LEN * p_bcb->sent_mcast_filters));
347 for (xx = 0; xx < p_bcb->sent_mcast_filters; xx++)
349 memcpy (p, p_bcb->sent_mcast_filter_start[xx], BD_ADDR_LEN);
351 memcpy (p, p_bcb->sent_mcast_filter_end[xx], BD_ADDR_LEN);
355 p_buf->len = 4 + (2 * BD_ADDR_LEN * p_bcb->sent_mcast_filters);
357 bnepu_check_send_packet (p_bcb, p_buf);
359 p_bcb->con_flags |= BNEP_FLAGS_MULTI_RESP_PEND;
361 /* Start timer waiting for setup response */
362 btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_FILTER_SET_TIMEOUT);
366 /*******************************************************************************
368 ** Function bnepu_send_peer_filter_rsp
370 ** Description This function sends a filter response to a peer
374 *******************************************************************************/
375 void bnepu_send_peer_filter_rsp (tBNEP_CONN *p_bcb, UINT16 response_code)
380 BNEP_TRACE_DEBUG ("BNEP sending filter response");
381 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (BNEP_POOL_ID)) == NULL)
383 BNEP_TRACE_ERROR ("BNEP - no buffer filter rsp");
387 p_buf->offset = L2CAP_MIN_OFFSET;
388 p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
390 /* Put in BNEP frame type - filter control */
391 UINT8_TO_BE_STREAM (p, BNEP_FRAME_CONTROL);
393 /* Put in filter message type - set filters */
394 UINT8_TO_BE_STREAM (p, BNEP_FILTER_NET_TYPE_RESPONSE_MSG);
396 UINT16_TO_BE_STREAM (p, response_code);
400 bnepu_check_send_packet (p_bcb, p_buf);
404 /*******************************************************************************
406 ** Function bnep_send_command_not_understood
408 ** Description This function sends a BNEP command not understood message
412 *******************************************************************************/
413 void bnep_send_command_not_understood (tBNEP_CONN *p_bcb, UINT8 cmd_code)
418 BNEP_TRACE_EVENT ("BNEP - bnep_send_command_not_understood for CID: 0x%x, cmd 0x%x", p_bcb->l2cap_cid, cmd_code);
419 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (BNEP_POOL_ID)) == NULL)
421 BNEP_TRACE_ERROR ("BNEP - not able to send connection response");
425 p_buf->offset = L2CAP_MIN_OFFSET;
426 p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
428 /* Put in BNEP frame type - filter control */
429 UINT8_TO_BE_STREAM (p, BNEP_FRAME_CONTROL);
431 /* Put in filter message type - set filters */
432 UINT8_TO_BE_STREAM (p, BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD);
434 UINT8_TO_BE_STREAM (p, cmd_code);
438 bnepu_check_send_packet (p_bcb, p_buf);
443 /*******************************************************************************
445 ** Function bnepu_check_send_packet
447 ** Description This function tries to send a packet to L2CAP.
448 ** If L2CAP is flow controlled, it enqueues the
449 ** packet to the transmit queue
453 *******************************************************************************/
454 void bnepu_check_send_packet (tBNEP_CONN *p_bcb, BT_HDR *p_buf)
456 BNEP_TRACE_EVENT ("BNEP - bnepu_check_send_packet for CID: 0x%x", p_bcb->l2cap_cid);
457 if (p_bcb->con_flags & BNEP_FLAGS_L2CAP_CONGESTED)
459 if (GKI_queue_length(&p_bcb->xmit_q) >= BNEP_MAX_XMITQ_DEPTH)
461 BNEP_TRACE_EVENT ("BNEP - congested, dropping buf, CID: 0x%x", p_bcb->l2cap_cid);
467 GKI_enqueue (&p_bcb->xmit_q, p_buf);
472 L2CA_DataWrite (p_bcb->l2cap_cid, p_buf);
477 /*******************************************************************************
479 ** Function bnepu_build_bnep_hdr
481 ** Description This function builds the BNEP header for a packet
482 ** Extension headers are not sent yet, so there is no
487 *******************************************************************************/
488 void bnepu_build_bnep_hdr (tBNEP_CONN *p_bcb, BT_HDR *p_buf, UINT16 protocol,
489 UINT8 *p_src_addr, UINT8 *p_dest_addr, BOOLEAN fw_ext_present)
491 const controller_t *controller = controller_get_interface();
492 UINT8 ext_bit, *p = (UINT8 *)NULL;
493 UINT8 type = BNEP_FRAME_COMPRESSED_ETHERNET;
495 ext_bit = fw_ext_present ? 0x80 : 0x00;
497 if ((p_src_addr) && (memcmp (p_src_addr, &controller->get_address()->address, BD_ADDR_LEN)))
498 type = BNEP_FRAME_COMPRESSED_ETHERNET_SRC_ONLY;
500 if (memcmp (p_dest_addr, p_bcb->rem_bda, BD_ADDR_LEN))
501 type = (type == BNEP_FRAME_COMPRESSED_ETHERNET) ? BNEP_FRAME_COMPRESSED_ETHERNET_DEST_ONLY : BNEP_FRAME_GENERAL_ETHERNET;
504 p_src_addr = (UINT8 *)controller->get_address();
508 case BNEP_FRAME_GENERAL_ETHERNET:
509 p = bnepu_init_hdr (p_buf, 15, (UINT8)(ext_bit | BNEP_FRAME_GENERAL_ETHERNET));
511 memcpy (p, p_dest_addr, BD_ADDR_LEN);
514 memcpy (p, p_src_addr, BD_ADDR_LEN);
518 case BNEP_FRAME_COMPRESSED_ETHERNET:
519 p = bnepu_init_hdr (p_buf, 3, (UINT8)(ext_bit | BNEP_FRAME_COMPRESSED_ETHERNET));
522 case BNEP_FRAME_COMPRESSED_ETHERNET_SRC_ONLY:
523 p = bnepu_init_hdr (p_buf, 9, (UINT8)(ext_bit | BNEP_FRAME_COMPRESSED_ETHERNET_SRC_ONLY));
525 memcpy (p, p_src_addr, BD_ADDR_LEN);
529 case BNEP_FRAME_COMPRESSED_ETHERNET_DEST_ONLY:
530 p = bnepu_init_hdr (p_buf, 9, (UINT8)(ext_bit | BNEP_FRAME_COMPRESSED_ETHERNET_DEST_ONLY));
532 memcpy (p, p_dest_addr, BD_ADDR_LEN);
537 UINT16_TO_BE_STREAM (p, protocol);
541 /*******************************************************************************
543 ** Function bnepu_init_hdr
545 ** Description This function initializes the BNEP header
547 ** Returns pointer to header in buffer
549 *******************************************************************************/
550 static UINT8 *bnepu_init_hdr (BT_HDR *p_buf, UINT16 hdr_len, UINT8 pkt_type)
552 UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
554 /* See if we need to make space in the buffer */
555 if (p_buf->offset < (hdr_len + L2CAP_MIN_OFFSET))
557 UINT16 xx, diff = BNEP_MINIMUM_OFFSET - p_buf->offset;
558 p = p + p_buf->len - 1;
559 for (xx = 0; xx < p_buf->len; xx++, p--)
562 p_buf->offset = BNEP_MINIMUM_OFFSET;
563 p = (UINT8 *)(p_buf + 1) + p_buf->offset;
566 p_buf->len += hdr_len;
567 p_buf->offset -= hdr_len;
576 /*******************************************************************************
578 ** Function bnep_process_setup_conn_req
580 ** Description This function processes a peer's setup connection request
581 ** message. The destination UUID is verified and response sent
582 ** Connection open indication will be given to PAN profile
586 *******************************************************************************/
587 void bnep_process_setup_conn_req (tBNEP_CONN *p_bcb, UINT8 *p_setup, UINT8 len)
589 BNEP_TRACE_EVENT ("BNEP - bnep_process_setup_conn_req for CID: 0x%x", p_bcb->l2cap_cid);
591 if (p_bcb->con_state != BNEP_STATE_CONN_SETUP &&
592 p_bcb->con_state != BNEP_STATE_SEC_CHECKING &&
593 p_bcb->con_state != BNEP_STATE_CONNECTED)
595 BNEP_TRACE_ERROR ("BNEP - setup request in bad state %d", p_bcb->con_state);
596 bnep_send_conn_responce (p_bcb, BNEP_SETUP_CONN_NOT_ALLOWED);
600 /* Check if we already initiated security check or if waiting for user responce */
601 if (p_bcb->con_flags & BNEP_FLAGS_SETUP_RCVD)
603 BNEP_TRACE_EVENT ("BNEP - Duplicate Setup message received while doing security check");
607 /* Check if peer is the originator */
608 if (p_bcb->con_state != BNEP_STATE_CONNECTED &&
609 (!(p_bcb->con_flags & BNEP_FLAGS_SETUP_RCVD)) &&
610 (p_bcb->con_flags & BNEP_FLAGS_IS_ORIG))
612 BNEP_TRACE_ERROR ("BNEP - setup request when we are originator", p_bcb->con_state);
613 bnep_send_conn_responce (p_bcb, BNEP_SETUP_CONN_NOT_ALLOWED);
617 if (p_bcb->con_state == BNEP_STATE_CONNECTED)
619 memcpy ((UINT8 *)&(p_bcb->prv_src_uuid), (UINT8 *)&(p_bcb->src_uuid), sizeof (tBT_UUID));
620 memcpy ((UINT8 *)&(p_bcb->prv_dst_uuid), (UINT8 *)&(p_bcb->dst_uuid), sizeof (tBT_UUID));
623 p_bcb->dst_uuid.len = p_bcb->src_uuid.len = len;
625 if (p_bcb->dst_uuid.len == 2)
627 /* because peer initiated connection keep src uuid as dst uuid */
628 BE_STREAM_TO_UINT16 (p_bcb->src_uuid.uu.uuid16, p_setup);
629 BE_STREAM_TO_UINT16 (p_bcb->dst_uuid.uu.uuid16, p_setup);
631 /* If nothing has changed don't bother the profile */
632 if (p_bcb->con_state == BNEP_STATE_CONNECTED &&
633 p_bcb->src_uuid.uu.uuid16 == p_bcb->prv_src_uuid.uu.uuid16 &&
634 p_bcb->dst_uuid.uu.uuid16 == p_bcb->prv_dst_uuid.uu.uuid16)
636 bnep_send_conn_responce (p_bcb, BNEP_SETUP_CONN_OK);
640 else if (p_bcb->dst_uuid.len == 4)
642 BE_STREAM_TO_UINT32 (p_bcb->src_uuid.uu.uuid32, p_setup);
643 BE_STREAM_TO_UINT32 (p_bcb->dst_uuid.uu.uuid32, p_setup);
645 else if (p_bcb->dst_uuid.len == 16)
647 memcpy (p_bcb->src_uuid.uu.uuid128, p_setup, p_bcb->src_uuid.len);
648 p_setup += p_bcb->src_uuid.len;
649 memcpy (p_bcb->dst_uuid.uu.uuid128, p_setup, p_bcb->dst_uuid.len);
650 p_setup += p_bcb->dst_uuid.len;
654 BNEP_TRACE_ERROR ("BNEP - Bad UID len %d in ConnReq", p_bcb->dst_uuid.len);
655 bnep_send_conn_responce (p_bcb, BNEP_SETUP_INVALID_UUID_SIZE);
659 p_bcb->con_state = BNEP_STATE_SEC_CHECKING;
660 p_bcb->con_flags |= BNEP_FLAGS_SETUP_RCVD;
662 BNEP_TRACE_EVENT ("BNEP initiating security check for incoming call for uuid 0x%x", p_bcb->src_uuid.uu.uuid16);
663 #if (!defined (BNEP_DO_AUTH_FOR_ROLE_SWITCH) || BNEP_DO_AUTH_FOR_ROLE_SWITCH == FALSE)
664 if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)
665 bnep_sec_check_complete (p_bcb->rem_bda, p_bcb, BTM_SUCCESS);
668 btm_sec_mx_access_request (p_bcb->rem_bda, BT_PSM_BNEP, FALSE,
669 BTM_SEC_PROTO_BNEP, bnep_get_uuid32(&(p_bcb->src_uuid)),
670 &bnep_sec_check_complete, p_bcb);
676 /*******************************************************************************
678 ** Function bnep_process_setup_conn_responce
680 ** Description This function processes a peer's setup connection response
681 ** message. The response code is verified and
682 ** Connection open indication will be given to PAN profile
686 *******************************************************************************/
687 void bnep_process_setup_conn_responce (tBNEP_CONN *p_bcb, UINT8 *p_setup)
692 BNEP_TRACE_DEBUG ("BNEP received setup responce");
693 /* The state should be either SETUP or CONNECTED */
694 if (p_bcb->con_state != BNEP_STATE_CONN_SETUP)
696 /* Should we disconnect ? */
697 BNEP_TRACE_ERROR ("BNEP - setup response in bad state %d", p_bcb->con_state);
701 /* Check if we are the originator */
702 if (!(p_bcb->con_flags & BNEP_FLAGS_IS_ORIG))
704 BNEP_TRACE_ERROR ("BNEP - setup response when we are not originator", p_bcb->con_state);
708 BE_STREAM_TO_UINT16 (resp_code, p_setup);
712 case BNEP_SETUP_INVALID_SRC_UUID:
713 resp = BNEP_CONN_FAILED_SRC_UUID;
716 case BNEP_SETUP_INVALID_DEST_UUID:
717 resp = BNEP_CONN_FAILED_DST_UUID;
720 case BNEP_SETUP_INVALID_UUID_SIZE:
721 resp = BNEP_CONN_FAILED_UUID_SIZE;
724 case BNEP_SETUP_CONN_NOT_ALLOWED:
726 resp = BNEP_CONN_FAILED;
730 /* Check the responce code */
731 if (resp_code != BNEP_SETUP_CONN_OK)
733 if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)
735 BNEP_TRACE_EVENT ("BNEP - role change response is %d", resp_code);
737 /* Restore the earlier BNEP status */
738 p_bcb->con_state = BNEP_STATE_CONNECTED;
739 p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
740 memcpy ((UINT8 *)&(p_bcb->src_uuid), (UINT8 *)&(p_bcb->prv_src_uuid), sizeof (tBT_UUID));
741 memcpy ((UINT8 *)&(p_bcb->dst_uuid), (UINT8 *)&(p_bcb->prv_dst_uuid), sizeof (tBT_UUID));
743 /* Ensure timer is stopped */
744 btu_stop_timer (&p_bcb->conn_tle);
745 p_bcb->re_transmits = 0;
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, resp, TRUE);
755 BNEP_TRACE_ERROR ("BNEP - setup response %d is not OK", resp_code);
757 L2CA_DisconnectReq (p_bcb->l2cap_cid);
759 /* Tell the user if he has a callback */
760 if ((p_bcb->con_flags & BNEP_FLAGS_IS_ORIG) && (bnep_cb.p_conn_state_cb))
761 (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, resp, FALSE);
763 bnepu_release_bcb (p_bcb);
768 /* Received successful responce */
769 bnep_connected (p_bcb);
773 /*******************************************************************************
775 ** Function bnep_process_control_packet
777 ** Description This function processes a peer's setup connection request
778 ** message. The destination UUID is verified and response sent
779 ** Connection open indication will be given to PAN profile
783 *******************************************************************************/
784 UINT8 *bnep_process_control_packet (tBNEP_CONN *p_bcb, UINT8 *p, UINT16 *rem_len, BOOLEAN is_ext)
787 BOOLEAN bad_pkt = FALSE;
788 UINT16 len, ext_len = 0;
793 *rem_len = *rem_len - 1;
797 *rem_len = *rem_len - 1;
799 BNEP_TRACE_EVENT ("BNEP processing control packet rem_len %d, is_ext %d, ctrl_type %d", *rem_len, is_ext, control_type);
801 switch (control_type)
803 case BNEP_CONTROL_COMMAND_NOT_UNDERSTOOD:
804 BNEP_TRACE_ERROR ("BNEP Received Cmd not understood for ctl pkt type: %d", *p);
806 *rem_len = *rem_len - 1;
809 case BNEP_SETUP_CONNECTION_REQUEST_MSG:
811 if (*rem_len < ((2 * len) + 1))
814 BNEP_TRACE_ERROR ("BNEP Received Setup message with bad length");
818 bnep_process_setup_conn_req (p_bcb, p, (UINT8)len);
820 *rem_len = *rem_len - (2 * len) - 1;
823 case BNEP_SETUP_CONNECTION_RESPONSE_MSG:
825 bnep_process_setup_conn_responce (p_bcb, p);
827 *rem_len = *rem_len - 2;
830 case BNEP_FILTER_NET_TYPE_SET_MSG:
831 BE_STREAM_TO_UINT16 (len, p);
832 if (*rem_len < (len + 2))
835 BNEP_TRACE_ERROR ("BNEP Received Filter set message with bad length");
838 bnepu_process_peer_filter_set (p_bcb, p, len);
840 *rem_len = *rem_len - len - 2;
843 case BNEP_FILTER_NET_TYPE_RESPONSE_MSG:
844 bnepu_process_peer_filter_rsp (p_bcb, p);
846 *rem_len = *rem_len - 2;
849 case BNEP_FILTER_MULTI_ADDR_SET_MSG:
850 BE_STREAM_TO_UINT16 (len, p);
851 if (*rem_len < (len + 2))
854 BNEP_TRACE_ERROR ("BNEP Received Multicast Filter Set message with bad length");
857 bnepu_process_peer_multicast_filter_set (p_bcb, p, len);
859 *rem_len = *rem_len - len - 2;
862 case BNEP_FILTER_MULTI_ADDR_RESPONSE_MSG:
863 bnepu_process_multicast_filter_rsp (p_bcb, p);
865 *rem_len = *rem_len - 2;
869 BNEP_TRACE_ERROR ("BNEP - bad ctl pkt type: %d", control_type);
870 bnep_send_command_not_understood (p_bcb, control_type);
874 *rem_len -= (ext_len - 1);
881 BNEP_TRACE_ERROR ("BNEP - bad ctl pkt length: %d", *rem_len);
890 /*******************************************************************************
892 ** Function bnepu_process_peer_filter_set
894 ** Description This function processes a peer's filter control
895 ** 'set' message. The filters are stored in the BCB,
896 ** and an appropriate filter response message sent.
900 *******************************************************************************/
901 void bnepu_process_peer_filter_set (tBNEP_CONN *p_bcb, UINT8 *p_filters, UINT16 len)
903 UINT16 num_filters = 0;
904 UINT16 xx, resp_code = BNEP_FILTER_CRL_OK;
906 UINT8 *p_temp_filters;
908 if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
909 (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
911 BNEP_TRACE_DEBUG ("BNEP received filter set from peer when there is no connection");
915 BNEP_TRACE_DEBUG ("BNEP received filter set from peer");
916 /* Check for length not a multiple of 4 */
919 BNEP_TRACE_EVENT ("BNEP - bad filter len: %d", len);
920 bnepu_send_peer_filter_rsp (p_bcb, BNEP_FILTER_CRL_BAD_RANGE);
925 num_filters = (UINT16) (len >> 2);
927 /* Validate filter values */
928 if (num_filters <= BNEP_MAX_PROT_FILTERS)
930 p_temp_filters = p_filters;
931 for (xx = 0; xx < num_filters; xx++)
933 BE_STREAM_TO_UINT16 (start, p_temp_filters);
934 BE_STREAM_TO_UINT16 (end, p_temp_filters);
938 resp_code = BNEP_FILTER_CRL_BAD_RANGE;
944 resp_code = BNEP_FILTER_CRL_MAX_REACHED;
946 if (resp_code != BNEP_FILTER_CRL_OK)
948 bnepu_send_peer_filter_rsp (p_bcb, resp_code);
952 if (bnep_cb.p_filter_ind_cb)
953 (*bnep_cb.p_filter_ind_cb) (p_bcb->handle, TRUE, 0, len, p_filters);
955 p_bcb->rcvd_num_filters = num_filters;
956 for (xx = 0; xx < num_filters; xx++)
958 BE_STREAM_TO_UINT16 (start, p_filters);
959 BE_STREAM_TO_UINT16 (end, p_filters);
961 p_bcb->rcvd_prot_filter_start[xx] = start;
962 p_bcb->rcvd_prot_filter_end[xx] = end;
965 bnepu_send_peer_filter_rsp (p_bcb, resp_code);
969 /*******************************************************************************
971 ** Function bnepu_process_peer_filter_rsp
973 ** Description This function processes a peer's filter control
974 ** 'response' message.
978 *******************************************************************************/
979 void bnepu_process_peer_filter_rsp (tBNEP_CONN *p_bcb, UINT8 *p_data)
984 BNEP_TRACE_DEBUG ("BNEP received filter responce");
985 /* The state should be CONNECTED */
986 if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
987 (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
989 BNEP_TRACE_ERROR ("BNEP - filter response in bad state %d", p_bcb->con_state);
993 /* Check if we are the originator */
994 if (!(p_bcb->con_flags & BNEP_FLAGS_FILTER_RESP_PEND))
996 BNEP_TRACE_ERROR ("BNEP - filter response when not expecting");
1000 /* Ensure timer is stopped */
1001 btu_stop_timer (&p_bcb->conn_tle);
1002 p_bcb->con_flags &= ~BNEP_FLAGS_FILTER_RESP_PEND;
1003 p_bcb->re_transmits = 0;
1005 BE_STREAM_TO_UINT16 (resp_code, p_data);
1007 result = BNEP_SUCCESS;
1008 if (resp_code != BNEP_FILTER_CRL_OK)
1009 result = BNEP_SET_FILTER_FAIL;
1011 if (bnep_cb.p_filter_ind_cb)
1012 (*bnep_cb.p_filter_ind_cb) (p_bcb->handle, FALSE, result, 0, NULL);
1015 /*******************************************************************************
1017 ** Function bnepu_process_multicast_filter_rsp
1019 ** Description This function processes multicast filter control
1020 ** 'response' message.
1024 *******************************************************************************/
1025 void bnepu_process_multicast_filter_rsp (tBNEP_CONN *p_bcb, UINT8 *p_data)
1028 tBNEP_RESULT result;
1030 BNEP_TRACE_DEBUG ("BNEP received multicast filter responce");
1031 /* The state should be CONNECTED */
1032 if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
1033 (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
1035 BNEP_TRACE_ERROR ("BNEP - multicast filter response in bad state %d", p_bcb->con_state);
1039 /* Check if we are the originator */
1040 if (!(p_bcb->con_flags & BNEP_FLAGS_MULTI_RESP_PEND))
1042 BNEP_TRACE_ERROR ("BNEP - multicast filter response when not expecting");
1046 /* Ensure timer is stopped */
1047 btu_stop_timer (&p_bcb->conn_tle);
1048 p_bcb->con_flags &= ~BNEP_FLAGS_MULTI_RESP_PEND;
1049 p_bcb->re_transmits = 0;
1051 BE_STREAM_TO_UINT16 (resp_code, p_data);
1053 result = BNEP_SUCCESS;
1054 if (resp_code != BNEP_FILTER_CRL_OK)
1055 result = BNEP_SET_FILTER_FAIL;
1057 if (bnep_cb.p_mfilter_ind_cb)
1058 (*bnep_cb.p_mfilter_ind_cb) (p_bcb->handle, FALSE, result, 0, NULL);
1061 /*******************************************************************************
1063 ** Function bnepu_process_peer_multicast_filter_set
1065 ** Description This function processes a peer's filter control
1066 ** 'set' message. The filters are stored in the BCB,
1067 ** and an appropriate filter response message sent.
1071 *******************************************************************************/
1072 void bnepu_process_peer_multicast_filter_set (tBNEP_CONN *p_bcb, UINT8 *p_filters, UINT16 len)
1074 UINT16 resp_code = BNEP_FILTER_CRL_OK;
1075 UINT16 num_filters, xx;
1076 UINT8 *p_temp_filters, null_bda[BD_ADDR_LEN] = {0,0,0,0,0,0};
1078 if ((p_bcb->con_state != BNEP_STATE_CONNECTED) &&
1079 (!(p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)))
1081 BNEP_TRACE_DEBUG ("BNEP received multicast filter set from peer when there is no connection");
1087 BNEP_TRACE_EVENT ("BNEP - bad filter len: %d", len);
1088 bnepu_send_peer_multicast_filter_rsp (p_bcb, BNEP_FILTER_CRL_BAD_RANGE);
1092 if (len > (BNEP_MAX_MULTI_FILTERS * 2 * BD_ADDR_LEN))
1094 BNEP_TRACE_EVENT ("BNEP - Too many filters");
1095 bnepu_send_peer_multicast_filter_rsp (p_bcb, BNEP_FILTER_CRL_MAX_REACHED);
1101 num_filters = (UINT16) (len / 12);
1103 /* Validate filter values */
1104 if (num_filters <= BNEP_MAX_MULTI_FILTERS)
1106 p_temp_filters = p_filters;
1107 for (xx = 0; xx < num_filters; xx++)
1109 if (memcmp (p_temp_filters, p_temp_filters + BD_ADDR_LEN, BD_ADDR_LEN) > 0)
1111 bnepu_send_peer_multicast_filter_rsp (p_bcb, BNEP_FILTER_CRL_BAD_RANGE);
1115 p_temp_filters += (BD_ADDR_LEN * 2);
1119 p_bcb->rcvd_mcast_filters = num_filters;
1120 for (xx = 0; xx < num_filters; xx++)
1122 memcpy (p_bcb->rcvd_mcast_filter_start[xx], p_filters, BD_ADDR_LEN);
1123 memcpy (p_bcb->rcvd_mcast_filter_end[xx], p_filters + BD_ADDR_LEN, BD_ADDR_LEN);
1124 p_filters += (BD_ADDR_LEN * 2);
1126 /* Check if any of the ranges have all zeros as both starting and ending addresses */
1127 if ((memcmp (null_bda, p_bcb->rcvd_mcast_filter_start[xx], BD_ADDR_LEN) == 0) &&
1128 (memcmp (null_bda, p_bcb->rcvd_mcast_filter_end[xx], BD_ADDR_LEN) == 0))
1130 p_bcb->rcvd_mcast_filters = 0xFFFF;
1135 BNEP_TRACE_EVENT ("BNEP multicast filters %d", p_bcb->rcvd_mcast_filters);
1136 bnepu_send_peer_multicast_filter_rsp (p_bcb, resp_code);
1138 if (bnep_cb.p_mfilter_ind_cb)
1139 (*bnep_cb.p_mfilter_ind_cb) (p_bcb->handle, TRUE, 0, len, p_filters);
1143 /*******************************************************************************
1145 ** Function bnepu_send_peer_multicast_filter_rsp
1147 ** Description This function sends a filter response to a peer
1151 *******************************************************************************/
1152 void bnepu_send_peer_multicast_filter_rsp (tBNEP_CONN *p_bcb, UINT16 response_code)
1157 BNEP_TRACE_DEBUG ("BNEP sending multicast filter response %d", response_code);
1158 if ((p_buf = (BT_HDR *)GKI_getpoolbuf (BNEP_POOL_ID)) == NULL)
1160 BNEP_TRACE_ERROR ("BNEP - no buffer filter rsp");
1164 p_buf->offset = L2CAP_MIN_OFFSET;
1165 p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
1167 /* Put in BNEP frame type - filter control */
1168 UINT8_TO_BE_STREAM (p, BNEP_FRAME_CONTROL);
1170 /* Put in filter message type - set filters */
1171 UINT8_TO_BE_STREAM (p, BNEP_FILTER_MULTI_ADDR_RESPONSE_MSG);
1173 UINT16_TO_BE_STREAM (p, response_code);
1177 bnepu_check_send_packet (p_bcb, p_buf);
1182 /*******************************************************************************
1184 ** Function bnep_sec_check_complete
1186 ** Description This function is registered with BTM and will be called
1187 ** after completing the security procedures
1191 *******************************************************************************/
1192 void bnep_sec_check_complete (BD_ADDR bd_addr, tBT_TRANSPORT trasnport,
1193 void *p_ref_data, UINT8 result)
1195 tBNEP_CONN *p_bcb = (tBNEP_CONN *)p_ref_data;
1196 UINT16 resp_code = BNEP_SETUP_CONN_OK;
1197 BOOLEAN is_role_change;
1201 BNEP_TRACE_EVENT ("BNEP security callback returned result %d", result);
1202 if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)
1203 is_role_change = TRUE;
1205 is_role_change = FALSE;
1207 /* check if the port is still waiting for security to complete */
1208 if (p_bcb->con_state != BNEP_STATE_SEC_CHECKING)
1210 BNEP_TRACE_ERROR ("BNEP Connection in wrong state %d when security is completed", p_bcb->con_state);
1214 /* if it is outgoing call and result is FAILURE return security fail error */
1215 if (!(p_bcb->con_flags & BNEP_FLAGS_SETUP_RCVD))
1217 if (result != BTM_SUCCESS)
1219 if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)
1221 /* Tell the user that role change is failed because of security */
1222 if (bnep_cb.p_conn_state_cb)
1223 (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_SECURITY_FAIL, is_role_change);
1225 p_bcb->con_state = BNEP_STATE_CONNECTED;
1226 memcpy ((UINT8 *)&(p_bcb->src_uuid), (UINT8 *)&(p_bcb->prv_src_uuid), sizeof (tBT_UUID));
1227 memcpy ((UINT8 *)&(p_bcb->dst_uuid), (UINT8 *)&(p_bcb->prv_dst_uuid), sizeof (tBT_UUID));
1231 L2CA_DisconnectReq (p_bcb->l2cap_cid);
1233 /* Tell the user if he has a callback */
1234 if (bnep_cb.p_conn_state_cb)
1235 (*bnep_cb.p_conn_state_cb) (p_bcb->handle, p_bcb->rem_bda, BNEP_SECURITY_FAIL, is_role_change);
1237 bnepu_release_bcb (p_bcb);
1241 /* Transition to the next appropriate state, waiting for connection confirm. */
1242 p_bcb->con_state = BNEP_STATE_CONN_SETUP;
1244 bnep_send_conn_req (p_bcb);
1245 btu_start_timer (&p_bcb->conn_tle, BTU_TTYPE_BNEP, BNEP_CONN_TIMEOUT);
1249 /* it is an incoming call respond appropriately */
1250 if (result != BTM_SUCCESS)
1252 bnep_send_conn_responce (p_bcb, BNEP_SETUP_CONN_NOT_ALLOWED);
1253 if (p_bcb->con_flags & BNEP_FLAGS_CONN_COMPLETED)
1255 /* Role change is failed because of security. Revert back to connected state */
1256 p_bcb->con_state = BNEP_STATE_CONNECTED;
1257 p_bcb->con_flags &= (~BNEP_FLAGS_SETUP_RCVD);
1258 memcpy ((UINT8 *)&(p_bcb->src_uuid), (UINT8 *)&(p_bcb->prv_src_uuid), sizeof (tBT_UUID));
1259 memcpy ((UINT8 *)&(p_bcb->dst_uuid), (UINT8 *)&(p_bcb->prv_dst_uuid), sizeof (tBT_UUID));
1263 L2CA_DisconnectReq (p_bcb->l2cap_cid);
1265 bnepu_release_bcb (p_bcb);
1269 if (bnep_cb.p_conn_ind_cb)
1271 p_bcb->con_state = BNEP_STATE_CONN_SETUP;
1272 (*bnep_cb.p_conn_ind_cb) (p_bcb->handle, p_bcb->rem_bda, &p_bcb->dst_uuid, &p_bcb->src_uuid, is_role_change);
1276 /* Profile didn't register connection indication call back */
1277 bnep_send_conn_responce (p_bcb, resp_code);
1278 bnep_connected (p_bcb);
1285 /*******************************************************************************
1287 ** Function bnep_is_packet_allowed
1289 ** Description This function verifies whether the protocol passes through
1290 ** the protocol filters set by the peer
1292 ** Returns BNEP_SUCCESS - if the protocol is allowed
1293 ** BNEP_IGNORE_CMD - if the protocol is filtered out
1295 *******************************************************************************/
1296 tBNEP_RESULT bnep_is_packet_allowed (tBNEP_CONN *p_bcb,
1297 BD_ADDR p_dest_addr,
1299 BOOLEAN fw_ext_present,
1302 if (p_bcb->rcvd_num_filters)
1306 /* Findout the actual protocol to check for the filtering */
1308 if (proto == BNEP_802_1_P_PROTOCOL)
1313 /* parse the extension headers and findout actual protocol */
1320 } while (ext & 0x80);
1323 BE_STREAM_TO_UINT16 (proto, p_data);
1326 for (i=0; i<p_bcb->rcvd_num_filters; i++)
1328 if ((p_bcb->rcvd_prot_filter_start[i] <= proto) &&
1329 (proto <= p_bcb->rcvd_prot_filter_end[i]))
1333 if (i == p_bcb->rcvd_num_filters)
1335 BNEP_TRACE_DEBUG ("Ignoring protocol 0x%x in BNEP data write", proto);
1336 return BNEP_IGNORE_CMD;
1340 /* Ckeck for multicast address filtering */
1341 if ((p_dest_addr[0] & 0x01) &&
1342 p_bcb->rcvd_mcast_filters)
1346 /* Check if every multicast should be filtered */
1347 if (p_bcb->rcvd_mcast_filters != 0xFFFF)
1349 /* Check if the address is mentioned in the filter range */
1350 for (i = 0; i < p_bcb->rcvd_mcast_filters; i++)
1352 if ((memcmp (p_bcb->rcvd_mcast_filter_start[i], p_dest_addr, BD_ADDR_LEN) <= 0) &&
1353 (memcmp (p_bcb->rcvd_mcast_filter_end[i], p_dest_addr, BD_ADDR_LEN) >= 0))
1359 ** If every multicast should be filtered or the address is not in the filter range
1362 if ((p_bcb->rcvd_mcast_filters == 0xFFFF) || (i == p_bcb->rcvd_mcast_filters))
1364 BNEP_TRACE_DEBUG ("Ignoring multicast address %x.%x.%x.%x.%x.%x in BNEP data write",
1365 p_dest_addr[0], p_dest_addr[1], p_dest_addr[2],
1366 p_dest_addr[3], p_dest_addr[4], p_dest_addr[5]);
1367 return BNEP_IGNORE_CMD;
1371 return BNEP_SUCCESS;
1374 /*******************************************************************************
1376 ** Function bnep_get_uuid32
1378 ** Description This function returns the 32 bit equivalent of the given UUID
1380 ** Returns UINT32 - 32 bit equivalent of the UUID
1382 *******************************************************************************/
1383 UINT32 bnep_get_uuid32 (tBT_UUID *src_uuid)
1387 if (src_uuid->len == 2)
1388 return ((UINT32)src_uuid->uu.uuid16);
1389 else if (src_uuid->len == 4)
1390 return (src_uuid->uu.uuid32 & 0x0000FFFF);
1393 result = src_uuid->uu.uuid128[2];
1394 result = (result << 8) | (src_uuid->uu.uuid128[3]);