| /****************************************************************************** |
| * |
| * Copyright (C) 1999-2012 Broadcom Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at: |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| ******************************************************************************/ |
| |
| /****************************************************************************** |
| * |
| * This file contains main functions to support PAN profile |
| * commands and events. |
| * |
| ******************************************************************************/ |
| |
| #include <string.h> |
| #include "gki.h" |
| #include "bt_types.h" |
| #include "bt_utils.h" |
| #include "bnep_api.h" |
| #include "pan_api.h" |
| #include "pan_int.h" |
| #include "sdp_api.h" |
| #include "sdpdefs.h" |
| #include "l2c_api.h" |
| #include "hcidefs.h" |
| |
| |
| #if PAN_DYNAMIC_MEMORY == FALSE |
| tPAN_CB pan_cb; |
| #endif |
| |
| #define UUID_CONSTANT_PART 12 |
| UINT8 constant_pan_uuid[UUID_CONSTANT_PART] = {0, 0, 0x10, 0, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}; |
| |
| |
| /******************************************************************************* |
| ** |
| ** Function pan_register_with_bnep |
| ** |
| ** Description This function registers PAN profile with BNEP |
| ** |
| ** Parameters: none |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void pan_register_with_bnep (void) |
| { |
| tBNEP_REGISTER reg_info; |
| |
| memset (®_info, 0, sizeof (tBNEP_REGISTER)); |
| |
| reg_info.p_conn_ind_cb = pan_conn_ind_cb; |
| reg_info.p_conn_state_cb = pan_connect_state_cb; |
| reg_info.p_data_buf_cb = pan_data_buf_ind_cb; |
| reg_info.p_data_ind_cb = NULL; |
| reg_info.p_tx_data_flow_cb = pan_tx_data_flow_cb; |
| reg_info.p_filter_ind_cb = pan_proto_filt_ind_cb; |
| reg_info.p_mfilter_ind_cb = pan_mcast_filt_ind_cb; |
| |
| BNEP_Register (®_info); |
| } |
| |
| |
| /******************************************************************************* |
| ** |
| ** Function pan_conn_ind_cb |
| ** |
| ** Description This function is registered with BNEP as connection indication |
| ** callback. BNEP will call this when there is connection |
| ** request from the peer. PAN should call BNEP_ConnectResp to |
| ** indicate whether to accept the connection or reject |
| ** |
| ** Parameters: handle - handle for the connection |
| ** p_bda - BD Addr of the peer requesting the connection |
| ** remote_uuid - UUID of the source role (peer device role) |
| ** local_uuid - UUID of the destination role (local device role) |
| ** is_role_change - Flag to indicate that it is a role change |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void pan_conn_ind_cb (UINT16 handle, |
| BD_ADDR p_bda, |
| tBT_UUID *remote_uuid, |
| tBT_UUID *local_uuid, |
| BOOLEAN is_role_change) |
| { |
| tPAN_CONN *pcb; |
| UINT8 req_role; |
| BOOLEAN wrong_uuid; |
| |
| /* |
| ** If we are in GN or NAP role and have one or more |
| ** active connections and the received connection is |
| ** for user role reject it. |
| ** If we are in user role with one connection active |
| ** reject the connection. |
| ** Allocate PCB and store the parameters |
| ** Make bridge request to the host system if connection |
| ** is for NAP |
| */ |
| wrong_uuid = FALSE; |
| #if (defined (BNEP_SUPPORTS_ALL_UUID_LENGTHS) && BNEP_SUPPORTS_ALL_UUID_LENGTHS == TRUE) |
| if (remote_uuid->len == 16) |
| { |
| /* |
| ** If the UUID is 16 bytes forst two bytes should be zeros |
| ** and last 12 bytes should match the spec defined constant value |
| */ |
| if (memcmp (constant_pan_uuid, remote_uuid->uu.uuid128 + 4, UUID_CONSTANT_PART)) |
| wrong_uuid = TRUE; |
| |
| if (remote_uuid->uu.uuid128[0] || remote_uuid->uu.uuid128[1]) |
| wrong_uuid = TRUE; |
| |
| /* Extract the 16 bit equivalent of the UUID */ |
| remote_uuid->uu.uuid16 = (UINT16)((remote_uuid->uu.uuid128[2] << 8) | remote_uuid->uu.uuid128[3]); |
| remote_uuid->len = 2; |
| } |
| if (remote_uuid->len == 4) |
| { |
| /* First two bytes should be zeros */ |
| if (remote_uuid->uu.uuid32 & 0xFFFF0000) |
| wrong_uuid = TRUE; |
| |
| remote_uuid->uu.uuid16 = (UINT16)remote_uuid->uu.uuid32; |
| remote_uuid->len = 2; |
| } |
| |
| if (wrong_uuid) |
| { |
| PAN_TRACE_ERROR0 ("PAN Connection failed because of wrong remote UUID "); |
| BNEP_ConnectResp (handle, BNEP_CONN_FAILED_SRC_UUID); |
| return; |
| } |
| |
| wrong_uuid = FALSE; |
| if (local_uuid->len == 16) |
| { |
| /* |
| ** If the UUID is 16 bytes forst two bytes should be zeros |
| ** and last 12 bytes should match the spec defined constant value |
| */ |
| if (memcmp (constant_pan_uuid, local_uuid->uu.uuid128 + 4, UUID_CONSTANT_PART)) |
| wrong_uuid = TRUE; |
| |
| if (local_uuid->uu.uuid128[0] || local_uuid->uu.uuid128[1]) |
| wrong_uuid = TRUE; |
| |
| /* Extract the 16 bit equivalent of the UUID */ |
| local_uuid->uu.uuid16 = (UINT16)((local_uuid->uu.uuid128[2] << 8) | local_uuid->uu.uuid128[3]); |
| local_uuid->len = 2; |
| } |
| if (local_uuid->len == 4) |
| { |
| /* First two bytes should be zeros */ |
| if (local_uuid->uu.uuid32 & 0xFFFF0000) |
| wrong_uuid = TRUE; |
| |
| local_uuid->uu.uuid16 = (UINT16)local_uuid->uu.uuid32; |
| local_uuid->len = 2; |
| } |
| |
| if (wrong_uuid) |
| { |
| PAN_TRACE_ERROR0 ("PAN Connection failed because of wrong local UUID "); |
| BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID); |
| return; |
| } |
| |
| PAN_TRACE_EVENT5 ("pan_conn_ind_cb - for handle %d, current role %d, dst uuid 0x%x, src uuid 0x%x, role change %s", |
| handle, pan_cb.role, local_uuid->uu.uuid16, remote_uuid->uu.uuid16, is_role_change?"YES":"NO"); |
| /* The acceptable UUID size is only 2 */ |
| if (remote_uuid->len != 2) |
| { |
| PAN_TRACE_ERROR1 ("PAN Connection failed because of wrong UUID size %d", remote_uuid->len); |
| BNEP_ConnectResp (handle, BNEP_CONN_FAILED_UUID_SIZE); |
| return; |
| } |
| #endif |
| |
| /* Check if the source UUID is a valid one */ |
| if (remote_uuid->uu.uuid16 != UUID_SERVCLASS_PANU && |
| remote_uuid->uu.uuid16 != UUID_SERVCLASS_NAP && |
| remote_uuid->uu.uuid16 != UUID_SERVCLASS_GN) |
| { |
| PAN_TRACE_ERROR1 ("Src UUID 0x%x is not valid", remote_uuid->uu.uuid16); |
| BNEP_ConnectResp (handle, BNEP_CONN_FAILED_SRC_UUID); |
| return; |
| } |
| |
| /* Check if the destination UUID is a valid one */ |
| if (local_uuid->uu.uuid16 != UUID_SERVCLASS_PANU && |
| local_uuid->uu.uuid16 != UUID_SERVCLASS_NAP && |
| local_uuid->uu.uuid16 != UUID_SERVCLASS_GN) |
| { |
| PAN_TRACE_ERROR1 ("Dst UUID 0x%x is not valid", remote_uuid->uu.uuid16); |
| BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID); |
| return; |
| } |
| |
| /* Check if currently we support the destination role requested */ |
| if (((!(pan_cb.role & UUID_SERVCLASS_PANU)) |
| && local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU) || |
| ((!(pan_cb.role & UUID_SERVCLASS_GN)) |
| && local_uuid->uu.uuid16 == UUID_SERVCLASS_GN) || |
| ((!(pan_cb.role & UUID_SERVCLASS_NAP)) |
| && local_uuid->uu.uuid16 == UUID_SERVCLASS_NAP)) |
| { |
| PAN_TRACE_ERROR1 ("PAN Connection failed because of unsupported destination UUID 0x%x", local_uuid->uu.uuid16); |
| BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID); |
| return; |
| } |
| |
| /* Requested destination role is */ |
| if (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU) |
| req_role = PAN_ROLE_CLIENT; |
| else if (local_uuid->uu.uuid16 == UUID_SERVCLASS_GN) |
| req_role = PAN_ROLE_GN_SERVER; |
| else |
| req_role = PAN_ROLE_NAP_SERVER; |
| |
| /* If the connection indication is for the existing connection |
| ** Check if the new destination role is acceptable |
| */ |
| pcb = pan_get_pcb_by_handle (handle); |
| if (pcb) |
| { |
| if (pan_cb.num_conns > 1 && local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU) |
| { |
| /* There are connections other than this one |
| ** so we cann't accept PANU role. Reject |
| */ |
| PAN_TRACE_ERROR0 ("Dst UUID should be either GN or NAP only because there are other connections"); |
| BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID); |
| return; |
| } |
| |
| /* If it is already in connected state check for bridging status */ |
| if (pcb->con_state == PAN_STATE_CONNECTED) |
| { |
| PAN_TRACE_EVENT2 ("PAN Role changing New Src 0x%x Dst 0x%x", |
| remote_uuid->uu.uuid16, local_uuid->uu.uuid16); |
| |
| pcb->prv_src_uuid = pcb->src_uuid; |
| pcb->prv_dst_uuid = pcb->dst_uuid; |
| |
| if (pcb->src_uuid == UUID_SERVCLASS_NAP && |
| local_uuid->uu.uuid16 != UUID_SERVCLASS_NAP) |
| { |
| /* Remove bridging */ |
| if (pan_cb.pan_bridge_req_cb) |
| (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, FALSE); |
| } |
| } |
| /* Set the latest active PAN role */ |
| pan_cb.active_role = req_role; |
| pcb->src_uuid = local_uuid->uu.uuid16; |
| pcb->dst_uuid = remote_uuid->uu.uuid16; |
| BNEP_ConnectResp (handle, BNEP_SUCCESS); |
| return; |
| } |
| else |
| { |
| /* If this a new connection and destination is PANU role and |
| ** we already have a connection then reject the request. |
| ** If we have a connection in PANU role then reject it |
| */ |
| if (pan_cb.num_conns && |
| (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU || |
| pan_cb.active_role == PAN_ROLE_CLIENT)) |
| { |
| PAN_TRACE_ERROR0 ("PAN already have a connection and can't be user"); |
| BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID); |
| return; |
| } |
| } |
| |
| /* This is a new connection */ |
| PAN_TRACE_DEBUG1 ("New connection indication for handle %d", handle); |
| pcb = pan_allocate_pcb (p_bda, handle); |
| if (!pcb) |
| { |
| PAN_TRACE_ERROR0 ("PAN no control block for new connection"); |
| BNEP_ConnectResp (handle, BNEP_CONN_FAILED); |
| return; |
| } |
| |
| PAN_TRACE_EVENT1 ("PAN connection destination UUID is 0x%x", local_uuid->uu.uuid16); |
| /* Set the latest active PAN role */ |
| pan_cb.active_role = req_role; |
| pcb->src_uuid = local_uuid->uu.uuid16; |
| pcb->dst_uuid = remote_uuid->uu.uuid16; |
| pcb->con_state = PAN_STATE_CONN_START; |
| pan_cb.num_conns++; |
| |
| BNEP_ConnectResp (handle, BNEP_SUCCESS); |
| return; |
| } |
| |
| |
| /******************************************************************************* |
| ** |
| ** Function pan_connect_state_cb |
| ** |
| ** Description This function is registered with BNEP as connection state |
| ** change callback. BNEP will call this when the connection |
| ** is established successfully or terminated |
| ** |
| ** Parameters: handle - handle for the connection given in the connection |
| ** indication callback |
| ** rem_bda - remote device bd addr |
| ** result - indicates whether the connection is up or down |
| ** BNEP_SUCCESS if the connection is up |
| ** all other values indicates appropriate errors |
| ** is_role_change - flag to indicate that it is a role change |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void pan_connect_state_cb (UINT16 handle, BD_ADDR rem_bda, tBNEP_RESULT result, BOOLEAN is_role_change) |
| { |
| tPAN_CONN *pcb; |
| UINT8 peer_role; |
| UNUSED(rem_bda); |
| |
| PAN_TRACE_EVENT2 ("pan_connect_state_cb - for handle %d, result %d", handle, result); |
| pcb = pan_get_pcb_by_handle (handle); |
| if (!pcb) |
| { |
| PAN_TRACE_ERROR1 ("PAN State change indication for wrong handle %d", handle); |
| return; |
| } |
| |
| /* If the connection is getting terminated remove bridging */ |
| if (result != BNEP_SUCCESS) |
| { |
| /* Inform the application that connection is down */ |
| if (pan_cb.pan_conn_state_cb) |
| (*pan_cb.pan_conn_state_cb) (pcb->handle, pcb->rem_bda, result, is_role_change, PAN_ROLE_INACTIVE, PAN_ROLE_INACTIVE); |
| |
| /* Check if this failure is for role change only */ |
| if (pcb->con_state != PAN_STATE_CONNECTED && |
| (pcb->con_flags & PAN_FLAGS_CONN_COMPLETED)) |
| { |
| /* restore the original values */ |
| PAN_TRACE_EVENT0 ("restoring the connection state to active"); |
| pcb->con_state = PAN_STATE_CONNECTED; |
| pcb->con_flags &= (~PAN_FLAGS_CONN_COMPLETED); |
| |
| pcb->src_uuid = pcb->prv_src_uuid; |
| pcb->dst_uuid = pcb->prv_dst_uuid; |
| pan_cb.active_role = pan_cb.prv_active_role; |
| |
| if ((pcb->src_uuid == UUID_SERVCLASS_NAP) && pan_cb.pan_bridge_req_cb) |
| (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, TRUE); |
| |
| return; |
| } |
| |
| if (pcb->con_state == PAN_STATE_CONNECTED) |
| { |
| /* If the connections destination role is NAP remove bridging */ |
| if ((pcb->src_uuid == UUID_SERVCLASS_NAP) && pan_cb.pan_bridge_req_cb) |
| (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, FALSE); |
| } |
| |
| pan_cb.num_conns--; |
| pan_release_pcb (pcb); |
| return; |
| } |
| |
| /* Requested destination role is */ |
| if (pcb->src_uuid == UUID_SERVCLASS_PANU) |
| pan_cb.active_role = PAN_ROLE_CLIENT; |
| else if (pcb->src_uuid == UUID_SERVCLASS_GN) |
| pan_cb.active_role = PAN_ROLE_GN_SERVER; |
| else |
| pan_cb.active_role = PAN_ROLE_NAP_SERVER; |
| |
| if (pcb->dst_uuid == UUID_SERVCLASS_PANU) |
| peer_role = PAN_ROLE_CLIENT; |
| else if (pcb->dst_uuid == UUID_SERVCLASS_GN) |
| peer_role = PAN_ROLE_GN_SERVER; |
| else |
| peer_role = PAN_ROLE_NAP_SERVER; |
| |
| pcb->con_state = PAN_STATE_CONNECTED; |
| |
| /* Inform the application that connection is down */ |
| if (pan_cb.pan_conn_state_cb) |
| (*pan_cb.pan_conn_state_cb) (pcb->handle, pcb->rem_bda, PAN_SUCCESS, is_role_change, pan_cb.active_role, peer_role); |
| |
| /* Create bridge if the destination role is NAP */ |
| if (pan_cb.pan_bridge_req_cb && pcb->src_uuid == UUID_SERVCLASS_NAP) |
| { |
| PAN_TRACE_EVENT0 ("PAN requesting for bridge"); |
| (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, TRUE); |
| } |
| } |
| |
| |
| /******************************************************************************* |
| ** |
| ** Function pan_data_ind_cb |
| ** |
| ** Description This function is registered with BNEP as data indication |
| ** callback. BNEP will call this when the peer sends any data |
| ** on this connection |
| ** |
| ** Parameters: handle - handle for the connection |
| ** src - source BD Addr |
| ** dst - destination BD Addr |
| ** protocol - Network protocol of the Eth packet |
| ** p_data - pointer to the data |
| ** len - length of the data |
| ** fw_ext_present - to indicate whether the data contains any |
| ** extension headers before the payload |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void pan_data_ind_cb (UINT16 handle, |
| UINT8 *src, |
| UINT8 *dst, |
| UINT16 protocol, |
| UINT8 *p_data, |
| UINT16 len, |
| BOOLEAN ext) |
| { |
| tPAN_CONN *pcb; |
| UINT16 i; |
| BOOLEAN forward; |
| |
| /* |
| ** Check the connection status |
| ** If the destination address is MAC broadcast send on all links |
| ** except on the one received |
| ** If the destination uuid is for NAP send to host system also |
| ** If the destination address is one of the devices connected |
| ** send the packet to over that link |
| ** If the destination address is unknown and destination uuid is NAP |
| ** send it to the host system |
| */ |
| |
| PAN_TRACE_EVENT1 ("pan_data_ind_cb - for handle %d", handle); |
| pcb = pan_get_pcb_by_handle (handle); |
| if (!pcb) |
| { |
| PAN_TRACE_ERROR1 ("PAN Data indication for wrong handle %d", handle); |
| return; |
| } |
| |
| if (pcb->con_state != PAN_STATE_CONNECTED) |
| { |
| PAN_TRACE_ERROR2 ("PAN Data indication in wrong state %d for handle %d", |
| pcb->con_state, handle); |
| return; |
| } |
| |
| /* Check if it is broadcast packet */ |
| if (dst[0] & 0x01) |
| { |
| PAN_TRACE_DEBUG2 ("PAN received broadcast packet on handle %d, src uuid 0x%x", |
| handle, pcb->src_uuid); |
| for (i=0; i<MAX_PAN_CONNS; i++) |
| { |
| if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED && |
| pan_cb.pcb[i].handle != handle && |
| pcb->src_uuid == pan_cb.pcb[i].src_uuid) |
| { |
| BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext); |
| } |
| } |
| |
| if (pan_cb.pan_data_ind_cb) |
| (*pan_cb.pan_data_ind_cb) (pcb->handle, src, dst, protocol, p_data, len, ext, TRUE); |
| |
| return; |
| } |
| |
| /* Check if it is for any other PAN connection */ |
| for (i=0; i<MAX_PAN_CONNS; i++) |
| { |
| if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED && |
| pcb->src_uuid == pan_cb.pcb[i].src_uuid) |
| { |
| if (memcmp (pan_cb.pcb[i].rem_bda, dst, BD_ADDR_LEN) == 0) |
| { |
| BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext); |
| return; |
| } |
| } |
| } |
| |
| if (pcb->src_uuid == UUID_SERVCLASS_NAP) |
| forward = TRUE; |
| else |
| forward = FALSE; |
| |
| /* Send it over the LAN or give it to host software */ |
| if (pan_cb.pan_data_ind_cb) |
| (*pan_cb.pan_data_ind_cb) (pcb->handle, src, dst, protocol, p_data, len, ext, forward); |
| |
| return; |
| } |
| |
| |
| /******************************************************************************* |
| ** |
| ** Function pan_data_buf_ind_cb |
| ** |
| ** Description This function is registered with BNEP as data buffer indication |
| ** callback. BNEP will call this when the peer sends any data |
| ** on this connection. PAN is responsible to release the buffer |
| ** |
| ** Parameters: handle - handle for the connection |
| ** src - source BD Addr |
| ** dst - destination BD Addr |
| ** protocol - Network protocol of the Eth packet |
| ** p_buf - pointer to the data buffer |
| ** ext - to indicate whether the data contains any |
| ** extension headers before the payload |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void pan_data_buf_ind_cb (UINT16 handle, |
| UINT8 *src, |
| UINT8 *dst, |
| UINT16 protocol, |
| BT_HDR *p_buf, |
| BOOLEAN ext) |
| { |
| tPAN_CONN *pcb, *dst_pcb; |
| tBNEP_RESULT result; |
| UINT16 i, len; |
| UINT8 *p_data; |
| BOOLEAN forward = FALSE; |
| |
| /* Check if the connection is in right state */ |
| pcb = pan_get_pcb_by_handle (handle); |
| if (!pcb) |
| { |
| PAN_TRACE_ERROR1 ("PAN Data buffer indication for wrong handle %d", handle); |
| GKI_freebuf (p_buf); |
| return; |
| } |
| |
| if (pcb->con_state != PAN_STATE_CONNECTED) |
| { |
| PAN_TRACE_ERROR2 ("PAN Data indication in wrong state %d for handle %d", |
| pcb->con_state, handle); |
| GKI_freebuf (p_buf); |
| return; |
| } |
| |
| p_data = (UINT8 *)(p_buf + 1) + p_buf->offset; |
| len = p_buf->len; |
| |
| PAN_TRACE_EVENT4 ("pan_data_buf_ind_cb - for handle %d, protocol 0x%x, length %d, ext %d", |
| handle, protocol, len, ext); |
| |
| if (pcb->src_uuid == UUID_SERVCLASS_NAP) |
| forward = TRUE; |
| else |
| forward = FALSE; |
| |
| /* Check if it is broadcast or multicast packet */ |
| if (pcb->src_uuid != UUID_SERVCLASS_PANU) |
| { |
| if (dst[0] & 0x01) |
| { |
| PAN_TRACE_DEBUG2 ("PAN received broadcast packet on handle %d, src uuid 0x%x", |
| handle, pcb->src_uuid); |
| for (i=0; i<MAX_PAN_CONNS; i++) |
| { |
| if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED && |
| pan_cb.pcb[i].handle != handle && |
| pcb->src_uuid == pan_cb.pcb[i].src_uuid) |
| { |
| BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext); |
| } |
| } |
| |
| if (pan_cb.pan_data_buf_ind_cb) |
| (*pan_cb.pan_data_buf_ind_cb) (pcb->handle, src, dst, protocol, p_buf, ext, forward); |
| else if (pan_cb.pan_data_ind_cb) |
| { |
| (*pan_cb.pan_data_ind_cb) (pcb->handle, src, dst, protocol, p_data, len, ext, forward); |
| GKI_freebuf (p_buf); |
| } |
| |
| return; |
| } |
| |
| /* Check if it is for any other PAN connection */ |
| dst_pcb = pan_get_pcb_by_addr (dst); |
| if (dst_pcb) |
| { |
| PAN_TRACE_EVENT0 ("pan_data_buf_ind_cb - destination PANU found and sending the data"); |
| result = BNEP_WriteBuf (dst_pcb->handle, dst, p_buf, protocol, src, ext); |
| if (result != BNEP_SUCCESS && result != BNEP_IGNORE_CMD) |
| PAN_TRACE_ERROR1 ("Failed to write data for PAN connection handle %d", dst_pcb->handle); |
| return; |
| } |
| } |
| |
| /* Send it over the LAN or give it to host software */ |
| if (pan_cb.pan_data_buf_ind_cb) |
| (*pan_cb.pan_data_buf_ind_cb) (pcb->handle, src, dst, protocol, p_buf, ext, forward); |
| else if (pan_cb.pan_data_ind_cb) |
| { |
| (*pan_cb.pan_data_ind_cb) (pcb->handle, src, dst, protocol, p_data, len, ext, forward); |
| GKI_freebuf (p_buf); |
| } |
| else |
| GKI_freebuf (p_buf); |
| |
| return; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function pan_proto_filt_ind_cb |
| ** |
| ** Description This function is registered with BNEP to receive tx data |
| ** flow status |
| ** |
| ** Parameters: handle - handle for the connection |
| ** event - flow status |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void pan_tx_data_flow_cb (UINT16 handle, |
| tBNEP_RESULT event) |
| { |
| |
| if (pan_cb.pan_tx_data_flow_cb) |
| (*pan_cb.pan_tx_data_flow_cb) (handle, event); |
| |
| return; |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Function pan_proto_filt_ind_cb |
| ** |
| ** Description This function is registered with BNEP as proto filter indication |
| ** callback. BNEP will call this when the peer sends any protocol |
| ** filter set for the connection or to indicate the result of the |
| ** protocol filter set by the local device |
| ** |
| ** Parameters: handle - handle for the connection |
| ** indication - TRUE if this is indication |
| ** FALSE if it is called to give the result of local |
| ** device protocol filter set |
| ** result - This gives the result of the filter set operation |
| ** num_filters - number of filters set by the peer device |
| ** p_filters - pointer to the filters set by the peer device |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void pan_proto_filt_ind_cb (UINT16 handle, |
| BOOLEAN indication, |
| tBNEP_RESULT result, |
| UINT16 num_filters, |
| UINT8 *p_filters) |
| { |
| #if (defined (BNEP_SUPPORTS_PROT_FILTERS) && BNEP_SUPPORTS_PROT_FILTERS == TRUE) |
| PAN_TRACE_EVENT4 ("pan_proto_filt_ind_cb - called for handle %d with ind %d, result %d, num %d", |
| handle, indication, result, num_filters); |
| |
| if (pan_cb.pan_pfilt_ind_cb) |
| (*pan_cb.pan_pfilt_ind_cb) (handle, indication, result, num_filters, p_filters); |
| #endif |
| |
| return; |
| } |
| |
| |
| /******************************************************************************* |
| ** |
| ** Function pan_mcast_filt_ind_cb |
| ** |
| ** Description This function is registered with BNEP as mcast filter indication |
| ** callback. BNEP will call this when the peer sends any multicast |
| ** filter set for the connection or to indicate the result of the |
| ** multicast filter set by the local device |
| ** |
| ** Parameters: handle - handle for the connection |
| ** indication - TRUE if this is indication |
| ** FALSE if it is called to give the result of local |
| ** device multicast filter set |
| ** result - This gives the result of the filter set operation |
| ** num_filters - number of filters set by the peer device |
| ** p_filters - pointer to the filters set by the peer device |
| ** |
| ** Returns none |
| ** |
| *******************************************************************************/ |
| void pan_mcast_filt_ind_cb (UINT16 handle, |
| BOOLEAN indication, |
| tBNEP_RESULT result, |
| UINT16 num_filters, |
| UINT8 *p_filters) |
| { |
| #if (defined (BNEP_SUPPORTS_MULTI_FILTERS) && BNEP_SUPPORTS_MULTI_FILTERS == TRUE) |
| PAN_TRACE_EVENT4 ("pan_mcast_filt_ind_cb - called for handle %d with ind %d, result %d, num %d", |
| handle, indication, result, num_filters); |
| |
| if (pan_cb.pan_mfilt_ind_cb) |
| (*pan_cb.pan_mfilt_ind_cb) (handle, indication, result, num_filters, p_filters); |
| #endif |
| |
| return; |
| } |
| |