757 lines
27 KiB
C
757 lines
27 KiB
C
/******************************************************************************
|
|
*
|
|
* 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 "bt_common.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 (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_ERROR ("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_ERROR ("PAN Connection failed because of wrong local UUID ");
|
|
BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID);
|
|
return;
|
|
}
|
|
|
|
PAN_TRACE_EVENT ("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_ERROR ("PAN Connection failed because of wrong UUID size %d", remote_uuid->len);
|
|
BNEP_ConnectResp (handle, BNEP_CONN_FAILED_UUID_SIZE);
|
|
return;
|
|
}
|
|
|
|
/* 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_ERROR ("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_ERROR ("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_ERROR ("PAN Connection failed because of unsupported destination UUID 0x%x", local_uuid->uu.uuid16);
|
|
BNEP_ConnectResp (handle, BNEP_CONN_FAILED_DST_UUID);
|
|
return;
|
|
}
|
|
|
|
/* Check for valid interactions between the three PAN profile roles */
|
|
/*
|
|
* For reference, see Table 1 in PAN Profile v1.0 spec.
|
|
* Note: the remote is the initiator.
|
|
*/
|
|
BOOLEAN is_valid_interaction = FALSE;
|
|
switch (remote_uuid->uu.uuid16) {
|
|
case UUID_SERVCLASS_NAP:
|
|
case UUID_SERVCLASS_GN:
|
|
if (local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU)
|
|
is_valid_interaction = TRUE;
|
|
break;
|
|
case UUID_SERVCLASS_PANU:
|
|
is_valid_interaction = TRUE;
|
|
break;
|
|
}
|
|
/*
|
|
* Explicitly disable connections to the local PANU if the remote is
|
|
* not PANU.
|
|
*/
|
|
if ((local_uuid->uu.uuid16 == UUID_SERVCLASS_PANU) &&
|
|
(remote_uuid->uu.uuid16 != UUID_SERVCLASS_PANU)) {
|
|
is_valid_interaction = FALSE;
|
|
}
|
|
if (!is_valid_interaction) {
|
|
PAN_TRACE_ERROR(
|
|
"PAN Connection failed because of invalid PAN profile roles "
|
|
"interaction: Remote UUID 0x%x Local UUID 0x%x",
|
|
remote_uuid->uu.uuid16, local_uuid->uu.uuid16);
|
|
BNEP_ConnectResp(handle, BNEP_CONN_FAILED_SRC_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_ERROR ("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_EVENT ("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_ERROR ("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_DEBUG ("New connection indication for handle %d", handle);
|
|
pcb = pan_allocate_pcb (p_bda, handle);
|
|
if (!pcb)
|
|
{
|
|
PAN_TRACE_ERROR ("PAN no control block for new connection");
|
|
BNEP_ConnectResp (handle, BNEP_CONN_FAILED);
|
|
return;
|
|
}
|
|
|
|
PAN_TRACE_EVENT ("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_EVENT ("pan_connect_state_cb - for handle %d, result %d", handle, result);
|
|
pcb = pan_get_pcb_by_handle (handle);
|
|
if (!pcb)
|
|
{
|
|
PAN_TRACE_ERROR ("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_EVENT ("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_EVENT ("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_EVENT ("pan_data_ind_cb - for handle %d", handle);
|
|
pcb = pan_get_pcb_by_handle (handle);
|
|
if (!pcb)
|
|
{
|
|
PAN_TRACE_ERROR ("PAN Data indication for wrong handle %d", handle);
|
|
return;
|
|
}
|
|
|
|
if (pcb->con_state != PAN_STATE_CONNECTED)
|
|
{
|
|
PAN_TRACE_ERROR ("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_DEBUG ("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_ERROR ("PAN Data buffer indication for wrong handle %d", handle);
|
|
osi_free(p_buf);
|
|
return;
|
|
}
|
|
|
|
if (pcb->con_state != PAN_STATE_CONNECTED)
|
|
{
|
|
PAN_TRACE_ERROR ("PAN Data indication in wrong state %d for handle %d",
|
|
pcb->con_state, handle);
|
|
osi_free(p_buf);
|
|
return;
|
|
}
|
|
|
|
p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
|
|
len = p_buf->len;
|
|
|
|
PAN_TRACE_EVENT ("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_DEBUG ("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);
|
|
osi_free(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_EVENT ("%s - destination PANU found on handle %d and sending data, len: %d",
|
|
__func__, dst_pcb->handle, len);
|
|
|
|
result = BNEP_Write (dst_pcb->handle, dst, p_data, len, protocol, src, ext);
|
|
if (result != BNEP_SUCCESS && result != BNEP_IGNORE_CMD)
|
|
PAN_TRACE_ERROR ("Failed to write data for PAN connection handle %d", dst_pcb->handle);
|
|
osi_free(p_buf);
|
|
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);
|
|
osi_free(p_buf);
|
|
}
|
|
else
|
|
osi_free(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)
|
|
{
|
|
PAN_TRACE_EVENT ("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);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
**
|
|
** 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)
|
|
{
|
|
PAN_TRACE_EVENT ("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);
|
|
}
|