diff options
author | Andre Eisenbach <andre@broadcom.com> | 2012-02-22 13:18:21 -0800 |
---|---|---|
committer | Matthew Xie <mattx@google.com> | 2012-07-14 11:19:11 -0700 |
commit | e448862a47c08eb23185aaed574b39264f5005fc (patch) | |
tree | 2bc6246e3091315e77224fd798ea2fe8074ef972 /bta/pan | |
parent | a2ca4b83ab8bbbfd8d5f6693e927ed4b82094624 (diff) | |
download | external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.zip external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.gz external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.bz2 |
Initial Bluedroid stack commit
Diffstat (limited to 'bta/pan')
-rw-r--r-- | bta/pan/bta_pan_act.c | 718 | ||||
-rw-r--r-- | bta/pan/bta_pan_api.c | 202 | ||||
-rw-r--r-- | bta/pan/bta_pan_ci.c | 248 | ||||
-rw-r--r-- | bta/pan/bta_pan_int.h | 200 | ||||
-rw-r--r-- | bta/pan/bta_pan_main.c | 409 |
5 files changed, 1777 insertions, 0 deletions
diff --git a/bta/pan/bta_pan_act.c b/bta/pan/bta_pan_act.c new file mode 100644 index 0000000..d9424ec --- /dev/null +++ b/bta/pan/bta_pan_act.c @@ -0,0 +1,718 @@ +/***************************************************************************** +** +** Name: bta_pan_act.c +** +** Description: This file contains the pan action functions +** for the state machine. +** +** Copyright (c) 2004-2011, Broadcom Corp., All Rights Reserved. +** Broadcom Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ + +#include "bt_target.h" + +#if defined(PAN_INCLUDED) && (PAN_INCLUDED == TRUE) + +#include "bta_api.h" +#include "bta_sys.h" +#include "bd.h" +#include "gki.h" +#include "pan_api.h" +#include "bta_pan_api.h" +#include "bta_pan_int.h" +#include "bta_pan_co.h" +#include <string.h> + + +/* RX and TX data flow mask */ +#define BTA_PAN_RX_MASK 0x0F +#define BTA_PAN_TX_MASK 0xF0 + +/******************************************************************************* +** +** Function bta_pan_conn_state_cback +** +** Description Connection state callback from Pan profile +** +** +** Returns void +** +*******************************************************************************/ +static void bta_pan_conn_state_cback(UINT16 handle, BD_ADDR bd_addr, tPAN_RESULT state, + BOOLEAN is_role_change, UINT8 src_role, UINT8 dst_role) +{ + + tBTA_PAN_CONN * p_buf; + tBTA_PAN_SCB *p_scb; + + + if ((p_buf = (tBTA_PAN_CONN *) GKI_getbuf(sizeof(tBTA_PAN_CONN))) != NULL) + { + if((state == PAN_SUCCESS) && !is_role_change) + { + p_buf->hdr.event = BTA_PAN_CONN_OPEN_EVT; + if((p_scb = bta_pan_scb_by_handle(handle)) == NULL) + { + /* allocate an scb */ + p_scb = bta_pan_scb_alloc(); + + } + /* we have exceeded maximum number of connections */ + if(!p_scb) + { + PAN_Disconnect (handle); + return; + } + + p_scb->handle = handle; + p_scb->local_role = src_role; + p_scb->peer_role = dst_role; + p_scb->pan_flow_enable = TRUE; + bdcpy(p_scb->bd_addr, bd_addr); + GKI_init_q(&p_scb->data_queue); + + if(src_role == PAN_ROLE_CLIENT) + p_scb->app_id = bta_pan_cb.app_id[0]; + else if (src_role == PAN_ROLE_GN_SERVER) + p_scb->app_id = bta_pan_cb.app_id[1]; + else if (src_role == PAN_ROLE_NAP_SERVER) + p_scb->app_id = bta_pan_cb.app_id[2]; + + } + else if((state != PAN_SUCCESS) && !is_role_change) + { + p_buf->hdr.event = BTA_PAN_CONN_CLOSE_EVT; + + } + else + { + return; + } + + p_buf->result = state; + p_buf->hdr.layer_specific = handle; + bta_sys_sendmsg(p_buf); + + } + + + +} + +/******************************************************************************* +** +** Function bta_pan_data_flow_cb +** +** Description Data flow status callback from PAN +** +** +** Returns void +** +*******************************************************************************/ +static void bta_pan_data_flow_cb(UINT16 handle, tPAN_RESULT result) +{ + BT_HDR *p_buf; + tBTA_PAN_SCB *p_scb; + + if((p_scb = bta_pan_scb_by_handle(handle)) == NULL) + return; + + if(result == PAN_TX_FLOW_ON) + { + if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_buf->layer_specific = handle; + p_buf->event = BTA_PAN_BNEP_FLOW_ENABLE_EVT; + bta_sys_sendmsg(p_buf); + } + bta_pan_co_rx_flow(handle, p_scb->app_id, TRUE); + + } + else if(result == PAN_TX_FLOW_OFF) + { + + p_scb->pan_flow_enable = FALSE; + bta_pan_co_rx_flow(handle, p_scb->app_id, FALSE); + + } + + +} + + +/******************************************************************************* +** +** Function bta_pan_data_buf_ind_cback +** +** Description data indication callback from pan profile +** +** +** Returns void +** +*******************************************************************************/ +static void bta_pan_data_buf_ind_cback(UINT16 handle, BD_ADDR src, BD_ADDR dst, UINT16 protocol, BT_HDR *p_buf, + BOOLEAN ext, BOOLEAN forward) +{ + tBTA_PAN_SCB *p_scb; + BT_HDR * p_event; + BT_HDR *p_new_buf; + + if ( sizeof(tBTA_PAN_DATA_PARAMS) > p_buf->offset ) + { + /* offset smaller than data structure in front of actual data */ + p_new_buf = (BT_HDR *)GKI_getpoolbuf( PAN_POOL_ID ); + if(!p_new_buf) + { + APPL_TRACE_WARNING0("Cannot get a PAN GKI buffer"); + GKI_freebuf( p_buf ); + return; + } + else + { + memcpy( (UINT8 *)(p_new_buf+1)+sizeof(tBTA_PAN_DATA_PARAMS), (UINT8 *)(p_buf+1)+p_buf->offset, p_buf->len ); + p_new_buf->len = p_buf->len; + p_new_buf->offset = sizeof(tBTA_PAN_DATA_PARAMS); + GKI_freebuf( p_buf ); + } + } + else + { + p_new_buf = p_buf; + } + /* copy params into the space before the data */ + bdcpy(((tBTA_PAN_DATA_PARAMS *)p_new_buf)->src, src); + bdcpy(((tBTA_PAN_DATA_PARAMS *)p_new_buf)->dst, dst); + ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->protocol = protocol; + ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->ext = ext; + ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->forward = forward; + + + if((p_scb = bta_pan_scb_by_handle(handle)) == NULL) + { + + GKI_freebuf( p_new_buf ); + return; + } + + GKI_enqueue(&p_scb->data_queue, p_new_buf); + if ((p_event = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_event->layer_specific = handle; + p_event->event = BTA_PAN_RX_FROM_BNEP_READY_EVT; + bta_sys_sendmsg(p_event); + } + +} + + +/******************************************************************************* +** +** Function bta_pan_pfilt_ind_cback +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +static void bta_pan_pfilt_ind_cback(UINT16 handle, BOOLEAN indication,tBNEP_RESULT result, + UINT16 num_filters, UINT8 *p_filters) +{ + + bta_pan_co_pfilt_ind(handle, indication, (tBTA_PAN_STATUS)((result == BNEP_SUCCESS) ? BTA_PAN_SUCCESS : BTA_PAN_FAIL), + num_filters, p_filters); + + +} + + +/******************************************************************************* +** +** Function bta_pan_mfilt_ind_cback +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +static void bta_pan_mfilt_ind_cback(UINT16 handle, BOOLEAN indication,tBNEP_RESULT result, + UINT16 num_mfilters, UINT8 *p_mfilters) +{ + + bta_pan_co_mfilt_ind(handle, indication, (tBTA_PAN_STATUS)((result == BNEP_SUCCESS) ? BTA_PAN_SUCCESS : BTA_PAN_FAIL), + num_mfilters, p_mfilters); +} + + + +/******************************************************************************* +** +** Function bta_pan_enable +** +** Description +** +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_enable(tBTA_PAN_DATA *p_data) +{ + tPAN_REGISTER reg_data; + UINT16 initial_discoverability; + UINT16 initial_connectability; + UINT16 d_window; + UINT16 d_interval; + UINT16 c_window; + UINT16 c_interval; + + bta_pan_cb.p_cback = p_data->api_enable.p_cback; + + reg_data.pan_conn_state_cb = bta_pan_conn_state_cback; + reg_data.pan_bridge_req_cb = NULL; + reg_data.pan_data_buf_ind_cb = bta_pan_data_buf_ind_cback; + reg_data.pan_data_ind_cb = NULL; + reg_data.pan_pfilt_ind_cb = bta_pan_pfilt_ind_cback; + reg_data.pan_mfilt_ind_cb = bta_pan_mfilt_ind_cback; + reg_data.pan_tx_data_flow_cb = bta_pan_data_flow_cb; + + /* read connectability and discoverability settings. + Pan profile changes the settings. We have to change it back to + be consistent with other bta subsystems */ + initial_connectability = BTM_ReadConnectability(&c_window, &c_interval); + initial_discoverability = BTM_ReadDiscoverability(&d_window, &d_interval); + + + PAN_Register (®_data); + + + /* set it back to original value */ + BTM_SetDiscoverability(initial_discoverability, d_window, d_interval); + BTM_SetConnectability(initial_connectability, c_window, c_interval); + + bta_pan_cb.flow_mask = bta_pan_co_init(&bta_pan_cb.q_level); + bta_pan_cb.p_cback(BTA_PAN_ENABLE_EVT, NULL); + +} + +/******************************************************************************* +** +** Function bta_pan_set_role +** +** Description +** +** Returns void +** +*******************************************************************************/ +void bta_pan_set_role(tBTA_PAN_DATA *p_data) +{ + tPAN_RESULT status; + tBTA_PAN_SET_ROLE set_role; + UINT8 sec[3]; + + + bta_pan_cb.app_id[0] = p_data->api_set_role.user_app_id; + bta_pan_cb.app_id[1] = p_data->api_set_role.gn_app_id; + bta_pan_cb.app_id[2] = p_data->api_set_role.nap_app_id; + + sec[0] = p_data->api_set_role.user_sec_mask; + sec[1] = p_data->api_set_role.gn_sec_mask; + sec[2] = p_data->api_set_role.nap_sec_mask; + + /* set security correctly in api and here */ + status = PAN_SetRole(p_data->api_set_role.role, sec, + p_data->api_set_role.user_name, + p_data->api_set_role.gn_name, + p_data->api_set_role.nap_name); + + if(status == PAN_SUCCESS) + { + if(p_data->api_set_role.role & PAN_ROLE_NAP_SERVER ) + bta_sys_add_uuid(UUID_SERVCLASS_NAP); + else + bta_sys_remove_uuid(UUID_SERVCLASS_NAP); + + if(p_data->api_set_role.role & PAN_ROLE_GN_SERVER ) + bta_sys_add_uuid(UUID_SERVCLASS_GN); + else + bta_sys_remove_uuid(UUID_SERVCLASS_GN); + + if(p_data->api_set_role.role & PAN_ROLE_CLIENT ) + bta_sys_add_uuid(UUID_SERVCLASS_PANU); + else + bta_sys_remove_uuid(UUID_SERVCLASS_PANU); + + set_role.role = p_data->api_set_role.role; + bta_pan_cb.p_cback(BTA_PAN_SET_ROLE_EVT, (tBTA_PAN *)&set_role); + } + /* if status is not success clear everything */ + else + { + PAN_SetRole(0, 0, NULL, NULL, NULL); + + bta_sys_remove_uuid(UUID_SERVCLASS_NAP); + bta_sys_remove_uuid(UUID_SERVCLASS_GN); + bta_sys_remove_uuid(UUID_SERVCLASS_PANU); + set_role.role = 0; + bta_pan_cb.p_cback(BTA_PAN_SET_ROLE_EVT, (tBTA_PAN *)&set_role); + } + +} + + + +/******************************************************************************* +** +** Function bta_pan_disable +** +** Description +** +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_disable(void) +{ + + BT_HDR *p_buf; + tBTA_PAN_SCB *p_scb = &bta_pan_cb.scb[0]; + UINT8 i; + + + /* close all connections */ + PAN_SetRole (0, NULL, NULL, NULL, NULL); + +#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE) + bta_sys_remove_uuid(UUID_SERVCLASS_NAP); + bta_sys_remove_uuid(UUID_SERVCLASS_GN); + bta_sys_remove_uuid(UUID_SERVCLASS_PANU); +#endif + /* free all queued up data buffers */ + for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++) + { + if (p_scb->in_use) + { + while((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL) + GKI_freebuf(p_buf); + + bta_pan_co_close(p_scb->handle, p_scb->app_id); + + } + } + + + + PAN_Deregister(); + +} + +/******************************************************************************* +** +** Function bta_pan_open +** +** Description +** +** Returns void +** +*******************************************************************************/ +void bta_pan_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + tPAN_RESULT status; + tBTA_PAN_OPEN data; + tBTA_PAN_OPENING opening; + + + status = PAN_Connect (p_data->api_open.bd_addr, p_data->api_open.local_role, p_data->api_open.peer_role, + &p_scb->handle); + + + if(status == PAN_SUCCESS) + { + + bdcpy(p_scb->bd_addr, p_data->api_open.bd_addr); + p_scb->local_role = p_data->api_open.local_role; + p_scb->peer_role = p_data->api_open.peer_role; + bdcpy(opening.bd_addr, p_data->api_open.bd_addr); + opening.handle = p_scb->handle; + bta_pan_cb.p_cback(BTA_PAN_OPENING_EVT, (tBTA_PAN *)&opening); + + + } + else + { + bta_pan_scb_dealloc(p_scb); + bdcpy(data.bd_addr, p_data->api_open.bd_addr); + data.status = BTA_PAN_FAIL; + bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data); + } + +} + + +/******************************************************************************* +** +** Function bta_pan_close +** +** Description +** +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_api_close (tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + tBTA_PAN_CONN * p_buf; + + PAN_Disconnect (p_scb->handle); + + + /* send an event to BTA so that application will get the connection + close event */ + if ((p_buf = (tBTA_PAN_CONN *) GKI_getbuf(sizeof(tBTA_PAN_CONN))) != NULL) + { + p_buf->hdr.event = BTA_PAN_CONN_CLOSE_EVT; + + p_buf->hdr.layer_specific = p_scb->handle; + bta_sys_sendmsg(p_buf); + + } +} + + +/******************************************************************************* +** +** Function bta_pan_conn_open +** +** Description process connection open event +** +** Returns void +** +*******************************************************************************/ +void bta_pan_conn_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + + tBTA_PAN_OPEN data; + + bdcpy(data.bd_addr, p_scb->bd_addr); + data.handle = p_scb->handle; + data.local_role = p_scb->local_role; + data.peer_role = p_scb->peer_role; + + if(p_data->conn.result == PAN_SUCCESS) + { + data.status = BTA_PAN_SUCCESS; + bta_pan_co_open(p_scb->handle, p_scb->app_id, p_scb->local_role, p_scb->peer_role, p_scb->bd_addr); + + } + else + { + bta_pan_scb_dealloc(p_scb); + data.status = BTA_PAN_FAIL; + } + + p_scb->pan_flow_enable = TRUE; + p_scb->app_flow_enable = TRUE; + + bta_sys_conn_open( BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr); + + bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data); + + +} + +/******************************************************************************* +** +** Function bta_pan_conn_close +** +** Description process connection close event +** +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_conn_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + + tBTA_PAN_CLOSE data; + BT_HDR *p_buf; + + data.handle = p_data->hdr.layer_specific; + + + bta_sys_conn_close( BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr); + + /* free all queued up data buffers */ + while((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL) + GKI_freebuf(p_buf); + + GKI_init_q(&p_scb->data_queue); + + bta_pan_co_close(p_scb->handle, p_scb->app_id); + + bta_pan_scb_dealloc(p_scb); + + bta_pan_cb.p_cback(BTA_PAN_CLOSE_EVT, (tBTA_PAN *)&data); + +} + + + + +/******************************************************************************* +** +** Function bta_pan_rx_path +** +** Description Handle data on the RX path (data sent from the phone to +** BTA). +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_rx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + /* if data path configured for rx pull */ + if ((bta_pan_cb.flow_mask & BTA_PAN_RX_MASK) == BTA_PAN_RX_PULL) + { + /* if we can accept data */ + if (p_scb->pan_flow_enable == TRUE) + { + /* call application callout function for rx path */ + bta_pan_co_rx_path(p_scb->handle, p_scb->app_id); + } + } + /* else data path configured for rx push */ + else + { + + } +} + +/******************************************************************************* +** +** Function bta_pan_tx_path +** +** Description Handle the TX data path (data sent from BTA to the phone). +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_tx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + + BT_HDR * p_buf; + /* if data path configured for tx pull */ + if ((bta_pan_cb.flow_mask & BTA_PAN_TX_MASK) == BTA_PAN_TX_PULL) + { + /* call application callout function for tx path */ + bta_pan_co_tx_path(p_scb->handle, p_scb->app_id); + + /* free data that exceeds queue level */ + while(p_scb->data_queue.count > bta_pan_cb.q_level) + GKI_freebuf(GKI_dequeue(&p_scb->data_queue)); + } + /* if configured for zero copy push */ + else if ((bta_pan_cb.flow_mask & BTA_PAN_TX_MASK) == BTA_PAN_TX_PUSH_BUF) + { + /* if app can accept data */ + if (p_scb->app_flow_enable == TRUE) + { + /* read data from the queue */ + if ((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL) + { + /* send data to application */ + bta_pan_co_tx_writebuf(p_scb->handle, + p_scb->app_id, + ((tBTA_PAN_DATA_PARAMS *)p_buf)->src, + ((tBTA_PAN_DATA_PARAMS *)p_buf)->dst, + ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol, + p_buf, + ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext, + ((tBTA_PAN_DATA_PARAMS *)p_buf)->forward); + + } + /* free data that exceeds queue level */ + while(p_scb->data_queue.count > bta_pan_cb.q_level) + GKI_freebuf(GKI_dequeue(&p_scb->data_queue)); + + /* if there is more data to be passed to + upper layer */ + if(p_scb->data_queue.count) + { + if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_buf->layer_specific = p_scb->handle; + p_buf->event = BTA_PAN_RX_FROM_BNEP_READY_EVT; + bta_sys_sendmsg(p_buf); + } + + } + + } + } +} + +/******************************************************************************* +** +** Function bta_pan_tx_flow +** +** Description Set the application flow control state. +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_tx_flow(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + p_scb->app_flow_enable = p_data->ci_tx_flow.enable; +} + +/******************************************************************************* +** +** Function bta_pan_write_buf +** +** Description Handle a bta_pan_ci_rx_writebuf() and send data to PAN. +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_write_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + if ((bta_pan_cb.flow_mask & BTA_PAN_RX_MASK) == BTA_PAN_RX_PUSH_BUF) + { + + PAN_WriteBuf (p_scb->handle, + ((tBTA_PAN_DATA_PARAMS *)p_data)->dst, + ((tBTA_PAN_DATA_PARAMS *)p_data)->src, + ((tBTA_PAN_DATA_PARAMS *)p_data)->protocol, + (BT_HDR *)p_data, + ((tBTA_PAN_DATA_PARAMS *)p_data)->ext); + + } +} + +/******************************************************************************* +** +** Function bta_pan_free_buf +** +** Description Frees the data buffer during closing state +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_free_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + + GKI_freebuf(p_data); + +} + +#endif /* PAN_INCLUDED */ diff --git a/bta/pan/bta_pan_api.c b/bta/pan/bta_pan_api.c new file mode 100644 index 0000000..5a84668 --- /dev/null +++ b/bta/pan/bta_pan_api.c @@ -0,0 +1,202 @@ +/***************************************************************************** +** +** Name: bta_pan_api.c +** +** Description: This is the implementation of the API for PAN +** subsystem of BTA, Widcomm's Bluetooth application +** layer for mobile phones. +** +** Copyright (c) 2004-2011, Broadcom Corp., All Rights Reserved. +** Broadcom Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ + +#include "bt_target.h" + +#if defined(BTA_PAN_INCLUDED) && (BTA_PAN_INCLUDED == TRUE) + +#include "bta_api.h" +#include "bta_sys.h" +#include "pan_api.h" +#include "gki.h" +#include "bta_pan_api.h" +#include "bta_pan_int.h" +#include "bd.h" +#include <string.h> + +static const tBTA_SYS_REG bta_pan_reg = +{ + bta_pan_hdl_event, + BTA_PanDisable +}; + +/******************************************************************************* +** +** Function BTA_PanEnable +** +** Description Enable PAN service. This function must be +** called before any other functions in the PAN API are called. +** When the enable operation is complete the callback function +** will be called with a BTA_PAN_ENABLE_EVT. +** +** Returns void +** +*******************************************************************************/ +void BTA_PanEnable(tBTA_PAN_CBACK p_cback) +{ + tBTA_PAN_API_ENABLE *p_buf; + + /* register with BTA system manager */ + GKI_sched_lock(); + bta_sys_register(BTA_ID_PAN, &bta_pan_reg); + GKI_sched_unlock(); + + if ((p_buf = (tBTA_PAN_API_ENABLE *) GKI_getbuf(sizeof(tBTA_PAN_API_ENABLE))) != NULL) + { + p_buf->hdr.event = BTA_PAN_API_ENABLE_EVT; + p_buf->p_cback = p_cback; + + bta_sys_sendmsg(p_buf); + } +} + + + +/******************************************************************************* +** +** Function BTA_PanDisable +** +** Description Disables PAN service. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_PanDisable(void) +{ + BT_HDR *p_buf; + + bta_sys_deregister(BTA_ID_PAN); + if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_buf->event = BTA_PAN_API_DISABLE_EVT; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_PanSetRole +** +** Description Sets PAN roles. When the enable operation is complete +** the callback function will be called with a BTA_PAN_SET_ROLE_EVT. +** +** Returns void +** +*******************************************************************************/ +void BTA_PanSetRole(tBTA_PAN_ROLE role, tBTA_PAN_ROLE_INFO *p_user_info, tBTA_PAN_ROLE_INFO *p_gn_info, + tBTA_PAN_ROLE_INFO *p_nap_info) +{ + + tBTA_PAN_API_SET_ROLE *p_buf; + + if ((p_buf = (tBTA_PAN_API_SET_ROLE *) GKI_getbuf(sizeof(tBTA_PAN_API_SET_ROLE))) != NULL) + { + p_buf->hdr.event = BTA_PAN_API_SET_ROLE_EVT; + p_buf->role = role; + + if(p_user_info && (role & BTA_PAN_ROLE_PANU)) + { + if(p_user_info->p_srv_name) + BCM_STRNCPY_S(p_buf->user_name, sizeof(p_buf->user_name), p_user_info->p_srv_name, BTA_SERVICE_NAME_LEN); + else + p_buf->user_name[0] = 0; + + p_buf->user_name[BTA_SERVICE_NAME_LEN] = 0; + p_buf->user_app_id = p_user_info->app_id; + p_buf->user_sec_mask = p_user_info->sec_mask; + } + + if(p_gn_info && (role & BTA_PAN_ROLE_GN)) + { + if(p_gn_info->p_srv_name) + BCM_STRNCPY_S(p_buf->gn_name, sizeof(p_buf->gn_name), p_gn_info->p_srv_name, BTA_SERVICE_NAME_LEN); + else + p_buf->gn_name[0] = 0; + + p_buf->gn_name[BTA_SERVICE_NAME_LEN] = 0; + p_buf->gn_app_id = p_gn_info->app_id; + p_buf->gn_sec_mask = p_gn_info->sec_mask; + + } + + if(p_nap_info && (role & BTA_PAN_ROLE_NAP)) + { + if(p_nap_info->p_srv_name) + BCM_STRNCPY_S(p_buf->nap_name, sizeof(p_buf->nap_name), p_nap_info->p_srv_name, BTA_SERVICE_NAME_LEN); + else + p_buf->nap_name[0] = 0; + + p_buf->nap_name[BTA_SERVICE_NAME_LEN] = 0; + p_buf->nap_app_id = p_nap_info->app_id; + p_buf->nap_sec_mask = p_nap_info->sec_mask; + + } + + bta_sys_sendmsg(p_buf); + } + + + +} + +/******************************************************************************* +** +** Function BTA_PanOpen +** +** Description Opens a connection to a peer device. +** When connection is open callback function is called +** with a BTA_PAN_OPEN_EVT. +** +** +** Returns void +** +*******************************************************************************/ +BTA_API void BTA_PanOpen(BD_ADDR bd_addr, tBTA_PAN_ROLE local_role, tBTA_PAN_ROLE peer_role) +{ + + tBTA_PAN_API_OPEN *p_buf; + + if ((p_buf = (tBTA_PAN_API_OPEN *) GKI_getbuf(sizeof(tBTA_PAN_API_OPEN))) != NULL) + { + p_buf->hdr.event = BTA_PAN_API_OPEN_EVT; + p_buf->local_role = local_role; + p_buf->peer_role = peer_role; + bdcpy(p_buf->bd_addr, bd_addr); + bta_sys_sendmsg(p_buf); + } + +} + +/******************************************************************************* +** +** Function BTA_PanClose +** +** Description Close a PAN connection to a peer device. +** +** +** Returns void +** +*******************************************************************************/ +BTA_API void BTA_PanClose(UINT16 handle) +{ + BT_HDR *p_buf; + + if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_buf->event = BTA_PAN_API_CLOSE_EVT; + p_buf->layer_specific = handle; + bta_sys_sendmsg(p_buf); + } +} +#endif /* BTA_PAN_INCLUDED */ diff --git a/bta/pan/bta_pan_ci.c b/bta/pan/bta_pan_ci.c new file mode 100644 index 0000000..843d2b9 --- /dev/null +++ b/bta/pan/bta_pan_ci.c @@ -0,0 +1,248 @@ +/***************************************************************************** +** +** Name: bta_pan_ci.c +** +** Description: This is the implementation file for data gateway call-in +** functions. +** +** Copyright (c) 2004, Widcomm Inc., All Rights Reserved. +** Widcomm Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ + +#include "bt_target.h" + +#if defined(BTA_PAN_INCLUDED) && (BTA_PAN_INCLUDED == TRUE) + +#include <string.h> + +#include "gki.h" +#include "pan_api.h" +#include "bd.h" +#include "bta_api.h" +#include "bta_pan_api.h" +#include "bta_pan_ci.h" +#include "bta_pan_int.h" + + +/******************************************************************************* +** +** Function bta_pan_ci_tx_ready +** +** Description This function sends an event to PAN indicating the phone is +** ready for more data and PAN should call bta_pan_co_tx_path(). +** This function is used when the TX data path is configured +** to use a pull interface. +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_ci_tx_ready(UINT16 handle) +{ + BT_HDR *p_buf; + + if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_buf->layer_specific = handle; + p_buf->event = BTA_PAN_CI_TX_READY_EVT; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function bta_pan_ci_rx_ready +** +** Description This function sends an event to PAN indicating the phone +** has data available to send to PAN and PAN should call +** bta_pan_co_rx_path(). This function is used when the RX +** data path is configured to use a pull interface. +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_ci_rx_ready(UINT16 handle) +{ + BT_HDR *p_buf; + + if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_buf->layer_specific = handle; + p_buf->event = BTA_PAN_CI_RX_READY_EVT; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function bta_pan_ci_tx_flow +** +** Description This function is called to enable or disable data flow on +** the TX path. The phone should call this function to +** disable data flow when it is congested and cannot handle +** any more data sent by bta_pan_co_tx_write() or +** bta_pan_co_tx_writebuf(). This function is used when the +** TX data path is configured to use a push interface. +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_ci_tx_flow(UINT16 handle, BOOLEAN enable) +{ + tBTA_PAN_CI_TX_FLOW *p_buf; + + if ((p_buf = (tBTA_PAN_CI_TX_FLOW *) GKI_getbuf(sizeof(tBTA_PAN_CI_TX_FLOW))) != NULL) + { + p_buf->hdr.layer_specific = handle; + p_buf->hdr.event = BTA_PAN_CI_TX_FLOW_EVT; + p_buf->enable = enable; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function bta_pan_ci_rx_write +** +** Description This function is called to send data to PAN when the RX path +** is configured to use a push interface. The function copies +** data to an event buffer and sends it to PAN. +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_ci_rx_write(UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol, + UINT8 *p_data, UINT16 len, BOOLEAN ext) +{ + BT_HDR * p_buf; + + if((p_buf = (BT_HDR *) GKI_getpoolbuf(PAN_POOL_ID)) != NULL) + { + + + p_buf->offset = PAN_MINIMUM_OFFSET; + + /* copy all other params before the data */ + bdcpy(((tBTA_PAN_DATA_PARAMS *)p_buf)->src, src); + bdcpy(((tBTA_PAN_DATA_PARAMS *)p_buf)->dst, dst); + ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol = protocol; + ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext = ext; + p_buf->len=len; + + /* copy data */ + memcpy((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, len); + + p_buf->layer_specific = handle; + p_buf->event = BTA_PAN_CI_RX_WRITEBUF_EVT; + bta_sys_sendmsg(p_buf); + } + +} + +/******************************************************************************* +** +** Function bta_pan_ci_rx_writebuf +** +** Description This function is called to send data to the phone when +** the RX path is configured to use a push interface with +** zero copy. The function sends an event to PAN containing +** the data buffer. The buffer must be allocated using +** functions GKI_getbuf() or GKI_getpoolbuf(). The buffer +** will be freed by BTA; the phone must not free the buffer. +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_ci_rx_writebuf(UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol, + BT_HDR *p_buf, BOOLEAN ext) +{ + + /* copy all other params before the data */ + bdcpy(((tBTA_PAN_DATA_PARAMS *)p_buf)->src, src); + bdcpy(((tBTA_PAN_DATA_PARAMS *)p_buf)->dst, dst); + ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol = protocol; + ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext = ext; + + p_buf->layer_specific = handle; + p_buf->event = BTA_PAN_CI_RX_WRITEBUF_EVT; + bta_sys_sendmsg(p_buf); +} + + + + +/******************************************************************************* +** +** Function bta_pan_ci_readbuf +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +BT_HDR * bta_pan_ci_readbuf(UINT16 handle, BD_ADDR src, BD_ADDR dst, UINT16* p_protocol, + BOOLEAN* p_ext, BOOLEAN* p_forward) +{ + tBTA_PAN_SCB * p_scb; + BT_HDR * p_buf; + + p_scb = bta_pan_scb_by_handle(handle); + + p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue); + + if(p_buf) + { + bdcpy(src,((tBTA_PAN_DATA_PARAMS *)p_buf)->src); + bdcpy(dst,((tBTA_PAN_DATA_PARAMS *)p_buf)->dst); + *p_protocol = ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol; + *p_ext = ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext; + *p_forward = ((tBTA_PAN_DATA_PARAMS *)p_buf)->forward; + } + + return p_buf; +} + + +/******************************************************************************* +** +** Function bta_pan_ci_set_mfilters +** +** Description This function is called to set multicast filters +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_ci_set_mfilters(UINT16 handle, UINT16 num_mcast_filters, UINT8 *p_start_array, + UINT8 *p_end_array) +{ + + PAN_SetMulticastFilters(handle, num_mcast_filters, p_start_array, p_end_array); + +} + + +/******************************************************************************* +** +** Function bta_pan_ci_set_mfilters +** +** Description This function is called to set protocol filters +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_ci_set_pfilters(UINT16 handle, UINT16 num_filters, UINT16 *p_start_array, UINT16 *p_end_array) +{ + + PAN_SetProtocolFilters(handle, num_filters, p_start_array, p_end_array ); + +} + +#endif /* BTA_PAN_API */ diff --git a/bta/pan/bta_pan_int.h b/bta/pan/bta_pan_int.h new file mode 100644 index 0000000..5715c31 --- /dev/null +++ b/bta/pan/bta_pan_int.h @@ -0,0 +1,200 @@ +/***************************************************************************** +** +** Name: bta_pan_int.h +** +** Description: This is the private interface file for the BTA data +** gateway. +** +** Copyright (c) 2004, Widcomm Inc., All Rights Reserved. +** Widcomm Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ +#ifndef BTA_PAN_INT_H +#define BTA_PAN_INT_H + +#include "bta_sys.h" +#include "bta_pan_api.h" + +/***************************************************************************** +** Constants +*****************************************************************************/ + + + + +/* PAN events */ +enum +{ + /* these events are handled by the state machine */ + BTA_PAN_API_CLOSE_EVT = BTA_SYS_EVT_START(BTA_ID_PAN), + BTA_PAN_CI_TX_READY_EVT, + BTA_PAN_CI_RX_READY_EVT, + BTA_PAN_CI_TX_FLOW_EVT, + BTA_PAN_CI_RX_WRITE_EVT, + BTA_PAN_CI_RX_WRITEBUF_EVT, + BTA_PAN_CONN_OPEN_EVT, + BTA_PAN_CONN_CLOSE_EVT, + BTA_PAN_BNEP_FLOW_ENABLE_EVT, + BTA_PAN_RX_FROM_BNEP_READY_EVT, + + /* these events are handled outside of the state machine */ + BTA_PAN_API_ENABLE_EVT, + BTA_PAN_API_DISABLE_EVT, + BTA_PAN_API_SET_ROLE_EVT, + BTA_PAN_API_OPEN_EVT +}; + + + + +/***************************************************************************** +** Data types +*****************************************************************************/ + +/* data type for BTA_PAN_API_ENABLE_EVT */ +typedef struct +{ + BT_HDR hdr; /* Event header */ + tBTA_PAN_CBACK *p_cback; /* PAN callback function */ +} tBTA_PAN_API_ENABLE; + +/* data type for BTA_PAN_API_REG_ROLE_EVT */ +typedef struct +{ + BT_HDR hdr; /* Event header */ + char user_name[BTA_SERVICE_NAME_LEN+1]; /* Service name */ + char gn_name[BTA_SERVICE_NAME_LEN+1]; /* Service name */ + char nap_name[BTA_SERVICE_NAME_LEN+1]; /* Service name */ + tBTA_PAN_ROLE role; + UINT8 user_app_id; + UINT8 gn_app_id; + UINT8 nap_app_id; + tBTA_SEC user_sec_mask; /* Security mask */ + tBTA_SEC gn_sec_mask; /* Security mask */ + tBTA_SEC nap_sec_mask; /* Security mask */ + + +} tBTA_PAN_API_SET_ROLE; + +/* data type for BTA_PAN_API_OPEN_EVT */ +typedef struct +{ + BT_HDR hdr; /* Event header */ + tBTA_PAN_ROLE local_role; /* local role */ + tBTA_PAN_ROLE peer_role; /* peer role */ + BD_ADDR bd_addr; /* peer bdaddr */ +} tBTA_PAN_API_OPEN; + +/* data type for BTA_PAN_CI_TX_FLOW_EVT */ +typedef struct +{ + BT_HDR hdr; /* Event header */ + BOOLEAN enable; /* Flow control setting */ +} tBTA_PAN_CI_TX_FLOW; + +/* data type for BTA_PAN_CONN_OPEN_EVT */ +typedef struct +{ + BT_HDR hdr; /* Event header */ + tPAN_RESULT result; + +} tBTA_PAN_CONN; + + + + +/* union of all data types */ +typedef union +{ + BT_HDR hdr; + tBTA_PAN_API_ENABLE api_enable; + tBTA_PAN_API_SET_ROLE api_set_role; + tBTA_PAN_API_OPEN api_open; + tBTA_PAN_CI_TX_FLOW ci_tx_flow; + tBTA_PAN_CONN conn; +} tBTA_PAN_DATA; + +/* state machine control block */ +typedef struct +{ + BD_ADDR bd_addr; /* peer bdaddr */ + BUFFER_Q data_queue; /* Queue of buffers waiting to be passed to application */ + UINT16 handle; /* BTA PAN/BNEP handle */ + BOOLEAN in_use; /* scb in use */ + tBTA_SEC sec_mask; /* Security mask */ + BOOLEAN pan_flow_enable;/* BNEP flow control state */ + BOOLEAN app_flow_enable;/* Application flow control state */ + UINT8 state; /* State machine state */ + tBTA_PAN_ROLE local_role; /* local role */ + tBTA_PAN_ROLE peer_role; /* peer role */ + UINT8 app_id; /* application id for the connection */ + +} tBTA_PAN_SCB; + + + +/* main control block */ +typedef struct +{ + tBTA_PAN_SCB scb[BTA_PAN_NUM_CONN]; /* state machine control blocks */ + tBTA_PAN_CBACK *p_cback; /* PAN callback function */ + UINT8 app_id[3]; /* application id for PAN roles */ + UINT8 flow_mask; /* Data flow mask */ + UINT8 q_level; /* queue level set by application for TX data */ + +} tBTA_PAN_CB; + + +/* pan data param */ +typedef struct +{ + BT_HDR hdr; + BD_ADDR src; + BD_ADDR dst; + UINT16 protocol; + BOOLEAN ext; + BOOLEAN forward; + +} tBTA_PAN_DATA_PARAMS; + + +/***************************************************************************** +** Global data +*****************************************************************************/ + +/* PAN control block */ + +#if BTA_DYNAMIC_MEMORY == FALSE +extern tBTA_PAN_CB bta_pan_cb; +#else +extern tBTA_PAN_CB *bta_pan_cb_ptr; +#define bta_pan_cb (*bta_pan_cb_ptr) +#endif + +/***************************************************************************** +** Function prototypes +*****************************************************************************/ +extern tBTA_PAN_SCB *bta_pan_scb_alloc(void); +extern void bta_pan_scb_dealloc(tBTA_PAN_SCB *p_scb); +extern UINT8 bta_pan_scb_to_idx(tBTA_PAN_SCB *p_scb); +extern tBTA_PAN_SCB *bta_pan_scb_by_handle(UINT16 handle); +extern BOOLEAN bta_pan_hdl_event(BT_HDR *p_msg); + +/* action functions */ +extern void bta_pan_enable(tBTA_PAN_DATA *p_data); +extern void bta_pan_disable(void); +extern void bta_pan_set_role(tBTA_PAN_DATA *p_data); +extern void bta_pan_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data); +extern void bta_pan_api_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data); +extern void bta_pan_set_shutdown(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data); +extern void bta_pan_rx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data); +extern void bta_pan_tx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data); +extern void bta_pan_tx_flow(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data); +extern void bta_pan_conn_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data); +extern void bta_pan_conn_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data); +extern void bta_pan_writebuf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data); +extern void bta_pan_write_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data); +extern void bta_pan_free_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data); + + +#endif /* BTA_PAN_INT_H */ diff --git a/bta/pan/bta_pan_main.c b/bta/pan/bta_pan_main.c new file mode 100644 index 0000000..34caf61 --- /dev/null +++ b/bta/pan/bta_pan_main.c @@ -0,0 +1,409 @@ +/***************************************************************************** +** +** Name: bta_pan_main.c +** +** Description: This file contains the PAN main functions and +** state machine. +** +** Copyright (c) 2004, Widcomm Inc., All Rights Reserved. +** Widcomm Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ + +#include "bt_target.h" + +#if defined(BTA_PAN_INCLUDED) && (BTA_PAN_INCLUDED == TRUE) + +#include <string.h> +#include "bta_api.h" +#include "bta_sys.h" +#include "gki.h" +#include "pan_api.h" +#include "bta_pan_api.h" +#include "bta_pan_int.h" +#include "bd.h" + +/***************************************************************************** +** Constants and types +*****************************************************************************/ + + + +/* state machine action enumeration list */ +enum +{ + BTA_PAN_API_CLOSE, + BTA_PAN_TX_PATH, + BTA_PAN_RX_PATH, + BTA_PAN_TX_FLOW, + BTA_PAN_WRITE_BUF, + BTA_PAN_CONN_OPEN, + BTA_PAN_CONN_CLOSE, + BTA_PAN_FREE_BUF, + BTA_PAN_IGNORE +}; + + + +/* type for action functions */ +typedef void (*tBTA_PAN_ACTION)(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data); + + + + +/* action function list */ +const tBTA_PAN_ACTION bta_pan_action[] = +{ + bta_pan_api_close, + bta_pan_tx_path, + bta_pan_rx_path, + bta_pan_tx_flow, + bta_pan_write_buf, + bta_pan_conn_open, + bta_pan_conn_close, + bta_pan_free_buf, + +}; + +/* state table information */ +#define BTA_PAN_ACTIONS 1 /* number of actions */ +#define BTA_PAN_NEXT_STATE 1 /* position of next state */ +#define BTA_PAN_NUM_COLS 2 /* number of columns in state tables */ + + +/* state machine states */ +enum +{ + BTA_PAN_IDLE_ST, + BTA_PAN_OPEN_ST, + BTA_PAN_CLOSING_ST +}; + + +/* state table for listen state */ +const UINT8 bta_pan_st_idle[][BTA_PAN_NUM_COLS] = +{ + /* API_CLOSE */ {BTA_PAN_API_CLOSE, BTA_PAN_IDLE_ST}, + /* CI_TX_READY */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST}, + /* CI_RX_READY */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST}, + /* CI_TX_FLOW */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST}, + /* CI_RX_WRITE */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST}, + /* CI_RX_WRITEBUF */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST}, + /* PAN_CONN_OPEN */ {BTA_PAN_CONN_OPEN, BTA_PAN_OPEN_ST}, + /* PAN_CONN_CLOSE */ {BTA_PAN_CONN_OPEN, BTA_PAN_IDLE_ST}, + /* FLOW_ENABLE */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST}, + /* BNEP_DATA */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST} + +}; + + + +/* state table for open state */ +const UINT8 bta_pan_st_open[][BTA_PAN_NUM_COLS] = +{ + /* API_CLOSE */ {BTA_PAN_API_CLOSE, BTA_PAN_OPEN_ST}, + /* CI_TX_READY */ {BTA_PAN_TX_PATH, BTA_PAN_OPEN_ST}, + /* CI_RX_READY */ {BTA_PAN_RX_PATH, BTA_PAN_OPEN_ST}, + /* CI_TX_FLOW */ {BTA_PAN_TX_FLOW, BTA_PAN_OPEN_ST}, + /* CI_RX_WRITE */ {BTA_PAN_IGNORE, BTA_PAN_OPEN_ST}, + /* CI_RX_WRITEBUF */ {BTA_PAN_WRITE_BUF, BTA_PAN_OPEN_ST}, + /* PAN_CONN_OPEN */ {BTA_PAN_IGNORE, BTA_PAN_OPEN_ST}, + /* PAN_CONN_CLOSE */ {BTA_PAN_CONN_CLOSE, BTA_PAN_IDLE_ST}, + /* FLOW_ENABLE */ {BTA_PAN_RX_PATH, BTA_PAN_OPEN_ST}, + /* BNEP_DATA */ {BTA_PAN_TX_PATH, BTA_PAN_OPEN_ST} +}; + +/* state table for closing state */ +const UINT8 bta_pan_st_closing[][BTA_PAN_NUM_COLS] = +{ + /* API_CLOSE */ {BTA_PAN_IGNORE, BTA_PAN_CLOSING_ST}, + /* CI_TX_READY */ {BTA_PAN_TX_PATH, BTA_PAN_CLOSING_ST}, + /* CI_RX_READY */ {BTA_PAN_RX_PATH, BTA_PAN_CLOSING_ST}, + /* CI_TX_FLOW */ {BTA_PAN_TX_FLOW, BTA_PAN_CLOSING_ST}, + /* CI_RX_WRITE */ {BTA_PAN_IGNORE, BTA_PAN_CLOSING_ST}, + /* CI_RX_WRITEBUF */ {BTA_PAN_FREE_BUF, BTA_PAN_CLOSING_ST}, + /* PAN_CONN_OPEN */ {BTA_PAN_IGNORE, BTA_PAN_CLOSING_ST}, + /* PAN_CONN_CLOSE */ {BTA_PAN_CONN_CLOSE, BTA_PAN_IDLE_ST}, + /* FLOW_ENABLE */ {BTA_PAN_RX_PATH, BTA_PAN_CLOSING_ST}, + /* BNEP_DATA */ {BTA_PAN_TX_PATH, BTA_PAN_CLOSING_ST} +}; + +/* type for state table */ +typedef const UINT8 (*tBTA_PAN_ST_TBL)[BTA_PAN_NUM_COLS]; + +/* state table */ +const tBTA_PAN_ST_TBL bta_pan_st_tbl[] = { + bta_pan_st_idle, + bta_pan_st_open, + bta_pan_st_closing +}; + +/***************************************************************************** +** Global data +*****************************************************************************/ + +/* PAN control block */ +#if BTA_DYNAMIC_MEMORY == FALSE +tBTA_PAN_CB bta_pan_cb; +#endif + +/******************************************************************************* +** +** Function bta_pan_scb_alloc +** +** Description Allocate a PAN server control block. +** +** +** Returns pointer to the scb, or NULL if none could be allocated. +** +*******************************************************************************/ +tBTA_PAN_SCB *bta_pan_scb_alloc(void) +{ + tBTA_PAN_SCB *p_scb = &bta_pan_cb.scb[0]; + int i; + + for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++) + { + if (!p_scb->in_use) + { + p_scb->in_use = TRUE; + APPL_TRACE_DEBUG1("bta_pan_scb_alloc %d", i); + break; + } + } + + if (i == BTA_PAN_NUM_CONN) + { + /* out of scbs */ + p_scb = NULL; + APPL_TRACE_WARNING0("Out of scbs"); + } + return p_scb; +} + +/******************************************************************************* +** +** Function bta_pan_sm_execute +** +** Description State machine event handling function for PAN +** +** +** Returns void +** +*******************************************************************************/ +static void bta_pan_sm_execute(tBTA_PAN_SCB *p_scb, UINT16 event, tBTA_PAN_DATA *p_data) +{ + tBTA_PAN_ST_TBL state_table; + UINT8 action; + int i; + + APPL_TRACE_EVENT3("PAN scb=%d event=0x%x state=%d", bta_pan_scb_to_idx(p_scb), event, p_scb->state); + + /* look up the state table for the current state */ + state_table = bta_pan_st_tbl[p_scb->state]; + + event &= 0x00FF; + + /* set next state */ + p_scb->state = state_table[event][BTA_PAN_NEXT_STATE]; + + /* execute action functions */ + for (i = 0; i < BTA_PAN_ACTIONS; i++) + { + if ((action = state_table[event][i]) != BTA_PAN_IGNORE) + { + (*bta_pan_action[action])(p_scb, p_data); + } + else + { + break; + } + } +} + +/******************************************************************************* +** +** Function bta_pan_api_enable +** +** Description Handle an API enable event. +** +** +** Returns void +** +*******************************************************************************/ +static void bta_pan_api_enable(tBTA_PAN_DATA *p_data) +{ + /* initialize control block */ + memset(&bta_pan_cb, 0, sizeof(bta_pan_cb)); + + /* store callback function */ + bta_pan_cb.p_cback = p_data->api_enable.p_cback; + bta_pan_enable(p_data); +} + +/******************************************************************************* +** +** Function bta_pan_api_disable +** +** Description Handle an API disable event. +** +** +** Returns void +** +*******************************************************************************/ +static void bta_pan_api_disable(tBTA_PAN_DATA *p_data) +{ + bta_pan_disable(); +} + + +/******************************************************************************* +** +** Function bta_pan_api_open +** +** Description Handle an API listen event. +** +** +** Returns void +** +*******************************************************************************/ +static void bta_pan_api_open(tBTA_PAN_DATA *p_data) +{ + tBTA_PAN_SCB *p_scb; + tBTA_PAN_OPEN data; + + /* allocate an scb */ + if ((p_scb = bta_pan_scb_alloc()) != NULL) + { + bta_pan_open(p_scb, p_data); + } + else + { + bdcpy(data.bd_addr, p_data->api_open.bd_addr); + data.status = BTA_PAN_FAIL; + bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data); + + } +} +/******************************************************************************* +** +** Function bta_pan_scb_dealloc +** +** Description Deallocate a link control block. +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_scb_dealloc(tBTA_PAN_SCB *p_scb) +{ + APPL_TRACE_DEBUG1("bta_pan_scb_dealloc %d", bta_pan_scb_to_idx(p_scb)); + memset(p_scb, 0, sizeof(tBTA_PAN_SCB)); +} + +/******************************************************************************* +** +** Function bta_pan_scb_to_idx +** +** Description Given a pointer to an scb, return its index. +** +** +** Returns Index of scb. +** +*******************************************************************************/ +UINT8 bta_pan_scb_to_idx(tBTA_PAN_SCB *p_scb) +{ + + return ((UINT8) (p_scb - bta_pan_cb.scb)) + 1; +} + + + +/******************************************************************************* +** +** Function bta_pan_scb_by_handle +** +** Description Find scb associated with handle. +** +** +** Returns Pointer to scb or NULL if not found. +** +*******************************************************************************/ +tBTA_PAN_SCB *bta_pan_scb_by_handle(UINT16 handle) +{ + tBTA_PAN_SCB *p_scb = &bta_pan_cb.scb[0]; + UINT8 i; + + for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++) + { + if (p_scb->handle == handle) + { + return p_scb;; + } + } + + + APPL_TRACE_WARNING1("No scb for handle %d", handle); + + return NULL; +} + +/******************************************************************************* +** +** Function bta_pan_hdl_event +** +** Description Data gateway main event handling function. +** +** +** Returns void +** +*******************************************************************************/ +BOOLEAN bta_pan_hdl_event(BT_HDR *p_msg) +{ + tBTA_PAN_SCB *p_scb; + BOOLEAN freebuf = TRUE; + + switch (p_msg->event) + { + /* handle enable event */ + case BTA_PAN_API_ENABLE_EVT: + bta_pan_api_enable((tBTA_PAN_DATA *) p_msg); + break; + + /* handle disable event */ + case BTA_PAN_API_DISABLE_EVT: + bta_pan_api_disable((tBTA_PAN_DATA *) p_msg); + break; + + /* handle set role event */ + case BTA_PAN_API_SET_ROLE_EVT: + bta_pan_set_role((tBTA_PAN_DATA *) p_msg); + break; + + /* handle open event */ + case BTA_PAN_API_OPEN_EVT: + bta_pan_api_open((tBTA_PAN_DATA *) p_msg); + break; + + + /* events that require buffer not be released */ + case BTA_PAN_CI_RX_WRITEBUF_EVT: + freebuf = FALSE; + if ((p_scb = bta_pan_scb_by_handle(p_msg->layer_specific)) != NULL) + { + bta_pan_sm_execute(p_scb, p_msg->event, (tBTA_PAN_DATA *) p_msg); + } + break; + + /* all other events */ + default: + if ((p_scb = bta_pan_scb_by_handle(p_msg->layer_specific)) != NULL) + { + bta_pan_sm_execute(p_scb, p_msg->event, (tBTA_PAN_DATA *) p_msg); + } + break; + + } + return freebuf; +} +#endif /* BTA_PAN_INCLUDED */ |