summaryrefslogtreecommitdiffstats
path: root/stack/pan
diff options
context:
space:
mode:
authorAndre Eisenbach <andre@broadcom.com>2012-02-22 13:18:21 -0800
committerMatthew Xie <mattx@google.com>2012-07-14 11:19:11 -0700
commite448862a47c08eb23185aaed574b39264f5005fc (patch)
tree2bc6246e3091315e77224fd798ea2fe8074ef972 /stack/pan
parenta2ca4b83ab8bbbfd8d5f6693e927ed4b82094624 (diff)
downloadexternal_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.zip
external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.gz
external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.bz2
Initial Bluedroid stack commit
Diffstat (limited to 'stack/pan')
-rw-r--r--stack/pan/pan_api.c840
-rw-r--r--stack/pan/pan_int.h145
-rw-r--r--stack/pan/pan_main.c717
-rw-r--r--stack/pan/pan_utils.c338
4 files changed, 2040 insertions, 0 deletions
diff --git a/stack/pan/pan_api.c b/stack/pan/pan_api.c
new file mode 100644
index 0000000..3cc6dec
--- /dev/null
+++ b/stack/pan/pan_api.c
@@ -0,0 +1,840 @@
+/****************************************************************************/
+/* */
+/* Name: pan_api.c */
+/* */
+/* Function: this file contains main functions to support PAN profile */
+/* commands and events. */
+/* */
+/* Copyright (c) 1999-2011, Broadcom Corp., All Rights Reserved. */
+/* Broadcom Bluetooth Core. Proprietary and confidential. */
+/* */
+/****************************************************************************/
+
+#include <string.h>
+#include "gki.h"
+#include "bt_types.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"
+#include "btm_api.h"
+
+
+/*******************************************************************************
+**
+** Function PAN_Register
+**
+** Description This function is called by the application to register
+** its callbacks with PAN profile. The application then
+** should set the PAN role explicitly.
+**
+** Parameters: p_register - contains all callback function pointers
+**
+**
+** Returns none
+**
+*******************************************************************************/
+void PAN_Register (tPAN_REGISTER *p_register)
+{
+ BTM_SetDiscoverability (BTM_GENERAL_DISCOVERABLE, 0, 0);
+ BTM_SetConnectability (BTM_CONNECTABLE, 0, 0);
+
+ pan_register_with_bnep ();
+
+ if (!p_register)
+ return;
+
+ pan_cb.pan_conn_state_cb = p_register->pan_conn_state_cb;
+ pan_cb.pan_bridge_req_cb = p_register->pan_bridge_req_cb;
+ pan_cb.pan_data_buf_ind_cb = p_register->pan_data_buf_ind_cb;
+ pan_cb.pan_data_ind_cb = p_register->pan_data_ind_cb;
+ pan_cb.pan_pfilt_ind_cb = p_register->pan_pfilt_ind_cb;
+ pan_cb.pan_mfilt_ind_cb = p_register->pan_mfilt_ind_cb;
+ pan_cb.pan_tx_data_flow_cb = p_register->pan_tx_data_flow_cb;
+
+ return;
+}
+
+
+
+/*******************************************************************************
+**
+** Function PAN_Deregister
+**
+** Description This function is called by the application to de-register
+** its callbacks with PAN profile. This will make the PAN to
+** become inactive. This will deregister PAN services from SDP
+** and close all active connections
+**
+** Parameters: none
+**
+**
+** Returns none
+**
+*******************************************************************************/
+void PAN_Deregister (void)
+{
+ pan_cb.pan_bridge_req_cb = NULL;
+ pan_cb.pan_data_buf_ind_cb = NULL;
+ pan_cb.pan_data_ind_cb = NULL;
+ pan_cb.pan_conn_state_cb = NULL;
+ pan_cb.pan_pfilt_ind_cb = NULL;
+ pan_cb.pan_mfilt_ind_cb = NULL;
+
+ PAN_SetRole (PAN_ROLE_INACTIVE, NULL, NULL, NULL, NULL);
+ BNEP_Deregister ();
+
+ return;
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function PAN_SetRole
+**
+** Description This function is called by the application to set the PAN
+** profile role. This should be called after PAN_Register.
+** This can be called any time to change the PAN role
+**
+** Parameters: role - is bit map of roles to be active
+** PAN_ROLE_CLIENT is for PANU role
+** PAN_ROLE_GN_SERVER is for GN role
+** PAN_ROLE_NAP_SERVER is for NAP role
+** sec_mask - Security mask for different roles
+** It is array of UINT8. The byte represent the
+** security for roles PANU, GN and NAP in order
+** p_user_name - Service name for PANU role
+** p_gn_name - Service name for GN role
+** p_nap_name - Service name for NAP role
+** Can be NULL if user wants it to be default
+**
+** Returns PAN_SUCCESS - if the role is set successfully
+** PAN_FAILURE - if the role is not valid
+**
+*******************************************************************************/
+tPAN_RESULT PAN_SetRole (UINT8 role,
+ UINT8 *sec_mask,
+ char *p_user_name,
+ char *p_gn_name,
+ char *p_nap_name)
+{
+ char *p_desc;
+ UINT8 security[3] = {PAN_PANU_SECURITY_LEVEL,
+ PAN_GN_SECURITY_LEVEL,
+ PAN_NAP_SECURITY_LEVEL};
+ UINT8 *p_sec;
+
+ /* If the role is not a valid combination reject it */
+ if ((!(role & (PAN_ROLE_CLIENT | PAN_ROLE_GN_SERVER | PAN_ROLE_NAP_SERVER))) &&
+ role != PAN_ROLE_INACTIVE)
+ {
+ PAN_TRACE_ERROR1 ("PAN role %d is invalid", role);
+ return PAN_FAILURE;
+ }
+
+ /* If the current active role is same as the role being set do nothing */
+ if (pan_cb.role == role)
+ {
+ PAN_TRACE_EVENT1 ("PAN role already was set to: %d", role);
+ return PAN_SUCCESS;
+ }
+
+ if (!sec_mask)
+ p_sec = security;
+ else
+ p_sec = sec_mask;
+
+ /* Register all the roles with SDP */
+ PAN_TRACE_API1 ("PAN_SetRole() called with role 0x%x", role);
+#if (defined (PAN_SUPPORTS_ROLE_NAP) && PAN_SUPPORTS_ROLE_NAP == TRUE)
+ /* Check the service name */
+ if ((p_nap_name == NULL) || (*p_nap_name == 0))
+ p_nap_name = PAN_NAP_DEFAULT_SERVICE_NAME;
+
+ if (role & PAN_ROLE_NAP_SERVER)
+ {
+ /* Registering for NAP service with SDP */
+ p_desc = PAN_NAP_DEFAULT_DESCRIPTION;
+
+ if (pan_cb.pan_nap_sdp_handle != 0)
+ SDP_DeleteRecord (pan_cb.pan_nap_sdp_handle);
+
+ pan_cb.pan_nap_sdp_handle = pan_register_with_sdp (UUID_SERVCLASS_NAP, p_sec[2], p_nap_name, p_desc);
+// btla-specific ++
+ bta_sys_add_uuid(UUID_SERVCLASS_NAP);
+// btla-specific --
+ }
+ /* If the NAP role is already active and now being cleared delete the record */
+ else if (pan_cb.role & PAN_ROLE_NAP_SERVER)
+ {
+ if (pan_cb.pan_nap_sdp_handle != 0)
+ {
+ SDP_DeleteRecord (pan_cb.pan_nap_sdp_handle);
+ pan_cb.pan_nap_sdp_handle = 0;
+// btla-specific ++
+ bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
+// btla-specific --
+ }
+ }
+#endif
+
+#if (defined (PAN_SUPPORTS_ROLE_GN) && PAN_SUPPORTS_ROLE_GN == TRUE)
+ /* Check the service name */
+ if ((p_gn_name == NULL) || (*p_gn_name == 0))
+ p_gn_name = PAN_GN_DEFAULT_SERVICE_NAME;
+
+ if (role & PAN_ROLE_GN_SERVER)
+ {
+ /* Registering for GN service with SDP */
+ p_desc = PAN_GN_DEFAULT_DESCRIPTION;
+
+ if (pan_cb.pan_gn_sdp_handle != 0)
+ SDP_DeleteRecord (pan_cb.pan_gn_sdp_handle);
+
+ pan_cb.pan_gn_sdp_handle = pan_register_with_sdp (UUID_SERVCLASS_GN, p_sec[1], p_gn_name, p_desc);
+// btla-specific ++
+ bta_sys_add_uuid(UUID_SERVCLASS_GN);
+// btla-specific --
+ }
+ /* If the GN role is already active and now being cleared delete the record */
+ else if (pan_cb.role & PAN_ROLE_GN_SERVER)
+ {
+ if (pan_cb.pan_gn_sdp_handle != 0)
+ {
+ SDP_DeleteRecord (pan_cb.pan_gn_sdp_handle);
+ pan_cb.pan_gn_sdp_handle = 0;
+// btla-specific ++
+ bta_sys_remove_uuid(UUID_SERVCLASS_GN);
+// btla-specific --
+ }
+ }
+#endif
+
+#if (defined (PAN_SUPPORTS_ROLE_PANU) && PAN_SUPPORTS_ROLE_PANU == TRUE)
+ /* Check the service name */
+ if ((p_user_name == NULL) || (*p_user_name == 0))
+ p_user_name = PAN_PANU_DEFAULT_SERVICE_NAME;
+
+ if (role & PAN_ROLE_CLIENT)
+ {
+ /* Registering for PANU service with SDP */
+ p_desc = PAN_PANU_DEFAULT_DESCRIPTION;
+ if (pan_cb.pan_user_sdp_handle != 0)
+ SDP_DeleteRecord (pan_cb.pan_user_sdp_handle);
+
+ pan_cb.pan_user_sdp_handle = pan_register_with_sdp (UUID_SERVCLASS_PANU, p_sec[0], p_user_name, p_desc);
+// btla-specific ++
+ bta_sys_add_uuid(UUID_SERVCLASS_PANU);
+// btla-specific --
+ }
+ /* If the PANU role is already active and now being cleared delete the record */
+ else if (pan_cb.role & PAN_ROLE_CLIENT)
+ {
+ if (pan_cb.pan_user_sdp_handle != 0)
+ {
+ SDP_DeleteRecord (pan_cb.pan_user_sdp_handle);
+ pan_cb.pan_user_sdp_handle = 0;
+// btla-specific ++
+ bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
+// btla-specific --
+ }
+ }
+#endif
+
+ /* Check if it is a shutdown request */
+ if (role == PAN_ROLE_INACTIVE)
+ pan_close_all_connections ();
+
+ pan_cb.role = role;
+ PAN_TRACE_EVENT1 ("PAN role set to: %d", role);
+ return PAN_SUCCESS;
+}
+
+
+
+/*******************************************************************************
+**
+** Function PAN_Connect
+**
+** Description This function is called by the application to initiate a
+** connection to the remote device
+**
+** Parameters: rem_bda - BD Addr of the remote device
+** src_role - Role of the local device for the connection
+** dst_role - Role of the remote device for the connection
+** PAN_ROLE_CLIENT is for PANU role
+** PAN_ROLE_GN_SERVER is for GN role
+** PAN_ROLE_NAP_SERVER is for NAP role
+** *handle - Pointer for returning Handle to the connection
+**
+** Returns PAN_SUCCESS - if the connection is initiated successfully
+** PAN_NO_RESOURCES - resources are not sufficent
+** PAN_FAILURE - if the connection cannot be initiated
+** this can be because of the combination of
+** src and dst roles may not be valid or
+** allowed at that point of time
+**
+*******************************************************************************/
+tPAN_RESULT PAN_Connect (BD_ADDR rem_bda, UINT8 src_role, UINT8 dst_role, UINT16 *handle)
+{
+ tPAN_CONN *pcb;
+ tBNEP_RESULT result;
+ tBT_UUID src_uuid, dst_uuid;
+ UINT8 service_id;
+ UINT32 mx_chan_id;
+
+ /*
+ ** Initialize the handle so that in case of failure return values
+ ** the profile will not get confused
+ */
+ *handle = BNEP_INVALID_HANDLE;
+
+ /* Check if PAN is active or not */
+ if (!(pan_cb.role & src_role))
+ {
+ PAN_TRACE_ERROR1 ("PAN is not active for the role %d", src_role);
+ return PAN_FAILURE;
+ }
+
+ /* Validate the parameters before proceeding */
+ if ((src_role != PAN_ROLE_CLIENT && src_role != PAN_ROLE_GN_SERVER && src_role != PAN_ROLE_NAP_SERVER) ||
+ (dst_role != PAN_ROLE_CLIENT && dst_role != PAN_ROLE_GN_SERVER && dst_role != PAN_ROLE_NAP_SERVER))
+ {
+ PAN_TRACE_ERROR2 ("Either source %d or destination role %d is invalid", src_role, dst_role);
+ return PAN_FAILURE;
+ }
+
+ /* Check if connection exists for this remote device */
+ pcb = pan_get_pcb_by_addr (rem_bda);
+
+ /* If we are PANU for this role validate destination role */
+ if (src_role == PAN_ROLE_CLIENT)
+ {
+ if ((pan_cb.num_conns > 1) || (pan_cb.num_conns && (!pcb)))
+ {
+ /*
+ ** If the request is not for existing connection reject it
+ ** because if there is already a connection we cannot accept
+ ** another connection in PANU role
+ */
+ PAN_TRACE_ERROR0 ("Cannot make PANU connections when there are more than one connection");
+ return PAN_INVALID_SRC_ROLE;
+ }
+
+ src_uuid.uu.uuid16 = UUID_SERVCLASS_PANU;
+ if (dst_role == PAN_ROLE_CLIENT)
+ {
+ service_id = BTM_SEC_SERVICE_BNEP_PANU;
+ dst_uuid.uu.uuid16 = UUID_SERVCLASS_PANU;
+ }
+ else if (dst_role == PAN_ROLE_GN_SERVER)
+ {
+ service_id = BTM_SEC_SERVICE_BNEP_GN;
+ dst_uuid.uu.uuid16 = UUID_SERVCLASS_GN;
+ }
+ else
+ {
+ service_id = BTM_SEC_SERVICE_BNEP_NAP;
+ dst_uuid.uu.uuid16 = UUID_SERVCLASS_NAP;
+ }
+ mx_chan_id = dst_uuid.uu.uuid16;
+ }
+ /* If destination is PANU role validate source role */
+ else if (dst_role == PAN_ROLE_CLIENT)
+ {
+ if (pan_cb.num_conns && pan_cb.active_role == PAN_ROLE_CLIENT && !pcb)
+ {
+ PAN_TRACE_ERROR0 ("Device already have a connection in PANU role");
+ return PAN_INVALID_SRC_ROLE;
+ }
+
+ dst_uuid.uu.uuid16 = UUID_SERVCLASS_PANU;
+ if (src_role == PAN_ROLE_GN_SERVER)
+ {
+ service_id = BTM_SEC_SERVICE_BNEP_GN;
+ src_uuid.uu.uuid16 = UUID_SERVCLASS_GN;
+ }
+ else
+ {
+ service_id = BTM_SEC_SERVICE_BNEP_NAP;
+ src_uuid.uu.uuid16 = UUID_SERVCLASS_NAP;
+ }
+ mx_chan_id = src_uuid.uu.uuid16;
+ }
+ /* The role combination is not valid */
+ else
+ {
+ PAN_TRACE_ERROR2 ("Source %d and Destination roles %d are not valid combination",
+ src_role, dst_role);
+ return PAN_FAILURE;
+ }
+
+ /* Allocate control block and initiate connection */
+ if (!pcb)
+ pcb = pan_allocate_pcb (rem_bda, BNEP_INVALID_HANDLE);
+ if (!pcb)
+ {
+ PAN_TRACE_ERROR0 ("PAN Connection failed because of no resources");
+ return PAN_NO_RESOURCES;
+ }
+ BTM_SetOutService(rem_bda, BTM_SEC_SERVICE_BNEP_PANU, mx_chan_id);
+
+ PAN_TRACE_API6 ("PAN_Connect() for BD Addr %x.%x.%x.%x.%x.%x",
+ rem_bda[0], rem_bda[1], rem_bda[2], rem_bda[3], rem_bda[4], rem_bda[5]);
+ if (pcb->con_state == PAN_STATE_IDLE)
+ {
+ pan_cb.num_conns++;
+ }
+ else if (pcb->con_state == PAN_STATE_CONNECTED)
+ {
+ pcb->con_flags |= PAN_FLAGS_CONN_COMPLETED;
+ }
+ else
+ /* PAN connection is still in progress */
+ return PAN_WRONG_STATE;
+
+ pcb->con_state = PAN_STATE_CONN_START;
+ pcb->prv_src_uuid = pcb->src_uuid;
+ pcb->prv_dst_uuid = pcb->dst_uuid;
+
+ pcb->src_uuid = src_uuid.uu.uuid16;
+ pcb->dst_uuid = dst_uuid.uu.uuid16;
+
+ src_uuid.len = 2;
+ dst_uuid.len = 2;
+
+ result = BNEP_Connect (rem_bda, &src_uuid, &dst_uuid, &(pcb->handle));
+ if (result != BNEP_SUCCESS)
+ {
+ pan_release_pcb (pcb);
+ return result;
+ }
+
+ PAN_TRACE_DEBUG1 ("PAN_Connect() current active role set to %d", src_role);
+ pan_cb.prv_active_role = pan_cb.active_role;
+ pan_cb.active_role = src_role;
+ *handle = pcb->handle;
+ return PAN_SUCCESS;
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function PAN_Disconnect
+**
+** Description This is used to disconnect the connection
+**
+** Parameters: handle - handle for the connection
+**
+** Returns PAN_SUCCESS - if the connection is closed successfully
+** PAN_FAILURE - if the connection is not found or
+** there is an error in disconnecting
+**
+*******************************************************************************/
+tPAN_RESULT PAN_Disconnect (UINT16 handle)
+{
+ tPAN_CONN *pcb;
+ tBNEP_RESULT result;
+
+ /* Check if the connection exists */
+ pcb = pan_get_pcb_by_handle (handle);
+ if(!pcb)
+ {
+ PAN_TRACE_ERROR1 ("PAN connection not found for the handle %d", handle);
+ return PAN_FAILURE;
+ }
+
+ result = BNEP_Disconnect (pcb->handle);
+ if (pcb->con_state == PAN_STATE_CONNECTED)
+ pan_cb.num_conns--;
+
+ if (pan_cb.pan_bridge_req_cb && pcb->src_uuid == UUID_SERVCLASS_NAP)
+ (*pan_cb.pan_bridge_req_cb) (pcb->rem_bda, FALSE);
+
+ pan_release_pcb (pcb);
+
+ if (result != BNEP_SUCCESS)
+ {
+ PAN_TRACE_EVENT0 ("Error in closing PAN connection");
+ return PAN_FAILURE;
+ }
+
+ PAN_TRACE_EVENT0 ("PAN connection closed");
+ return PAN_SUCCESS;
+}
+
+
+/*******************************************************************************
+**
+** Function PAN_Write
+**
+** Description This sends data over the PAN connections. If this is called
+** on GN or NAP side and the packet is multicast or broadcast
+** it will be sent on all the links. Otherwise the correct link
+** is found based on the destination address and forwarded on it
+** If the return value is not PAN_SUCCESS the application should
+** take care of releasing the message buffer
+**
+** Parameters: handle - handle for the connection
+** dst - MAC or BD Addr of the destination device
+** src - MAC or BD Addr of the source who sent this packet
+** protocol - protocol of the ethernet packet like IP or ARP
+** p_data - pointer to the data
+** len - length of the data
+** ext - to indicate that extension headers present
+**
+** Returns PAN_SUCCESS - if the data is sent successfully
+** PAN_FAILURE - if the connection is not found or
+** there is an error in sending data
+**
+*******************************************************************************/
+tPAN_RESULT PAN_Write (UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol, UINT8 *p_data, UINT16 len, BOOLEAN ext)
+{
+ tPAN_CONN *pcb;
+ UINT16 i;
+ tBNEP_RESULT result;
+
+ if (pan_cb.role == PAN_ROLE_INACTIVE || (!(pan_cb.num_conns)))
+ {
+ PAN_TRACE_ERROR0 ("PAN is not active Data write failed");
+ return PAN_FAILURE;
+ }
+
+ /* Check if it is broadcast or multicast packet */
+ if (dst[0] & 0x01)
+ {
+ for (i=0; i<MAX_PAN_CONNS; i++)
+ {
+ if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED)
+ BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
+ }
+
+ return PAN_SUCCESS;
+ }
+
+ if (pan_cb.active_role == PAN_ROLE_CLIENT)
+ {
+ /* Data write is on PANU connection */
+ for (i=0; i<MAX_PAN_CONNS; i++)
+ {
+ if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
+ pan_cb.pcb[i].src_uuid == UUID_SERVCLASS_PANU)
+ break;
+ }
+
+ if (i == MAX_PAN_CONNS)
+ {
+ PAN_TRACE_ERROR0 ("PAN Don't have any user connections");
+ return PAN_FAILURE;
+ }
+
+ result = BNEP_Write (pan_cb.pcb[i].handle, dst, p_data, len, protocol, src, ext);
+ if (result == BNEP_IGNORE_CMD)
+ {
+ PAN_TRACE_DEBUG0 ("PAN ignored data for PANU connection");
+ return result;
+ }
+ else if (result != BNEP_SUCCESS)
+ {
+ PAN_TRACE_ERROR0 ("PAN failed to write data for the PANU connection");
+ return result;
+ }
+
+ PAN_TRACE_DEBUG0 ("PAN successfully wrote data for the PANU connection");
+ return PAN_SUCCESS;
+ }
+
+ pcb = pan_get_pcb_by_handle (handle);
+ if (!pcb)
+ {
+ PAN_TRACE_ERROR0 ("PAN Data write for wrong addr");
+ return PAN_FAILURE;
+ }
+
+ if (pcb->con_state != PAN_STATE_CONNECTED)
+ {
+ PAN_TRACE_ERROR0 ("PAN Data write when conn is not active");
+ return PAN_FAILURE;
+ }
+
+ result = BNEP_Write (pcb->handle, dst, p_data, len, protocol, src, ext);
+ if (result == BNEP_IGNORE_CMD)
+ {
+ PAN_TRACE_DEBUG0 ("PAN ignored data write to PANU");
+ return result;
+ }
+ else if (result != BNEP_SUCCESS)
+ {
+ PAN_TRACE_ERROR0 ("PAN failed to send data to the PANU");
+ return result;
+ }
+
+ PAN_TRACE_DEBUG0 ("PAN successfully sent data to the PANU");
+ return PAN_SUCCESS;
+}
+
+
+/*******************************************************************************
+**
+** Function PAN_WriteBuf
+**
+** Description This sends data over the PAN connections. If this is called
+** on GN or NAP side and the packet is multicast or broadcast
+** it will be sent on all the links. Otherwise the correct link
+** is found based on the destination address and forwarded on it
+** If the return value is not PAN_SUCCESS the application should
+** take care of releasing the message buffer
+**
+** Parameters: handle - handle for the connection
+** dst - MAC or BD Addr of the destination device
+** src - MAC or BD Addr of the source who sent this packet
+** protocol - protocol of the ethernet packet like IP or ARP
+** p_buf - pointer to the data buffer
+** ext - to indicate that extension headers present
+**
+** Returns PAN_SUCCESS - if the data is sent successfully
+** PAN_FAILURE - if the connection is not found or
+** there is an error in sending data
+**
+*******************************************************************************/
+tPAN_RESULT PAN_WriteBuf (UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol, BT_HDR *p_buf, BOOLEAN ext)
+{
+ tPAN_CONN *pcb;
+ UINT16 i;
+ tBNEP_RESULT result;
+
+ /* Check if it is broadcast or multicast packet */
+ if (dst[0] & 0x01)
+ {
+ UINT8 *p_data;
+ UINT16 len;
+
+ p_data = (UINT8 *)(p_buf + 1) + p_buf->offset;
+ len = p_buf->len;
+ PAN_Write (handle, dst, src, protocol, p_data, len, ext);
+ GKI_freebuf (p_buf);
+ return PAN_SUCCESS;
+ }
+
+ if (pan_cb.role == PAN_ROLE_INACTIVE || (!(pan_cb.num_conns)))
+ {
+ PAN_TRACE_ERROR0 ("PAN is not active Data write failed");
+ GKI_freebuf (p_buf);
+ return PAN_FAILURE;
+ }
+
+ /* Check if the data write is on PANU side */
+ if (pan_cb.active_role == PAN_ROLE_CLIENT)
+ {
+ /* Data write is on PANU connection */
+ for (i=0; i<MAX_PAN_CONNS; i++)
+ {
+ if (pan_cb.pcb[i].con_state == PAN_STATE_CONNECTED &&
+ pan_cb.pcb[i].src_uuid == UUID_SERVCLASS_PANU)
+ break;
+ }
+
+ if (i == MAX_PAN_CONNS)
+ {
+ PAN_TRACE_ERROR0 ("PAN Don't have any user connections");
+ GKI_freebuf (p_buf);
+ return PAN_FAILURE;
+ }
+
+ result = BNEP_WriteBuf (pan_cb.pcb[i].handle, dst, p_buf, protocol, src, ext);
+ if (result == BNEP_IGNORE_CMD)
+ {
+ PAN_TRACE_DEBUG0 ("PAN ignored data write for PANU connection");
+ return result;
+ }
+ else if (result != BNEP_SUCCESS)
+ {
+ PAN_TRACE_ERROR0 ("PAN failed to write data for the PANU connection");
+ return result;
+ }
+
+ PAN_TRACE_DEBUG0 ("PAN successfully wrote data for the PANU connection");
+ return PAN_SUCCESS;
+ }
+
+ /* findout to which connection the data is meant for */
+ pcb = pan_get_pcb_by_handle (handle);
+ if (!pcb)
+ {
+ PAN_TRACE_ERROR0 ("PAN Buf write for wrong handle");
+ GKI_freebuf (p_buf);
+ return PAN_FAILURE;
+ }
+
+ if (pcb->con_state != PAN_STATE_CONNECTED)
+ {
+ PAN_TRACE_ERROR0 ("PAN Buf write when conn is not active");
+ GKI_freebuf (p_buf);
+ return PAN_FAILURE;
+ }
+
+ result = BNEP_WriteBuf (pcb->handle, dst, p_buf, protocol, src, ext);
+ if (result == BNEP_IGNORE_CMD)
+ {
+ PAN_TRACE_DEBUG0 ("PAN ignored data buf write to PANU");
+ return result;
+ }
+ else if (result != BNEP_SUCCESS)
+ {
+ PAN_TRACE_ERROR0 ("PAN failed to send data buf to the PANU");
+ return result;
+ }
+
+ PAN_TRACE_DEBUG0 ("PAN successfully sent data buf to the PANU");
+ return PAN_SUCCESS;
+}
+
+
+/*******************************************************************************
+**
+** Function PAN_SetProtocolFilters
+**
+** Description This function is used to set protocol filters on the peer
+**
+** Parameters: handle - handle for the connection
+** num_filters - number of protocol filter ranges
+** start - array of starting protocol numbers
+** end - array of ending protocol numbers
+**
+**
+** Returns PAN_SUCCESS if protocol filters are set successfully
+** PAN_FAILURE if connection not found or error in setting
+**
+*******************************************************************************/
+tPAN_RESULT PAN_SetProtocolFilters (UINT16 handle,
+ UINT16 num_filters,
+ UINT16 *p_start_array,
+ UINT16 *p_end_array)
+{
+#if (defined (BNEP_SUPPORTS_PROT_FILTERS) && BNEP_SUPPORTS_PROT_FILTERS == TRUE)
+ tPAN_CONN *pcb;
+ tPAN_RESULT result;
+
+ /* Check if the connection exists */
+ pcb = pan_get_pcb_by_handle (handle);
+ if(!pcb)
+ {
+ PAN_TRACE_ERROR1 ("PAN connection not found for the handle %d", handle);
+ return PAN_FAILURE;
+ }
+
+ result = BNEP_SetProtocolFilters (pcb->handle, num_filters, p_start_array, p_end_array);
+ if (result != BNEP_SUCCESS)
+ {
+ PAN_TRACE_ERROR1 ("PAN failed to set protocol filters for handle %d", handle);
+ return result;
+ }
+
+ PAN_TRACE_API1 ("PAN successfully sent protocol filters for handle %d", handle);
+ return PAN_SUCCESS;
+#else
+ return PAN_FAILURE;
+#endif
+}
+
+
+
+/*******************************************************************************
+**
+** Function PAN_SetMulticastFilters
+**
+** Description This function is used to set multicast filters on the peer
+**
+** Parameters: handle - handle for the connection
+** num_filters - number of multicast filter ranges
+** start - array of starting multicast filter addresses
+** end - array of ending multicast filter addresses
+**
+**
+** Returns PAN_SUCCESS if multicast filters are set successfully
+** PAN_FAILURE if connection not found or error in setting
+**
+*******************************************************************************/
+tBNEP_RESULT PAN_SetMulticastFilters (UINT16 handle,
+ UINT16 num_mcast_filters,
+ UINT8 *p_start_array,
+ UINT8 *p_end_array)
+{
+#if (defined (BNEP_SUPPORTS_MULTI_FILTERS) && BNEP_SUPPORTS_MULTI_FILTERS == TRUE)
+ tPAN_CONN *pcb;
+ tPAN_RESULT result;
+
+ /* Check if the connection exists */
+ pcb = pan_get_pcb_by_handle (handle);
+ if(!pcb)
+ {
+ PAN_TRACE_ERROR1 ("PAN connection not found for the handle %d", handle);
+ return PAN_FAILURE;
+ }
+
+ result = BNEP_SetMulticastFilters (pcb->handle,
+ num_mcast_filters, p_start_array, p_end_array);
+ if (result != BNEP_SUCCESS)
+ {
+ PAN_TRACE_ERROR1 ("PAN failed to set multicast filters for handle %d", handle);
+ return result;
+ }
+
+ PAN_TRACE_API1 ("PAN successfully sent multicast filters for handle %d", handle);
+ return PAN_SUCCESS;
+#else
+ return PAN_FAILURE;
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function PAN_SetTraceLevel
+**
+** Description This function sets the trace level for PAN. If called with
+** a value of 0xFF, it simply reads the current trace level.
+**
+** Returns the new (current) trace level
+**
+*******************************************************************************/
+UINT8 PAN_SetTraceLevel (UINT8 new_level)
+{
+ if (new_level != 0xFF)
+ pan_cb.trace_level = new_level;
+ else
+ pan_dump_status ();
+
+ return (pan_cb.trace_level);
+}
+
+/*******************************************************************************
+**
+** Function PAN_Init
+**
+** Description This function initializes the PAN module variables
+**
+** Parameters: none
+**
+** Returns none
+**
+*******************************************************************************/
+void PAN_Init (void)
+{
+ memset (&pan_cb, 0, sizeof (tPAN_CB));
+
+#if defined(PAN_INITIAL_TRACE_LEVEL)
+ pan_cb.trace_level = PAN_INITIAL_TRACE_LEVEL;
+#else
+ pan_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
+#endif
+}
+
+
diff --git a/stack/pan/pan_int.h b/stack/pan/pan_int.h
new file mode 100644
index 0000000..3c24d08
--- /dev/null
+++ b/stack/pan/pan_int.h
@@ -0,0 +1,145 @@
+/****************************************************************************/
+/* */
+/* Name: pan_int.h */
+/* */
+/* Function this file contains internally used PAN definitions */
+/* */
+/* */
+/* Copyright (c) 2001-2004, WIDCOMM Inc., All Rights Reserved. */
+/* WIDCOMM Bluetooth Core. Proprietary and confidential. */
+/* */
+/****************************************************************************/
+#ifndef PAN_INT_H
+#define PAN_INT_H
+
+#include "pan_api.h"
+
+/*
+** This role is used to shutdown the profile. Used internally
+** Applications should call PAN_Deregister to shutdown the profile
+*/
+#define PAN_ROLE_INACTIVE 0
+
+/* Protocols supported by the host internal stack, are registered with SDP */
+#define PAN_PROTOCOL_IP 0x0800
+#define PAN_PROTOCOL_ARP 0x0806
+
+#define PAN_PROFILE_VERSION 0x0100 /* Version 1.00 */
+
+/* Define the PAN Connection Control Block
+*/
+typedef struct
+{
+#define PAN_STATE_IDLE 0
+#define PAN_STATE_CONN_START 1
+#define PAN_STATE_CONNECTED 2
+ UINT8 con_state;
+
+#define PAN_FLAGS_CONN_COMPLETED 0x01
+ UINT8 con_flags;
+
+ UINT16 handle;
+ BD_ADDR rem_bda;
+
+ UINT16 bad_pkts_rcvd;
+ UINT16 src_uuid;
+ UINT16 dst_uuid;
+ UINT16 prv_src_uuid;
+ UINT16 prv_dst_uuid;
+ UINT16 ip_addr_known;
+ UINT32 ip_addr;
+
+} tPAN_CONN;
+
+
+/* The main PAN control block
+*/
+typedef struct
+{
+ UINT8 role;
+ UINT8 active_role;
+ UINT8 prv_active_role;
+ tPAN_CONN pcb[MAX_PAN_CONNS];
+
+ tPAN_CONN_STATE_CB *pan_conn_state_cb; /* Connection state callback */
+ tPAN_BRIDGE_REQ_CB *pan_bridge_req_cb;
+ tPAN_DATA_IND_CB *pan_data_ind_cb;
+ tPAN_DATA_BUF_IND_CB *pan_data_buf_ind_cb;
+ tPAN_FILTER_IND_CB *pan_pfilt_ind_cb; /* protocol filter indication callback */
+ tPAN_MFILTER_IND_CB *pan_mfilt_ind_cb; /* multicast filter indication callback */
+ tPAN_TX_DATA_FLOW_CB *pan_tx_data_flow_cb;
+
+ BD_ADDR my_bda; /* BD Address of this device */
+ char *user_service_name;
+ char *gn_service_name;
+ char *nap_service_name;
+ UINT32 pan_user_sdp_handle;
+ UINT32 pan_gn_sdp_handle;
+ UINT32 pan_nap_sdp_handle;
+ UINT8 num_conns;
+ UINT8 trace_level;
+} tPAN_CB;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Global PAN data
+*/
+#if PAN_DYNAMIC_MEMORY == FALSE
+PAN_API extern tPAN_CB pan_cb;
+#else
+PAN_API extern tPAN_CB *pan_cb_ptr;
+#define pan_cb (*pan_cb_ptr)
+#endif
+
+/*******************************************************************************/
+extern void pan_register_with_bnep (void);
+extern void pan_conn_ind_cb (UINT16 handle,
+ BD_ADDR p_bda,
+ tBT_UUID *remote_uuid,
+ tBT_UUID *local_uuid,
+ BOOLEAN is_role_change);
+extern void pan_connect_state_cb (UINT16 handle, BD_ADDR rem_bda, tBNEP_RESULT result, BOOLEAN is_role_change);
+extern void pan_data_ind_cb (UINT16 handle,
+ UINT8 *src,
+ UINT8 *dst,
+ UINT16 protocol,
+ UINT8 *p_data,
+ UINT16 len,
+ BOOLEAN fw_ext_present);
+extern void pan_data_buf_ind_cb (UINT16 handle,
+ UINT8 *src,
+ UINT8 *dst,
+ UINT16 protocol,
+ BT_HDR *p_buf,
+ BOOLEAN ext);
+extern void pan_tx_data_flow_cb (UINT16 handle,
+ tBNEP_RESULT event);
+void pan_proto_filt_ind_cb (UINT16 handle,
+ BOOLEAN indication,
+ tBNEP_RESULT result,
+ UINT16 num_filters,
+ UINT8 *p_filters);
+void pan_mcast_filt_ind_cb (UINT16 handle,
+ BOOLEAN indication,
+ tBNEP_RESULT result,
+ UINT16 num_filters,
+ UINT8 *p_filters);
+extern UINT32 pan_register_with_sdp (UINT16 uuid, UINT8 sec_mask, char *p_name, char *p_desc);
+extern tPAN_CONN *pan_allocate_pcb (BD_ADDR p_bda, UINT16 handle);
+extern tPAN_CONN *pan_get_pcb_by_handle (UINT16 handle);
+extern tPAN_CONN *pan_get_pcb_by_addr (BD_ADDR p_bda);
+extern void pan_close_all_connections (void);
+extern void pan_release_pcb (tPAN_CONN *p_pcb);
+extern void pan_dump_status (void);
+
+/********************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/stack/pan/pan_main.c b/stack/pan/pan_main.c
new file mode 100644
index 0000000..36d7a8c
--- /dev/null
+++ b/stack/pan/pan_main.c
@@ -0,0 +1,717 @@
+/****************************************************************************/
+/* */
+/* Name: pan_main.c */
+/* */
+/* Function: this file contains main functions to support PAN profile */
+/* commands and events. */
+/* */
+/* Copyright (c) 1999-2004, WIDCOMM Inc., All Rights Reserved. */
+/* WIDCOMM Bluetooth Core. Proprietary and confidential. */
+/* */
+/****************************************************************************/
+
+#include <string.h>
+#include "gki.h"
+#include "bt_types.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 (&reg_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 (&reg_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;
+
+ 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;
+}
+
diff --git a/stack/pan/pan_utils.c b/stack/pan/pan_utils.c
new file mode 100644
index 0000000..33cd151
--- /dev/null
+++ b/stack/pan/pan_utils.c
@@ -0,0 +1,338 @@
+/****************************************************************************/
+/* */
+/* Name: pan_utils.c */
+/* */
+/* Function: this file contains main functions to support PAN profile */
+/* commands and events. */
+/* */
+/* Copyright (c) 1999-2004, WIDCOMM Inc., All Rights Reserved. */
+/* WIDCOMM Bluetooth Core. Proprietary and confidential. */
+/* */
+/****************************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+#include "gki.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"
+#include "btm_api.h"
+
+
+static const UINT8 pan_proto_elem_data[] = {
+ 0x35, 0x18, /* data element sequence of length 0x18 bytes */
+ 0x35, 0x06, /* data element sequence for L2CAP descriptor */
+ 0x19, 0x01, 0x00, /* UUID for L2CAP - 0x0100 */
+ 0x09, 0x00, 0x0F, /* PSM for BNEP - 0x000F */
+ 0x35, 0x0E, /* data element seqence for BNEP descriptor */
+ 0x19, 0x00, 0x0F, /* UUID for BNEP - 0x000F */
+ 0x09, 0x01, 0x00, /* BNEP specific parameter 0 -- Version of BNEP = version 1 = 0x0001 */
+ 0x35, 0x06, /* BNEP specific parameter 1 -- Supported network packet type list */
+ 0x09, 0x08, 0x00, /* network packet type IPv4 = 0x0800 */
+ 0x09, 0x08, 0x06 /* network packet type ARP = 0x0806 */
+};
+
+/*******************************************************************************
+**
+** Function pan_register_with_sdp
+**
+** Description
+**
+** Returns
+**
+*******************************************************************************/
+UINT32 pan_register_with_sdp (UINT16 uuid, UINT8 sec_mask, char *p_name, char *p_desc)
+{
+ UINT32 sdp_handle;
+ UINT16 browse_list = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
+ UINT16 security = 0;
+ UINT8 availability;
+ UINT32 proto_len = (UINT32)pan_proto_elem_data[1];
+
+ /* Create a record */
+ sdp_handle = SDP_CreateRecord ();
+
+ if (sdp_handle == 0)
+ {
+ PAN_TRACE_ERROR0 ("PAN_SetRole - could not create SDP record");
+ return 0;
+ }
+
+ /* Service Class ID List */
+ SDP_AddServiceClassIdList (sdp_handle, 1, &uuid);
+
+ /* Add protocol element sequence from the constant string */
+ SDP_AddAttribute (sdp_handle, ATTR_ID_PROTOCOL_DESC_LIST, DATA_ELE_SEQ_DESC_TYPE,
+ proto_len, (UINT8 *)(pan_proto_elem_data+2));
+
+// btla-specific ++
+#if 0
+ availability = 0xFF;
+ SDP_AddAttribute (sdp_handle, ATTR_ID_SERVICE_AVAILABILITY, UINT_DESC_TYPE, 1, &availability);
+#endif
+// btla-specific --
+
+ /* Language base */
+ SDP_AddLanguageBaseAttrIDList (sdp_handle, LANG_ID_CODE_ENGLISH, LANG_ID_CHAR_ENCODE_UTF8, LANGUAGE_BASE_ID);
+
+ /* Profile descriptor list */
+ SDP_AddProfileDescriptorList (sdp_handle, uuid, PAN_PROFILE_VERSION);
+
+ /* Service Name */
+ SDP_AddAttribute (sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
+ (UINT8) (strlen(p_name) + 1), (UINT8 *)p_name);
+
+ /* Service description */
+ SDP_AddAttribute (sdp_handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE,
+ (UINT8) (strlen(p_desc) + 1), (UINT8 *)p_desc);
+
+ /* Security description */
+ if (sec_mask)
+ {
+ UINT16_TO_BE_FIELD(&security, 0x0001);
+ }
+ SDP_AddAttribute (sdp_handle, ATTR_ID_SECURITY_DESCRIPTION, UINT_DESC_TYPE, 2, (UINT8 *)&security);
+
+#if (defined (PAN_SUPPORTS_ROLE_NAP) && PAN_SUPPORTS_ROLE_NAP == TRUE)
+ if (uuid == UUID_SERVCLASS_NAP)
+ {
+ UINT16 NetAccessType = 0x0005; /* Ethernet */
+ UINT32 NetAccessRate = 0x0001312D0; /* 10Mb/sec */
+ UINT8 array[10], *p;
+
+ /* Net access type. */
+ p = array;
+ UINT16_TO_BE_STREAM (p, NetAccessType);
+ SDP_AddAttribute (sdp_handle, ATTR_ID_NET_ACCESS_TYPE, UINT_DESC_TYPE, 2, array);
+
+ /* Net access rate. */
+ p = array;
+ UINT32_TO_BE_STREAM (p, NetAccessRate);
+ SDP_AddAttribute (sdp_handle, ATTR_ID_MAX_NET_ACCESS_RATE, UINT_DESC_TYPE, 4, array);
+
+ /* Register with Security Manager for the specific security level */
+ if ((!BTM_SetSecurityLevel (TRUE, p_name, BTM_SEC_SERVICE_BNEP_NAP,
+ sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_NAP))
+ || (!BTM_SetSecurityLevel (FALSE, p_name, BTM_SEC_SERVICE_BNEP_NAP,
+ sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_NAP)))
+ {
+ PAN_TRACE_ERROR0 ("PAN Security Registration failed for PANU");
+ }
+ }
+#endif
+#if (defined (PAN_SUPPORTS_ROLE_GN) && PAN_SUPPORTS_ROLE_GN == TRUE)
+ if (uuid == UUID_SERVCLASS_GN)
+ {
+ if ((!BTM_SetSecurityLevel (TRUE, p_name, BTM_SEC_SERVICE_BNEP_GN,
+ sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_GN))
+ || (!BTM_SetSecurityLevel (FALSE, p_name, BTM_SEC_SERVICE_BNEP_GN,
+ sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_GN)))
+ {
+ PAN_TRACE_ERROR0 ("PAN Security Registration failed for GN");
+ }
+ }
+#endif
+#if (defined (PAN_SUPPORTS_ROLE_PANU) && PAN_SUPPORTS_ROLE_PANU == TRUE)
+ if (uuid == UUID_SERVCLASS_PANU)
+ {
+ if ((!BTM_SetSecurityLevel (TRUE, p_name, BTM_SEC_SERVICE_BNEP_PANU,
+ sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_PANU))
+ || (!BTM_SetSecurityLevel (FALSE, p_name, BTM_SEC_SERVICE_BNEP_PANU,
+ sec_mask, BT_PSM_BNEP, BTM_SEC_PROTO_BNEP, UUID_SERVCLASS_PANU)))
+ {
+ PAN_TRACE_ERROR0 ("PAN Security Registration failed for PANU");
+ }
+ }
+#endif
+
+ /* Make the service browsable */
+ SDP_AddUuidSequence (sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse_list);
+
+
+ return sdp_handle;
+}
+
+
+
+/*******************************************************************************
+**
+** Function pan_allocate_pcb
+**
+** Description
+**
+** Returns
+**
+*******************************************************************************/
+tPAN_CONN *pan_allocate_pcb (BD_ADDR p_bda, UINT16 handle)
+{
+ UINT16 i;
+
+ for (i=0; i<MAX_PAN_CONNS; i++)
+ {
+ if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE &&
+ pan_cb.pcb[i].handle == handle)
+ return NULL;
+ }
+
+ for (i=0; i<MAX_PAN_CONNS; i++)
+ {
+ if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE &&
+ memcmp (pan_cb.pcb[i].rem_bda, p_bda, BD_ADDR_LEN) == 0)
+ return NULL;
+ }
+
+ for (i=0; i<MAX_PAN_CONNS; i++)
+ {
+ if (pan_cb.pcb[i].con_state == PAN_STATE_IDLE)
+ {
+ memset (&(pan_cb.pcb[i]), 0, sizeof (tPAN_CONN));
+ memcpy (pan_cb.pcb[i].rem_bda, p_bda, BD_ADDR_LEN);
+ pan_cb.pcb[i].handle = handle;
+ return &(pan_cb.pcb[i]);
+ }
+ }
+ return NULL;
+}
+
+
+/*******************************************************************************
+**
+** Function pan_get_pcb_by_handle
+**
+** Description
+**
+** Returns
+**
+*******************************************************************************/
+tPAN_CONN *pan_get_pcb_by_handle (UINT16 handle)
+{
+ UINT16 i;
+
+ for (i=0; i<MAX_PAN_CONNS; i++)
+ {
+ if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE &&
+ pan_cb.pcb[i].handle == handle)
+ return &(pan_cb.pcb[i]);
+ }
+
+ return NULL;
+}
+
+
+/*******************************************************************************
+**
+** Function pan_get_pcb_by_addr
+**
+** Description
+**
+** Returns
+**
+*******************************************************************************/
+tPAN_CONN *pan_get_pcb_by_addr (BD_ADDR p_bda)
+{
+ UINT16 i;
+
+ for (i=0; i<MAX_PAN_CONNS; i++)
+ {
+ if (pan_cb.pcb[i].con_state == PAN_STATE_IDLE)
+ continue;
+
+ if (memcmp (pan_cb.pcb[i].rem_bda, p_bda, BD_ADDR_LEN) == 0)
+ return &(pan_cb.pcb[i]);
+
+ /*
+ if (pan_cb.pcb[i].mfilter_present &&
+ (memcmp (p_bda, pan_cb.pcb[i].multi_cast_bridge, BD_ADDR_LEN) == 0))
+ return &(pan_cb.pcb[i]);
+ */
+ }
+
+ return NULL;
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function pan_close_all_connections
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+void pan_close_all_connections (void)
+{
+ UINT16 i;
+
+ for (i=0; i<MAX_PAN_CONNS; i++)
+ {
+ if (pan_cb.pcb[i].con_state != PAN_STATE_IDLE)
+ {
+ BNEP_Disconnect (pan_cb.pcb[i].handle);
+ pan_cb.pcb[i].con_state = PAN_STATE_IDLE;
+ }
+ }
+
+ pan_cb.active_role = PAN_ROLE_INACTIVE;
+ pan_cb.num_conns = 0;
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function pan_release_pcb
+**
+** Description This function releases a PCB.
+**
+** Returns void
+**
+*******************************************************************************/
+void pan_release_pcb (tPAN_CONN *p_pcb)
+{
+ /* Drop any response pointer we may be holding */
+ memset (p_pcb, 0, sizeof (tPAN_CONN));
+ p_pcb->con_state = PAN_STATE_IDLE;
+}
+
+
+/*******************************************************************************
+**
+** Function pan_dump_status
+**
+** Description This function dumps the pan control block and connection
+** blocks information
+**
+** Returns none
+**
+*******************************************************************************/
+void pan_dump_status (void)
+{
+#if (defined (PAN_SUPPORTS_DEBUG_DUMP) && PAN_SUPPORTS_DEBUG_DUMP == TRUE)
+ UINT16 i;
+ char buff[200];
+ tPAN_CONN *p_pcb;
+
+ PAN_TRACE_DEBUG3 ("PAN role %x, active role %d, num_conns %d",
+ pan_cb.role, pan_cb.active_role, pan_cb.num_conns);
+
+ for (i = 0, p_pcb = pan_cb.pcb; i < MAX_PAN_CONNS; i++, p_pcb++)
+ {
+ sprintf (buff, "%d state %d, handle %d, src 0x%x, dst 0x%x, BD %x.%x.%x.%x.%x.%x",
+ i, p_pcb->con_state, p_pcb->handle, p_pcb->src_uuid, p_pcb->dst_uuid,
+ p_pcb->rem_bda[0], p_pcb->rem_bda[1], p_pcb->rem_bda[2],
+ p_pcb->rem_bda[3], p_pcb->rem_bda[4], p_pcb->rem_bda[5]);
+
+ PAN_TRACE_DEBUG0 (buff);
+ }
+#endif
+}
+
+
+